backup: implement qemu incremental pull backup
[libvirt/ericb.git] / src / qemu / qemu_driver.c
blob73c9db91b4e85b780db6d21a2f7ee2efaf3d5596
1 /*
2 * qemu_driver.c: core driver methods for managing qemu guests
4 * Copyright (C) 2006-2019 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
22 #include <config.h>
24 #include <sys/types.h>
25 #include <sys/poll.h>
26 #include <sys/time.h>
27 #include <dirent.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <signal.h>
33 #include <sys/wait.h>
34 #include <sys/ioctl.h>
35 #include <sys/un.h>
36 #include <byteswap.h>
39 #include "qemu_driver.h"
40 #include "qemu_agent.h"
41 #include "qemu_alias.h"
42 #include "qemu_block.h"
43 #include "qemu_conf.h"
44 #include "qemu_capabilities.h"
45 #include "qemu_command.h"
46 #include "qemu_parse_command.h"
47 #include "qemu_cgroup.h"
48 #include "qemu_hostdev.h"
49 #include "qemu_hotplug.h"
50 #include "qemu_monitor.h"
51 #include "qemu_monitor_json.h"
52 #include "qemu_process.h"
53 #include "qemu_migration.h"
54 #include "qemu_migration_params.h"
55 #include "qemu_blockjob.h"
56 #include "qemu_security.h"
58 #include "virerror.h"
59 #include "virlog.h"
60 #include "datatypes.h"
61 #include "virbuffer.h"
62 #include "virhostcpu.h"
63 #include "virhostmem.h"
64 #include "virnetdevtap.h"
65 #include "virnetdevopenvswitch.h"
66 #include "capabilities.h"
67 #include "viralloc.h"
68 #include "virarptable.h"
69 #include "viruuid.h"
70 #include "domain_conf.h"
71 #include "domain_audit.h"
72 #include "node_device_conf.h"
73 #include "virpci.h"
74 #include "virusb.h"
75 #include "virprocess.h"
76 #include "libvirt_internal.h"
77 #include "virxml.h"
78 #include "cpu/cpu.h"
79 #include "virsysinfo.h"
80 #include "domain_nwfilter.h"
81 #include "virhook.h"
82 #include "virstoragefile.h"
83 #include "virfile.h"
84 #include "virfdstream.h"
85 #include "configmake.h"
86 #include "virthreadpool.h"
87 #include "locking/lock_manager.h"
88 #include "locking/domain_lock.h"
89 #include "virkeycode.h"
90 #include "virnodesuspend.h"
91 #include "virtime.h"
92 #include "virtypedparam.h"
93 #include "virbitmap.h"
94 #include "virstring.h"
95 #include "viraccessapicheck.h"
96 #include "viraccessapicheckqemu.h"
97 #include "virhostdev.h"
98 #include "domain_capabilities.h"
99 #include "vircgroup.h"
100 #include "virperf.h"
101 #include "virnuma.h"
102 #include "dirname.h"
103 #include "netdev_bandwidth_conf.h"
104 #include "virqemu.h"
106 #define VIR_FROM_THIS VIR_FROM_QEMU
108 VIR_LOG_INIT("qemu.qemu_driver");
110 #define QEMU_NB_MEM_PARAM 3
112 #define QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS 6
113 #define QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS 7
114 #define QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS 6
115 #define QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS 1
116 #define QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS (QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS + \
117 QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS + \
118 QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS + \
119 QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS)
121 #define QEMU_NB_NUMA_PARAM 2
123 #define QEMU_SCHED_MIN_PERIOD 1000LL
124 #define QEMU_SCHED_MAX_PERIOD 1000000LL
125 #define QEMU_SCHED_MIN_QUOTA 1000LL
126 #define QEMU_SCHED_MAX_QUOTA 18446744073709551LL
128 #define QEMU_GUEST_VCPU_MAX_ID 4096
130 #define QEMU_NB_BLKIO_PARAM 6
132 #define QEMU_NB_BANDWIDTH_PARAM 7
134 static void qemuProcessEventHandler(void *data, void *opaque);
136 static int qemuStateCleanup(void);
138 static int qemuDomainObjStart(virConnectPtr conn,
139 virQEMUDriverPtr driver,
140 virDomainObjPtr vm,
141 unsigned int flags,
142 qemuDomainAsyncJob asyncJob);
144 static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
145 void *opaque);
147 static int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
148 bool dynamicOwnership,
149 const char *path, int oflags,
150 bool *needUnlink);
152 static int qemuGetDHCPInterfaces(virDomainPtr dom,
153 virDomainObjPtr vm,
154 virDomainInterfacePtr **ifaces);
156 static int qemuARPGetInterfaces(virDomainObjPtr vm,
157 virDomainInterfacePtr **ifaces);
159 static virQEMUDriverPtr qemu_driver;
162 * qemuDomObjFromDomain:
163 * @domain: Domain pointer that has to be looked up
165 * This function looks up @domain and returns the appropriate virDomainObjPtr
166 * that has to be released by calling virDomainObjEndAPI().
168 * Returns the domain object with incremented reference counter which is locked
169 * on success, NULL otherwise.
171 static virDomainObjPtr
172 qemuDomObjFromDomain(virDomainPtr domain)
174 virDomainObjPtr vm;
175 virQEMUDriverPtr driver = domain->conn->privateData;
176 char uuidstr[VIR_UUID_STRING_BUFLEN];
178 vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
179 if (!vm) {
180 virUUIDFormat(domain->uuid, uuidstr);
181 virReportError(VIR_ERR_NO_DOMAIN,
182 _("no domain with matching uuid '%s' (%s)"),
183 uuidstr, domain->name);
184 return NULL;
187 return vm;
190 /* Looks up the domain object from snapshot and unlocks the
191 * driver. The returned domain object is locked and ref'd and the
192 * caller must call virDomainObjEndAPI() on it. */
193 static virDomainObjPtr
194 qemuDomObjFromSnapshot(virDomainSnapshotPtr snapshot)
196 return qemuDomObjFromDomain(snapshot->domain);
200 /* Looks up snapshot object from VM and name */
201 static virDomainSnapshotObjPtr
202 qemuSnapObjFromName(virDomainObjPtr vm,
203 const char *name)
205 virDomainSnapshotObjPtr snap = NULL;
206 snap = virDomainSnapshotFindByName(vm->snapshots, name);
207 if (!snap)
208 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
209 _("no domain snapshot with matching name '%s'"),
210 name);
212 return snap;
216 /* Looks up snapshot object from VM and snapshotPtr */
217 static virDomainSnapshotObjPtr
218 qemuSnapObjFromSnapshot(virDomainObjPtr vm,
219 virDomainSnapshotPtr snapshot)
221 return qemuSnapObjFromName(vm, snapshot->name);
224 /* Looks up the domain object from checkpoint and unlocks the
225 * driver. The returned domain object is locked and ref'd and the
226 * caller must call virDomainObjEndAPI() on it. */
227 static virDomainObjPtr
228 qemuDomObjFromCheckpoint(virDomainCheckpointPtr checkpoint)
230 return qemuDomObjFromDomain(checkpoint->domain);
234 /* Looks up checkpoint object from VM and name */
235 static virDomainCheckpointObjPtr
236 qemuCheckObjFromName(virDomainObjPtr vm,
237 const char *name)
239 virDomainCheckpointObjPtr chk = NULL;
240 chk = virDomainCheckpointFindByName(vm->checkpoints, name);
241 if (!chk)
242 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
243 _("no domain checkpoint with matching name '%s'"),
244 name);
246 return chk;
250 /* Looks up checkpoint object from VM and checkpointPtr */
251 static virDomainCheckpointObjPtr
252 qemuCheckObjFromCheckpoint(virDomainObjPtr vm,
253 virDomainCheckpointPtr checkpoint)
255 return qemuCheckObjFromName(vm, checkpoint->name);
258 static int
259 qemuAutostartDomain(virDomainObjPtr vm,
260 void *opaque)
262 virQEMUDriverPtr driver = opaque;
263 int flags = 0;
264 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
265 int ret = -1;
267 if (cfg->autoStartBypassCache)
268 flags |= VIR_DOMAIN_START_BYPASS_CACHE;
270 virObjectLock(vm);
271 virObjectRef(vm);
272 virResetLastError();
273 if (vm->autostart &&
274 !virDomainObjIsActive(vm)) {
275 if (qemuProcessBeginJob(driver, vm,
276 VIR_DOMAIN_JOB_OPERATION_START, flags) < 0) {
277 virReportError(VIR_ERR_INTERNAL_ERROR,
278 _("Failed to start job on VM '%s': %s"),
279 vm->def->name, virGetLastErrorMessage());
280 goto cleanup;
283 if (qemuDomainObjStart(NULL, driver, vm, flags,
284 QEMU_ASYNC_JOB_START) < 0) {
285 virReportError(VIR_ERR_INTERNAL_ERROR,
286 _("Failed to autostart VM '%s': %s"),
287 vm->def->name, virGetLastErrorMessage());
290 qemuProcessEndJob(driver, vm);
293 ret = 0;
294 cleanup:
295 virDomainObjEndAPI(&vm);
296 virObjectUnref(cfg);
297 return ret;
301 static void
302 qemuAutostartDomains(virQEMUDriverPtr driver)
304 virDomainObjListForEach(driver->domains, qemuAutostartDomain, driver);
308 static int
309 qemuSecurityChownCallback(const virStorageSource *src,
310 uid_t uid,
311 gid_t gid)
313 struct stat sb;
314 int save_errno = 0;
315 int ret = -1;
316 int rv;
317 VIR_AUTOUNREF(virStorageSourcePtr) cpy = NULL;
319 rv = virStorageFileSupportsSecurityDriver(src);
320 if (rv <= 0)
321 return rv;
323 if (virStorageSourceIsLocalStorage(src)) {
324 /* use direct chown for local files so that the file doesn't
325 * need to be initialized */
326 if (!src->path)
327 return 0;
329 if (stat(src->path, &sb) >= 0) {
330 if (sb.st_uid == uid &&
331 sb.st_gid == gid) {
332 /* It's alright, there's nothing to change anyway. */
333 return 0;
337 if (chown(src->path, uid, gid) < 0)
338 goto cleanup;
339 } else {
340 if (!(cpy = virStorageSourceCopy(src, false)))
341 goto cleanup;
343 /* src file init reports errors, return -2 on failure */
344 if (virStorageFileInit(cpy) < 0) {
345 ret = -2;
346 goto cleanup;
349 if (virStorageFileChown(cpy, uid, gid) < 0)
350 goto cleanup;
353 ret = 0;
355 cleanup:
356 save_errno = errno;
357 virStorageFileDeinit(cpy);
358 errno = save_errno;
360 return ret;
364 static int
365 qemuSecurityInit(virQEMUDriverPtr driver)
367 char **names;
368 virSecurityManagerPtr mgr = NULL;
369 virSecurityManagerPtr stack = NULL;
370 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
371 unsigned int flags = 0;
373 if (cfg->securityDefaultConfined)
374 flags |= VIR_SECURITY_MANAGER_DEFAULT_CONFINED;
375 if (cfg->securityRequireConfined)
376 flags |= VIR_SECURITY_MANAGER_REQUIRE_CONFINED;
377 if (virQEMUDriverIsPrivileged(driver))
378 flags |= VIR_SECURITY_MANAGER_PRIVILEGED;
380 if (cfg->securityDriverNames &&
381 cfg->securityDriverNames[0]) {
382 names = cfg->securityDriverNames;
383 while (names && *names) {
384 if (!(mgr = qemuSecurityNew(*names,
385 QEMU_DRIVER_NAME,
386 flags)))
387 goto error;
388 if (!stack) {
389 if (!(stack = qemuSecurityNewStack(mgr)))
390 goto error;
391 } else {
392 if (qemuSecurityStackAddNested(stack, mgr) < 0)
393 goto error;
395 mgr = NULL;
396 names++;
398 } else {
399 if (!(mgr = qemuSecurityNew(NULL,
400 QEMU_DRIVER_NAME,
401 flags)))
402 goto error;
403 if (!(stack = qemuSecurityNewStack(mgr)))
404 goto error;
405 mgr = NULL;
408 if (virQEMUDriverIsPrivileged(driver)) {
409 if (cfg->dynamicOwnership)
410 flags |= VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP;
411 if (virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT))
412 flags |= VIR_SECURITY_MANAGER_MOUNT_NAMESPACE;
413 if (!(mgr = qemuSecurityNewDAC(QEMU_DRIVER_NAME,
414 cfg->user,
415 cfg->group,
416 flags,
417 qemuSecurityChownCallback)))
418 goto error;
419 if (!stack) {
420 if (!(stack = qemuSecurityNewStack(mgr)))
421 goto error;
422 } else {
423 if (qemuSecurityStackAddNested(stack, mgr) < 0)
424 goto error;
426 mgr = NULL;
429 driver->securityManager = stack;
430 virObjectUnref(cfg);
431 return 0;
433 error:
434 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
435 _("Failed to initialize security drivers"));
436 virObjectUnref(stack);
437 virObjectUnref(mgr);
438 virObjectUnref(cfg);
439 return -1;
443 static int
444 qemuDomainSnapshotLoad(virDomainObjPtr vm,
445 void *data)
447 char *baseDir = (char *)data;
448 char *snapDir = NULL;
449 DIR *dir = NULL;
450 struct dirent *entry;
451 char *xmlStr;
452 char *fullpath;
453 virDomainSnapshotDefPtr def = NULL;
454 virDomainSnapshotObjPtr snap = NULL;
455 virDomainSnapshotObjPtr current = NULL;
456 unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE |
457 VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
458 VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL);
459 int ret = -1;
460 virCapsPtr caps = NULL;
461 int direrr;
463 virObjectLock(vm);
464 if (virAsprintf(&snapDir, "%s/%s", baseDir, vm->def->name) < 0) {
465 virReportError(VIR_ERR_INTERNAL_ERROR,
466 _("Failed to allocate memory for "
467 "snapshot directory for domain %s"),
468 vm->def->name);
469 goto cleanup;
472 if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
473 goto cleanup;
475 VIR_INFO("Scanning for snapshots for domain %s in %s", vm->def->name,
476 snapDir);
478 if (virDirOpenIfExists(&dir, snapDir) <= 0)
479 goto cleanup;
481 while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
482 /* NB: ignoring errors, so one malformed config doesn't
483 kill the whole process */
484 VIR_INFO("Loading snapshot file '%s'", entry->d_name);
486 if (virAsprintf(&fullpath, "%s/%s", snapDir, entry->d_name) < 0) {
487 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
488 _("Failed to allocate memory for path"));
489 continue;
492 if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
493 /* Nothing we can do here, skip this one */
494 virReportSystemError(errno,
495 _("Failed to read snapshot file %s"),
496 fullpath);
497 VIR_FREE(fullpath);
498 continue;
501 def = virDomainSnapshotDefParseString(xmlStr, caps,
502 qemu_driver->xmlopt,
503 flags);
504 if (def == NULL) {
505 /* Nothing we can do here, skip this one */
506 virReportError(VIR_ERR_INTERNAL_ERROR,
507 _("Failed to parse snapshot XML from file '%s'"),
508 fullpath);
509 VIR_FREE(fullpath);
510 VIR_FREE(xmlStr);
511 continue;
514 snap = virDomainSnapshotAssignDef(vm->snapshots, def);
515 if (snap == NULL) {
516 virDomainSnapshotDefFree(def);
517 } else if (snap->def->current) {
518 current = snap;
519 if (!vm->current_snapshot)
520 vm->current_snapshot = snap;
523 VIR_FREE(fullpath);
524 VIR_FREE(xmlStr);
526 if (direrr < 0)
527 virReportError(VIR_ERR_INTERNAL_ERROR,
528 _("Failed to fully read directory %s"),
529 snapDir);
531 if (vm->current_snapshot != current) {
532 virReportError(VIR_ERR_INTERNAL_ERROR,
533 _("Too many snapshots claiming to be current for domain %s"),
534 vm->def->name);
535 vm->current_snapshot = NULL;
538 if (virDomainSnapshotUpdateRelations(vm->snapshots) < 0)
539 virReportError(VIR_ERR_INTERNAL_ERROR,
540 _("Snapshots have inconsistent relations for domain %s"),
541 vm->def->name);
543 /* FIXME: qemu keeps internal track of snapshots. We can get access
544 * to this info via the "info snapshots" monitor command for running
545 * domains, or via "qemu-img snapshot -l" for shutoff domains. It would
546 * be nice to update our internal state based on that, but there is a
547 * a problem. qemu doesn't track all of the same metadata that we do.
548 * In particular we wouldn't be able to fill in the <parent>, which is
549 * pretty important in our metadata.
552 virResetLastError();
554 ret = 0;
555 cleanup:
556 VIR_DIR_CLOSE(dir);
557 VIR_FREE(snapDir);
558 virObjectUnref(caps);
559 virObjectUnlock(vm);
560 return ret;
564 static int
565 qemuDomainCheckpointLoad(virDomainObjPtr vm,
566 void *data)
568 char *baseDir = (char *)data;
569 char *chkDir = NULL;
570 DIR *dir = NULL;
571 struct dirent *entry;
572 char *xmlStr;
573 char *fullpath;
574 virDomainCheckpointDefPtr def = NULL;
575 virDomainCheckpointObjPtr chk = NULL;
576 virDomainCheckpointObjPtr current = NULL;
577 unsigned int flags = (VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE |
578 VIR_DOMAIN_CHECKPOINT_PARSE_DISKS |
579 VIR_DOMAIN_CHECKPOINT_PARSE_INTERNAL);
580 int ret = -1;
581 virCapsPtr caps = NULL;
582 int direrr;
584 virObjectLock(vm);
585 if (virAsprintf(&chkDir, "%s/%s", baseDir, vm->def->name) < 0) {
586 virReportError(VIR_ERR_INTERNAL_ERROR,
587 _("Failed to allocate memory for "
588 "checkpoint directory for domain %s"),
589 vm->def->name);
590 goto cleanup;
593 if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
594 goto cleanup;
596 VIR_INFO("Scanning for checkpoints for domain %s in %s", vm->def->name,
597 chkDir);
599 if (virDirOpenIfExists(&dir, chkDir) <= 0)
600 goto cleanup;
602 while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
603 /* NB: ignoring errors, so one malformed config doesn't
604 kill the whole process */
605 VIR_INFO("Loading checkpoint file '%s'", entry->d_name);
607 if (virAsprintf(&fullpath, "%s/%s", chkDir, entry->d_name) < 0) {
608 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
609 _("Failed to allocate memory for path"));
610 continue;
613 if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
614 /* Nothing we can do here, skip this one */
615 virReportSystemError(errno,
616 _("Failed to read checkpoint file %s"),
617 fullpath);
618 VIR_FREE(fullpath);
619 continue;
622 def = virDomainCheckpointDefParseString(xmlStr, caps,
623 qemu_driver->xmlopt,
624 flags);
625 if (!def || virDomainCheckpointAlignDisks(def) < 0) {
626 /* Nothing we can do here, skip this one */
627 virReportError(VIR_ERR_INTERNAL_ERROR,
628 _("Failed to parse checkpoint XML from file '%s'"),
629 fullpath);
630 VIR_FREE(fullpath);
631 VIR_FREE(xmlStr);
632 continue;
635 chk = virDomainCheckpointAssignDef(vm->checkpoints, def);
636 if (chk == NULL) {
637 virDomainCheckpointDefFree(def);
638 } else if (chk->def->current) {
639 current = chk;
640 if (!vm->current_checkpoint)
641 vm->current_checkpoint = chk;
644 VIR_FREE(fullpath);
645 VIR_FREE(xmlStr);
647 if (direrr < 0)
648 virReportError(VIR_ERR_INTERNAL_ERROR,
649 _("Failed to fully read directory %s"),
650 chkDir);
652 if (vm->current_checkpoint != current) {
653 virReportError(VIR_ERR_INTERNAL_ERROR,
654 _("Too many checkpoints claiming to be current for domain %s"),
655 vm->def->name);
656 vm->current_checkpoint = NULL;
659 if (virDomainCheckpointUpdateRelations(vm->checkpoints) < 0)
660 virReportError(VIR_ERR_INTERNAL_ERROR,
661 _("Checkpoints have inconsistent relations for domain %s"),
662 vm->def->name);
664 /* FIXME: qemu keeps internal track of bitmaps, which form the
665 * basis for checkpoints; it would be nice if we could update our
666 * internal state to reflect that information automatically. But
667 * qemu 3.0 did not have access to this via qemu-img for offline
668 * images (you have to use QMP commands on a running guest), and
669 * it also does not track <parent> relations which we find
670 * important in our metadata.
673 virResetLastError();
675 ret = 0;
676 cleanup:
677 VIR_DIR_CLOSE(dir);
678 VIR_FREE(chkDir);
679 virObjectUnref(caps);
680 virObjectUnlock(vm);
681 return ret;
685 static int
686 qemuDomainNetsRestart(virDomainObjPtr vm,
687 void *data ATTRIBUTE_UNUSED)
689 size_t i;
690 virDomainDefPtr def = vm->def;
692 virObjectLock(vm);
694 for (i = 0; i < def->nnets; i++) {
695 virDomainNetDefPtr net = def->nets[i];
696 if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT &&
697 virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_VEPA) {
698 VIR_DEBUG("VEPA mode device %s active in domain %s. Reassociating.",
699 net->ifname, def->name);
700 ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname,
701 &net->mac,
702 virDomainNetGetActualDirectDev(net),
703 def->uuid,
704 virDomainNetGetActualVirtPortProfile(net),
705 VIR_NETDEV_VPORT_PROFILE_OP_CREATE));
709 virObjectUnlock(vm);
710 return 0;
714 static int
715 qemuDomainFindMaxID(virDomainObjPtr vm,
716 void *data)
718 int *driver_maxid = data;
720 if (vm->def->id > *driver_maxid)
721 *driver_maxid = vm->def->id;
723 return 0;
728 * qemuStateInitialize:
730 * Initialization function for the QEMU daemon
732 static int
733 qemuStateInitialize(bool privileged,
734 virStateInhibitCallback callback,
735 void *opaque)
737 char *driverConf = NULL;
738 virQEMUDriverConfigPtr cfg;
739 uid_t run_uid = -1;
740 gid_t run_gid = -1;
741 char *hugepagePath = NULL;
742 char *memoryBackingPath = NULL;
743 size_t i;
744 virCPUDefPtr hostCPU = NULL;
745 unsigned int microcodeVersion = 0;
747 if (VIR_ALLOC(qemu_driver) < 0)
748 return -1;
750 if (virMutexInit(&qemu_driver->lock) < 0) {
751 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
752 _("cannot initialize mutex"));
753 VIR_FREE(qemu_driver);
754 return -1;
757 qemu_driver->inhibitCallback = callback;
758 qemu_driver->inhibitOpaque = opaque;
760 qemu_driver->privileged = privileged;
762 if (!(qemu_driver->domains = virDomainObjListNew()))
763 goto error;
765 /* Init domain events */
766 qemu_driver->domainEventState = virObjectEventStateNew();
767 if (!qemu_driver->domainEventState)
768 goto error;
770 /* read the host sysinfo */
771 if (privileged)
772 qemu_driver->hostsysinfo = virSysinfoRead();
774 if (!(qemu_driver->config = cfg = virQEMUDriverConfigNew(privileged)))
775 goto error;
777 if (virAsprintf(&driverConf, "%s/qemu.conf", cfg->configBaseDir) < 0)
778 goto error;
780 if (virQEMUDriverConfigLoadFile(cfg, driverConf, privileged) < 0)
781 goto error;
782 VIR_FREE(driverConf);
784 if (virQEMUDriverConfigValidate(cfg) < 0)
785 goto error;
787 if (virQEMUDriverConfigSetDefaults(cfg) < 0)
788 goto error;
790 if (virFileMakePath(cfg->stateDir) < 0) {
791 virReportSystemError(errno, _("Failed to create state dir %s"),
792 cfg->stateDir);
793 goto error;
795 if (virFileMakePath(cfg->libDir) < 0) {
796 virReportSystemError(errno, _("Failed to create lib dir %s"),
797 cfg->libDir);
798 goto error;
800 if (virFileMakePath(cfg->cacheDir) < 0) {
801 virReportSystemError(errno, _("Failed to create cache dir %s"),
802 cfg->cacheDir);
803 goto error;
805 if (virFileMakePath(cfg->saveDir) < 0) {
806 virReportSystemError(errno, _("Failed to create save dir %s"),
807 cfg->saveDir);
808 goto error;
810 if (virFileMakePath(cfg->snapshotDir) < 0) {
811 virReportSystemError(errno, _("Failed to create snapshot dir %s"),
812 cfg->snapshotDir);
813 goto error;
815 if (virFileMakePath(cfg->checkpointDir) < 0) {
816 virReportSystemError(errno, _("Failed to create checkpoint dir %s"),
817 cfg->checkpointDir);
818 goto error;
820 if (virFileMakePath(cfg->autoDumpPath) < 0) {
821 virReportSystemError(errno, _("Failed to create dump dir %s"),
822 cfg->autoDumpPath);
823 goto error;
825 if (virFileMakePath(cfg->channelTargetDir) < 0) {
826 virReportSystemError(errno, _("Failed to create channel target dir %s"),
827 cfg->channelTargetDir);
828 goto error;
830 if (virFileMakePath(cfg->nvramDir) < 0) {
831 virReportSystemError(errno, _("Failed to create nvram dir %s"),
832 cfg->nvramDir);
833 goto error;
835 if (virFileMakePath(cfg->memoryBackingDir) < 0) {
836 virReportSystemError(errno, _("Failed to create memory backing dir %s"),
837 cfg->memoryBackingDir);
838 goto error;
841 qemu_driver->qemuImgBinary = virFindFileInPath("qemu-img");
843 if (!(qemu_driver->lockManager =
844 virLockManagerPluginNew(cfg->lockManagerName ?
845 cfg->lockManagerName : "nop",
846 "qemu",
847 cfg->configBaseDir,
848 0)))
849 goto error;
851 if (cfg->macFilter) {
852 if (!(qemu_driver->ebtables = ebtablesContextNew("qemu"))) {
853 virReportSystemError(errno,
854 _("failed to enable mac filter in '%s'"),
855 __FILE__);
856 goto error;
859 if (ebtablesAddForwardPolicyReject(qemu_driver->ebtables) < 0)
860 goto error;
863 /* Allocate bitmap for remote display port reservations. We cannot
864 * do this before the config is loaded properly, since the port
865 * numbers are configurable now */
866 if ((qemu_driver->remotePorts =
867 virPortAllocatorRangeNew(_("display"),
868 cfg->remotePortMin,
869 cfg->remotePortMax)) == NULL)
870 goto error;
872 if ((qemu_driver->webSocketPorts =
873 virPortAllocatorRangeNew(_("webSocket"),
874 cfg->webSocketPortMin,
875 cfg->webSocketPortMax)) == NULL)
876 goto error;
878 if ((qemu_driver->migrationPorts =
879 virPortAllocatorRangeNew(_("migration"),
880 cfg->migrationPortMin,
881 cfg->migrationPortMax)) == NULL)
882 goto error;
884 if (qemuSecurityInit(qemu_driver) < 0)
885 goto error;
887 if (!(qemu_driver->hostdevMgr = virHostdevManagerGetDefault()))
888 goto error;
890 if (!(qemu_driver->sharedDevices = virHashCreate(30, qemuSharedDeviceEntryFree)))
891 goto error;
893 if (qemuMigrationDstErrorInit(qemu_driver) < 0)
894 goto error;
896 if (privileged) {
897 char *channeldir;
899 if (chown(cfg->libDir, cfg->user, cfg->group) < 0) {
900 virReportSystemError(errno,
901 _("unable to set ownership of '%s' to user %d:%d"),
902 cfg->libDir, (int)cfg->user,
903 (int)cfg->group);
904 goto error;
906 if (chown(cfg->cacheDir, cfg->user, cfg->group) < 0) {
907 virReportSystemError(errno,
908 _("unable to set ownership of '%s' to %d:%d"),
909 cfg->cacheDir, (int)cfg->user,
910 (int)cfg->group);
911 goto error;
913 if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) {
914 virReportSystemError(errno,
915 _("unable to set ownership of '%s' to %d:%d"),
916 cfg->saveDir, (int)cfg->user,
917 (int)cfg->group);
918 goto error;
920 if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) {
921 virReportSystemError(errno,
922 _("unable to set ownership of '%s' to %d:%d"),
923 cfg->snapshotDir, (int)cfg->user,
924 (int)cfg->group);
925 goto error;
927 if (chown(cfg->checkpointDir, cfg->user, cfg->group) < 0) {
928 virReportSystemError(errno,
929 _("unable to set ownership of '%s' to %d:%d"),
930 cfg->checkpointDir, (int)cfg->user,
931 (int)cfg->group);
932 goto error;
934 if (chown(cfg->autoDumpPath, cfg->user, cfg->group) < 0) {
935 virReportSystemError(errno,
936 _("unable to set ownership of '%s' to %d:%d"),
937 cfg->autoDumpPath, (int)cfg->user,
938 (int)cfg->group);
939 goto error;
941 if (!(channeldir = mdir_name(cfg->channelTargetDir))) {
942 virReportOOMError();
943 goto error;
945 if (chown(channeldir, cfg->user, cfg->group) < 0) {
946 virReportSystemError(errno,
947 _("unable to set ownership of '%s' to %d:%d"),
948 channeldir, (int)cfg->user,
949 (int)cfg->group);
950 VIR_FREE(channeldir);
951 goto error;
953 VIR_FREE(channeldir);
954 if (chown(cfg->channelTargetDir, cfg->user, cfg->group) < 0) {
955 virReportSystemError(errno,
956 _("unable to set ownership of '%s' to %d:%d"),
957 cfg->channelTargetDir, (int)cfg->user,
958 (int)cfg->group);
959 goto error;
961 if (chown(cfg->nvramDir, cfg->user, cfg->group) < 0) {
962 virReportSystemError(errno,
963 _("unable to set ownership of '%s' to %d:%d"),
964 cfg->nvramDir, (int)cfg->user,
965 (int)cfg->group);
966 goto error;
968 if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) {
969 virReportSystemError(errno,
970 _("unable to set ownership of '%s' to %d:%d"),
971 cfg->memoryBackingDir, (int)cfg->user,
972 (int)cfg->group);
973 goto error;
976 run_uid = cfg->user;
977 run_gid = cfg->group;
980 if ((hostCPU = virCPUProbeHost(virArchFromHost())))
981 microcodeVersion = hostCPU->microcodeVersion;
982 virCPUDefFree(hostCPU);
984 qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
985 cfg->cacheDir,
986 run_uid,
987 run_gid,
988 microcodeVersion);
989 if (!qemu_driver->qemuCapsCache)
990 goto error;
992 if ((qemu_driver->caps = virQEMUDriverCreateCapabilities(qemu_driver)) == NULL)
993 goto error;
995 if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver)))
996 goto error;
998 /* If hugetlbfs is present, then we need to create a sub-directory within
999 * it, since we can't assume the root mount point has permissions that
1000 * will let our spawned QEMU instances use it. */
1001 for (i = 0; i < cfg->nhugetlbfs; i++) {
1002 hugepagePath = qemuGetBaseHugepagePath(&cfg->hugetlbfs[i]);
1004 if (!hugepagePath)
1005 goto error;
1007 if (virFileMakePath(hugepagePath) < 0) {
1008 virReportSystemError(errno,
1009 _("unable to create hugepage path %s"),
1010 hugepagePath);
1011 goto error;
1013 if (privileged &&
1014 virFileUpdatePerm(cfg->hugetlbfs[i].mnt_dir,
1015 0, S_IXGRP | S_IXOTH) < 0)
1016 goto error;
1017 VIR_FREE(hugepagePath);
1020 if (qemuGetMemoryBackingBasePath(cfg, &memoryBackingPath) < 0)
1021 goto error;
1023 if (virFileMakePath(memoryBackingPath) < 0) {
1024 virReportSystemError(errno,
1025 _("unable to create memory backing path %s"),
1026 memoryBackingPath);
1027 goto error;
1030 if (privileged &&
1031 virFileUpdatePerm(memoryBackingPath,
1032 0, S_IXGRP | S_IXOTH) < 0)
1033 goto error;
1034 VIR_FREE(memoryBackingPath);
1036 if (!(qemu_driver->closeCallbacks = virCloseCallbacksNew()))
1037 goto error;
1039 /* Get all the running persistent or transient configs first */
1040 if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
1041 cfg->stateDir,
1042 NULL, true,
1043 qemu_driver->caps,
1044 qemu_driver->xmlopt,
1045 NULL, NULL) < 0)
1046 goto error;
1048 /* find the maximum ID from active and transient configs to initialize
1049 * the driver with. This is to avoid race between autostart and reconnect
1050 * threads */
1051 virDomainObjListForEach(qemu_driver->domains,
1052 qemuDomainFindMaxID,
1053 &qemu_driver->lastvmid);
1055 virDomainObjListForEach(qemu_driver->domains,
1056 qemuDomainNetsRestart,
1057 NULL);
1059 /* Then inactive persistent configs */
1060 if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
1061 cfg->configDir,
1062 cfg->autostartDir, false,
1063 qemu_driver->caps,
1064 qemu_driver->xmlopt,
1065 NULL, NULL) < 0)
1066 goto error;
1068 virDomainObjListForEach(qemu_driver->domains,
1069 qemuDomainSnapshotLoad,
1070 cfg->snapshotDir);
1072 virDomainObjListForEach(qemu_driver->domains,
1073 qemuDomainCheckpointLoad,
1074 cfg->checkpointDir);
1076 virDomainObjListForEach(qemu_driver->domains,
1077 qemuDomainManagedSaveLoad,
1078 qemu_driver);
1080 /* must be initialized before trying to reconnect to all the
1081 * running domains since there might occur some QEMU monitor
1082 * events that will be dispatched to the worker pool */
1083 qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, qemuProcessEventHandler, qemu_driver);
1084 if (!qemu_driver->workerPool)
1085 goto error;
1087 qemuProcessReconnectAll(qemu_driver);
1089 qemuAutostartDomains(qemu_driver);
1091 return 0;
1093 error:
1094 VIR_FREE(driverConf);
1095 VIR_FREE(hugepagePath);
1096 VIR_FREE(memoryBackingPath);
1097 qemuStateCleanup();
1098 return -1;
1101 static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
1103 virQEMUDriverPtr driver = opaque;
1105 if (newVM) {
1106 virObjectEventPtr event =
1107 virDomainEventLifecycleNewFromObj(vm,
1108 VIR_DOMAIN_EVENT_DEFINED,
1109 VIR_DOMAIN_EVENT_DEFINED_ADDED);
1110 virObjectEventStateQueue(driver->domainEventState, event);
1115 * qemuStateReload:
1117 * Function to restart the QEMU daemon, it will recheck the configuration
1118 * files and update its state and the networking
1120 static int
1121 qemuStateReload(void)
1123 virQEMUDriverConfigPtr cfg = NULL;
1124 virCapsPtr caps = NULL;
1126 if (!qemu_driver)
1127 return 0;
1129 if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
1130 goto cleanup;
1132 cfg = virQEMUDriverGetConfig(qemu_driver);
1133 virDomainObjListLoadAllConfigs(qemu_driver->domains,
1134 cfg->configDir,
1135 cfg->autostartDir, false,
1136 caps, qemu_driver->xmlopt,
1137 qemuNotifyLoadDomain, qemu_driver);
1138 cleanup:
1139 virObjectUnref(cfg);
1140 virObjectUnref(caps);
1141 return 0;
1146 * qemuStateStop:
1148 * Save any VMs in preparation for shutdown
1151 static int
1152 qemuStateStop(void)
1154 int ret = -1;
1155 virConnectPtr conn;
1156 int numDomains = 0;
1157 size_t i;
1158 int state;
1159 virDomainPtr *domains = NULL;
1160 unsigned int *flags = NULL;
1161 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(qemu_driver);
1163 if (!(conn = virConnectOpen(cfg->uri)))
1164 goto cleanup;
1166 if ((numDomains = virConnectListAllDomains(conn,
1167 &domains,
1168 VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
1169 goto cleanup;
1171 if (VIR_ALLOC_N(flags, numDomains) < 0)
1172 goto cleanup;
1174 /* First we pause all VMs to make them stop dirtying
1175 pages, etc. We remember if any VMs were paused so
1176 we can restore that on resume. */
1177 for (i = 0; i < numDomains; i++) {
1178 flags[i] = VIR_DOMAIN_SAVE_RUNNING;
1179 if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
1180 if (state == VIR_DOMAIN_PAUSED)
1181 flags[i] = VIR_DOMAIN_SAVE_PAUSED;
1183 virDomainSuspend(domains[i]);
1186 ret = 0;
1187 /* Then we save the VMs to disk */
1188 for (i = 0; i < numDomains; i++)
1189 if (virDomainManagedSave(domains[i], flags[i]) < 0)
1190 ret = -1;
1192 cleanup:
1193 if (domains) {
1194 for (i = 0; i < numDomains; i++)
1195 virObjectUnref(domains[i]);
1196 VIR_FREE(domains);
1198 VIR_FREE(flags);
1199 virObjectUnref(conn);
1200 virObjectUnref(cfg);
1202 return ret;
1206 * qemuStateCleanup:
1208 * Shutdown the QEMU daemon, it will stop all active domains and networks
1210 static int
1211 qemuStateCleanup(void)
1213 if (!qemu_driver)
1214 return -1;
1216 virThreadPoolFree(qemu_driver->workerPool);
1217 virObjectUnref(qemu_driver->config);
1218 virObjectUnref(qemu_driver->hostdevMgr);
1219 virHashFree(qemu_driver->sharedDevices);
1220 virObjectUnref(qemu_driver->caps);
1221 virObjectUnref(qemu_driver->qemuCapsCache);
1223 virObjectUnref(qemu_driver->domains);
1224 virPortAllocatorRangeFree(qemu_driver->remotePorts);
1225 virPortAllocatorRangeFree(qemu_driver->webSocketPorts);
1226 virPortAllocatorRangeFree(qemu_driver->migrationPorts);
1227 virObjectUnref(qemu_driver->migrationErrors);
1229 virObjectUnref(qemu_driver->xmlopt);
1231 virSysinfoDefFree(qemu_driver->hostsysinfo);
1233 virObjectUnref(qemu_driver->closeCallbacks);
1235 VIR_FREE(qemu_driver->qemuImgBinary);
1237 virObjectUnref(qemu_driver->securityManager);
1239 ebtablesContextFree(qemu_driver->ebtables);
1241 /* Free domain callback list */
1242 virObjectUnref(qemu_driver->domainEventState);
1244 virLockManagerPluginUnref(qemu_driver->lockManager);
1246 virMutexDestroy(&qemu_driver->lock);
1247 VIR_FREE(qemu_driver);
1249 return 0;
1253 static int
1254 qemuConnectURIProbe(char **uri)
1256 virQEMUDriverConfigPtr cfg = NULL;
1257 int ret = -1;
1259 if (qemu_driver == NULL)
1260 return 0;
1262 cfg = virQEMUDriverGetConfig(qemu_driver);
1263 if (VIR_STRDUP(*uri, cfg->uri) < 0)
1264 goto cleanup;
1266 ret = 0;
1267 cleanup:
1268 virObjectUnref(cfg);
1269 return ret;
1272 static virDrvOpenStatus qemuConnectOpen(virConnectPtr conn,
1273 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1274 virConfPtr conf ATTRIBUTE_UNUSED,
1275 unsigned int flags)
1277 virQEMUDriverConfigPtr cfg = NULL;
1278 virDrvOpenStatus ret = VIR_DRV_OPEN_ERROR;
1279 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
1281 if (qemu_driver == NULL) {
1282 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1283 _("qemu state driver is not active"));
1284 goto cleanup;
1287 cfg = virQEMUDriverGetConfig(qemu_driver);
1289 if (virQEMUDriverIsPrivileged(qemu_driver)) {
1290 if (STRNEQ(conn->uri->path, "/system") &&
1291 STRNEQ(conn->uri->path, "/session")) {
1292 virReportError(VIR_ERR_INTERNAL_ERROR,
1293 _("unexpected QEMU URI path '%s', try qemu:///system"),
1294 conn->uri->path);
1295 goto cleanup;
1297 } else {
1298 if (STRNEQ(conn->uri->path, "/session")) {
1299 virReportError(VIR_ERR_INTERNAL_ERROR,
1300 _("unexpected QEMU URI path '%s', try qemu:///session"),
1301 conn->uri->path);
1302 goto cleanup;
1306 if (virConnectOpenEnsureACL(conn) < 0)
1307 goto cleanup;
1309 conn->privateData = qemu_driver;
1311 ret = VIR_DRV_OPEN_SUCCESS;
1312 cleanup:
1313 virObjectUnref(cfg);
1314 return ret;
1317 static int qemuConnectClose(virConnectPtr conn)
1319 virQEMUDriverPtr driver = conn->privateData;
1321 /* Get rid of callbacks registered for this conn */
1322 virCloseCallbacksRun(driver->closeCallbacks, conn, driver->domains, driver);
1324 conn->privateData = NULL;
1326 return 0;
1329 /* Which features are supported by this driver? */
1330 static int
1331 qemuConnectSupportsFeature(virConnectPtr conn, int feature)
1333 if (virConnectSupportsFeatureEnsureACL(conn) < 0)
1334 return -1;
1336 switch ((virDrvFeature) feature) {
1337 case VIR_DRV_FEATURE_MIGRATION_V2:
1338 case VIR_DRV_FEATURE_MIGRATION_V3:
1339 case VIR_DRV_FEATURE_MIGRATION_P2P:
1340 case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
1341 case VIR_DRV_FEATURE_FD_PASSING:
1342 case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
1343 case VIR_DRV_FEATURE_XML_MIGRATABLE:
1344 case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
1345 case VIR_DRV_FEATURE_MIGRATION_PARAMS:
1346 return 1;
1347 case VIR_DRV_FEATURE_MIGRATION_DIRECT:
1348 case VIR_DRV_FEATURE_MIGRATION_V1:
1349 case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
1350 case VIR_DRV_FEATURE_REMOTE:
1351 case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
1352 case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
1353 default:
1354 return 0;
1358 static const char *qemuConnectGetType(virConnectPtr conn) {
1359 if (virConnectGetTypeEnsureACL(conn) < 0)
1360 return NULL;
1362 return "QEMU";
1366 static int qemuConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1368 /* Trivially secure, since always inside the daemon */
1369 return 1;
1372 static int qemuConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1374 /* Not encrypted, but remote driver takes care of that */
1375 return 0;
1378 static int qemuConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1380 return 1;
1384 static char *
1385 qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
1387 virQEMUDriverPtr driver = conn->privateData;
1388 virBuffer buf = VIR_BUFFER_INITIALIZER;
1390 virCheckFlags(0, NULL);
1392 if (virConnectGetSysinfoEnsureACL(conn) < 0)
1393 return NULL;
1395 if (!driver->hostsysinfo) {
1396 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1397 _("Host SMBIOS information is not available"));
1398 return NULL;
1401 if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
1402 return NULL;
1403 if (virBufferCheckError(&buf) < 0)
1404 return NULL;
1405 return virBufferContentAndReset(&buf);
1408 static int
1409 qemuConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type)
1411 if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
1412 return -1;
1414 if (!type)
1415 return 16;
1417 if (STRCASEEQ(type, "qemu"))
1418 return 16;
1420 if (STRCASEEQ(type, "kvm"))
1421 return virHostCPUGetKVMMaxVCPUs();
1423 virReportError(VIR_ERR_INVALID_ARG,
1424 _("unknown type '%s'"), type);
1425 return -1;
1429 static char *qemuConnectGetCapabilities(virConnectPtr conn) {
1430 virQEMUDriverPtr driver = conn->privateData;
1431 virCapsPtr caps = NULL;
1432 char *xml = NULL;
1434 if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
1435 return NULL;
1437 if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
1438 goto cleanup;
1440 xml = virCapabilitiesFormatXML(caps);
1441 virObjectUnref(caps);
1443 cleanup:
1445 return xml;
1449 static int
1450 qemuGetSchedInfo(unsigned long long *cpuWait,
1451 pid_t pid, pid_t tid)
1453 char *proc = NULL;
1454 char *data = NULL;
1455 char **lines = NULL;
1456 size_t i;
1457 int ret = -1;
1458 double val;
1460 *cpuWait = 0;
1462 /* In general, we cannot assume pid_t fits in int; but /proc parsing
1463 * is specific to Linux where int works fine. */
1464 if (tid)
1465 ret = virAsprintf(&proc, "/proc/%d/task/%d/sched", (int)pid, (int)tid);
1466 else
1467 ret = virAsprintf(&proc, "/proc/%d/sched", (int)pid);
1468 if (ret < 0)
1469 goto cleanup;
1470 ret = -1;
1472 /* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
1473 if (access(proc, R_OK) < 0) {
1474 ret = 0;
1475 goto cleanup;
1478 if (virFileReadAll(proc, (1<<16), &data) < 0)
1479 goto cleanup;
1481 lines = virStringSplit(data, "\n", 0);
1482 if (!lines)
1483 goto cleanup;
1485 for (i = 0; lines[i] != NULL; i++) {
1486 const char *line = lines[i];
1488 /* Needs CONFIG_SCHEDSTATS. The second check
1489 * is the old name the kernel used in past */
1490 if (STRPREFIX(line, "se.statistics.wait_sum") ||
1491 STRPREFIX(line, "se.wait_sum")) {
1492 line = strchr(line, ':');
1493 if (!line) {
1494 virReportError(VIR_ERR_INTERNAL_ERROR,
1495 _("Missing separator in sched info '%s'"),
1496 lines[i]);
1497 goto cleanup;
1499 line++;
1500 while (*line == ' ')
1501 line++;
1503 if (virStrToDouble(line, NULL, &val) < 0) {
1504 virReportError(VIR_ERR_INTERNAL_ERROR,
1505 _("Unable to parse sched info value '%s'"),
1506 line);
1507 goto cleanup;
1510 *cpuWait = (unsigned long long)(val * 1000000);
1511 break;
1515 ret = 0;
1517 cleanup:
1518 VIR_FREE(data);
1519 VIR_FREE(proc);
1520 virStringListFree(lines);
1521 return ret;
1525 static int
1526 qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
1527 pid_t pid, int tid)
1529 char *proc;
1530 FILE *pidinfo;
1531 unsigned long long usertime = 0, systime = 0;
1532 long rss = 0;
1533 int cpu = 0;
1534 int ret;
1536 /* In general, we cannot assume pid_t fits in int; but /proc parsing
1537 * is specific to Linux where int works fine. */
1538 if (tid)
1539 ret = virAsprintf(&proc, "/proc/%d/task/%d/stat", (int)pid, tid);
1540 else
1541 ret = virAsprintf(&proc, "/proc/%d/stat", (int)pid);
1542 if (ret < 0)
1543 return -1;
1545 pidinfo = fopen(proc, "r");
1546 VIR_FREE(proc);
1548 /* See 'man proc' for information about what all these fields are. We're
1549 * only interested in a very few of them */
1550 if (!pidinfo ||
1551 fscanf(pidinfo,
1552 /* pid -> stime */
1553 "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu"
1554 /* cutime -> endcode */
1555 "%*d %*d %*d %*d %*d %*d %*u %*u %ld %*u %*u %*u"
1556 /* startstack -> processor */
1557 "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
1558 &usertime, &systime, &rss, &cpu) != 4) {
1559 VIR_WARN("cannot parse process status data");
1562 /* We got jiffies
1563 * We want nanoseconds
1564 * _SC_CLK_TCK is jiffies per second
1565 * So calculate thus....
1567 if (cpuTime)
1568 *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
1569 / (unsigned long long)sysconf(_SC_CLK_TCK);
1570 if (lastCpu)
1571 *lastCpu = cpu;
1573 if (vm_rss)
1574 *vm_rss = rss * virGetSystemPageSizeKB();
1577 VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
1578 (int)pid, tid, usertime, systime, cpu, rss);
1580 VIR_FORCE_FCLOSE(pidinfo);
1582 return 0;
1586 static int
1587 qemuDomainHelperGetVcpus(virDomainObjPtr vm,
1588 virVcpuInfoPtr info,
1589 unsigned long long *cpuwait,
1590 int maxinfo,
1591 unsigned char *cpumaps,
1592 int maplen)
1594 size_t ncpuinfo = 0;
1595 size_t i;
1597 if (maxinfo == 0)
1598 return 0;
1600 if (!qemuDomainHasVcpuPids(vm)) {
1601 virReportError(VIR_ERR_OPERATION_INVALID,
1602 "%s", _("cpu affinity is not supported"));
1603 return -1;
1606 if (info)
1607 memset(info, 0, sizeof(*info) * maxinfo);
1609 if (cpumaps)
1610 memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
1612 for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; i++) {
1613 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
1614 pid_t vcpupid = qemuDomainGetVcpuPid(vm, i);
1615 virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
1617 if (!vcpu->online)
1618 continue;
1620 if (info) {
1621 vcpuinfo->number = i;
1622 vcpuinfo->state = VIR_VCPU_RUNNING;
1624 if (qemuGetProcessInfo(&vcpuinfo->cpuTime,
1625 &vcpuinfo->cpu, NULL,
1626 vm->pid, vcpupid) < 0) {
1627 virReportSystemError(errno, "%s",
1628 _("cannot get vCPU placement & pCPU time"));
1629 return -1;
1633 if (cpumaps) {
1634 unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
1635 virBitmapPtr map = NULL;
1637 if (!(map = virProcessGetAffinity(vcpupid)))
1638 return -1;
1640 virBitmapToDataBuf(map, cpumap, maplen);
1641 virBitmapFree(map);
1644 if (cpuwait) {
1645 if (qemuGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) < 0)
1646 return -1;
1649 ncpuinfo++;
1652 return ncpuinfo;
1656 static virDomainPtr qemuDomainLookupByID(virConnectPtr conn,
1657 int id)
1659 virQEMUDriverPtr driver = conn->privateData;
1660 virDomainObjPtr vm;
1661 virDomainPtr dom = NULL;
1663 vm = virDomainObjListFindByID(driver->domains, id);
1665 if (!vm) {
1666 virReportError(VIR_ERR_NO_DOMAIN,
1667 _("no domain with matching id %d"), id);
1668 goto cleanup;
1671 if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
1672 goto cleanup;
1674 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1676 cleanup:
1677 virDomainObjEndAPI(&vm);
1678 return dom;
1681 static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn,
1682 const unsigned char *uuid)
1684 virQEMUDriverPtr driver = conn->privateData;
1685 virDomainObjPtr vm;
1686 virDomainPtr dom = NULL;
1688 vm = virDomainObjListFindByUUID(driver->domains, uuid);
1690 if (!vm) {
1691 char uuidstr[VIR_UUID_STRING_BUFLEN];
1692 virUUIDFormat(uuid, uuidstr);
1693 virReportError(VIR_ERR_NO_DOMAIN,
1694 _("no domain with matching uuid '%s'"), uuidstr);
1695 goto cleanup;
1698 if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
1699 goto cleanup;
1701 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1703 cleanup:
1704 virDomainObjEndAPI(&vm);
1705 return dom;
1708 static virDomainPtr qemuDomainLookupByName(virConnectPtr conn,
1709 const char *name)
1711 virQEMUDriverPtr driver = conn->privateData;
1712 virDomainObjPtr vm;
1713 virDomainPtr dom = NULL;
1715 vm = virDomainObjListFindByName(driver->domains, name);
1717 if (!vm) {
1718 virReportError(VIR_ERR_NO_DOMAIN,
1719 _("no domain with matching name '%s'"), name);
1720 goto cleanup;
1723 if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
1724 goto cleanup;
1726 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1728 cleanup:
1729 virDomainObjEndAPI(&vm);
1730 return dom;
1734 static int qemuDomainIsActive(virDomainPtr dom)
1736 virDomainObjPtr obj;
1737 int ret = -1;
1739 if (!(obj = qemuDomObjFromDomain(dom)))
1740 goto cleanup;
1742 if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
1743 goto cleanup;
1745 ret = virDomainObjIsActive(obj);
1747 cleanup:
1748 virDomainObjEndAPI(&obj);
1749 return ret;
1752 static int qemuDomainIsPersistent(virDomainPtr dom)
1754 virDomainObjPtr obj;
1755 int ret = -1;
1757 if (!(obj = qemuDomObjFromDomain(dom)))
1758 goto cleanup;
1760 if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
1761 goto cleanup;
1763 ret = obj->persistent;
1765 cleanup:
1766 virDomainObjEndAPI(&obj);
1767 return ret;
1770 static int qemuDomainIsUpdated(virDomainPtr dom)
1772 virDomainObjPtr obj;
1773 int ret = -1;
1775 if (!(obj = qemuDomObjFromDomain(dom)))
1776 goto cleanup;
1778 if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0)
1779 goto cleanup;
1781 ret = obj->updated;
1783 cleanup:
1784 virDomainObjEndAPI(&obj);
1785 return ret;
1788 static int qemuConnectGetVersion(virConnectPtr conn, unsigned long *version)
1790 virQEMUDriverPtr driver = conn->privateData;
1791 int ret = -1;
1792 unsigned int qemuVersion = 0;
1793 virCapsPtr caps = NULL;
1795 if (virConnectGetVersionEnsureACL(conn) < 0)
1796 return -1;
1798 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
1799 goto cleanup;
1801 if (virQEMUCapsGetDefaultVersion(caps,
1802 driver->qemuCapsCache,
1803 &qemuVersion) < 0)
1804 goto cleanup;
1806 *version = qemuVersion;
1807 ret = 0;
1809 cleanup:
1810 virObjectUnref(caps);
1811 return ret;
1815 static char *qemuConnectGetHostname(virConnectPtr conn)
1817 if (virConnectGetHostnameEnsureACL(conn) < 0)
1818 return NULL;
1820 return virGetHostname();
1824 static int qemuConnectListDomains(virConnectPtr conn, int *ids, int nids)
1826 virQEMUDriverPtr driver = conn->privateData;
1827 int n;
1829 if (virConnectListDomainsEnsureACL(conn) < 0)
1830 return -1;
1832 n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
1833 virConnectListDomainsCheckACL, conn);
1835 return n;
1838 static int qemuConnectNumOfDomains(virConnectPtr conn)
1840 virQEMUDriverPtr driver = conn->privateData;
1841 int n;
1843 if (virConnectNumOfDomainsEnsureACL(conn) < 0)
1844 return -1;
1846 n = virDomainObjListNumOfDomains(driver->domains, true,
1847 virConnectNumOfDomainsCheckACL, conn);
1849 return n;
1853 static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
1854 const char *xml,
1855 unsigned int flags)
1857 virQEMUDriverPtr driver = conn->privateData;
1858 virDomainDefPtr def = NULL;
1859 virDomainObjPtr vm = NULL;
1860 virDomainPtr dom = NULL;
1861 virObjectEventPtr event = NULL;
1862 virObjectEventPtr event2 = NULL;
1863 unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
1864 virCapsPtr caps = NULL;
1865 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
1866 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
1868 virCheckFlags(VIR_DOMAIN_START_PAUSED |
1869 VIR_DOMAIN_START_AUTODESTROY |
1870 VIR_DOMAIN_START_VALIDATE, NULL);
1872 if (flags & VIR_DOMAIN_START_VALIDATE)
1873 parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1874 if (flags & VIR_DOMAIN_START_PAUSED)
1875 start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
1876 if (flags & VIR_DOMAIN_START_AUTODESTROY)
1877 start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
1879 virNWFilterReadLockFilterUpdates();
1881 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
1882 goto cleanup;
1884 if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
1885 NULL, parse_flags)))
1886 goto cleanup;
1888 if (virDomainCreateXMLEnsureACL(conn, def) < 0)
1889 goto cleanup;
1891 if (!(vm = virDomainObjListAdd(driver->domains, def,
1892 driver->xmlopt,
1893 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1894 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
1895 NULL)))
1896 goto cleanup;
1897 def = NULL;
1899 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
1900 flags) < 0) {
1901 qemuDomainRemoveInactiveJob(driver, vm);
1902 goto cleanup;
1905 if (qemuProcessStart(conn, driver, vm, NULL, QEMU_ASYNC_JOB_START,
1906 NULL, -1, NULL, NULL,
1907 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
1908 start_flags) < 0) {
1909 virDomainAuditStart(vm, "booted", false);
1910 qemuDomainRemoveInactive(driver, vm);
1911 qemuProcessEndJob(driver, vm);
1912 goto cleanup;
1915 event = virDomainEventLifecycleNewFromObj(vm,
1916 VIR_DOMAIN_EVENT_STARTED,
1917 VIR_DOMAIN_EVENT_STARTED_BOOTED);
1918 if (event && (flags & VIR_DOMAIN_START_PAUSED)) {
1919 /* There are two classes of event-watching clients - those
1920 * that only care about on/off (and must see a started event
1921 * no matter what, but don't care about suspend events), and
1922 * those that also care about running/paused. To satisfy both
1923 * client types, we have to send two events. */
1924 event2 = virDomainEventLifecycleNewFromObj(vm,
1925 VIR_DOMAIN_EVENT_SUSPENDED,
1926 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1928 virDomainAuditStart(vm, "booted", true);
1930 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1932 qemuProcessEndJob(driver, vm);
1934 cleanup:
1935 virDomainDefFree(def);
1936 virDomainObjEndAPI(&vm);
1937 virObjectEventStateQueue(driver->domainEventState, event);
1938 virObjectEventStateQueue(driver->domainEventState, event2);
1939 virObjectUnref(caps);
1940 virNWFilterUnlockFilterUpdates();
1941 return dom;
1945 static int qemuDomainSuspend(virDomainPtr dom)
1947 virQEMUDriverPtr driver = dom->conn->privateData;
1948 virDomainObjPtr vm;
1949 int ret = -1;
1950 virObjectEventPtr event = NULL;
1951 qemuDomainObjPrivatePtr priv;
1952 virDomainPausedReason reason;
1953 int eventDetail;
1954 int state;
1955 virQEMUDriverConfigPtr cfg = NULL;
1957 if (!(vm = qemuDomObjFromDomain(dom)))
1958 return -1;
1960 if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
1961 goto cleanup;
1963 cfg = virQEMUDriverGetConfig(driver);
1964 priv = vm->privateData;
1966 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND) < 0)
1967 goto cleanup;
1969 if (virDomainObjCheckActive(vm) < 0)
1970 goto endjob;
1972 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
1973 reason = VIR_DOMAIN_PAUSED_MIGRATION;
1974 eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED;
1975 } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_SNAPSHOT) {
1976 reason = VIR_DOMAIN_PAUSED_SNAPSHOT;
1977 eventDetail = -1; /* don't create lifecycle events when doing snapshot */
1978 } else {
1979 reason = VIR_DOMAIN_PAUSED_USER;
1980 eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
1983 state = virDomainObjGetState(vm, NULL);
1984 if (state == VIR_DOMAIN_PMSUSPENDED) {
1985 virReportError(VIR_ERR_OPERATION_INVALID,
1986 "%s", _("domain is pmsuspended"));
1987 goto endjob;
1988 } else if (state != VIR_DOMAIN_PAUSED) {
1989 if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0)
1990 goto endjob;
1992 if (eventDetail >= 0) {
1993 event = virDomainEventLifecycleNewFromObj(vm,
1994 VIR_DOMAIN_EVENT_SUSPENDED,
1995 eventDetail);
1998 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
1999 goto endjob;
2000 ret = 0;
2002 endjob:
2003 qemuDomainObjEndJob(driver, vm);
2005 cleanup:
2006 virDomainObjEndAPI(&vm);
2008 virObjectEventStateQueue(driver->domainEventState, event);
2009 virObjectUnref(cfg);
2010 return ret;
2014 static int qemuDomainResume(virDomainPtr dom)
2016 virQEMUDriverPtr driver = dom->conn->privateData;
2017 virDomainObjPtr vm;
2018 int ret = -1;
2019 int state;
2020 int reason;
2021 virQEMUDriverConfigPtr cfg = NULL;
2023 if (!(vm = qemuDomObjFromDomain(dom)))
2024 return -1;
2026 cfg = virQEMUDriverGetConfig(driver);
2028 if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
2029 goto cleanup;
2031 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2032 goto cleanup;
2034 if (virDomainObjCheckActive(vm) < 0)
2035 goto endjob;
2037 state = virDomainObjGetState(vm, &reason);
2038 if (state == VIR_DOMAIN_PMSUSPENDED) {
2039 virReportError(VIR_ERR_OPERATION_INVALID,
2040 "%s", _("domain is pmsuspended"));
2041 goto endjob;
2042 } else if (state == VIR_DOMAIN_RUNNING) {
2043 virReportError(VIR_ERR_OPERATION_INVALID,
2044 "%s", _("domain is already running"));
2045 goto endjob;
2046 } else if ((state == VIR_DOMAIN_CRASHED &&
2047 reason == VIR_DOMAIN_CRASHED_PANICKED) ||
2048 state == VIR_DOMAIN_PAUSED) {
2049 if (qemuProcessStartCPUs(driver, vm,
2050 VIR_DOMAIN_RUNNING_UNPAUSED,
2051 QEMU_ASYNC_JOB_NONE) < 0) {
2052 if (virGetLastErrorCode() == VIR_ERR_OK)
2053 virReportError(VIR_ERR_OPERATION_FAILED,
2054 "%s", _("resume operation failed"));
2055 goto endjob;
2058 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
2059 goto endjob;
2060 ret = 0;
2062 endjob:
2063 qemuDomainObjEndJob(driver, vm);
2065 cleanup:
2066 virDomainObjEndAPI(&vm);
2067 virObjectUnref(cfg);
2068 return ret;
2071 static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
2073 virQEMUDriverPtr driver = dom->conn->privateData;
2074 virDomainObjPtr vm;
2075 int ret = -1;
2076 qemuDomainObjPrivatePtr priv;
2077 bool useAgent = false, agentRequested, acpiRequested;
2078 bool isReboot = false;
2079 bool agentForced;
2080 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
2081 int agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
2083 virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
2084 VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
2086 if (!(vm = qemuDomObjFromDomain(dom)))
2087 goto cleanup;
2089 if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
2090 vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME) {
2091 isReboot = true;
2092 agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
2093 VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
2096 priv = vm->privateData;
2097 agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
2098 acpiRequested = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
2100 /* Prefer agent unless we were requested to not to. */
2101 if (agentRequested || (!flags && priv->agent))
2102 useAgent = true;
2104 if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2105 goto cleanup;
2107 if (useAgent)
2108 agentJob = QEMU_AGENT_JOB_MODIFY;
2110 if (qemuDomainObjBeginJobWithAgent(driver, vm,
2111 QEMU_JOB_MODIFY,
2112 agentJob) < 0)
2113 goto cleanup;
2115 if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
2116 virReportError(VIR_ERR_OPERATION_INVALID,
2117 "%s", _("domain is not running"));
2118 goto endjob;
2121 agentForced = agentRequested && !acpiRequested;
2122 if (!qemuDomainAgentAvailable(vm, agentForced)) {
2123 if (agentForced)
2124 goto endjob;
2125 useAgent = false;
2129 if (useAgent) {
2130 qemuAgentPtr agent;
2131 qemuDomainSetFakeReboot(driver, vm, false);
2132 agent = qemuDomainObjEnterAgent(vm);
2133 ret = qemuAgentShutdown(agent, agentFlag);
2134 qemuDomainObjExitAgent(vm, agent);
2137 /* If we are not enforced to use just an agent, try ACPI
2138 * shutdown as well in case agent did not succeed.
2140 if (!useAgent ||
2141 (ret < 0 && (acpiRequested || !flags))) {
2143 /* Even if agent failed, we have to check if guest went away
2144 * by itself while our locks were down. */
2145 if (useAgent && !virDomainObjIsActive(vm)) {
2146 ret = 0;
2147 goto endjob;
2150 qemuDomainSetFakeReboot(driver, vm, isReboot);
2151 qemuDomainObjEnterMonitor(driver, vm);
2152 ret = qemuMonitorSystemPowerdown(priv->mon);
2153 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2154 ret = -1;
2157 endjob:
2158 if (agentJob)
2159 qemuDomainObjEndJobWithAgent(driver, vm);
2160 else
2161 qemuDomainObjEndJob(driver, vm);
2163 cleanup:
2164 virDomainObjEndAPI(&vm);
2165 return ret;
2168 static int qemuDomainShutdown(virDomainPtr dom)
2170 return qemuDomainShutdownFlags(dom, 0);
2174 static int
2175 qemuDomainReboot(virDomainPtr dom, unsigned int flags)
2177 virQEMUDriverPtr driver = dom->conn->privateData;
2178 virDomainObjPtr vm;
2179 int ret = -1;
2180 qemuDomainObjPrivatePtr priv;
2181 bool useAgent = false, agentRequested, acpiRequested;
2182 bool isReboot = true;
2183 bool agentForced;
2184 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
2185 int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
2187 virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
2188 VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
2190 if (!(vm = qemuDomObjFromDomain(dom)))
2191 goto cleanup;
2193 if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
2194 vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE) {
2195 agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
2196 isReboot = false;
2197 VIR_INFO("Domain on_reboot setting overridden, shutting down");
2200 priv = vm->privateData;
2201 agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
2202 acpiRequested = flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
2204 /* Prefer agent unless we were requested to not to. */
2205 if (agentRequested || (!flags && priv->agent))
2206 useAgent = true;
2208 if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
2209 goto cleanup;
2211 if (useAgent)
2212 agentJob = QEMU_AGENT_JOB_MODIFY;
2214 if (qemuDomainObjBeginJobWithAgent(driver, vm,
2215 QEMU_JOB_MODIFY,
2216 agentJob) < 0)
2217 goto cleanup;
2219 agentForced = agentRequested && !acpiRequested;
2220 if (!qemuDomainAgentAvailable(vm, agentForced)) {
2221 if (agentForced)
2222 goto endjob;
2223 useAgent = false;
2226 if (virDomainObjCheckActive(vm) < 0)
2227 goto endjob;
2229 if (useAgent) {
2230 qemuAgentPtr agent;
2232 qemuDomainSetFakeReboot(driver, vm, false);
2233 agent = qemuDomainObjEnterAgent(vm);
2234 ret = qemuAgentShutdown(agent, agentFlag);
2235 qemuDomainObjExitAgent(vm, agent);
2238 /* If we are not enforced to use just an agent, try ACPI
2239 * shutdown as well in case agent did not succeed.
2241 if ((!useAgent) ||
2242 (ret < 0 && (acpiRequested || !flags))) {
2243 #if !WITH_YAJL
2244 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2245 _("ACPI reboot is not supported without the JSON monitor"));
2246 goto endjob;
2247 #endif
2248 qemuDomainSetFakeReboot(driver, vm, isReboot);
2249 qemuDomainObjEnterMonitor(driver, vm);
2250 ret = qemuMonitorSystemPowerdown(priv->mon);
2251 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2252 ret = -1;
2255 endjob:
2256 if (agentJob)
2257 qemuDomainObjEndJobWithAgent(driver, vm);
2258 else
2259 qemuDomainObjEndJob(driver, vm);
2261 cleanup:
2262 virDomainObjEndAPI(&vm);
2263 return ret;
2267 static int
2268 qemuDomainReset(virDomainPtr dom, unsigned int flags)
2270 virQEMUDriverPtr driver = dom->conn->privateData;
2271 virDomainObjPtr vm;
2272 int ret = -1;
2273 qemuDomainObjPrivatePtr priv;
2274 virDomainState state;
2276 virCheckFlags(0, -1);
2278 if (!(vm = qemuDomObjFromDomain(dom)))
2279 goto cleanup;
2281 if (virDomainResetEnsureACL(dom->conn, vm->def) < 0)
2282 goto cleanup;
2284 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2285 goto cleanup;
2287 if (virDomainObjCheckActive(vm) < 0)
2288 goto endjob;
2290 priv = vm->privateData;
2291 qemuDomainObjEnterMonitor(driver, vm);
2292 ret = qemuMonitorSystemReset(priv->mon);
2293 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2294 ret = -1;
2296 priv->fakeReboot = false;
2298 state = virDomainObjGetState(vm, NULL);
2299 if (state == VIR_DOMAIN_CRASHED)
2300 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED);
2302 endjob:
2303 qemuDomainObjEndJob(driver, vm);
2305 cleanup:
2306 virDomainObjEndAPI(&vm);
2307 return ret;
2311 /* Count how many snapshots in a set are external snapshots. */
2312 static int
2313 qemuDomainSnapshotCountExternal(void *payload,
2314 const void *name ATTRIBUTE_UNUSED,
2315 void *data)
2317 virDomainSnapshotObjPtr snap = payload;
2318 int *count = data;
2320 if (virDomainSnapshotIsExternal(snap))
2321 (*count)++;
2322 return 0;
2325 static int
2326 qemuDomainDestroyFlags(virDomainPtr dom,
2327 unsigned int flags)
2329 virQEMUDriverPtr driver = dom->conn->privateData;
2330 virDomainObjPtr vm;
2331 int ret = -1;
2332 virObjectEventPtr event = NULL;
2333 qemuDomainObjPrivatePtr priv;
2334 unsigned int stopFlags = 0;
2335 int state;
2336 int reason;
2337 bool starting;
2339 virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
2341 if (!(vm = qemuDomObjFromDomain(dom)))
2342 return -1;
2344 priv = vm->privateData;
2346 if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
2347 goto cleanup;
2349 if (virDomainObjCheckActive(vm) < 0)
2350 goto cleanup;
2352 state = virDomainObjGetState(vm, &reason);
2353 starting = (state == VIR_DOMAIN_PAUSED &&
2354 reason == VIR_DOMAIN_PAUSED_STARTING_UP &&
2355 !priv->beingDestroyed);
2357 if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY,
2358 !(flags & VIR_DOMAIN_DESTROY_GRACEFUL)) < 0)
2359 goto cleanup;
2361 if (!virDomainObjIsActive(vm)) {
2362 if (starting) {
2363 VIR_DEBUG("Domain %s is not running anymore", vm->def->name);
2364 ret = 0;
2365 } else {
2366 virReportError(VIR_ERR_OPERATION_INVALID,
2367 "%s", _("domain is not running"));
2369 goto endjob;
2372 qemuDomainSetFakeReboot(driver, vm, false);
2374 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN)
2375 stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
2377 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED,
2378 QEMU_ASYNC_JOB_NONE, stopFlags);
2379 event = virDomainEventLifecycleNewFromObj(vm,
2380 VIR_DOMAIN_EVENT_STOPPED,
2381 VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2382 virDomainAuditStop(vm, "destroyed");
2384 ret = 0;
2385 endjob:
2386 if (ret == 0)
2387 qemuDomainRemoveInactive(driver, vm);
2388 qemuDomainObjEndJob(driver, vm);
2390 cleanup:
2391 virDomainObjEndAPI(&vm);
2392 virObjectEventStateQueue(driver->domainEventState, event);
2393 return ret;
2396 static int
2397 qemuDomainDestroy(virDomainPtr dom)
2399 return qemuDomainDestroyFlags(dom, 0);
2402 static char *qemuDomainGetOSType(virDomainPtr dom) {
2403 virDomainObjPtr vm;
2404 char *type = NULL;
2406 if (!(vm = qemuDomObjFromDomain(dom)))
2407 goto cleanup;
2409 if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
2410 goto cleanup;
2412 ignore_value(VIR_STRDUP(type, virDomainOSTypeToString(vm->def->os.type)));
2414 cleanup:
2415 virDomainObjEndAPI(&vm);
2416 return type;
2419 /* Returns max memory in kb, 0 if error */
2420 static unsigned long long
2421 qemuDomainGetMaxMemory(virDomainPtr dom)
2423 virDomainObjPtr vm;
2424 unsigned long long ret = 0;
2426 if (!(vm = qemuDomObjFromDomain(dom)))
2427 goto cleanup;
2429 if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
2430 goto cleanup;
2432 ret = virDomainDefGetMemoryTotal(vm->def);
2434 cleanup:
2435 virDomainObjEndAPI(&vm);
2436 return ret;
2439 static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
2440 unsigned int flags)
2442 virQEMUDriverPtr driver = dom->conn->privateData;
2443 qemuDomainObjPrivatePtr priv;
2444 virDomainObjPtr vm;
2445 virDomainDefPtr def;
2446 virDomainDefPtr persistentDef;
2447 int ret = -1, r;
2448 virQEMUDriverConfigPtr cfg = NULL;
2450 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2451 VIR_DOMAIN_AFFECT_CONFIG |
2452 VIR_DOMAIN_MEM_MAXIMUM, -1);
2454 if (!(vm = qemuDomObjFromDomain(dom)))
2455 goto cleanup;
2457 cfg = virQEMUDriverGetConfig(driver);
2459 if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2460 goto cleanup;
2462 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2463 goto cleanup;
2465 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2466 goto endjob;
2469 if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
2470 /* resize the maximum memory */
2472 if (def) {
2473 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2474 _("cannot resize the maximum memory on an "
2475 "active domain"));
2476 goto endjob;
2479 if (persistentDef) {
2480 /* resizing memory with NUMA nodes specified doesn't work as there
2481 * is no way to change the individual node sizes with this API */
2482 if (virDomainNumaGetNodeCount(persistentDef->numa) > 0) {
2483 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2484 _("initial memory size of a domain with NUMA "
2485 "nodes cannot be modified with this API"));
2486 goto endjob;
2489 if (persistentDef->mem.max_memory &&
2490 persistentDef->mem.max_memory < newmem) {
2491 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2492 _("cannot set initial memory size greater than "
2493 "the maximum memory size"));
2494 goto endjob;
2497 virDomainDefSetMemoryTotal(persistentDef, newmem);
2499 if (persistentDef->mem.cur_balloon > newmem)
2500 persistentDef->mem.cur_balloon = newmem;
2501 ret = virDomainSaveConfig(cfg->configDir, driver->caps,
2502 persistentDef);
2503 goto endjob;
2506 } else {
2507 /* resize the current memory */
2508 unsigned long oldmax = 0;
2510 if (def)
2511 oldmax = virDomainDefGetMemoryTotal(def);
2512 if (persistentDef) {
2513 if (!oldmax || oldmax > virDomainDefGetMemoryTotal(persistentDef))
2514 oldmax = virDomainDefGetMemoryTotal(persistentDef);
2517 if (newmem > oldmax) {
2518 virReportError(VIR_ERR_INVALID_ARG, "%s",
2519 _("cannot set memory higher than max memory"));
2520 goto endjob;
2523 if (def) {
2524 priv = vm->privateData;
2525 qemuDomainObjEnterMonitor(driver, vm);
2526 r = qemuMonitorSetBalloon(priv->mon, newmem);
2527 if (qemuDomainObjExitMonitor(driver, vm) < 0 || r < 0)
2528 goto endjob;
2530 /* Lack of balloon support is a fatal error */
2531 if (r == 0) {
2532 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2533 _("Unable to change memory of active domain without "
2534 "the balloon device and guest OS balloon driver"));
2535 goto endjob;
2539 if (persistentDef) {
2540 persistentDef->mem.cur_balloon = newmem;
2541 ret = virDomainSaveConfig(cfg->configDir, driver->caps,
2542 persistentDef);
2543 goto endjob;
2547 ret = 0;
2548 endjob:
2549 qemuDomainObjEndJob(driver, vm);
2551 cleanup:
2552 virDomainObjEndAPI(&vm);
2553 virObjectUnref(cfg);
2554 return ret;
2557 static int qemuDomainSetMemory(virDomainPtr dom, unsigned long newmem)
2559 return qemuDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
2562 static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
2564 return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
2567 static int qemuDomainSetMemoryStatsPeriod(virDomainPtr dom, int period,
2568 unsigned int flags)
2570 virQEMUDriverPtr driver = dom->conn->privateData;
2571 qemuDomainObjPrivatePtr priv;
2572 virDomainObjPtr vm;
2573 virDomainDefPtr def;
2574 virDomainDefPtr persistentDef;
2575 int ret = -1, r;
2576 virQEMUDriverConfigPtr cfg = NULL;
2578 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2579 VIR_DOMAIN_AFFECT_CONFIG, -1);
2581 if (!(vm = qemuDomObjFromDomain(dom)))
2582 goto cleanup;
2584 cfg = virQEMUDriverGetConfig(driver);
2586 if (virDomainSetMemoryStatsPeriodEnsureACL(dom->conn, vm->def, flags) < 0)
2587 goto cleanup;
2589 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2590 goto cleanup;
2592 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2593 goto endjob;
2595 /* Set the balloon driver collection interval */
2596 priv = vm->privateData;
2598 if (def) {
2599 if (!virDomainDefHasMemballoon(def)) {
2600 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2601 _("No memory balloon device configured, "
2602 "can not set the collection period"));
2603 goto endjob;
2606 qemuDomainObjEnterMonitor(driver, vm);
2607 r = qemuMonitorSetMemoryStatsPeriod(priv->mon, def->memballoon, period);
2608 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2609 goto endjob;
2610 if (r < 0) {
2611 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2612 _("unable to set balloon driver collection period"));
2613 goto endjob;
2616 def->memballoon->period = period;
2617 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
2618 goto endjob;
2621 if (persistentDef) {
2622 if (!virDomainDefHasMemballoon(persistentDef)) {
2623 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2624 _("No memory balloon device configured, "
2625 "can not set the collection period"));
2626 goto endjob;
2628 persistentDef->memballoon->period = period;
2629 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
2630 goto endjob;
2633 ret = 0;
2634 endjob:
2635 qemuDomainObjEndJob(driver, vm);
2637 cleanup:
2638 virDomainObjEndAPI(&vm);
2639 virObjectUnref(cfg);
2640 return ret;
2643 static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
2645 virQEMUDriverPtr driver = domain->conn->privateData;
2646 virDomainObjPtr vm = NULL;
2647 int ret = -1;
2648 qemuDomainObjPrivatePtr priv;
2650 virCheckFlags(0, -1);
2652 if (!(vm = qemuDomObjFromDomain(domain)))
2653 return -1;
2655 if (virDomainInjectNMIEnsureACL(domain->conn, vm->def) < 0)
2656 goto cleanup;
2658 priv = vm->privateData;
2660 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2661 goto cleanup;
2663 if (virDomainObjCheckActive(vm) < 0)
2664 goto endjob;
2666 qemuDomainObjEnterMonitor(driver, vm);
2667 ret = qemuMonitorInjectNMI(priv->mon);
2668 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2669 ret = -1;
2671 endjob:
2672 qemuDomainObjEndJob(driver, vm);
2674 cleanup:
2675 virDomainObjEndAPI(&vm);
2676 return ret;
2679 static int qemuDomainSendKey(virDomainPtr domain,
2680 unsigned int codeset,
2681 unsigned int holdtime,
2682 unsigned int *keycodes,
2683 int nkeycodes,
2684 unsigned int flags)
2686 virQEMUDriverPtr driver = domain->conn->privateData;
2687 virDomainObjPtr vm = NULL;
2688 int ret = -1;
2689 qemuDomainObjPrivatePtr priv;
2691 virCheckFlags(0, -1);
2693 /* translate the keycode to QNUM for qemu driver */
2694 if (codeset != VIR_KEYCODE_SET_QNUM) {
2695 size_t i;
2696 int keycode;
2698 for (i = 0; i < nkeycodes; i++) {
2699 keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_QNUM,
2700 keycodes[i]);
2701 if (keycode < 0) {
2702 virReportError(VIR_ERR_INTERNAL_ERROR,
2703 _("cannot translate keycode %u of %s codeset to qnum keycode"),
2704 keycodes[i],
2705 virKeycodeSetTypeToString(codeset));
2706 return -1;
2708 keycodes[i] = keycode;
2712 if (!(vm = qemuDomObjFromDomain(domain)))
2713 goto cleanup;
2715 priv = vm->privateData;
2717 if (virDomainSendKeyEnsureACL(domain->conn, vm->def) < 0)
2718 goto cleanup;
2720 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2721 goto cleanup;
2723 if (virDomainObjCheckActive(vm) < 0)
2724 goto endjob;
2726 qemuDomainObjEnterMonitor(driver, vm);
2727 ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2728 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2729 ret = -1;
2731 endjob:
2732 qemuDomainObjEndJob(driver, vm);
2734 cleanup:
2735 virDomainObjEndAPI(&vm);
2736 return ret;
2740 static int
2741 qemuDomainGetInfo(virDomainPtr dom,
2742 virDomainInfoPtr info)
2744 unsigned long long maxmem;
2745 virDomainObjPtr vm;
2746 int ret = -1;
2748 if (!(vm = qemuDomObjFromDomain(dom)))
2749 goto cleanup;
2751 if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
2752 goto cleanup;
2754 qemuDomainUpdateCurrentMemorySize(vm);
2756 memset(info, 0, sizeof(*info));
2758 info->state = virDomainObjGetState(vm, NULL);
2760 maxmem = virDomainDefGetMemoryTotal(vm->def);
2761 if (VIR_ASSIGN_IS_OVERFLOW(info->maxMem, maxmem)) {
2762 virReportError(VIR_ERR_OVERFLOW, "%s",
2763 _("Initial memory size too large"));
2764 goto cleanup;
2767 if (VIR_ASSIGN_IS_OVERFLOW(info->memory, vm->def->mem.cur_balloon)) {
2768 virReportError(VIR_ERR_OVERFLOW, "%s",
2769 _("Current memory size too large"));
2770 goto cleanup;
2773 if (virDomainObjIsActive(vm)) {
2774 if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) < 0) {
2775 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2776 _("cannot read cputime for domain"));
2777 goto cleanup;
2781 if (VIR_ASSIGN_IS_OVERFLOW(info->nrVirtCpu, virDomainDefGetVcpus(vm->def))) {
2782 virReportError(VIR_ERR_OVERFLOW, "%s", _("cpu count too large"));
2783 goto cleanup;
2786 ret = 0;
2788 cleanup:
2789 virDomainObjEndAPI(&vm);
2790 return ret;
2793 static int
2794 qemuDomainGetState(virDomainPtr dom,
2795 int *state,
2796 int *reason,
2797 unsigned int flags)
2799 virDomainObjPtr vm;
2800 int ret = -1;
2802 virCheckFlags(0, -1);
2804 if (!(vm = qemuDomObjFromDomain(dom)))
2805 goto cleanup;
2807 if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
2808 goto cleanup;
2810 *state = virDomainObjGetState(vm, reason);
2811 ret = 0;
2813 cleanup:
2814 virDomainObjEndAPI(&vm);
2815 return ret;
2818 static int
2819 qemuDomainGetControlInfo(virDomainPtr dom,
2820 virDomainControlInfoPtr info,
2821 unsigned int flags)
2823 virDomainObjPtr vm;
2824 qemuDomainObjPrivatePtr priv;
2825 int ret = -1;
2827 virCheckFlags(0, -1);
2829 if (!(vm = qemuDomObjFromDomain(dom)))
2830 goto cleanup;
2832 if (virDomainGetControlInfoEnsureACL(dom->conn, vm->def) < 0)
2833 goto cleanup;
2835 if (virDomainObjCheckActive(vm) < 0)
2836 goto cleanup;
2838 priv = vm->privateData;
2840 memset(info, 0, sizeof(*info));
2842 if (priv->monError) {
2843 info->state = VIR_DOMAIN_CONTROL_ERROR;
2844 info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_MONITOR;
2845 } else if (priv->job.active) {
2846 if (virTimeMillisNow(&info->stateTime) < 0)
2847 goto cleanup;
2848 if (priv->job.current) {
2849 info->state = VIR_DOMAIN_CONTROL_JOB;
2850 info->stateTime -= priv->job.current->started;
2851 } else {
2852 if (priv->monStart > 0) {
2853 info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2854 info->stateTime -= priv->monStart;
2855 } else {
2856 /* At this point the domain has an active job, but monitor was
2857 * not entered and the domain object lock is not held thus we
2858 * are stuck in the job forever due to a programming error.
2860 info->state = VIR_DOMAIN_CONTROL_ERROR;
2861 info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_INTERNAL;
2862 info->stateTime = 0;
2865 } else {
2866 info->state = VIR_DOMAIN_CONTROL_OK;
2869 ret = 0;
2871 cleanup:
2872 virDomainObjEndAPI(&vm);
2873 return ret;
2877 /* It would be nice to replace 'Qemud' with 'Qemu' but
2878 * this magic string is ABI, so it can't be changed
2880 #define QEMU_SAVE_MAGIC "LibvirtQemudSave"
2881 #define QEMU_SAVE_PARTIAL "LibvirtQemudPart"
2882 #define QEMU_SAVE_VERSION 2
2884 verify(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL));
2886 typedef enum {
2887 QEMU_SAVE_FORMAT_RAW = 0,
2888 QEMU_SAVE_FORMAT_GZIP = 1,
2889 QEMU_SAVE_FORMAT_BZIP2 = 2,
2891 * Deprecated by xz and never used as part of a release
2892 * QEMU_SAVE_FORMAT_LZMA
2894 QEMU_SAVE_FORMAT_XZ = 3,
2895 QEMU_SAVE_FORMAT_LZOP = 4,
2896 /* Note: add new members only at the end.
2897 These values are used in the on-disk format.
2898 Do not change or re-use numbers. */
2900 QEMU_SAVE_FORMAT_LAST
2901 } virQEMUSaveFormat;
2903 VIR_ENUM_DECL(qemuSaveCompression);
2904 VIR_ENUM_IMPL(qemuSaveCompression, QEMU_SAVE_FORMAT_LAST,
2905 "raw",
2906 "gzip",
2907 "bzip2",
2908 "xz",
2909 "lzop",
2912 VIR_ENUM_DECL(qemuDumpFormat);
2913 VIR_ENUM_IMPL(qemuDumpFormat, VIR_DOMAIN_CORE_DUMP_FORMAT_LAST,
2914 "elf",
2915 "kdump-zlib",
2916 "kdump-lzo",
2917 "kdump-snappy",
2920 typedef struct _virQEMUSaveHeader virQEMUSaveHeader;
2921 typedef virQEMUSaveHeader *virQEMUSaveHeaderPtr;
2922 struct _virQEMUSaveHeader {
2923 char magic[sizeof(QEMU_SAVE_MAGIC)-1];
2924 uint32_t version;
2925 uint32_t data_len;
2926 uint32_t was_running;
2927 uint32_t compressed;
2928 uint32_t cookieOffset;
2929 uint32_t unused[14];
2932 typedef struct _virQEMUSaveData virQEMUSaveData;
2933 typedef virQEMUSaveData *virQEMUSaveDataPtr;
2934 struct _virQEMUSaveData {
2935 virQEMUSaveHeader header;
2936 char *xml;
2937 char *cookie;
2941 static inline void
2942 bswap_header(virQEMUSaveHeaderPtr hdr)
2944 hdr->version = bswap_32(hdr->version);
2945 hdr->data_len = bswap_32(hdr->data_len);
2946 hdr->was_running = bswap_32(hdr->was_running);
2947 hdr->compressed = bswap_32(hdr->compressed);
2948 hdr->cookieOffset = bswap_32(hdr->cookieOffset);
2952 static void
2953 virQEMUSaveDataFree(virQEMUSaveDataPtr data)
2955 if (!data)
2956 return;
2958 VIR_FREE(data->xml);
2959 VIR_FREE(data->cookie);
2960 VIR_FREE(data);
2965 * This function steals @domXML on success.
2967 static virQEMUSaveDataPtr
2968 virQEMUSaveDataNew(char *domXML,
2969 qemuDomainSaveCookiePtr cookieObj,
2970 bool running,
2971 int compressed,
2972 virDomainXMLOptionPtr xmlopt)
2974 virQEMUSaveDataPtr data = NULL;
2975 virQEMUSaveHeaderPtr header;
2977 if (VIR_ALLOC(data) < 0)
2978 return NULL;
2980 VIR_STEAL_PTR(data->xml, domXML);
2982 if (cookieObj &&
2983 !(data->cookie = virSaveCookieFormat((virObjectPtr) cookieObj,
2984 virDomainXMLOptionGetSaveCookie(xmlopt))))
2985 goto error;
2987 header = &data->header;
2988 memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic));
2989 header->version = QEMU_SAVE_VERSION;
2990 header->was_running = running ? 1 : 0;
2991 header->compressed = compressed;
2993 return data;
2995 error:
2996 virQEMUSaveDataFree(data);
2997 return NULL;
3001 /* virQEMUSaveDataWrite:
3003 * Writes libvirt's header (including domain XML) into a saved image of a
3004 * running domain. If @header has data_len filled in (because it was previously
3005 * read from the file), the function will make sure the new data will fit
3006 * within data_len.
3008 * Returns -1 on failure, or 0 on success.
3010 static int
3011 virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
3012 int fd,
3013 const char *path)
3015 virQEMUSaveHeaderPtr header = &data->header;
3016 size_t len;
3017 size_t xml_len;
3018 size_t cookie_len = 0;
3019 int ret = -1;
3020 size_t zerosLen = 0;
3021 char *zeros = NULL;
3023 xml_len = strlen(data->xml) + 1;
3024 if (data->cookie)
3025 cookie_len = strlen(data->cookie) + 1;
3027 len = xml_len + cookie_len;
3029 if (header->data_len > 0) {
3030 if (len > header->data_len) {
3031 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3032 _("new xml too large to fit in file"));
3033 goto cleanup;
3036 zerosLen = header->data_len - len;
3037 if (VIR_ALLOC_N(zeros, zerosLen) < 0)
3038 goto cleanup;
3039 } else {
3040 header->data_len = len;
3043 if (data->cookie)
3044 header->cookieOffset = xml_len;
3046 if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
3047 virReportSystemError(errno,
3048 _("failed to write header to domain save file '%s'"),
3049 path);
3050 goto cleanup;
3053 if (safewrite(fd, data->xml, xml_len) != xml_len) {
3054 virReportSystemError(errno,
3055 _("failed to write domain xml to '%s'"),
3056 path);
3057 goto cleanup;
3060 if (data->cookie &&
3061 safewrite(fd, data->cookie, cookie_len) != cookie_len) {
3062 virReportSystemError(errno,
3063 _("failed to write cookie to '%s'"),
3064 path);
3065 goto cleanup;
3068 if (safewrite(fd, zeros, zerosLen) != zerosLen) {
3069 virReportSystemError(errno,
3070 _("failed to write padding to '%s'"),
3071 path);
3072 goto cleanup;
3075 ret = 0;
3077 cleanup:
3078 VIR_FREE(zeros);
3079 return ret;
3083 static int
3084 virQEMUSaveDataFinish(virQEMUSaveDataPtr data,
3085 int *fd,
3086 const char *path)
3088 virQEMUSaveHeaderPtr header = &data->header;
3090 memcpy(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic));
3092 if (safewrite(*fd, header, sizeof(*header)) != sizeof(*header) ||
3093 VIR_CLOSE(*fd) < 0) {
3094 virReportSystemError(errno,
3095 _("failed to write header to domain save file '%s'"),
3096 path);
3097 return -1;
3100 return 0;
3104 static virCommandPtr
3105 qemuCompressGetCommand(virQEMUSaveFormat compression)
3107 virCommandPtr ret = NULL;
3108 const char *prog = qemuSaveCompressionTypeToString(compression);
3110 if (!prog) {
3111 virReportError(VIR_ERR_OPERATION_FAILED,
3112 _("Invalid compressed save format %d"),
3113 compression);
3114 return NULL;
3117 ret = virCommandNew(prog);
3118 virCommandAddArg(ret, "-dc");
3120 if (compression == QEMU_SAVE_FORMAT_LZOP)
3121 virCommandAddArg(ret, "--ignore-warn");
3123 return ret;
3127 * qemuOpenFile:
3128 * @driver: driver object
3129 * @vm: domain object
3130 * @path: path to file to open
3131 * @oflags: flags for opening/creation of the file
3132 * @needUnlink: set to true if file was created by this function
3134 * Internal function to properly create or open existing files, with
3135 * ownership affected by qemu driver setup and domain DAC label.
3137 * Returns the file descriptor on success and negative errno on failure.
3139 * This function should not be used on storage sources. Use
3140 * qemuDomainStorageFileInit and storage driver APIs if possible.
3142 static int
3143 qemuOpenFile(virQEMUDriverPtr driver,
3144 virDomainObjPtr vm,
3145 const char *path,
3146 int oflags,
3147 bool *needUnlink)
3149 int ret = -1;
3150 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3151 uid_t user = cfg->user;
3152 gid_t group = cfg->group;
3153 bool dynamicOwnership = cfg->dynamicOwnership;
3154 virSecurityLabelDefPtr seclabel;
3156 virObjectUnref(cfg);
3158 /* TODO: Take imagelabel into account? */
3159 if (vm &&
3160 (seclabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) != NULL &&
3161 seclabel->label != NULL &&
3162 (virParseOwnershipIds(seclabel->label, &user, &group) < 0))
3163 goto cleanup;
3165 ret = qemuOpenFileAs(user, group, dynamicOwnership,
3166 path, oflags, needUnlink);
3168 cleanup:
3169 return ret;
3172 static int
3173 qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
3174 bool dynamicOwnership,
3175 const char *path, int oflags,
3176 bool *needUnlink)
3178 struct stat sb;
3179 bool is_reg = true;
3180 bool need_unlink = false;
3181 unsigned int vfoflags = 0;
3182 int fd = -1;
3183 int path_shared = virFileIsSharedFS(path);
3184 uid_t uid = geteuid();
3185 gid_t gid = getegid();
3187 /* path might be a pre-existing block dev, in which case
3188 * we need to skip the create step, and also avoid unlink
3189 * in the failure case */
3190 if (oflags & O_CREAT) {
3191 need_unlink = true;
3193 /* Don't force chown on network-shared FS
3194 * as it is likely to fail. */
3195 if (path_shared <= 0 || dynamicOwnership)
3196 vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
3198 if (stat(path, &sb) == 0) {
3199 /* It already exists, we don't want to delete it on error */
3200 need_unlink = false;
3202 is_reg = !!S_ISREG(sb.st_mode);
3203 /* If the path is regular file which exists
3204 * already and dynamic_ownership is off, we don't
3205 * want to change its ownership, just open it as-is */
3206 if (is_reg && !dynamicOwnership) {
3207 uid = sb.st_uid;
3208 gid = sb.st_gid;
3213 /* First try creating the file as root */
3214 if (!is_reg) {
3215 if ((fd = open(path, oflags & ~O_CREAT)) < 0) {
3216 fd = -errno;
3217 goto error;
3219 } else {
3220 if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
3221 vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
3222 /* If we failed as root, and the error was permission-denied
3223 (EACCES or EPERM), assume it's on a network-connected share
3224 where root access is restricted (eg, root-squashed NFS). If the
3225 qemu user is non-root, just set a flag to
3226 bypass security driver shenanigans, and retry the operation
3227 after doing setuid to qemu user */
3228 if ((fd != -EACCES && fd != -EPERM) || fallback_uid == geteuid())
3229 goto error;
3231 /* On Linux we can also verify the FS-type of the directory. */
3232 switch (path_shared) {
3233 case 1:
3234 /* it was on a network share, so we'll continue
3235 * as outlined above
3237 break;
3239 case -1:
3240 virReportSystemError(-fd, oflags & O_CREAT
3241 ? _("Failed to create file "
3242 "'%s': couldn't determine fs type")
3243 : _("Failed to open file "
3244 "'%s': couldn't determine fs type"),
3245 path);
3246 goto cleanup;
3248 case 0:
3249 default:
3250 /* local file - log the error returned by virFileOpenAs */
3251 goto error;
3254 /* If we created the file above, then we need to remove it;
3255 * otherwise, the next attempt to create will fail. If the
3256 * file had already existed before we got here, then we also
3257 * don't want to delete it and allow the following to succeed
3258 * or fail based on existing protections
3260 if (need_unlink)
3261 unlink(path);
3263 /* Retry creating the file as qemu user */
3265 /* Since we're passing different modes... */
3266 vfoflags |= VIR_FILE_OPEN_FORCE_MODE;
3268 if ((fd = virFileOpenAs(path, oflags,
3269 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
3270 fallback_uid, fallback_gid,
3271 vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
3272 virReportSystemError(-fd, oflags & O_CREAT
3273 ? _("Error from child process creating '%s'")
3274 : _("Error from child process opening '%s'"),
3275 path);
3276 goto cleanup;
3280 cleanup:
3281 if (needUnlink)
3282 *needUnlink = need_unlink;
3283 return fd;
3285 error:
3286 virReportSystemError(-fd, oflags & O_CREAT
3287 ? _("Failed to create file '%s'")
3288 : _("Failed to open file '%s'"),
3289 path);
3290 goto cleanup;
3294 static int
3295 qemuFileWrapperFDClose(virDomainObjPtr vm,
3296 virFileWrapperFdPtr fd)
3298 int ret;
3300 /* virFileWrapperFd uses iohelper to write data onto disk.
3301 * However, iohelper calls fdatasync() which may take ages to
3302 * finish. Therefore, we shouldn't be waiting with the domain
3303 * object locked. */
3305 /* XXX Currently, this function is intended for *Save() only
3306 * as restore needs some reworking before it's ready for
3307 * this. */
3309 virObjectUnlock(vm);
3310 ret = virFileWrapperFdClose(fd);
3311 virObjectLock(vm);
3312 if (!virDomainObjIsActive(vm)) {
3313 if (virGetLastErrorCode() == VIR_ERR_OK)
3314 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3315 _("domain is no longer running"));
3316 ret = -1;
3318 return ret;
3322 /* Helper function to execute a migration to file with a correct save header
3323 * the caller needs to make sure that the processors are stopped and do all other
3324 * actions besides saving memory */
3325 static int
3326 qemuDomainSaveMemory(virQEMUDriverPtr driver,
3327 virDomainObjPtr vm,
3328 const char *path,
3329 virQEMUSaveDataPtr data,
3330 const char *compressedpath,
3331 unsigned int flags,
3332 qemuDomainAsyncJob asyncJob)
3334 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3335 bool needUnlink = false;
3336 int ret = -1;
3337 int fd = -1;
3338 int directFlag = 0;
3339 virFileWrapperFdPtr wrapperFd = NULL;
3340 unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
3342 /* Obtain the file handle. */
3343 if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
3344 wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3345 directFlag = virFileDirectFdFlag();
3346 if (directFlag < 0) {
3347 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3348 _("bypass cache unsupported by this system"));
3349 goto cleanup;
3353 fd = qemuOpenFileAs(cfg->user, cfg->group, false, path,
3354 O_WRONLY | O_TRUNC | O_CREAT | directFlag,
3355 &needUnlink);
3356 if (fd < 0)
3357 goto cleanup;
3359 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
3360 goto cleanup;
3362 if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
3363 goto cleanup;
3365 if (virQEMUSaveDataWrite(data, fd, path) < 0)
3366 goto cleanup;
3368 /* Perform the migration */
3369 if (qemuMigrationSrcToFile(driver, vm, fd, compressedpath, asyncJob) < 0)
3370 goto cleanup;
3372 /* Touch up file header to mark image complete. */
3374 /* Reopen the file to touch up the header, since we aren't set
3375 * up to seek backwards on wrapperFd. The reopened fd will
3376 * trigger a single page of file system cache pollution, but
3377 * that's acceptable. */
3378 if (VIR_CLOSE(fd) < 0) {
3379 virReportSystemError(errno, _("unable to close %s"), path);
3380 goto cleanup;
3383 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3384 goto cleanup;
3386 if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL)) < 0 ||
3387 virQEMUSaveDataFinish(data, &fd, path) < 0)
3388 goto cleanup;
3390 ret = 0;
3392 cleanup:
3393 VIR_FORCE_CLOSE(fd);
3394 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3395 ret = -1;
3396 virFileWrapperFdFree(wrapperFd);
3397 virObjectUnref(cfg);
3399 if (ret < 0 && needUnlink)
3400 unlink(path);
3402 return ret;
3405 /* The vm must be active + locked. Vm will be unlocked and
3406 * potentially free'd after this returns (eg transient VMs are freed
3407 * shutdown). So 'vm' must not be referenced by the caller after
3408 * this returns (whether returning success or failure).
3410 static int
3411 qemuDomainSaveInternal(virQEMUDriverPtr driver,
3412 virDomainObjPtr vm, const char *path,
3413 int compressed, const char *compressedpath,
3414 const char *xmlin, unsigned int flags)
3416 char *xml = NULL;
3417 bool was_running = false;
3418 int ret = -1;
3419 virObjectEventPtr event = NULL;
3420 qemuDomainObjPrivatePtr priv = vm->privateData;
3421 virCapsPtr caps;
3422 virQEMUSaveDataPtr data = NULL;
3423 qemuDomainSaveCookiePtr cookie = NULL;
3425 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
3426 goto cleanup;
3428 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
3429 goto cleanup;
3431 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SAVE,
3432 VIR_DOMAIN_JOB_OPERATION_SAVE, flags) < 0)
3433 goto cleanup;
3435 if (!virDomainObjIsActive(vm)) {
3436 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3437 _("guest unexpectedly quit"));
3438 goto endjob;
3441 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
3443 /* Pause */
3444 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3445 was_running = true;
3446 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
3447 QEMU_ASYNC_JOB_SAVE) < 0)
3448 goto endjob;
3450 if (!virDomainObjIsActive(vm)) {
3451 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3452 _("guest unexpectedly quit"));
3453 goto endjob;
3457 /* libvirt-domain.c already guaranteed these two flags are exclusive. */
3458 if (flags & VIR_DOMAIN_SAVE_RUNNING)
3459 was_running = true;
3460 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
3461 was_running = false;
3463 /* Get XML for the domain. Restore needs only the inactive xml,
3464 * including secure. We should get the same result whether xmlin
3465 * is NULL or whether it was the live xml of the domain moments
3466 * before. */
3467 if (xmlin) {
3468 virDomainDefPtr def = NULL;
3470 if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt, NULL,
3471 VIR_DOMAIN_DEF_PARSE_INACTIVE |
3472 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) {
3473 goto endjob;
3475 if (!qemuDomainCheckABIStability(driver, vm, def)) {
3476 virDomainDefFree(def);
3477 goto endjob;
3479 xml = qemuDomainDefFormatLive(driver, def, NULL, true, true);
3480 } else {
3481 xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, true, true);
3483 if (!xml) {
3484 virReportError(VIR_ERR_OPERATION_FAILED,
3485 "%s", _("failed to get domain xml"));
3486 goto endjob;
3489 if (!(cookie = qemuDomainSaveCookieNew(vm)))
3490 goto endjob;
3492 if (!(data = virQEMUSaveDataNew(xml, cookie, was_running, compressed,
3493 driver->xmlopt)))
3494 goto endjob;
3495 xml = NULL;
3497 ret = qemuDomainSaveMemory(driver, vm, path, data, compressedpath,
3498 flags, QEMU_ASYNC_JOB_SAVE);
3499 if (ret < 0)
3500 goto endjob;
3502 /* Shut it down */
3503 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED,
3504 QEMU_ASYNC_JOB_SAVE, 0);
3505 virDomainAuditStop(vm, "saved");
3506 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
3507 VIR_DOMAIN_EVENT_STOPPED_SAVED);
3508 endjob:
3509 if (ret < 0) {
3510 if (was_running && virDomainObjIsActive(vm)) {
3511 virErrorPtr save_err = virSaveLastError();
3512 if (qemuProcessStartCPUs(driver, vm,
3513 VIR_DOMAIN_RUNNING_SAVE_CANCELED,
3514 QEMU_ASYNC_JOB_SAVE) < 0) {
3515 VIR_WARN("Unable to resume guest CPUs after save failure");
3516 virObjectEventStateQueue(driver->domainEventState,
3517 virDomainEventLifecycleNewFromObj(vm,
3518 VIR_DOMAIN_EVENT_SUSPENDED,
3519 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR));
3521 virSetError(save_err);
3522 virFreeError(save_err);
3525 qemuDomainObjEndAsyncJob(driver, vm);
3526 if (ret == 0)
3527 qemuDomainRemoveInactiveJob(driver, vm);
3529 cleanup:
3530 virObjectUnref(cookie);
3531 VIR_FREE(xml);
3532 virQEMUSaveDataFree(data);
3533 virObjectEventStateQueue(driver->domainEventState, event);
3534 virObjectUnref(caps);
3535 return ret;
3539 /* qemuGetCompressionProgram:
3540 * @imageFormat: String representation from qemu.conf for the compression
3541 * image format being used (dump, save, or snapshot).
3542 * @compresspath: Pointer to a character string to store the fully qualified
3543 * path from virFindFileInPath.
3544 * @styleFormat: String representing the style of format (dump, save, snapshot)
3545 * @use_raw_on_fail: Boolean indicating how to handle the error path. For
3546 * callers that are OK with invalid data or inability to
3547 * find the compression program, just return a raw format
3548 * and let the path remain as NULL.
3550 * Returns:
3551 * virQEMUSaveFormat - Integer representation of the compression
3552 * program to be used for particular style
3553 * (e.g. dump, save, or snapshot).
3554 * QEMU_SAVE_FORMAT_RAW - If there is no qemu.conf imageFormat value or
3555 * no there was an error, then just return RAW
3556 * indicating none.
3558 static int ATTRIBUTE_NONNULL(2)
3559 qemuGetCompressionProgram(const char *imageFormat,
3560 char **compresspath,
3561 const char *styleFormat,
3562 bool use_raw_on_fail)
3564 int ret;
3566 *compresspath = NULL;
3568 if (!imageFormat)
3569 return QEMU_SAVE_FORMAT_RAW;
3571 if ((ret = qemuSaveCompressionTypeFromString(imageFormat)) < 0)
3572 goto error;
3574 if (ret == QEMU_SAVE_FORMAT_RAW)
3575 return QEMU_SAVE_FORMAT_RAW;
3577 if (!(*compresspath = virFindFileInPath(imageFormat)))
3578 goto error;
3580 return ret;
3582 error:
3583 if (ret < 0) {
3584 if (use_raw_on_fail)
3585 VIR_WARN("Invalid %s image format specified in "
3586 "configuration file, using raw",
3587 styleFormat);
3588 else
3589 virReportError(VIR_ERR_OPERATION_FAILED,
3590 _("Invalid %s image format specified "
3591 "in configuration file"),
3592 styleFormat);
3593 } else {
3594 if (use_raw_on_fail)
3595 VIR_WARN("Compression program for %s image format in "
3596 "configuration file isn't available, using raw",
3597 styleFormat);
3598 else
3599 virReportError(VIR_ERR_OPERATION_FAILED,
3600 _("Compression program for %s image format "
3601 "in configuration file isn't available"),
3602 styleFormat);
3605 /* Use "raw" as the format if the specified format is not valid,
3606 * or the compress program is not available. */
3607 if (use_raw_on_fail)
3608 return QEMU_SAVE_FORMAT_RAW;
3610 return -1;
3614 static int
3615 qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
3616 unsigned int flags)
3618 virQEMUDriverPtr driver = dom->conn->privateData;
3619 int compressed;
3620 char *compressedpath = NULL;
3621 int ret = -1;
3622 virDomainObjPtr vm = NULL;
3623 virQEMUDriverConfigPtr cfg = NULL;
3625 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
3626 VIR_DOMAIN_SAVE_RUNNING |
3627 VIR_DOMAIN_SAVE_PAUSED, -1);
3629 cfg = virQEMUDriverGetConfig(driver);
3630 if ((compressed = qemuGetCompressionProgram(cfg->saveImageFormat,
3631 &compressedpath,
3632 "save", false)) < 0)
3633 goto cleanup;
3635 if (!(vm = qemuDomObjFromDomain(dom)))
3636 goto cleanup;
3638 if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
3639 goto cleanup;
3641 if (virDomainObjCheckActive(vm) < 0)
3642 goto cleanup;
3644 ret = qemuDomainSaveInternal(driver, vm, path, compressed,
3645 compressedpath, dxml, flags);
3647 cleanup:
3648 virDomainObjEndAPI(&vm);
3649 VIR_FREE(compressedpath);
3650 virObjectUnref(cfg);
3651 return ret;
3654 static int
3655 qemuDomainSave(virDomainPtr dom, const char *path)
3657 return qemuDomainSaveFlags(dom, path, NULL, 0);
3660 static char *
3661 qemuDomainManagedSavePath(virQEMUDriverPtr driver, virDomainObjPtr vm)
3663 char *ret;
3664 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3666 if (virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name) < 0) {
3667 virObjectUnref(cfg);
3668 return NULL;
3671 virObjectUnref(cfg);
3672 return ret;
3675 static int
3676 qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
3678 virQEMUDriverPtr driver = dom->conn->privateData;
3679 virQEMUDriverConfigPtr cfg = NULL;
3680 int compressed;
3681 char *compressedpath = NULL;
3682 virDomainObjPtr vm;
3683 char *name = NULL;
3684 int ret = -1;
3686 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
3687 VIR_DOMAIN_SAVE_RUNNING |
3688 VIR_DOMAIN_SAVE_PAUSED, -1);
3690 if (!(vm = qemuDomObjFromDomain(dom)))
3691 return -1;
3693 if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
3694 goto cleanup;
3696 if (virDomainObjCheckActive(vm) < 0)
3697 goto cleanup;
3699 if (!vm->persistent) {
3700 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3701 _("cannot do managed save for transient domain"));
3702 goto cleanup;
3705 cfg = virQEMUDriverGetConfig(driver);
3706 if ((compressed = qemuGetCompressionProgram(cfg->saveImageFormat,
3707 &compressedpath,
3708 "save", false)) < 0)
3709 goto cleanup;
3711 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3712 goto cleanup;
3714 VIR_INFO("Saving state of domain '%s' to '%s'", vm->def->name, name);
3716 ret = qemuDomainSaveInternal(driver, vm, name, compressed,
3717 compressedpath, NULL, flags);
3718 if (ret == 0)
3719 vm->hasManagedSave = true;
3721 cleanup:
3722 virDomainObjEndAPI(&vm);
3723 VIR_FREE(name);
3724 VIR_FREE(compressedpath);
3725 virObjectUnref(cfg);
3727 return ret;
3730 static int
3731 qemuDomainManagedSaveLoad(virDomainObjPtr vm,
3732 void *opaque)
3734 virQEMUDriverPtr driver = opaque;
3735 char *name;
3736 int ret = -1;
3738 virObjectLock(vm);
3740 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3741 goto cleanup;
3743 vm->hasManagedSave = virFileExists(name);
3745 ret = 0;
3746 cleanup:
3747 virObjectUnlock(vm);
3748 VIR_FREE(name);
3749 return ret;
3753 static int
3754 qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
3756 virDomainObjPtr vm = NULL;
3757 int ret = -1;
3759 virCheckFlags(0, -1);
3761 if (!(vm = qemuDomObjFromDomain(dom)))
3762 return -1;
3764 if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
3765 goto cleanup;
3767 ret = vm->hasManagedSave;
3769 cleanup:
3770 virDomainObjEndAPI(&vm);
3771 return ret;
3774 static int
3775 qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
3777 virQEMUDriverPtr driver = dom->conn->privateData;
3778 virDomainObjPtr vm;
3779 int ret = -1;
3780 char *name = NULL;
3782 virCheckFlags(0, -1);
3784 if (!(vm = qemuDomObjFromDomain(dom)))
3785 return -1;
3787 if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
3788 goto cleanup;
3790 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3791 goto cleanup;
3793 if (unlink(name) < 0) {
3794 virReportSystemError(errno,
3795 _("Failed to remove managed save file '%s'"),
3796 name);
3797 goto cleanup;
3800 vm->hasManagedSave = false;
3801 ret = 0;
3803 cleanup:
3804 VIR_FREE(name);
3805 virDomainObjEndAPI(&vm);
3806 return ret;
3811 * qemuDumpWaitForCompletion:
3812 * @vm: domain object
3814 * If the query dump capability exists, then it's possible to start a
3815 * guest memory dump operation using a thread via a 'detach' qualifier
3816 * to the dump guest memory command. This allows the async check if the
3817 * dump is done.
3819 * Returns 0 on success, -1 on failure
3821 static int
3822 qemuDumpWaitForCompletion(virDomainObjPtr vm)
3824 qemuDomainObjPrivatePtr priv = vm->privateData;
3825 int ret = -1;
3827 VIR_DEBUG("Waiting for dump completion");
3828 while (!priv->job.dumpCompleted && !priv->job.abortJob) {
3829 if (virDomainObjWait(vm) < 0)
3830 return -1;
3833 if (priv->job.current->stats.dump.status == QEMU_MONITOR_DUMP_STATUS_FAILED) {
3834 if (priv->job.error)
3835 virReportError(VIR_ERR_OPERATION_FAILED,
3836 _("memory-only dump failed: %s"),
3837 priv->job.error);
3838 else
3839 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3840 _("memory-only dump failed for unknown reason"));
3842 goto cleanup;
3844 qemuDomainJobInfoUpdateTime(priv->job.current);
3846 ret = 0;
3848 cleanup:
3849 return ret;
3853 static int
3854 qemuDumpToFd(virQEMUDriverPtr driver,
3855 virDomainObjPtr vm,
3856 int fd,
3857 qemuDomainAsyncJob asyncJob,
3858 const char *dumpformat)
3860 qemuDomainObjPrivatePtr priv = vm->privateData;
3861 bool detach = false;
3862 int ret = -1;
3864 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
3865 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3866 _("dump-guest-memory is not supported"));
3867 return -1;
3870 detach = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_COMPLETED);
3872 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
3873 return -1;
3875 if (detach)
3876 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP;
3877 else
3878 VIR_FREE(priv->job.current);
3880 if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
3881 return -1;
3883 if (dumpformat) {
3884 ret = qemuMonitorGetDumpGuestMemoryCapability(priv->mon, dumpformat);
3886 if (ret <= 0) {
3887 virReportError(VIR_ERR_INVALID_ARG,
3888 _("unsupported dumpformat '%s' "
3889 "for this QEMU binary"),
3890 dumpformat);
3891 ret = -1;
3892 ignore_value(qemuDomainObjExitMonitor(driver, vm));
3893 goto cleanup;
3897 ret = qemuMonitorDumpToFd(priv->mon, fd, dumpformat, detach);
3899 if ((qemuDomainObjExitMonitor(driver, vm) < 0) || ret < 0)
3900 goto cleanup;
3902 if (detach)
3903 ret = qemuDumpWaitForCompletion(vm);
3905 cleanup:
3906 return ret;
3910 static int
3911 doCoreDump(virQEMUDriverPtr driver,
3912 virDomainObjPtr vm,
3913 const char *path,
3914 unsigned int dump_flags,
3915 unsigned int dumpformat)
3917 int fd = -1;
3918 int ret = -1;
3919 virFileWrapperFdPtr wrapperFd = NULL;
3920 int directFlag = 0;
3921 unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
3922 const char *memory_dump_format = NULL;
3923 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3924 char *compressedpath = NULL;
3926 /* We reuse "save" flag for "dump" here. Then, we can support the same
3927 * format in "save" and "dump". This path doesn't need the compression
3928 * program to exist and can ignore the return value - it only cares to
3929 * get the compressedpath */
3930 ignore_value(qemuGetCompressionProgram(cfg->dumpImageFormat,
3931 &compressedpath,
3932 "dump", true));
3934 /* Create an empty file with appropriate ownership. */
3935 if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
3936 flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3937 directFlag = virFileDirectFdFlag();
3938 if (directFlag < 0) {
3939 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3940 _("bypass cache unsupported by this system"));
3941 goto cleanup;
3944 /* Core dumps usually imply last-ditch analysis efforts are
3945 * desired, so we intentionally do not unlink even if a file was
3946 * created. */
3947 if ((fd = qemuOpenFileAs(cfg->user, cfg->group, false, path,
3948 O_CREAT | O_TRUNC | O_WRONLY | directFlag,
3949 NULL)) < 0)
3950 goto cleanup;
3952 if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
3953 goto cleanup;
3955 if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
3956 if (!(memory_dump_format = qemuDumpFormatTypeToString(dumpformat))) {
3957 virReportError(VIR_ERR_INVALID_ARG,
3958 _("unknown dumpformat '%d'"), dumpformat);
3959 goto cleanup;
3962 /* qemu dumps in "elf" without dumpformat set */
3963 if (STREQ(memory_dump_format, "elf"))
3964 memory_dump_format = NULL;
3966 ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP,
3967 memory_dump_format);
3968 } else {
3969 if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) {
3970 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3971 _("kdump-compressed format is only supported with "
3972 "memory-only dump"));
3973 goto cleanup;
3976 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
3977 goto cleanup;
3979 ret = qemuMigrationSrcToFile(driver, vm, fd, compressedpath,
3980 QEMU_ASYNC_JOB_DUMP);
3983 if (ret < 0)
3984 goto cleanup;
3986 if (VIR_CLOSE(fd) < 0) {
3987 virReportSystemError(errno,
3988 _("unable to close file %s"),
3989 path);
3990 goto cleanup;
3992 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3993 goto cleanup;
3995 ret = 0;
3997 cleanup:
3998 VIR_FORCE_CLOSE(fd);
3999 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
4000 ret = -1;
4001 virFileWrapperFdFree(wrapperFd);
4002 if (ret != 0)
4003 unlink(path);
4004 VIR_FREE(compressedpath);
4005 virObjectUnref(cfg);
4006 return ret;
4010 static int
4011 qemuDomainCoreDumpWithFormat(virDomainPtr dom,
4012 const char *path,
4013 unsigned int dumpformat,
4014 unsigned int flags)
4016 virQEMUDriverPtr driver = dom->conn->privateData;
4017 virDomainObjPtr vm;
4018 qemuDomainObjPrivatePtr priv = NULL;
4019 bool resume = false, paused = false;
4020 int ret = -1;
4021 virObjectEventPtr event = NULL;
4023 virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
4024 VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
4025 VIR_DUMP_MEMORY_ONLY, -1);
4027 if (!(vm = qemuDomObjFromDomain(dom)))
4028 return -1;
4030 if (virDomainCoreDumpWithFormatEnsureACL(dom->conn, vm->def) < 0)
4031 goto cleanup;
4033 if (qemuDomainObjBeginAsyncJob(driver, vm,
4034 QEMU_ASYNC_JOB_DUMP,
4035 VIR_DOMAIN_JOB_OPERATION_DUMP,
4036 flags) < 0)
4037 goto cleanup;
4039 if (virDomainObjCheckActive(vm) < 0)
4040 goto endjob;
4042 priv = vm->privateData;
4043 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
4045 /* Migrate will always stop the VM, so the resume condition is
4046 independent of whether the stop command is issued. */
4047 resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
4049 /* Pause domain for non-live dump */
4050 if (!(flags & VIR_DUMP_LIVE) &&
4051 virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
4052 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
4053 QEMU_ASYNC_JOB_DUMP) < 0)
4054 goto endjob;
4055 paused = true;
4057 if (!virDomainObjIsActive(vm)) {
4058 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4059 _("guest unexpectedly quit"));
4060 goto endjob;
4064 if ((ret = doCoreDump(driver, vm, path, flags, dumpformat)) < 0)
4065 goto endjob;
4067 paused = true;
4069 endjob:
4070 if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
4071 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
4072 QEMU_ASYNC_JOB_DUMP, 0);
4073 virDomainAuditStop(vm, "crashed");
4074 event = virDomainEventLifecycleNewFromObj(vm,
4075 VIR_DOMAIN_EVENT_STOPPED,
4076 VIR_DOMAIN_EVENT_STOPPED_CRASHED);
4077 } else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
4078 virDomainObjIsActive(vm)) {
4079 if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
4080 qemuDomainObjEnterMonitor(driver, vm);
4081 ret = qemuMonitorSystemReset(priv->mon);
4082 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4083 ret = -1;
4086 if (resume && virDomainObjIsActive(vm)) {
4087 if (qemuProcessStartCPUs(driver, vm,
4088 VIR_DOMAIN_RUNNING_UNPAUSED,
4089 QEMU_ASYNC_JOB_DUMP) < 0) {
4090 event = virDomainEventLifecycleNewFromObj(vm,
4091 VIR_DOMAIN_EVENT_SUSPENDED,
4092 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
4093 if (virGetLastErrorCode() == VIR_ERR_OK)
4094 virReportError(VIR_ERR_OPERATION_FAILED,
4095 "%s", _("resuming after dump failed"));
4100 qemuDomainObjEndAsyncJob(driver, vm);
4101 if (ret == 0 && flags & VIR_DUMP_CRASH)
4102 qemuDomainRemoveInactiveJob(driver, vm);
4104 cleanup:
4105 virDomainObjEndAPI(&vm);
4106 virObjectEventStateQueue(driver->domainEventState, event);
4107 return ret;
4111 static int
4112 qemuDomainCoreDump(virDomainPtr dom,
4113 const char *path,
4114 unsigned int flags)
4116 return qemuDomainCoreDumpWithFormat(dom, path,
4117 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW,
4118 flags);
4122 static char *
4123 qemuDomainScreenshot(virDomainPtr dom,
4124 virStreamPtr st,
4125 unsigned int screen,
4126 unsigned int flags)
4128 virQEMUDriverPtr driver = dom->conn->privateData;
4129 virDomainObjPtr vm;
4130 qemuDomainObjPrivatePtr priv;
4131 char *tmp = NULL;
4132 int tmp_fd = -1;
4133 size_t i;
4134 const char *videoAlias = NULL;
4135 char *ret = NULL;
4136 bool unlink_tmp = false;
4137 virQEMUDriverConfigPtr cfg = NULL;
4139 virCheckFlags(0, NULL);
4141 if (!(vm = qemuDomObjFromDomain(dom)))
4142 goto cleanup;
4144 priv = vm->privateData;
4145 cfg = virQEMUDriverGetConfig(driver);
4147 if (virDomainScreenshotEnsureACL(dom->conn, vm->def) < 0)
4148 goto cleanup;
4150 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
4151 goto cleanup;
4153 if (virDomainObjCheckActive(vm) < 0)
4154 goto endjob;
4156 if (!vm->def->nvideos) {
4157 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4158 _("no screens to take screenshot from"));
4159 goto endjob;
4162 if (screen) {
4163 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SCREENDUMP_DEVICE)) {
4164 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4165 _("qemu does not allow specifying screen ID"));
4166 goto endjob;
4169 for (i = 0; i < vm->def->nvideos; i++) {
4170 const virDomainVideoDef *video = vm->def->videos[i];
4172 if (screen < video->heads) {
4173 videoAlias = video->info.alias;
4174 break;
4177 screen -= video->heads;
4180 if (i == vm->def->nvideos) {
4181 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4182 _("no such screen ID"));
4183 goto endjob;
4187 if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", cfg->cacheDir) < 0)
4188 goto endjob;
4190 if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
4191 virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
4192 goto endjob;
4194 unlink_tmp = true;
4196 qemuSecuritySetSavedStateLabel(driver, vm, tmp);
4198 qemuDomainObjEnterMonitor(driver, vm);
4199 if (qemuMonitorScreendump(priv->mon, videoAlias, screen, tmp) < 0) {
4200 ignore_value(qemuDomainObjExitMonitor(driver, vm));
4201 goto endjob;
4203 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4204 goto endjob;
4206 if (VIR_CLOSE(tmp_fd) < 0) {
4207 virReportSystemError(errno, _("unable to close %s"), tmp);
4208 goto endjob;
4211 if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
4212 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
4213 _("unable to open stream"));
4214 goto endjob;
4217 ignore_value(VIR_STRDUP(ret, "image/x-portable-pixmap"));
4219 endjob:
4220 VIR_FORCE_CLOSE(tmp_fd);
4221 if (unlink_tmp)
4222 unlink(tmp);
4223 VIR_FREE(tmp);
4225 qemuDomainObjEndJob(driver, vm);
4227 cleanup:
4228 virDomainObjEndAPI(&vm);
4229 virObjectUnref(cfg);
4230 return ret;
4233 static char *
4234 getAutoDumpPath(virQEMUDriverPtr driver,
4235 virDomainObjPtr vm)
4237 char *dumpfile = NULL;
4238 char *domname = virDomainDefGetShortName(vm->def);
4239 char timestr[100];
4240 struct tm time_info;
4241 time_t curtime = time(NULL);
4242 virQEMUDriverConfigPtr cfg = NULL;
4244 if (!domname)
4245 return NULL;
4247 cfg = virQEMUDriverGetConfig(driver);
4249 localtime_r(&curtime, &time_info);
4250 strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info);
4252 ignore_value(virAsprintf(&dumpfile, "%s/%s-%s",
4253 cfg->autoDumpPath,
4254 domname,
4255 timestr));
4257 virObjectUnref(cfg);
4258 VIR_FREE(domname);
4259 return dumpfile;
4262 static void
4263 processWatchdogEvent(virQEMUDriverPtr driver,
4264 virDomainObjPtr vm,
4265 int action)
4267 int ret;
4268 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4269 char *dumpfile = getAutoDumpPath(driver, vm);
4270 unsigned int flags = VIR_DUMP_MEMORY_ONLY;
4272 if (!dumpfile)
4273 goto cleanup;
4275 switch (action) {
4276 case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
4277 if (qemuDomainObjBeginAsyncJob(driver, vm,
4278 QEMU_ASYNC_JOB_DUMP,
4279 VIR_DOMAIN_JOB_OPERATION_DUMP,
4280 flags) < 0) {
4281 goto cleanup;
4284 if (virDomainObjCheckActive(vm) < 0)
4285 goto endjob;
4287 flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
4288 if ((ret = doCoreDump(driver, vm, dumpfile, flags,
4289 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
4290 virReportError(VIR_ERR_OPERATION_FAILED,
4291 "%s", _("Dump failed"));
4293 ret = qemuProcessStartCPUs(driver, vm,
4294 VIR_DOMAIN_RUNNING_UNPAUSED,
4295 QEMU_ASYNC_JOB_DUMP);
4297 if (ret < 0)
4298 virReportError(VIR_ERR_OPERATION_FAILED,
4299 "%s", _("Resuming after dump failed"));
4300 break;
4301 default:
4302 goto cleanup;
4305 endjob:
4306 qemuDomainObjEndAsyncJob(driver, vm);
4308 cleanup:
4309 virObjectUnref(cfg);
4310 VIR_FREE(dumpfile);
4313 static int
4314 doCoreDumpToAutoDumpPath(virQEMUDriverPtr driver,
4315 virDomainObjPtr vm,
4316 unsigned int flags)
4318 int ret = -1;
4319 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4320 char *dumpfile = getAutoDumpPath(driver, vm);
4322 if (!dumpfile)
4323 goto cleanup;
4325 flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
4326 if ((ret = doCoreDump(driver, vm, dumpfile, flags,
4327 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
4328 virReportError(VIR_ERR_OPERATION_FAILED,
4329 "%s", _("Dump failed"));
4330 cleanup:
4331 VIR_FREE(dumpfile);
4332 virObjectUnref(cfg);
4333 return ret;
4337 static void
4338 qemuProcessGuestPanicEventInfo(virQEMUDriverPtr driver,
4339 virDomainObjPtr vm,
4340 qemuMonitorEventPanicInfoPtr info)
4342 char *msg = qemuMonitorGuestPanicEventInfoFormatMsg(info);
4343 char *timestamp = virTimeStringNow();
4345 if (msg && timestamp)
4346 qemuDomainLogAppendMessage(driver, vm, "%s: panic %s\n", timestamp, msg);
4348 VIR_FREE(timestamp);
4349 VIR_FREE(msg);
4353 static void
4354 processGuestPanicEvent(virQEMUDriverPtr driver,
4355 virDomainObjPtr vm,
4356 int action,
4357 qemuMonitorEventPanicInfoPtr info)
4359 qemuDomainObjPrivatePtr priv = vm->privateData;
4360 virObjectEventPtr event = NULL;
4361 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4362 bool removeInactive = false;
4363 unsigned long flags = VIR_DUMP_MEMORY_ONLY;
4365 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_DUMP,
4366 VIR_DOMAIN_JOB_OPERATION_DUMP, flags) < 0)
4367 goto cleanup;
4369 if (!virDomainObjIsActive(vm)) {
4370 VIR_DEBUG("Ignoring GUEST_PANICKED event from inactive domain %s",
4371 vm->def->name);
4372 goto endjob;
4375 if (info)
4376 qemuProcessGuestPanicEventInfo(driver, vm, info);
4378 virDomainObjSetState(vm, VIR_DOMAIN_CRASHED, VIR_DOMAIN_CRASHED_PANICKED);
4380 event = virDomainEventLifecycleNewFromObj(vm,
4381 VIR_DOMAIN_EVENT_CRASHED,
4382 VIR_DOMAIN_EVENT_CRASHED_PANICKED);
4384 virObjectEventStateQueue(driver->domainEventState, event);
4386 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
4387 VIR_WARN("Unable to save status on vm %s after state change",
4388 vm->def->name);
4391 if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
4392 VIR_WARN("Unable to release lease on %s", vm->def->name);
4393 VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
4395 switch (action) {
4396 case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
4397 if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
4398 goto endjob;
4399 ATTRIBUTE_FALLTHROUGH;
4401 case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
4402 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
4403 QEMU_ASYNC_JOB_DUMP, 0);
4404 event = virDomainEventLifecycleNewFromObj(vm,
4405 VIR_DOMAIN_EVENT_STOPPED,
4406 VIR_DOMAIN_EVENT_STOPPED_CRASHED);
4408 virObjectEventStateQueue(driver->domainEventState, event);
4409 virDomainAuditStop(vm, "destroyed");
4410 removeInactive = true;
4411 break;
4413 case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
4414 if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
4415 goto endjob;
4416 ATTRIBUTE_FALLTHROUGH;
4418 case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
4419 qemuDomainSetFakeReboot(driver, vm, true);
4420 qemuProcessShutdownOrReboot(driver, vm);
4421 break;
4423 case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
4424 break;
4426 default:
4427 break;
4430 endjob:
4431 qemuDomainObjEndAsyncJob(driver, vm);
4432 if (removeInactive)
4433 qemuDomainRemoveInactiveJob(driver, vm);
4435 cleanup:
4436 virObjectUnref(cfg);
4440 static void
4441 processDeviceDeletedEvent(virQEMUDriverPtr driver,
4442 virDomainObjPtr vm,
4443 const char *devAlias)
4445 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4446 virDomainDeviceDef dev;
4448 VIR_DEBUG("Removing device %s from domain %p %s",
4449 devAlias, vm, vm->def->name);
4451 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4452 goto cleanup;
4454 if (!virDomainObjIsActive(vm)) {
4455 VIR_DEBUG("Domain is not running");
4456 goto endjob;
4459 if (STRPREFIX(devAlias, "vcpu")) {
4460 qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
4461 } else {
4462 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
4463 goto endjob;
4465 if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
4466 goto endjob;
4469 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
4470 VIR_WARN("unable to save domain status after removing device %s",
4471 devAlias);
4473 endjob:
4474 qemuDomainObjEndJob(driver, vm);
4476 cleanup:
4477 virObjectUnref(cfg);
4481 static void
4482 syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter,
4483 virNetDevRxFilterPtr hostFilter)
4485 char newMacStr[VIR_MAC_STRING_BUFLEN];
4487 if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
4488 virMacAddrFormat(&guestFilter->mac, newMacStr);
4490 /* set new MAC address from guest to associated macvtap device */
4491 if (virNetDevSetMAC(ifname, &guestFilter->mac) < 0) {
4492 VIR_WARN("Couldn't set new MAC address %s to device %s "
4493 "while responding to NIC_RX_FILTER_CHANGED",
4494 newMacStr, ifname);
4495 } else {
4496 VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
4502 static void
4503 syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
4504 virNetDevRxFilterPtr hostFilter)
4506 size_t i, j;
4507 bool found;
4508 char macstr[VIR_MAC_STRING_BUFLEN];
4510 for (i = 0; i < guestFilter->multicast.nTable; i++) {
4511 found = false;
4513 for (j = 0; j < hostFilter->multicast.nTable; j++) {
4514 if (virMacAddrCmp(&guestFilter->multicast.table[i],
4515 &hostFilter->multicast.table[j]) == 0) {
4516 found = true;
4517 break;
4521 if (!found) {
4522 virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
4524 if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i]) < 0) {
4525 VIR_WARN("Couldn't add new multicast MAC address %s to "
4526 "device %s while responding to NIC_RX_FILTER_CHANGED",
4527 macstr, ifname);
4528 } else {
4529 VIR_DEBUG("Added multicast MAC %s to %s interface",
4530 macstr, ifname);
4537 static void
4538 syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
4539 virNetDevRxFilterPtr hostFilter)
4541 size_t i, j;
4542 bool found;
4543 char macstr[VIR_MAC_STRING_BUFLEN];
4545 for (i = 0; i < hostFilter->multicast.nTable; i++) {
4546 found = false;
4548 for (j = 0; j < guestFilter->multicast.nTable; j++) {
4549 if (virMacAddrCmp(&hostFilter->multicast.table[i],
4550 &guestFilter->multicast.table[j]) == 0) {
4551 found = true;
4552 break;
4556 if (!found) {
4557 virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
4559 if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i]) < 0) {
4560 VIR_WARN("Couldn't delete multicast MAC address %s from "
4561 "device %s while responding to NIC_RX_FILTER_CHANGED",
4562 macstr, ifname);
4563 } else {
4564 VIR_DEBUG("Deleted multicast MAC %s from %s interface",
4565 macstr, ifname);
4572 static void
4573 syncNicRxFilterPromiscMode(char *ifname,
4574 virNetDevRxFilterPtr guestFilter,
4575 virNetDevRxFilterPtr hostFilter)
4577 bool promisc;
4578 bool setpromisc = false;
4580 /* Set macvtap promisc mode to true if the guest has vlans defined */
4581 /* or synchronize the macvtap promisc mode if different from guest */
4582 if (guestFilter->vlan.nTable > 0) {
4583 if (!hostFilter->promiscuous) {
4584 setpromisc = true;
4585 promisc = true;
4587 } else if (hostFilter->promiscuous != guestFilter->promiscuous) {
4588 setpromisc = true;
4589 promisc = guestFilter->promiscuous;
4592 if (setpromisc) {
4593 if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
4594 VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
4595 "while responding to NIC_RX_FILTER_CHANGED",
4596 promisc ? "true" : "false", ifname);
4602 static void
4603 syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
4604 virNetDevRxFilterPtr hostFilter)
4606 if (hostFilter->multicast.mode != guestFilter->multicast.mode ||
4607 (guestFilter->multicast.overflow &&
4608 guestFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_NORMAL)) {
4609 switch (guestFilter->multicast.mode) {
4610 case VIR_NETDEV_RX_FILTER_MODE_ALL:
4611 if (virNetDevSetRcvAllMulti(ifname, true) < 0) {
4612 VIR_WARN("Couldn't set allmulticast flag to 'on' for "
4613 "device %s while responding to "
4614 "NIC_RX_FILTER_CHANGED", ifname);
4616 break;
4618 case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
4619 if (guestFilter->multicast.overflow &&
4620 (hostFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_ALL)) {
4621 break;
4624 if (virNetDevSetRcvMulti(ifname, true) < 0) {
4625 VIR_WARN("Couldn't set multicast flag to 'on' for "
4626 "device %s while responding to "
4627 "NIC_RX_FILTER_CHANGED", ifname);
4630 if (virNetDevSetRcvAllMulti(ifname,
4631 guestFilter->multicast.overflow) < 0) {
4632 VIR_WARN("Couldn't set allmulticast flag to '%s' for "
4633 "device %s while responding to "
4634 "NIC_RX_FILTER_CHANGED",
4635 virTristateSwitchTypeToString(virTristateSwitchFromBool(guestFilter->multicast.overflow)),
4636 ifname);
4638 break;
4640 case VIR_NETDEV_RX_FILTER_MODE_NONE:
4641 if (virNetDevSetRcvAllMulti(ifname, false) < 0) {
4642 VIR_WARN("Couldn't set allmulticast flag to 'off' for "
4643 "device %s while responding to "
4644 "NIC_RX_FILTER_CHANGED", ifname);
4647 if (virNetDevSetRcvMulti(ifname, false) < 0) {
4648 VIR_WARN("Couldn't set multicast flag to 'off' for "
4649 "device %s while responding to "
4650 "NIC_RX_FILTER_CHANGED",
4651 ifname);
4653 break;
4659 static void
4660 syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
4661 virNetDevRxFilterPtr hostFilter)
4663 syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
4664 syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
4668 static void
4669 syncNicRxFilterMulticast(char *ifname,
4670 virNetDevRxFilterPtr guestFilter,
4671 virNetDevRxFilterPtr hostFilter)
4673 syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
4674 syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
4677 static void
4678 processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
4679 virDomainObjPtr vm,
4680 const char *devAlias)
4682 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4683 qemuDomainObjPrivatePtr priv = vm->privateData;
4684 virDomainDeviceDef dev;
4685 virDomainNetDefPtr def;
4686 virNetDevRxFilterPtr guestFilter = NULL;
4687 virNetDevRxFilterPtr hostFilter = NULL;
4688 int ret;
4690 VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
4691 "from domain %p %s",
4692 devAlias, vm, vm->def->name);
4694 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4695 goto cleanup;
4697 if (!virDomainObjIsActive(vm)) {
4698 VIR_DEBUG("Domain is not running");
4699 goto endjob;
4702 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
4703 VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
4704 "non-existent device %s in domain %s",
4705 devAlias, vm->def->name);
4706 goto endjob;
4708 if (dev.type != VIR_DOMAIN_DEVICE_NET) {
4709 VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
4710 "non-network device %s in domain %s",
4711 devAlias, vm->def->name);
4712 goto endjob;
4714 def = dev.data.net;
4716 if (!virDomainNetGetActualTrustGuestRxFilters(def)) {
4717 VIR_DEBUG("ignore NIC_RX_FILTER_CHANGED event for network "
4718 "device %s in domain %s",
4719 def->info.alias, vm->def->name);
4720 /* not sending "query-rx-filter" will also suppress any
4721 * further NIC_RX_FILTER_CHANGED events for this device
4723 goto endjob;
4726 /* handle the event - send query-rx-filter and respond to it. */
4728 VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
4729 "device %s in domain %s", def->info.alias, vm->def->name);
4731 qemuDomainObjEnterMonitor(driver, vm);
4732 ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
4733 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4734 ret = -1;
4735 if (ret < 0)
4736 goto endjob;
4738 if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4740 if (virNetDevGetRxFilter(def->ifname, &hostFilter)) {
4741 VIR_WARN("Couldn't get current RX filter for device %s "
4742 "while responding to NIC_RX_FILTER_CHANGED",
4743 def->ifname);
4744 goto endjob;
4747 /* For macvtap connections, set the following macvtap network device
4748 * attributes to match those of the guest network device:
4749 * - MAC address
4750 * - Multicast MAC address table
4751 * - Device options:
4752 * - PROMISC
4753 * - MULTICAST
4754 * - ALLMULTI
4756 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
4757 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
4758 syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
4761 if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_NETWORK) {
4762 const char *brname = virDomainNetGetActualBridgeName(def);
4764 /* For libivrt network connections, set the following TUN/TAP network
4765 * device attributes to match those of the guest network device:
4766 * - QoS filters (which are based on MAC address)
4768 if (virDomainNetGetActualBandwidth(def) &&
4769 def->data.network.actual &&
4770 virNetDevBandwidthUpdateFilter(brname, &guestFilter->mac,
4771 def->data.network.actual->class_id) < 0)
4772 goto endjob;
4775 endjob:
4776 qemuDomainObjEndJob(driver, vm);
4778 cleanup:
4779 virNetDevRxFilterFree(hostFilter);
4780 virNetDevRxFilterFree(guestFilter);
4781 virObjectUnref(cfg);
4785 static void
4786 processSerialChangedEvent(virQEMUDriverPtr driver,
4787 virDomainObjPtr vm,
4788 const char *devAlias,
4789 bool connected)
4791 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4792 virDomainChrDeviceState newstate;
4793 virObjectEventPtr event = NULL;
4794 virDomainDeviceDef dev;
4795 qemuDomainObjPrivatePtr priv = vm->privateData;
4797 if (connected)
4798 newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
4799 else
4800 newstate = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
4802 VIR_DEBUG("Changing serial port state %s in domain %p %s",
4803 devAlias, vm, vm->def->name);
4805 if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED &&
4806 virDomainObjIsActive(vm) && priv->agent) {
4807 /* peek into the domain definition to find the channel */
4808 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) == 0 &&
4809 dev.type == VIR_DOMAIN_DEVICE_CHR &&
4810 dev.data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
4811 dev.data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
4812 STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0"))
4813 /* Close agent monitor early, so that other threads
4814 * waiting for the agent to reply can finish and our
4815 * job we acquire below can succeed. */
4816 qemuAgentNotifyClose(priv->agent);
4818 /* now discard the data, since it may possibly change once we unlock
4819 * while entering the job */
4820 memset(&dev, 0, sizeof(dev));
4823 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4824 goto cleanup;
4826 if (!virDomainObjIsActive(vm)) {
4827 VIR_DEBUG("Domain is not running");
4828 goto endjob;
4831 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
4832 goto endjob;
4834 /* we care only about certain devices */
4835 if (dev.type != VIR_DOMAIN_DEVICE_CHR ||
4836 dev.data.chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
4837 dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
4838 goto endjob;
4840 dev.data.chr->state = newstate;
4842 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
4843 VIR_WARN("unable to save status of domain %s after updating state of "
4844 "channel %s", vm->def->name, devAlias);
4846 if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0")) {
4847 if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED) {
4848 if (qemuConnectAgent(driver, vm) < 0)
4849 goto endjob;
4850 } else {
4851 if (priv->agent) {
4852 qemuAgentClose(priv->agent);
4853 priv->agent = NULL;
4855 priv->agentError = false;
4858 event = virDomainEventAgentLifecycleNewFromObj(vm, newstate,
4859 VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL);
4860 virObjectEventStateQueue(driver->domainEventState, event);
4863 endjob:
4864 qemuDomainObjEndJob(driver, vm);
4866 cleanup:
4867 virObjectUnref(cfg);
4871 static void
4872 processBlockJobEvent(virQEMUDriverPtr driver,
4873 virDomainObjPtr vm,
4874 const char *diskAlias,
4875 int type,
4876 int status)
4878 virDomainDiskDefPtr disk;
4879 qemuBlockJobDataPtr job = NULL;
4881 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4882 return;
4884 if (!virDomainObjIsActive(vm)) {
4885 VIR_DEBUG("Domain is not running");
4886 goto endjob;
4889 if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL))) {
4890 VIR_DEBUG("disk %s not found", diskAlias);
4891 goto endjob;
4894 if (!(job = qemuBlockJobDiskGetJob(disk))) {
4895 if (!(job = qemuBlockJobDiskNew(disk, type, diskAlias)))
4896 goto endjob;
4897 qemuBlockJobStarted(job);
4900 job->newstate = status;
4902 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
4904 endjob:
4905 qemuBlockJobStartupFinalize(job);
4906 qemuDomainObjEndJob(driver, vm);
4910 static void
4911 processMonitorEOFEvent(virQEMUDriverPtr driver,
4912 virDomainObjPtr vm)
4914 qemuDomainObjPrivatePtr priv = vm->privateData;
4915 int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
4916 int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
4917 const char *auditReason = "shutdown";
4918 unsigned int stopFlags = 0;
4919 virObjectEventPtr event = NULL;
4921 if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY, true) < 0)
4922 return;
4924 if (!virDomainObjIsActive(vm)) {
4925 VIR_DEBUG("Domain %p '%s' is not active, ignoring EOF",
4926 vm, vm->def->name);
4927 goto endjob;
4930 if (priv->monJSON &&
4931 virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTDOWN) {
4932 VIR_DEBUG("Monitor connection to '%s' closed without SHUTDOWN event; "
4933 "assuming the domain crashed", vm->def->name);
4934 eventReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
4935 stopReason = VIR_DOMAIN_SHUTOFF_CRASHED;
4936 auditReason = "failed";
4939 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
4940 stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
4941 qemuMigrationDstErrorSave(driver, vm->def->name,
4942 qemuMonitorLastError(priv->mon));
4945 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
4946 eventReason);
4947 qemuProcessStop(driver, vm, stopReason, QEMU_ASYNC_JOB_NONE, stopFlags);
4948 virDomainAuditStop(vm, auditReason);
4949 virObjectEventStateQueue(driver->domainEventState, event);
4951 endjob:
4952 qemuDomainRemoveInactive(driver, vm);
4953 qemuDomainObjEndJob(driver, vm);
4957 static void
4958 processPRDisconnectEvent(virDomainObjPtr vm)
4960 qemuDomainObjPrivatePtr priv = vm->privateData;
4962 if (!virDomainObjIsActive(vm))
4963 return;
4965 if (!priv->prDaemonRunning &&
4966 virDomainDefHasManagedPR(vm->def))
4967 qemuProcessStartManagedPRDaemon(vm);
4971 static void
4972 processRdmaGidStatusChangedEvent(virDomainObjPtr vm,
4973 qemuMonitorRdmaGidStatusPtr info)
4975 unsigned int prefix_len;
4976 virSocketAddr addr;
4977 VIR_AUTOFREE(char *) addrStr = NULL;
4978 int rc;
4980 if (!virDomainObjIsActive(vm))
4981 return;
4983 VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%llx, interface_id=0x%llx",
4984 info->netdev, info->gid_status, info->subnet_prefix,
4985 info->interface_id);
4987 if (info->subnet_prefix) {
4988 uint32_t ipv6[4] = {0};
4990 prefix_len = 64;
4991 memcpy(&ipv6[0], &info->subnet_prefix, sizeof(info->subnet_prefix));
4992 memcpy(&ipv6[2], &info->interface_id, sizeof(info->interface_id));
4993 virSocketAddrSetIPv6AddrNetOrder(&addr, ipv6);
4994 } else {
4995 prefix_len = 24;
4996 virSocketAddrSetIPv4AddrNetOrder(&addr, info->interface_id >> 32);
4999 if (!(addrStr = virSocketAddrFormat(&addr)))
5000 return;
5002 if (info->gid_status) {
5003 VIR_DEBUG("Adding %s to %s", addrStr, info->netdev);
5004 rc = virNetDevIPAddrAdd(info->netdev, &addr, NULL, prefix_len);
5005 } else {
5006 VIR_DEBUG("Removing %s from %s", addrStr, info->netdev);
5007 rc = virNetDevIPAddrDel(info->netdev, &addr, prefix_len);
5010 if (rc < 0)
5011 VIR_WARN("Fail to update address %s to %s", addrStr, info->netdev);
5015 static void qemuProcessEventHandler(void *data, void *opaque)
5017 struct qemuProcessEvent *processEvent = data;
5018 virDomainObjPtr vm = processEvent->vm;
5019 virQEMUDriverPtr driver = opaque;
5021 VIR_DEBUG("vm=%p, event=%d", vm, processEvent->eventType);
5023 virObjectLock(vm);
5025 switch (processEvent->eventType) {
5026 case QEMU_PROCESS_EVENT_WATCHDOG:
5027 processWatchdogEvent(driver, vm, processEvent->action);
5028 break;
5029 case QEMU_PROCESS_EVENT_GUESTPANIC:
5030 processGuestPanicEvent(driver, vm, processEvent->action,
5031 processEvent->data);
5032 break;
5033 case QEMU_PROCESS_EVENT_DEVICE_DELETED:
5034 processDeviceDeletedEvent(driver, vm, processEvent->data);
5035 break;
5036 case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
5037 processNicRxFilterChangedEvent(driver, vm, processEvent->data);
5038 break;
5039 case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
5040 processSerialChangedEvent(driver, vm, processEvent->data,
5041 processEvent->action);
5042 break;
5043 case QEMU_PROCESS_EVENT_BLOCK_JOB:
5044 processBlockJobEvent(driver, vm,
5045 processEvent->data,
5046 processEvent->action,
5047 processEvent->status);
5048 break;
5049 case QEMU_PROCESS_EVENT_MONITOR_EOF:
5050 processMonitorEOFEvent(driver, vm);
5051 break;
5052 case QEMU_PROCESS_EVENT_PR_DISCONNECT:
5053 processPRDisconnectEvent(vm);
5054 break;
5055 case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
5056 processRdmaGidStatusChangedEvent(vm, processEvent->data);
5057 break;
5058 case QEMU_PROCESS_EVENT_LAST:
5059 break;
5062 virDomainObjEndAPI(&vm);
5063 qemuProcessEventFree(processEvent);
5067 static int
5068 qemuDomainSetVcpusAgent(virDomainObjPtr vm,
5069 unsigned int nvcpus)
5071 qemuAgentCPUInfoPtr cpuinfo = NULL;
5072 qemuAgentPtr agent;
5073 int ncpuinfo;
5074 int ret = -1;
5076 if (!qemuDomainAgentAvailable(vm, true))
5077 goto cleanup;
5079 if (nvcpus > virDomainDefGetVcpus(vm->def)) {
5080 virReportError(VIR_ERR_INVALID_ARG,
5081 _("requested vcpu count is greater than the count "
5082 "of enabled vcpus in the domain: %d > %d"),
5083 nvcpus, virDomainDefGetVcpus(vm->def));
5084 goto cleanup;
5087 agent = qemuDomainObjEnterAgent(vm);
5088 ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
5089 qemuDomainObjExitAgent(vm, agent);
5090 agent = NULL;
5092 if (ncpuinfo < 0)
5093 goto cleanup;
5095 if (qemuAgentUpdateCPUInfo(nvcpus, cpuinfo, ncpuinfo) < 0)
5096 goto cleanup;
5098 if (!qemuDomainAgentAvailable(vm, true))
5099 goto cleanup;
5101 agent = qemuDomainObjEnterAgent(vm);
5102 ret = qemuAgentSetVCPUs(agent, cpuinfo, ncpuinfo);
5103 qemuDomainObjExitAgent(vm, agent);
5105 cleanup:
5106 VIR_FREE(cpuinfo);
5108 return ret;
5112 static int
5113 qemuDomainSetVcpusMax(virQEMUDriverPtr driver,
5114 virDomainDefPtr def,
5115 virDomainDefPtr persistentDef,
5116 unsigned int nvcpus)
5118 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
5119 unsigned int topologycpus;
5120 int ret = -1;
5122 if (def) {
5123 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
5124 _("maximum vcpu count of a live domain can't be modified"));
5125 goto cleanup;
5128 if (virDomainNumaGetCPUCountTotal(persistentDef->numa) > nvcpus) {
5129 virReportError(VIR_ERR_INVALID_ARG, "%s",
5130 _("Number of CPUs in <numa> exceeds the desired "
5131 "maximum vcpu count"));
5132 goto cleanup;
5135 if (virDomainDefGetVcpusTopology(persistentDef, &topologycpus) == 0 &&
5136 nvcpus != topologycpus) {
5137 /* allow setting a valid vcpu count for the topology so an invalid
5138 * setting may be corrected via this API */
5139 virReportError(VIR_ERR_INVALID_ARG, "%s",
5140 _("CPU topology doesn't match the desired vcpu count"));
5141 goto cleanup;
5144 /* ordering information may become invalid, thus clear it */
5145 virDomainDefVcpuOrderClear(persistentDef);
5147 if (virDomainDefSetVcpusMax(persistentDef, nvcpus, driver->xmlopt) < 0)
5148 goto cleanup;
5150 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
5151 goto cleanup;
5153 ret = 0;
5155 cleanup:
5156 virObjectUnref(cfg);
5157 return ret;
5161 static int
5162 qemuDomainSetVcpusFlags(virDomainPtr dom,
5163 unsigned int nvcpus,
5164 unsigned int flags)
5166 virQEMUDriverPtr driver = dom->conn->privateData;
5167 virDomainObjPtr vm = NULL;
5168 virDomainDefPtr def;
5169 virDomainDefPtr persistentDef;
5170 bool hotpluggable = !!(flags & VIR_DOMAIN_VCPU_HOTPLUGGABLE);
5171 bool useAgent = !!(flags & VIR_DOMAIN_VCPU_GUEST);
5172 qemuDomainJob job = QEMU_JOB_NONE;
5173 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
5174 int ret = -1;
5176 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5177 VIR_DOMAIN_AFFECT_CONFIG |
5178 VIR_DOMAIN_VCPU_MAXIMUM |
5179 VIR_DOMAIN_VCPU_GUEST |
5180 VIR_DOMAIN_VCPU_HOTPLUGGABLE, -1);
5182 if (!(vm = qemuDomObjFromDomain(dom)))
5183 goto cleanup;
5185 if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5186 goto cleanup;
5188 if (useAgent)
5189 agentJob = QEMU_AGENT_JOB_MODIFY;
5190 else
5191 job = QEMU_JOB_MODIFY;
5193 if (qemuDomainObjBeginJobWithAgent(driver, vm, job, agentJob) < 0)
5194 goto cleanup;
5196 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5197 goto endjob;
5199 if (useAgent)
5200 ret = qemuDomainSetVcpusAgent(vm, nvcpus);
5201 else if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
5202 ret = qemuDomainSetVcpusMax(driver, def, persistentDef, nvcpus);
5203 else
5204 ret = qemuDomainSetVcpusInternal(driver, vm, def, persistentDef,
5205 nvcpus, hotpluggable);
5207 endjob:
5208 if (agentJob)
5209 qemuDomainObjEndAgentJob(vm);
5210 else
5211 qemuDomainObjEndJob(driver, vm);
5213 cleanup:
5214 virDomainObjEndAPI(&vm);
5215 return ret;
5219 static int
5220 qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
5222 return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
5226 static int
5227 qemuDomainPinVcpuLive(virDomainObjPtr vm,
5228 virDomainDefPtr def,
5229 int vcpu,
5230 virQEMUDriverPtr driver,
5231 virQEMUDriverConfigPtr cfg,
5232 virBitmapPtr cpumap)
5234 virBitmapPtr tmpmap = NULL;
5235 virDomainVcpuDefPtr vcpuinfo;
5236 qemuDomainObjPrivatePtr priv = vm->privateData;
5237 virCgroupPtr cgroup_vcpu = NULL;
5238 char *str = NULL;
5239 virObjectEventPtr event = NULL;
5240 char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
5241 virTypedParameterPtr eventParams = NULL;
5242 int eventNparams = 0;
5243 int eventMaxparams = 0;
5244 int ret = -1;
5246 if (!qemuDomainHasVcpuPids(vm)) {
5247 virReportError(VIR_ERR_OPERATION_INVALID,
5248 "%s", _("cpu affinity is not supported"));
5249 goto cleanup;
5252 if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
5253 virReportError(VIR_ERR_INVALID_ARG,
5254 _("vcpu %d is out of range of live cpu count %d"),
5255 vcpu, virDomainDefGetVcpusMax(def));
5256 goto cleanup;
5259 if (!(tmpmap = virBitmapNewCopy(cpumap)))
5260 goto cleanup;
5262 if (!(str = virBitmapFormat(cpumap)))
5263 goto cleanup;
5265 if (vcpuinfo->online) {
5266 /* Configure the corresponding cpuset cgroup before set affinity. */
5267 if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
5268 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
5269 false, &cgroup_vcpu) < 0)
5270 goto cleanup;
5271 if (qemuSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
5272 goto cleanup;
5275 if (virProcessSetAffinity(qemuDomainGetVcpuPid(vm, vcpu), cpumap) < 0)
5276 goto cleanup;
5279 virBitmapFree(vcpuinfo->cpumask);
5280 vcpuinfo->cpumask = tmpmap;
5281 tmpmap = NULL;
5283 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5284 goto cleanup;
5286 if (snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
5287 VIR_DOMAIN_TUNABLE_CPU_VCPUPIN, vcpu) < 0) {
5288 goto cleanup;
5291 if (virTypedParamsAddString(&eventParams, &eventNparams,
5292 &eventMaxparams, paramField, str) < 0)
5293 goto cleanup;
5295 event = virDomainEventTunableNewFromObj(vm, eventParams, eventNparams);
5297 ret = 0;
5299 cleanup:
5300 virBitmapFree(tmpmap);
5301 virCgroupFree(&cgroup_vcpu);
5302 VIR_FREE(str);
5303 virObjectEventStateQueue(driver->domainEventState, event);
5304 return ret;
5308 static int
5309 qemuDomainPinVcpuFlags(virDomainPtr dom,
5310 unsigned int vcpu,
5311 unsigned char *cpumap,
5312 int maplen,
5313 unsigned int flags)
5315 virQEMUDriverPtr driver = dom->conn->privateData;
5316 virDomainObjPtr vm;
5317 virDomainDefPtr def;
5318 virDomainDefPtr persistentDef;
5319 int ret = -1;
5320 virBitmapPtr pcpumap = NULL;
5321 virDomainVcpuDefPtr vcpuinfo = NULL;
5322 virQEMUDriverConfigPtr cfg = NULL;
5324 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5325 VIR_DOMAIN_AFFECT_CONFIG, -1);
5327 cfg = virQEMUDriverGetConfig(driver);
5329 if (!(vm = qemuDomObjFromDomain(dom)))
5330 goto cleanup;
5332 if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5333 goto cleanup;
5335 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5336 goto cleanup;
5338 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5339 goto endjob;
5341 if (persistentDef &&
5342 !(vcpuinfo = virDomainDefGetVcpu(persistentDef, vcpu))) {
5343 virReportError(VIR_ERR_INVALID_ARG,
5344 _("vcpu %d is out of range of persistent cpu count %d"),
5345 vcpu, virDomainDefGetVcpus(persistentDef));
5346 goto endjob;
5349 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5350 goto endjob;
5352 if (virBitmapIsAllClear(pcpumap)) {
5353 virReportError(VIR_ERR_INVALID_ARG, "%s",
5354 _("Empty cpu list for pinning"));
5355 goto endjob;
5358 if (def &&
5359 qemuDomainPinVcpuLive(vm, def, vcpu, driver, cfg, pcpumap) < 0)
5360 goto endjob;
5362 if (persistentDef) {
5363 virBitmapFree(vcpuinfo->cpumask);
5364 vcpuinfo->cpumask = pcpumap;
5365 pcpumap = NULL;
5367 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
5368 goto endjob;
5371 ret = 0;
5373 endjob:
5374 qemuDomainObjEndJob(driver, vm);
5376 cleanup:
5377 virDomainObjEndAPI(&vm);
5378 virBitmapFree(pcpumap);
5379 virObjectUnref(cfg);
5380 return ret;
5383 static int
5384 qemuDomainPinVcpu(virDomainPtr dom,
5385 unsigned int vcpu,
5386 unsigned char *cpumap,
5387 int maplen)
5389 return qemuDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
5390 VIR_DOMAIN_AFFECT_LIVE);
5393 static int
5394 qemuDomainGetVcpuPinInfo(virDomainPtr dom,
5395 int ncpumaps,
5396 unsigned char *cpumaps,
5397 int maplen,
5398 unsigned int flags)
5400 virDomainObjPtr vm = NULL;
5401 virDomainDefPtr def;
5402 bool live;
5403 int ret = -1;
5404 virBitmapPtr autoCpuset = NULL;
5406 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5407 VIR_DOMAIN_AFFECT_CONFIG, -1);
5409 if (!(vm = qemuDomObjFromDomain(dom)))
5410 goto cleanup;
5412 if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
5413 goto cleanup;
5415 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
5416 goto cleanup;
5418 if (live)
5419 autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
5421 ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
5422 virHostCPUGetCount(), autoCpuset);
5423 cleanup:
5424 virDomainObjEndAPI(&vm);
5425 return ret;
5428 static int
5429 qemuDomainPinEmulator(virDomainPtr dom,
5430 unsigned char *cpumap,
5431 int maplen,
5432 unsigned int flags)
5434 virQEMUDriverPtr driver = dom->conn->privateData;
5435 virDomainObjPtr vm;
5436 virCgroupPtr cgroup_emulator = NULL;
5437 virDomainDefPtr def;
5438 virDomainDefPtr persistentDef;
5439 int ret = -1;
5440 qemuDomainObjPrivatePtr priv;
5441 virBitmapPtr pcpumap = NULL;
5442 virQEMUDriverConfigPtr cfg = NULL;
5443 virObjectEventPtr event = NULL;
5444 char *str = NULL;
5445 virTypedParameterPtr eventParams = NULL;
5446 int eventNparams = 0;
5447 int eventMaxparams = 0;
5449 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5450 VIR_DOMAIN_AFFECT_CONFIG, -1);
5452 cfg = virQEMUDriverGetConfig(driver);
5454 if (!(vm = qemuDomObjFromDomain(dom)))
5455 goto cleanup;
5457 if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
5458 goto cleanup;
5460 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5461 goto cleanup;
5463 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5464 goto endjob;
5466 priv = vm->privateData;
5468 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5469 goto endjob;
5471 if (virBitmapIsAllClear(pcpumap)) {
5472 virReportError(VIR_ERR_INVALID_ARG, "%s",
5473 _("Empty cpu list for pinning"));
5474 goto endjob;
5477 if (def) {
5478 if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
5479 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
5480 0, false, &cgroup_emulator) < 0)
5481 goto endjob;
5483 if (qemuSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
5484 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5485 _("failed to set cpuset.cpus in cgroup"
5486 " for emulator threads"));
5487 goto endjob;
5491 if (virProcessSetAffinity(vm->pid, pcpumap) < 0)
5492 goto endjob;
5494 virBitmapFree(def->cputune.emulatorpin);
5495 def->cputune.emulatorpin = NULL;
5497 if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
5498 goto endjob;
5500 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5501 goto endjob;
5503 str = virBitmapFormat(pcpumap);
5504 if (virTypedParamsAddString(&eventParams, &eventNparams,
5505 &eventMaxparams,
5506 VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
5507 str) < 0)
5508 goto endjob;
5510 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
5513 if (persistentDef) {
5514 virBitmapFree(persistentDef->cputune.emulatorpin);
5515 persistentDef->cputune.emulatorpin = NULL;
5517 if (!(persistentDef->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
5518 goto endjob;
5520 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
5521 goto endjob;
5524 ret = 0;
5526 endjob:
5527 qemuDomainObjEndJob(driver, vm);
5529 cleanup:
5530 if (cgroup_emulator)
5531 virCgroupFree(&cgroup_emulator);
5532 virObjectEventStateQueue(driver->domainEventState, event);
5533 VIR_FREE(str);
5534 virBitmapFree(pcpumap);
5535 virDomainObjEndAPI(&vm);
5536 virObjectUnref(cfg);
5537 return ret;
5540 static int
5541 qemuDomainGetEmulatorPinInfo(virDomainPtr dom,
5542 unsigned char *cpumaps,
5543 int maplen,
5544 unsigned int flags)
5546 virDomainObjPtr vm = NULL;
5547 virDomainDefPtr def;
5548 bool live;
5549 int ret = -1;
5550 int hostcpus;
5551 virBitmapPtr cpumask = NULL;
5552 virBitmapPtr bitmap = NULL;
5553 virBitmapPtr autoCpuset = NULL;
5555 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5556 VIR_DOMAIN_AFFECT_CONFIG, -1);
5558 if (!(vm = qemuDomObjFromDomain(dom)))
5559 goto cleanup;
5561 if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
5562 goto cleanup;
5564 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
5565 goto cleanup;
5567 if ((hostcpus = virHostCPUGetCount()) < 0)
5568 goto cleanup;
5570 if (live)
5571 autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
5573 if (def->cputune.emulatorpin) {
5574 cpumask = def->cputune.emulatorpin;
5575 } else if (def->cpumask) {
5576 cpumask = def->cpumask;
5577 } else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
5578 autoCpuset) {
5579 cpumask = autoCpuset;
5580 } else {
5581 if (!(bitmap = virBitmapNew(hostcpus)))
5582 goto cleanup;
5583 virBitmapSetAll(bitmap);
5584 cpumask = bitmap;
5587 virBitmapToDataBuf(cpumask, cpumaps, maplen);
5589 ret = 1;
5591 cleanup:
5592 virDomainObjEndAPI(&vm);
5593 virBitmapFree(bitmap);
5594 return ret;
5597 static int
5598 qemuDomainGetVcpus(virDomainPtr dom,
5599 virVcpuInfoPtr info,
5600 int maxinfo,
5601 unsigned char *cpumaps,
5602 int maplen)
5604 virDomainObjPtr vm;
5605 int ret = -1;
5607 if (!(vm = qemuDomObjFromDomain(dom)))
5608 goto cleanup;
5610 if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
5611 goto cleanup;
5613 if (!virDomainObjIsActive(vm)) {
5614 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5615 _("cannot retrieve vcpu information for inactive domain"));
5616 goto cleanup;
5619 ret = qemuDomainHelperGetVcpus(vm, info, NULL, maxinfo, cpumaps, maplen);
5621 cleanup:
5622 virDomainObjEndAPI(&vm);
5623 return ret;
5627 static int
5628 qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
5630 virQEMUDriverPtr driver = dom->conn->privateData;
5631 virDomainObjPtr vm;
5632 virDomainDefPtr def;
5633 int ret = -1;
5634 qemuAgentCPUInfoPtr cpuinfo = NULL;
5635 qemuAgentPtr agent;
5636 int ncpuinfo = -1;
5637 size_t i;
5639 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5640 VIR_DOMAIN_AFFECT_CONFIG |
5641 VIR_DOMAIN_VCPU_MAXIMUM |
5642 VIR_DOMAIN_VCPU_GUEST, -1);
5644 if (!(vm = qemuDomObjFromDomain(dom)))
5645 return -1;
5647 if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5648 goto cleanup;
5650 if (!(def = virDomainObjGetOneDef(vm, flags)))
5651 goto cleanup;
5653 if (flags & VIR_DOMAIN_VCPU_GUEST) {
5654 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
5655 goto cleanup;
5657 if (!virDomainObjIsActive(vm)) {
5658 virReportError(VIR_ERR_INVALID_ARG, "%s",
5659 _("vCPU count provided by the guest agent can only be "
5660 "requested for live domains"));
5661 goto endjob;
5664 if (!qemuDomainAgentAvailable(vm, true))
5665 goto endjob;
5667 agent = qemuDomainObjEnterAgent(vm);
5668 ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
5669 qemuDomainObjExitAgent(vm, agent);
5671 endjob:
5672 qemuDomainObjEndAgentJob(vm);
5674 if (ncpuinfo < 0)
5675 goto cleanup;
5677 if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
5678 ret = ncpuinfo;
5679 goto cleanup;
5682 /* count the online vcpus */
5683 ret = 0;
5684 for (i = 0; i < ncpuinfo; i++) {
5685 if (cpuinfo[i].online)
5686 ret++;
5688 } else {
5689 if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
5690 ret = virDomainDefGetVcpusMax(def);
5691 else
5692 ret = virDomainDefGetVcpus(def);
5696 cleanup:
5697 virDomainObjEndAPI(&vm);
5698 VIR_FREE(cpuinfo);
5699 return ret;
5702 static int
5703 qemuDomainGetMaxVcpus(virDomainPtr dom)
5705 return qemuDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
5706 VIR_DOMAIN_VCPU_MAXIMUM));
5710 static int
5711 qemuDomainGetIOThreadsMon(virQEMUDriverPtr driver,
5712 virDomainObjPtr vm,
5713 qemuMonitorIOThreadInfoPtr **iothreads)
5715 qemuDomainObjPrivatePtr priv = vm->privateData;
5716 int niothreads = 0;
5718 qemuDomainObjEnterMonitor(driver, vm);
5719 niothreads = qemuMonitorGetIOThreads(priv->mon, iothreads);
5720 if (qemuDomainObjExitMonitor(driver, vm) < 0 || niothreads < 0)
5721 return -1;
5723 return niothreads;
5727 static int
5728 qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
5729 virDomainObjPtr vm,
5730 virDomainIOThreadInfoPtr **info)
5732 qemuDomainObjPrivatePtr priv;
5733 qemuMonitorIOThreadInfoPtr *iothreads = NULL;
5734 virDomainIOThreadInfoPtr *info_ret = NULL;
5735 int niothreads = 0;
5736 size_t i;
5737 int ret = -1;
5739 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
5740 goto cleanup;
5742 if (!virDomainObjIsActive(vm)) {
5743 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5744 _("cannot list IOThreads for an inactive domain"));
5745 goto endjob;
5748 priv = vm->privateData;
5749 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
5750 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5751 _("IOThreads not supported with this binary"));
5752 goto endjob;
5755 if ((niothreads = qemuDomainGetIOThreadsMon(driver, vm, &iothreads)) < 0)
5756 goto endjob;
5758 /* Nothing to do */
5759 if (niothreads == 0) {
5760 ret = 0;
5761 goto endjob;
5764 if (VIR_ALLOC_N(info_ret, niothreads) < 0)
5765 goto endjob;
5767 for (i = 0; i < niothreads; i++) {
5768 virBitmapPtr map = NULL;
5770 if (VIR_ALLOC(info_ret[i]) < 0)
5771 goto endjob;
5772 info_ret[i]->iothread_id = iothreads[i]->iothread_id;
5774 if (!(map = virProcessGetAffinity(iothreads[i]->thread_id)))
5775 goto endjob;
5777 if (virBitmapToData(map, &info_ret[i]->cpumap,
5778 &info_ret[i]->cpumaplen) < 0) {
5779 virBitmapFree(map);
5780 goto endjob;
5782 virBitmapFree(map);
5785 VIR_STEAL_PTR(*info, info_ret);
5786 ret = niothreads;
5788 endjob:
5789 qemuDomainObjEndJob(driver, vm);
5791 cleanup:
5792 if (info_ret) {
5793 for (i = 0; i < niothreads; i++)
5794 virDomainIOThreadInfoFree(info_ret[i]);
5795 VIR_FREE(info_ret);
5797 if (iothreads) {
5798 for (i = 0; i < niothreads; i++)
5799 VIR_FREE(iothreads[i]);
5800 VIR_FREE(iothreads);
5803 return ret;
5806 static int
5807 qemuDomainGetIOThreadsConfig(virDomainDefPtr targetDef,
5808 virDomainIOThreadInfoPtr **info)
5810 virDomainIOThreadInfoPtr *info_ret = NULL;
5811 virBitmapPtr bitmap = NULL;
5812 virBitmapPtr cpumask = NULL;
5813 int hostcpus;
5814 size_t i;
5815 int ret = -1;
5817 if (targetDef->niothreadids == 0)
5818 return 0;
5820 if ((hostcpus = virHostCPUGetCount()) < 0)
5821 goto cleanup;
5823 if (VIR_ALLOC_N(info_ret, targetDef->niothreadids) < 0)
5824 goto cleanup;
5826 for (i = 0; i < targetDef->niothreadids; i++) {
5827 if (VIR_ALLOC(info_ret[i]) < 0)
5828 goto cleanup;
5830 /* IOThread ID's are taken from the iothreadids list */
5831 info_ret[i]->iothread_id = targetDef->iothreadids[i]->iothread_id;
5833 cpumask = targetDef->iothreadids[i]->cpumask;
5834 if (!cpumask) {
5835 if (targetDef->cpumask) {
5836 cpumask = targetDef->cpumask;
5837 } else {
5838 if (!(bitmap = virBitmapNew(hostcpus)))
5839 goto cleanup;
5840 virBitmapSetAll(bitmap);
5841 cpumask = bitmap;
5844 if (virBitmapToData(cpumask, &info_ret[i]->cpumap,
5845 &info_ret[i]->cpumaplen) < 0)
5846 goto cleanup;
5847 virBitmapFree(bitmap);
5848 bitmap = NULL;
5851 *info = info_ret;
5852 info_ret = NULL;
5853 ret = targetDef->niothreadids;
5855 cleanup:
5856 if (info_ret) {
5857 for (i = 0; i < targetDef->niothreadids; i++)
5858 virDomainIOThreadInfoFree(info_ret[i]);
5859 VIR_FREE(info_ret);
5861 virBitmapFree(bitmap);
5863 return ret;
5866 static int
5867 qemuDomainGetIOThreadInfo(virDomainPtr dom,
5868 virDomainIOThreadInfoPtr **info,
5869 unsigned int flags)
5871 virQEMUDriverPtr driver = dom->conn->privateData;
5872 virDomainObjPtr vm;
5873 virDomainDefPtr targetDef = NULL;
5874 int ret = -1;
5876 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5877 VIR_DOMAIN_AFFECT_CONFIG, -1);
5879 if (!(vm = qemuDomObjFromDomain(dom)))
5880 goto cleanup;
5882 if (virDomainGetIOThreadInfoEnsureACL(dom->conn, vm->def) < 0)
5883 goto cleanup;
5885 if (virDomainObjGetDefs(vm, flags, NULL, &targetDef) < 0)
5886 goto cleanup;
5888 if (!targetDef)
5889 ret = qemuDomainGetIOThreadsLive(driver, vm, info);
5890 else
5891 ret = qemuDomainGetIOThreadsConfig(targetDef, info);
5893 cleanup:
5894 virDomainObjEndAPI(&vm);
5895 return ret;
5898 static int
5899 qemuDomainPinIOThread(virDomainPtr dom,
5900 unsigned int iothread_id,
5901 unsigned char *cpumap,
5902 int maplen,
5903 unsigned int flags)
5905 int ret = -1;
5906 virQEMUDriverPtr driver = dom->conn->privateData;
5907 virQEMUDriverConfigPtr cfg = NULL;
5908 virDomainObjPtr vm;
5909 virDomainDefPtr def;
5910 virDomainDefPtr persistentDef;
5911 virBitmapPtr pcpumap = NULL;
5912 qemuDomainObjPrivatePtr priv;
5913 virCgroupPtr cgroup_iothread = NULL;
5914 virObjectEventPtr event = NULL;
5915 char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
5916 char *str = NULL;
5917 virTypedParameterPtr eventParams = NULL;
5918 int eventNparams = 0;
5919 int eventMaxparams = 0;
5921 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5922 VIR_DOMAIN_AFFECT_CONFIG, -1);
5924 cfg = virQEMUDriverGetConfig(driver);
5926 if (!(vm = qemuDomObjFromDomain(dom)))
5927 goto cleanup;
5928 priv = vm->privateData;
5930 if (virDomainPinIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
5931 goto cleanup;
5933 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5934 goto cleanup;
5936 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5937 goto endjob;
5939 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5940 goto endjob;
5942 if (virBitmapIsAllClear(pcpumap)) {
5943 virReportError(VIR_ERR_INVALID_ARG, "%s",
5944 _("Empty iothread cpumap list for pinning"));
5945 goto endjob;
5948 if (def) {
5949 virDomainIOThreadIDDefPtr iothrid;
5950 virBitmapPtr cpumask;
5952 if (!(iothrid = virDomainIOThreadIDFind(def, iothread_id))) {
5953 virReportError(VIR_ERR_INVALID_ARG,
5954 _("iothread %d not found"), iothread_id);
5955 goto endjob;
5958 if (!(cpumask = virBitmapNewData(cpumap, maplen)))
5959 goto endjob;
5961 virBitmapFree(iothrid->cpumask);
5962 iothrid->cpumask = cpumask;
5963 iothrid->autofill = false;
5965 /* Configure the corresponding cpuset cgroup before set affinity. */
5966 if (virCgroupHasController(priv->cgroup,
5967 VIR_CGROUP_CONTROLLER_CPUSET)) {
5968 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
5969 iothread_id, false, &cgroup_iothread) < 0)
5970 goto endjob;
5971 if (qemuSetupCgroupCpusetCpus(cgroup_iothread, pcpumap) < 0) {
5972 virReportError(VIR_ERR_OPERATION_INVALID,
5973 _("failed to set cpuset.cpus in cgroup"
5974 " for iothread %d"), iothread_id);
5975 goto endjob;
5979 if (virProcessSetAffinity(iothrid->thread_id, pcpumap) < 0)
5980 goto endjob;
5982 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5983 goto endjob;
5985 if (snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
5986 VIR_DOMAIN_TUNABLE_CPU_IOTHREADSPIN, iothread_id) < 0) {
5987 goto endjob;
5990 str = virBitmapFormat(pcpumap);
5991 if (virTypedParamsAddString(&eventParams, &eventNparams,
5992 &eventMaxparams, paramField, str) < 0)
5993 goto endjob;
5995 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
5998 if (persistentDef) {
5999 virDomainIOThreadIDDefPtr iothrid;
6000 virBitmapPtr cpumask;
6002 if (!(iothrid = virDomainIOThreadIDFind(persistentDef, iothread_id))) {
6003 virReportError(VIR_ERR_INVALID_ARG,
6004 _("iothreadid %d not found"), iothread_id);
6005 goto endjob;
6008 if (!(cpumask = virBitmapNewData(cpumap, maplen)))
6009 goto endjob;
6011 virBitmapFree(iothrid->cpumask);
6012 iothrid->cpumask = cpumask;
6013 iothrid->autofill = false;
6015 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
6016 goto endjob;
6019 ret = 0;
6021 endjob:
6022 qemuDomainObjEndJob(driver, vm);
6024 cleanup:
6025 if (cgroup_iothread)
6026 virCgroupFree(&cgroup_iothread);
6027 virObjectEventStateQueue(driver->domainEventState, event);
6028 VIR_FREE(str);
6029 virBitmapFree(pcpumap);
6030 virDomainObjEndAPI(&vm);
6031 virObjectUnref(cfg);
6032 return ret;
6035 static int
6036 qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
6037 virDomainObjPtr vm,
6038 unsigned int iothread_id)
6040 qemuDomainObjPrivatePtr priv = vm->privateData;
6041 char *alias = NULL;
6042 size_t idx;
6043 int ret = -1;
6044 unsigned int orig_niothreads = vm->def->niothreadids;
6045 unsigned int exp_niothreads = vm->def->niothreadids;
6046 int new_niothreads = 0;
6047 qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
6048 virDomainIOThreadIDDefPtr iothrid;
6049 virJSONValuePtr props = NULL;
6051 if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
6052 return -1;
6054 if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0)
6055 goto cleanup;
6057 qemuDomainObjEnterMonitor(driver, vm);
6059 if (qemuMonitorAddObject(priv->mon, &props, NULL) < 0)
6060 goto exit_monitor;
6062 exp_niothreads++;
6064 /* After hotplugging the IOThreads we need to re-detect the
6065 * IOThreads thread_id's, adjust the cgroups, thread affinity,
6066 * and add the thread_id to the vm->def->iothreadids list.
6068 if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
6069 &new_iothreads)) < 0)
6070 goto exit_monitor;
6072 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6073 goto cleanup;
6075 if (new_niothreads != exp_niothreads) {
6076 virReportError(VIR_ERR_INTERNAL_ERROR,
6077 _("got wrong number of IOThread ids from QEMU monitor. "
6078 "got %d, wanted %d"),
6079 new_niothreads, exp_niothreads);
6080 goto cleanup;
6084 * If we've successfully added an IOThread, find out where we added it
6085 * in the QEMU IOThread list, so we can add it to our iothreadids list
6087 for (idx = 0; idx < new_niothreads; idx++) {
6088 if (new_iothreads[idx]->iothread_id == iothread_id)
6089 break;
6092 if (idx == new_niothreads) {
6093 virReportError(VIR_ERR_INTERNAL_ERROR,
6094 _("cannot find new IOThread '%u' in QEMU monitor."),
6095 iothread_id);
6096 goto cleanup;
6099 if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id)))
6100 goto cleanup;
6102 iothrid->thread_id = new_iothreads[idx]->thread_id;
6104 if (qemuProcessSetupIOThread(vm, iothrid) < 0)
6105 goto cleanup;
6107 ret = 0;
6109 cleanup:
6110 if (new_iothreads) {
6111 for (idx = 0; idx < new_niothreads; idx++)
6112 VIR_FREE(new_iothreads[idx]);
6113 VIR_FREE(new_iothreads);
6115 virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
6116 "update", ret == 0);
6117 VIR_FREE(alias);
6118 virJSONValueFree(props);
6119 return ret;
6121 exit_monitor:
6122 ignore_value(qemuDomainObjExitMonitor(driver, vm));
6123 goto cleanup;
6127 static int
6128 qemuDomainHotplugModIOThread(virQEMUDriverPtr driver,
6129 virDomainObjPtr vm,
6130 qemuMonitorIOThreadInfo iothread)
6132 qemuDomainObjPrivatePtr priv = vm->privateData;
6133 int rc;
6135 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) {
6136 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6137 _("IOThreads polling is not supported for this QEMU"));
6138 return -1;
6141 qemuDomainObjEnterMonitor(driver, vm);
6143 rc = qemuMonitorSetIOThread(priv->mon, &iothread);
6145 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6146 return -1;
6148 if (rc < 0)
6149 return -1;
6151 return 0;
6155 static int
6156 qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
6157 virDomainObjPtr vm,
6158 unsigned int iothread_id)
6160 qemuDomainObjPrivatePtr priv = vm->privateData;
6161 size_t idx;
6162 char *alias = NULL;
6163 int rc = -1;
6164 int ret = -1;
6165 unsigned int orig_niothreads = vm->def->niothreadids;
6166 unsigned int exp_niothreads = vm->def->niothreadids;
6167 int new_niothreads = 0;
6168 qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
6170 if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
6171 return -1;
6173 qemuDomainObjEnterMonitor(driver, vm);
6175 rc = qemuMonitorDelObject(priv->mon, alias);
6176 exp_niothreads--;
6177 if (rc < 0)
6178 goto exit_monitor;
6180 if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
6181 &new_iothreads)) < 0)
6182 goto exit_monitor;
6184 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6185 goto cleanup;
6187 if (new_niothreads != exp_niothreads) {
6188 virReportError(VIR_ERR_INTERNAL_ERROR,
6189 _("got wrong number of IOThread ids from QEMU monitor. "
6190 "got %d, wanted %d"),
6191 new_niothreads, exp_niothreads);
6192 goto cleanup;
6195 virDomainIOThreadIDDel(vm->def, iothread_id);
6197 if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
6198 iothread_id) < 0)
6199 goto cleanup;
6201 ret = 0;
6203 cleanup:
6204 if (new_iothreads) {
6205 for (idx = 0; idx < new_niothreads; idx++)
6206 VIR_FREE(new_iothreads[idx]);
6207 VIR_FREE(new_iothreads);
6209 virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
6210 "update", rc == 0);
6211 VIR_FREE(alias);
6212 return ret;
6214 exit_monitor:
6215 ignore_value(qemuDomainObjExitMonitor(driver, vm));
6216 goto cleanup;
6220 static int
6221 qemuDomainAddIOThreadCheck(virDomainDefPtr def,
6222 unsigned int iothread_id)
6224 if (virDomainIOThreadIDFind(def, iothread_id)) {
6225 virReportError(VIR_ERR_INVALID_ARG,
6226 _("an IOThread is already using iothread_id '%u'"),
6227 iothread_id);
6228 return -1;
6231 return 0;
6235 static int
6236 qemuDomainDelIOThreadCheck(virDomainDefPtr def,
6237 unsigned int iothread_id)
6239 size_t i;
6241 if (!virDomainIOThreadIDFind(def, iothread_id)) {
6242 virReportError(VIR_ERR_INVALID_ARG,
6243 _("cannot find IOThread '%u' in iothreadids list"),
6244 iothread_id);
6245 return -1;
6248 for (i = 0; i < def->ndisks; i++) {
6249 if (def->disks[i]->iothread == iothread_id) {
6250 virReportError(VIR_ERR_INVALID_ARG,
6251 _("cannot remove IOThread %u since it "
6252 "is being used by disk '%s'"),
6253 iothread_id, def->disks[i]->dst);
6254 return -1;
6258 for (i = 0; i < def->ncontrollers; i++) {
6259 if (def->controllers[i]->iothread == iothread_id) {
6260 virReportError(VIR_ERR_INVALID_ARG,
6261 _("cannot remove IOThread '%u' since it "
6262 "is being used by controller"),
6263 iothread_id);
6264 return -1;
6268 return 0;
6273 * @params: Pointer to params list
6274 * @nparams: Number of params to be parsed
6275 * @iothread: Buffer to store the values
6277 * The following is a description of each value parsed:
6279 * - "poll-max-ns" for each IOThread is the maximum time in nanoseconds
6280 * to allow each polling interval to occur. A polling interval is a
6281 * period of time allowed for a thread to process data before it returns
6282 * the CPU quantum back to the host. A value set too small will not allow
6283 * the IOThread to run long enough on a CPU to process data. A value set
6284 * too high will consume too much CPU time per IOThread failing to allow
6285 * other threads running on the CPU to get time. A value of 0 (zero) will
6286 * disable the polling.
6288 * - "poll-grow" - factor to grow the current polling time when deemed
6289 * necessary. If a 0 (zero) value is provided, QEMU currently doubles
6290 * its polling interval unless the current value is greater than the
6291 * poll-max-ns.
6293 * - "poll-shrink" - divisor to reduced the current polling time when deemed
6294 * necessary. If a 0 (zero) value is provided, QEMU resets the polling
6295 * interval to 0 (zero) allowing the poll-grow to manipulate the time.
6297 * QEMU keeps track of the polling time elapsed and may grow or shrink the
6298 * its polling interval based upon its heuristic algorithm. It is possible
6299 * that calculations determine that it has found a "sweet spot" and no
6300 * adjustments are made. The polling time value is not available.
6302 * Returns 0 on success, -1 on failure with error set.
6304 static int
6305 qemuDomainIOThreadParseParams(virTypedParameterPtr params,
6306 int nparams,
6307 qemuMonitorIOThreadInfoPtr iothread)
6309 int rc;
6311 if (virTypedParamsValidate(params, nparams,
6312 VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
6313 VIR_TYPED_PARAM_ULLONG,
6314 VIR_DOMAIN_IOTHREAD_POLL_GROW,
6315 VIR_TYPED_PARAM_UINT,
6316 VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
6317 VIR_TYPED_PARAM_UINT,
6318 NULL) < 0)
6319 return -1;
6321 if ((rc = virTypedParamsGetULLong(params, nparams,
6322 VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
6323 &iothread->poll_max_ns)) < 0)
6324 return -1;
6325 if (rc == 1)
6326 iothread->set_poll_max_ns = true;
6328 if ((rc = virTypedParamsGetUInt(params, nparams,
6329 VIR_DOMAIN_IOTHREAD_POLL_GROW,
6330 &iothread->poll_grow)) < 0)
6331 return -1;
6332 if (rc == 1)
6333 iothread->set_poll_grow = true;
6335 if ((rc = virTypedParamsGetUInt(params, nparams,
6336 VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
6337 &iothread->poll_shrink)) < 0)
6338 return -1;
6339 if (rc == 1)
6340 iothread->set_poll_shrink = true;
6342 if (iothread->set_poll_max_ns && iothread->poll_max_ns > INT_MAX) {
6343 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6344 _("poll-max-ns (%llu) must be less than or equal to %d"),
6345 iothread->poll_max_ns, INT_MAX);
6346 return -1;
6349 if (iothread->set_poll_grow && iothread->poll_grow > INT_MAX) {
6350 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6351 _("poll-grow (%u) must be less than or equal to %d"),
6352 iothread->poll_grow, INT_MAX);
6353 return -1;
6356 if (iothread->set_poll_shrink && iothread->poll_shrink > INT_MAX) {
6357 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6358 _("poll-shrink (%u) must be less than or equal to %d"),
6359 iothread->poll_shrink, INT_MAX);
6360 return -1;
6363 return 0;
6367 typedef enum {
6368 VIR_DOMAIN_IOTHREAD_ACTION_ADD,
6369 VIR_DOMAIN_IOTHREAD_ACTION_DEL,
6370 VIR_DOMAIN_IOTHREAD_ACTION_MOD,
6371 } virDomainIOThreadAction;
6373 static int
6374 qemuDomainChgIOThread(virQEMUDriverPtr driver,
6375 virDomainObjPtr vm,
6376 qemuMonitorIOThreadInfo iothread,
6377 virDomainIOThreadAction action,
6378 unsigned int flags)
6380 virQEMUDriverConfigPtr cfg = NULL;
6381 qemuDomainObjPrivatePtr priv;
6382 virDomainDefPtr def;
6383 virDomainDefPtr persistentDef;
6384 int ret = -1;
6386 cfg = virQEMUDriverGetConfig(driver);
6388 priv = vm->privateData;
6390 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
6391 goto cleanup;
6393 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
6394 goto endjob;
6396 if (def) {
6397 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
6398 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6399 _("IOThreads not supported with this binary"));
6400 goto endjob;
6403 switch (action) {
6404 case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
6405 if (qemuDomainAddIOThreadCheck(def, iothread.iothread_id) < 0)
6406 goto endjob;
6408 if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
6409 goto endjob;
6411 break;
6413 case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
6414 if (qemuDomainDelIOThreadCheck(def, iothread.iothread_id) < 0)
6415 goto endjob;
6417 if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
6418 goto endjob;
6420 break;
6422 case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
6423 if (!(virDomainIOThreadIDFind(def, iothread.iothread_id))) {
6424 virReportError(VIR_ERR_INVALID_ARG,
6425 _("cannot find IOThread '%u' in iothreadids"),
6426 iothread.iothread_id);
6427 goto endjob;
6430 if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
6431 goto endjob;
6433 break;
6437 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
6438 goto endjob;
6441 if (persistentDef) {
6442 switch (action) {
6443 case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
6444 if (qemuDomainAddIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
6445 goto endjob;
6447 if (!virDomainIOThreadIDAdd(persistentDef, iothread.iothread_id))
6448 goto endjob;
6450 break;
6452 case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
6453 if (qemuDomainDelIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
6454 goto endjob;
6456 virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);
6458 break;
6460 case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
6461 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6462 _("configuring persistent polling values is "
6463 "not supported"));
6464 goto endjob;
6466 break;
6469 if (virDomainSaveConfig(cfg->configDir, driver->caps,
6470 persistentDef) < 0)
6471 goto endjob;
6474 ret = 0;
6476 endjob:
6477 qemuDomainObjEndJob(driver, vm);
6479 cleanup:
6480 virObjectUnref(cfg);
6481 return ret;
6484 static int
6485 qemuDomainAddIOThread(virDomainPtr dom,
6486 unsigned int iothread_id,
6487 unsigned int flags)
6489 virQEMUDriverPtr driver = dom->conn->privateData;
6490 virDomainObjPtr vm = NULL;
6491 qemuMonitorIOThreadInfo iothread = {0};
6492 int ret = -1;
6494 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6495 VIR_DOMAIN_AFFECT_CONFIG, -1);
6497 if (iothread_id == 0) {
6498 virReportError(VIR_ERR_INVALID_ARG, "%s",
6499 _("invalid value of 0 for iothread_id"));
6500 return -1;
6503 if (!(vm = qemuDomObjFromDomain(dom)))
6504 goto cleanup;
6506 if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
6507 goto cleanup;
6509 iothread.iothread_id = iothread_id;
6510 ret = qemuDomainChgIOThread(driver, vm, iothread,
6511 VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);
6513 cleanup:
6514 virDomainObjEndAPI(&vm);
6515 return ret;
6519 static int
6520 qemuDomainDelIOThread(virDomainPtr dom,
6521 unsigned int iothread_id,
6522 unsigned int flags)
6524 virQEMUDriverPtr driver = dom->conn->privateData;
6525 virDomainObjPtr vm = NULL;
6526 qemuMonitorIOThreadInfo iothread = {0};
6527 int ret = -1;
6529 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6530 VIR_DOMAIN_AFFECT_CONFIG, -1);
6532 if (iothread_id == 0) {
6533 virReportError(VIR_ERR_INVALID_ARG, "%s",
6534 _("invalid value of 0 for iothread_id"));
6535 return -1;
6538 if (!(vm = qemuDomObjFromDomain(dom)))
6539 goto cleanup;
6541 if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
6542 goto cleanup;
6544 iothread.iothread_id = iothread_id;
6545 ret = qemuDomainChgIOThread(driver, vm, iothread,
6546 VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);
6548 cleanup:
6549 virDomainObjEndAPI(&vm);
6550 return ret;
6555 * @dom: Domain to set IOThread params
6556 * @iothread_id: IOThread 'id' that will be modified
6557 * @params: List of parameters to change
6558 * @nparams: Number of parameters in the list
6559 * @flags: Flags for the set (only supports live alteration)
6561 * Alter the specified @iothread_id with the values provided.
6563 * Returs 0 on success, -1 on failure
6565 static int
6566 qemuDomainSetIOThreadParams(virDomainPtr dom,
6567 unsigned int iothread_id,
6568 virTypedParameterPtr params,
6569 int nparams,
6570 unsigned int flags)
6572 virQEMUDriverPtr driver = dom->conn->privateData;
6573 virDomainObjPtr vm = NULL;
6574 qemuMonitorIOThreadInfo iothread = {0};
6575 int ret = -1;
6577 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE, -1);
6579 if (iothread_id == 0) {
6580 virReportError(VIR_ERR_INVALID_ARG, "%s",
6581 _("invalid value of 0 for iothread_id"));
6582 goto cleanup;
6585 iothread.iothread_id = iothread_id;
6587 if (!(vm = qemuDomObjFromDomain(dom)))
6588 goto cleanup;
6590 if (virDomainSetIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
6591 goto cleanup;
6593 if (qemuDomainIOThreadParseParams(params, nparams, &iothread) < 0)
6594 goto cleanup;
6596 ret = qemuDomainChgIOThread(driver, vm, iothread,
6597 VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags);
6599 cleanup:
6600 virDomainObjEndAPI(&vm);
6601 return ret;
6605 static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
6607 virQEMUDriverPtr driver = dom->conn->privateData;
6608 virDomainObjPtr vm;
6609 int ret = -1;
6611 memset(seclabel, 0, sizeof(*seclabel));
6613 if (!(vm = qemuDomObjFromDomain(dom)))
6614 return -1;
6616 if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0)
6617 goto cleanup;
6619 if (!virDomainVirtTypeToString(vm->def->virtType)) {
6620 virReportError(VIR_ERR_INTERNAL_ERROR,
6621 _("unknown virt type in domain definition '%d'"),
6622 vm->def->virtType);
6623 goto cleanup;
6627 * Theoretically, the pid can be replaced during this operation and
6628 * return the label of a different process. If atomicity is needed,
6629 * further validation will be required.
6631 * Comment from Dan Berrange:
6633 * Well the PID as stored in the virDomainObjPtr can't be changed
6634 * because you've got a locked object. The OS level PID could have
6635 * exited, though and in extreme circumstances have cycled through all
6636 * PIDs back to ours. We could sanity check that our PID still exists
6637 * after reading the label, by checking that our FD connecting to the
6638 * QEMU monitor hasn't seen SIGHUP/ERR on poll().
6640 if (virDomainObjIsActive(vm)) {
6641 if (qemuSecurityGetProcessLabel(driver->securityManager,
6642 vm->def, vm->pid, seclabel) < 0)
6643 goto cleanup;
6646 ret = 0;
6648 cleanup:
6649 virDomainObjEndAPI(&vm);
6650 return ret;
6653 static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
6654 virSecurityLabelPtr* seclabels)
6656 virQEMUDriverPtr driver = dom->conn->privateData;
6657 virDomainObjPtr vm;
6658 size_t i;
6659 int ret = -1;
6661 if (!(vm = qemuDomObjFromDomain(dom)))
6662 return -1;
6664 if (virDomainGetSecurityLabelListEnsureACL(dom->conn, vm->def) < 0)
6665 goto cleanup;
6667 if (!virDomainVirtTypeToString(vm->def->virtType)) {
6668 virReportError(VIR_ERR_INTERNAL_ERROR,
6669 _("unknown virt type in domain definition '%d'"),
6670 vm->def->virtType);
6671 goto cleanup;
6675 * Check the comment in qemuDomainGetSecurityLabel function.
6677 if (!virDomainObjIsActive(vm)) {
6678 /* No seclabels */
6679 *seclabels = NULL;
6680 ret = 0;
6681 } else {
6682 int len = 0;
6683 virSecurityManagerPtr* mgrs = qemuSecurityGetNested(driver->securityManager);
6684 if (!mgrs)
6685 goto cleanup;
6687 /* Allocate seclabels array */
6688 for (i = 0; mgrs[i]; i++)
6689 len++;
6691 if (VIR_ALLOC_N((*seclabels), len) < 0) {
6692 VIR_FREE(mgrs);
6693 goto cleanup;
6695 memset(*seclabels, 0, sizeof(**seclabels) * len);
6697 /* Fill the array */
6698 for (i = 0; i < len; i++) {
6699 if (qemuSecurityGetProcessLabel(mgrs[i], vm->def, vm->pid,
6700 &(*seclabels)[i]) < 0) {
6701 VIR_FREE(mgrs);
6702 VIR_FREE(*seclabels);
6703 goto cleanup;
6706 ret = len;
6707 VIR_FREE(mgrs);
6710 cleanup:
6711 virDomainObjEndAPI(&vm);
6712 return ret;
6716 static int qemuNodeGetSecurityModel(virConnectPtr conn,
6717 virSecurityModelPtr secmodel)
6719 virQEMUDriverPtr driver = conn->privateData;
6720 char *p;
6721 int ret = 0;
6722 virCapsPtr caps = NULL;
6724 memset(secmodel, 0, sizeof(*secmodel));
6726 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6727 goto cleanup;
6729 if (virNodeGetSecurityModelEnsureACL(conn) < 0)
6730 goto cleanup;
6732 /* We treat no driver as success, but simply return no data in *secmodel */
6733 if (caps->host.nsecModels == 0 ||
6734 caps->host.secModels[0].model == NULL)
6735 goto cleanup;
6737 p = caps->host.secModels[0].model;
6738 if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
6739 virReportError(VIR_ERR_INTERNAL_ERROR,
6740 _("security model string exceeds max %d bytes"),
6741 VIR_SECURITY_MODEL_BUFLEN-1);
6742 ret = -1;
6743 goto cleanup;
6745 strcpy(secmodel->model, p);
6747 p = caps->host.secModels[0].doi;
6748 if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
6749 virReportError(VIR_ERR_INTERNAL_ERROR,
6750 _("security DOI string exceeds max %d bytes"),
6751 VIR_SECURITY_DOI_BUFLEN-1);
6752 ret = -1;
6753 goto cleanup;
6755 strcpy(secmodel->doi, p);
6757 cleanup:
6758 virObjectUnref(caps);
6759 return ret;
6764 * qemuDomainSaveImageUpdateDef:
6765 * @driver: qemu driver data
6766 * @def: def of the domain from the save image
6767 * @newxml: user provided replacement XML
6769 * Returns the new domain definition in case @newxml is ABI compatible with the
6770 * guest.
6772 static virDomainDefPtr
6773 qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver,
6774 virDomainDefPtr def,
6775 const char *newxml)
6777 virDomainDefPtr ret = NULL;
6778 virDomainDefPtr newdef_migr = NULL;
6779 virDomainDefPtr newdef = NULL;
6780 virCapsPtr caps = NULL;
6782 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6783 goto cleanup;
6785 if (!(newdef = virDomainDefParseString(newxml, caps, driver->xmlopt, NULL,
6786 VIR_DOMAIN_DEF_PARSE_INACTIVE)))
6787 goto cleanup;
6789 if (!(newdef_migr = qemuDomainDefCopy(driver,
6790 newdef,
6791 QEMU_DOMAIN_FORMAT_LIVE_FLAGS |
6792 VIR_DOMAIN_XML_MIGRATABLE)))
6793 goto cleanup;
6795 if (!virDomainDefCheckABIStability(def, newdef_migr, driver->xmlopt)) {
6796 virErrorPtr err = virSaveLastError();
6798 /* Due to a bug in older version of external snapshot creation
6799 * code, the XML saved in the save image was not a migratable
6800 * XML. To ensure backwards compatibility with the change of the
6801 * saved XML type, we need to check the ABI compatibility against
6802 * the user provided XML if the check against the migratable XML
6803 * fails. Snapshots created prior to v1.1.3 have this issue. */
6804 if (!virDomainDefCheckABIStability(def, newdef, driver->xmlopt)) {
6805 virSetError(err);
6806 virFreeError(err);
6807 goto cleanup;
6809 virFreeError(err);
6811 /* use the user provided XML */
6812 VIR_STEAL_PTR(ret, newdef);
6813 } else {
6814 VIR_STEAL_PTR(ret, newdef_migr);
6817 cleanup:
6818 virObjectUnref(caps);
6819 virDomainDefFree(newdef);
6820 virDomainDefFree(newdef_migr);
6822 return ret;
6827 * qemuDomainSaveImageOpen:
6828 * @driver: qemu driver data
6829 * @path: path of the save image
6830 * @ret_def: returns domain definition created from the XML stored in the image
6831 * @ret_data: returns structure filled with data from the image header
6832 * @bypass_cache: bypass cache when opening the file
6833 * @wrapperFd: returns the file wrapper structure
6834 * @open_write: open the file for writing (for updates)
6835 * @unlink_corrupt: remove the image file if it is corrupted
6837 * Returns the opened fd of the save image file and fills the appropriate fields
6838 * on success. On error returns -1 on most failures, -3 if corrupt image was
6839 * unlinked (no error raised).
6841 static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
6842 qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
6843 const char *path,
6844 virDomainDefPtr *ret_def,
6845 virQEMUSaveDataPtr *ret_data,
6846 bool bypass_cache,
6847 virFileWrapperFdPtr *wrapperFd,
6848 bool open_write,
6849 bool unlink_corrupt)
6851 int fd = -1;
6852 virQEMUSaveDataPtr data = NULL;
6853 virQEMUSaveHeaderPtr header;
6854 virDomainDefPtr def = NULL;
6855 int oflags = open_write ? O_RDWR : O_RDONLY;
6856 virCapsPtr caps = NULL;
6857 size_t xml_len;
6858 size_t cookie_len;
6860 if (bypass_cache) {
6861 int directFlag = virFileDirectFdFlag();
6862 if (directFlag < 0) {
6863 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
6864 _("bypass cache unsupported by this system"));
6865 goto error;
6867 oflags |= directFlag;
6870 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6871 goto error;
6873 if ((fd = qemuOpenFile(driver, NULL, path, oflags, NULL)) < 0)
6874 goto error;
6875 if (bypass_cache &&
6876 !(*wrapperFd = virFileWrapperFdNew(&fd, path,
6877 VIR_FILE_WRAPPER_BYPASS_CACHE)))
6878 goto error;
6880 if (VIR_ALLOC(data) < 0)
6881 goto error;
6883 header = &data->header;
6884 if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) {
6885 if (unlink_corrupt) {
6886 if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
6887 virReportSystemError(errno,
6888 _("cannot remove corrupt file: %s"),
6889 path);
6890 } else {
6891 fd = -3;
6893 } else {
6894 virReportError(VIR_ERR_OPERATION_FAILED,
6895 "%s", _("failed to read qemu header"));
6897 goto error;
6900 if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) {
6901 const char *msg = _("image magic is incorrect");
6903 if (memcmp(header->magic, QEMU_SAVE_PARTIAL,
6904 sizeof(header->magic)) == 0) {
6905 msg = _("save image is incomplete");
6906 if (unlink_corrupt) {
6907 if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
6908 virReportSystemError(errno,
6909 _("cannot remove corrupt file: %s"),
6910 path);
6911 } else {
6912 fd = -3;
6914 goto error;
6917 virReportError(VIR_ERR_OPERATION_FAILED, "%s", msg);
6918 goto error;
6921 if (header->version > QEMU_SAVE_VERSION) {
6922 /* convert endianess and try again */
6923 bswap_header(header);
6926 if (header->version > QEMU_SAVE_VERSION) {
6927 virReportError(VIR_ERR_OPERATION_FAILED,
6928 _("image version is not supported (%d > %d)"),
6929 header->version, QEMU_SAVE_VERSION);
6930 goto error;
6933 if (header->data_len <= 0) {
6934 virReportError(VIR_ERR_OPERATION_FAILED,
6935 _("invalid header data length: %d"), header->data_len);
6936 goto error;
6939 if (header->cookieOffset)
6940 xml_len = header->cookieOffset;
6941 else
6942 xml_len = header->data_len;
6944 cookie_len = header->data_len - xml_len;
6946 if (VIR_ALLOC_N(data->xml, xml_len) < 0)
6947 goto error;
6949 if (saferead(fd, data->xml, xml_len) != xml_len) {
6950 virReportError(VIR_ERR_OPERATION_FAILED,
6951 "%s", _("failed to read domain XML"));
6952 goto error;
6955 if (cookie_len > 0) {
6956 if (VIR_ALLOC_N(data->cookie, cookie_len) < 0)
6957 goto error;
6959 if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
6960 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
6961 _("failed to read cookie"));
6962 goto error;
6966 /* Create a domain from this XML */
6967 if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL,
6968 VIR_DOMAIN_DEF_PARSE_INACTIVE |
6969 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
6970 goto error;
6972 *ret_def = def;
6973 *ret_data = data;
6975 cleanup:
6976 virObjectUnref(caps);
6977 return fd;
6979 error:
6980 virDomainDefFree(def);
6981 virQEMUSaveDataFree(data);
6982 VIR_FORCE_CLOSE(fd);
6983 goto cleanup;
6986 static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6)
6987 qemuDomainSaveImageStartVM(virConnectPtr conn,
6988 virQEMUDriverPtr driver,
6989 virDomainObjPtr vm,
6990 int *fd,
6991 virQEMUSaveDataPtr data,
6992 const char *path,
6993 bool start_paused,
6994 qemuDomainAsyncJob asyncJob)
6996 int ret = -1;
6997 bool restored = false;
6998 virObjectEventPtr event;
6999 int intermediatefd = -1;
7000 virCommandPtr cmd = NULL;
7001 char *errbuf = NULL;
7002 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
7003 virQEMUSaveHeaderPtr header = &data->header;
7004 qemuDomainSaveCookiePtr cookie = NULL;
7006 if (virSaveCookieParseString(data->cookie, (virObjectPtr *)&cookie,
7007 virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0)
7008 goto cleanup;
7010 if ((header->version == 2) &&
7011 (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
7012 if (!(cmd = qemuCompressGetCommand(header->compressed)))
7013 goto cleanup;
7015 intermediatefd = *fd;
7016 *fd = -1;
7018 virCommandSetInputFD(cmd, intermediatefd);
7019 virCommandSetOutputFD(cmd, fd);
7020 virCommandSetErrorBuffer(cmd, &errbuf);
7021 virCommandDoAsyncIO(cmd);
7023 if (virCommandRunAsync(cmd, NULL) < 0) {
7024 *fd = intermediatefd;
7025 goto cleanup;
7029 /* No cookie means libvirt which saved the domain was too old to mess up
7030 * the CPU definitions.
7032 if (cookie &&
7033 qemuDomainFixupCPUs(vm, &cookie->cpu) < 0)
7034 goto cleanup;
7036 if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
7037 asyncJob, "stdio", *fd, path, NULL,
7038 VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
7039 VIR_QEMU_PROCESS_START_PAUSED |
7040 VIR_QEMU_PROCESS_START_GEN_VMID) == 0)
7041 restored = true;
7043 if (intermediatefd != -1) {
7044 virErrorPtr orig_err = NULL;
7046 if (!restored) {
7047 /* if there was an error setting up qemu, the intermediate
7048 * process will wait forever to write to stdout, so we
7049 * must manually kill it and ignore any error related to
7050 * the process
7052 orig_err = virSaveLastError();
7053 VIR_FORCE_CLOSE(intermediatefd);
7054 VIR_FORCE_CLOSE(*fd);
7057 if (virCommandWait(cmd, NULL) < 0) {
7058 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, asyncJob, 0);
7059 restored = false;
7061 VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
7063 if (orig_err) {
7064 virSetError(orig_err);
7065 virFreeError(orig_err);
7068 VIR_FORCE_CLOSE(intermediatefd);
7070 if (VIR_CLOSE(*fd) < 0) {
7071 virReportSystemError(errno, _("cannot close file: %s"), path);
7072 restored = false;
7075 virDomainAuditStart(vm, "restored", restored);
7076 if (!restored)
7077 goto cleanup;
7079 /* qemuProcessStart doesn't unset the qemu error reporting infrastructure
7080 * in case of migration (which is used in this case) so we need to reset it
7081 * so that the handle to virtlogd is not held open unnecessarily */
7082 qemuMonitorSetDomainLog(qemuDomainGetMonitor(vm), NULL, NULL, NULL);
7084 event = virDomainEventLifecycleNewFromObj(vm,
7085 VIR_DOMAIN_EVENT_STARTED,
7086 VIR_DOMAIN_EVENT_STARTED_RESTORED);
7087 virObjectEventStateQueue(driver->domainEventState, event);
7090 /* If it was running before, resume it now unless caller requested pause. */
7091 if (header->was_running && !start_paused) {
7092 if (qemuProcessStartCPUs(driver, vm,
7093 VIR_DOMAIN_RUNNING_RESTORED,
7094 asyncJob) < 0) {
7095 if (virGetLastErrorCode() == VIR_ERR_OK)
7096 virReportError(VIR_ERR_OPERATION_FAILED,
7097 "%s", _("failed to resume domain"));
7098 goto cleanup;
7100 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
7101 VIR_WARN("Failed to save status on vm %s", vm->def->name);
7102 goto cleanup;
7104 } else {
7105 int detail = (start_paused ? VIR_DOMAIN_EVENT_SUSPENDED_PAUSED :
7106 VIR_DOMAIN_EVENT_SUSPENDED_RESTORED);
7107 event = virDomainEventLifecycleNewFromObj(vm,
7108 VIR_DOMAIN_EVENT_SUSPENDED,
7109 detail);
7110 virObjectEventStateQueue(driver->domainEventState, event);
7113 ret = 0;
7115 cleanup:
7116 virObjectUnref(cookie);
7117 virCommandFree(cmd);
7118 VIR_FREE(errbuf);
7119 if (qemuSecurityRestoreSavedStateLabel(driver, vm, path) < 0)
7120 VIR_WARN("failed to restore save state label on %s", path);
7121 virObjectUnref(cfg);
7122 return ret;
7125 static int
7126 qemuDomainRestoreFlags(virConnectPtr conn,
7127 const char *path,
7128 const char *dxml,
7129 unsigned int flags)
7131 virQEMUDriverPtr driver = conn->privateData;
7132 qemuDomainObjPrivatePtr priv = NULL;
7133 virDomainDefPtr def = NULL;
7134 virDomainObjPtr vm = NULL;
7135 char *xmlout = NULL;
7136 const char *newxml = dxml;
7137 int fd = -1;
7138 int ret = -1;
7139 virQEMUSaveDataPtr data = NULL;
7140 virFileWrapperFdPtr wrapperFd = NULL;
7141 bool hook_taint = false;
7143 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
7144 VIR_DOMAIN_SAVE_RUNNING |
7145 VIR_DOMAIN_SAVE_PAUSED, -1);
7148 virNWFilterReadLockFilterUpdates();
7150 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7151 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
7152 &wrapperFd, false, false);
7153 if (fd < 0)
7154 goto cleanup;
7156 if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
7157 goto cleanup;
7159 if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
7160 int hookret;
7162 if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
7163 VIR_HOOK_QEMU_OP_RESTORE,
7164 VIR_HOOK_SUBOP_BEGIN,
7165 NULL,
7166 dxml ? dxml : data->xml,
7167 &xmlout)) < 0)
7168 goto cleanup;
7170 if (hookret == 0 && !virStringIsEmpty(xmlout)) {
7171 VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
7172 hook_taint = true;
7173 newxml = xmlout;
7177 if (newxml) {
7178 virDomainDefPtr tmp;
7179 if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, newxml)))
7180 goto cleanup;
7182 virDomainDefFree(def);
7183 def = tmp;
7186 if (!(vm = virDomainObjListAdd(driver->domains, def,
7187 driver->xmlopt,
7188 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
7189 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
7190 NULL)))
7191 goto cleanup;
7192 def = NULL;
7194 if (flags & VIR_DOMAIN_SAVE_RUNNING)
7195 data->header.was_running = 1;
7196 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
7197 data->header.was_running = 0;
7199 if (hook_taint) {
7200 priv = vm->privateData;
7201 priv->hookRun = true;
7204 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_RESTORE,
7205 flags) < 0)
7206 goto cleanup;
7208 ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path,
7209 false, QEMU_ASYNC_JOB_START);
7211 qemuProcessEndJob(driver, vm);
7213 cleanup:
7214 virDomainDefFree(def);
7215 VIR_FORCE_CLOSE(fd);
7216 if (virFileWrapperFdClose(wrapperFd) < 0)
7217 ret = -1;
7218 virFileWrapperFdFree(wrapperFd);
7219 virQEMUSaveDataFree(data);
7220 VIR_FREE(xmlout);
7221 if (vm && ret < 0)
7222 qemuDomainRemoveInactiveJob(driver, vm);
7223 virDomainObjEndAPI(&vm);
7224 virNWFilterUnlockFilterUpdates();
7225 return ret;
7228 static int
7229 qemuDomainRestore(virConnectPtr conn,
7230 const char *path)
7232 return qemuDomainRestoreFlags(conn, path, NULL, 0);
7235 static char *
7236 qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
7237 unsigned int flags)
7239 virQEMUDriverPtr driver = conn->privateData;
7240 char *ret = NULL;
7241 virDomainDefPtr def = NULL;
7242 int fd = -1;
7243 virQEMUSaveDataPtr data = NULL;
7245 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
7247 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7248 false, NULL, false, false);
7250 if (fd < 0)
7251 goto cleanup;
7253 if (virDomainSaveImageGetXMLDescEnsureACL(conn, def, flags) < 0)
7254 goto cleanup;
7256 ret = qemuDomainDefFormatXML(driver, def, flags);
7258 cleanup:
7259 virQEMUSaveDataFree(data);
7260 virDomainDefFree(def);
7261 VIR_FORCE_CLOSE(fd);
7262 return ret;
7265 static int
7266 qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
7267 const char *dxml, unsigned int flags)
7269 virQEMUDriverPtr driver = conn->privateData;
7270 int ret = -1;
7271 virDomainDefPtr def = NULL;
7272 virDomainDefPtr newdef = NULL;
7273 int fd = -1;
7274 virQEMUSaveDataPtr data = NULL;
7275 int state = -1;
7277 virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
7278 VIR_DOMAIN_SAVE_PAUSED, -1);
7280 if (flags & VIR_DOMAIN_SAVE_RUNNING)
7281 state = 1;
7282 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
7283 state = 0;
7285 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7286 false, NULL, true, false);
7288 if (fd < 0)
7289 goto cleanup;
7291 if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0)
7292 goto cleanup;
7294 if (STREQ(data->xml, dxml) &&
7295 (state < 0 || state == data->header.was_running)) {
7296 /* no change to the XML */
7297 ret = 0;
7298 goto cleanup;
7301 if (state >= 0)
7302 data->header.was_running = state;
7304 if (!(newdef = qemuDomainSaveImageUpdateDef(driver, def, dxml)))
7305 goto cleanup;
7307 VIR_FREE(data->xml);
7309 if (!(data->xml = qemuDomainDefFormatXML(driver, newdef,
7310 VIR_DOMAIN_XML_INACTIVE |
7311 VIR_DOMAIN_XML_SECURE |
7312 VIR_DOMAIN_XML_MIGRATABLE)))
7313 goto cleanup;
7315 if (lseek(fd, 0, SEEK_SET) != 0) {
7316 virReportSystemError(errno, _("cannot seek in '%s'"), path);
7317 goto cleanup;
7320 if (virQEMUSaveDataWrite(data, fd, path) < 0)
7321 goto cleanup;
7323 if (VIR_CLOSE(fd) < 0) {
7324 virReportSystemError(errno, _("failed to write header data to '%s'"), path);
7325 goto cleanup;
7328 ret = 0;
7330 cleanup:
7331 virDomainDefFree(def);
7332 virDomainDefFree(newdef);
7333 VIR_FORCE_CLOSE(fd);
7334 virQEMUSaveDataFree(data);
7335 return ret;
7338 static char *
7339 qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
7341 virQEMUDriverPtr driver = dom->conn->privateData;
7342 virDomainObjPtr vm;
7343 char *path = NULL;
7344 char *ret = NULL;
7345 virDomainDefPtr def = NULL;
7346 int fd = -1;
7347 virQEMUSaveDataPtr data = NULL;
7349 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
7351 if (!(vm = qemuDomObjFromDomain(dom)))
7352 return ret;
7354 if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
7355 goto cleanup;
7357 if (!(path = qemuDomainManagedSavePath(driver, vm)))
7358 goto cleanup;
7360 if (!virFileExists(path)) {
7361 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7362 _("domain does not have managed save image"));
7363 goto cleanup;
7366 if ((fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7367 false, NULL, false, false)) < 0)
7368 goto cleanup;
7370 ret = qemuDomainDefFormatXML(driver, def, flags);
7372 cleanup:
7373 virQEMUSaveDataFree(data);
7374 virDomainDefFree(def);
7375 VIR_FORCE_CLOSE(fd);
7376 virDomainObjEndAPI(&vm);
7377 VIR_FREE(path);
7378 return ret;
7381 static int
7382 qemuDomainManagedSaveDefineXML(virDomainPtr dom, const char *dxml,
7383 unsigned int flags)
7385 virQEMUDriverPtr driver = dom->conn->privateData;
7386 virConnectPtr conn = dom->conn;
7387 virDomainObjPtr vm;
7388 char *path = NULL;
7389 int ret = -1;
7391 if (!(vm = qemuDomObjFromDomain(dom)))
7392 return -1;
7394 if (virDomainManagedSaveDefineXMLEnsureACL(conn, vm->def) < 0)
7395 goto cleanup;
7397 if (!(path = qemuDomainManagedSavePath(driver, vm)))
7398 goto cleanup;
7400 if (!virFileExists(path)) {
7401 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7402 _("domain does not have managed save image"));
7403 goto cleanup;
7406 ret = qemuDomainSaveImageDefineXML(conn, path, dxml, flags);
7408 cleanup:
7409 virDomainObjEndAPI(&vm);
7410 VIR_FREE(path);
7411 return ret;
7414 /* Return 0 on success, 1 if incomplete saved image was silently unlinked,
7415 * and -1 on failure with error raised. */
7416 static int
7417 qemuDomainObjRestore(virConnectPtr conn,
7418 virQEMUDriverPtr driver,
7419 virDomainObjPtr vm,
7420 const char *path,
7421 bool start_paused,
7422 bool bypass_cache,
7423 qemuDomainAsyncJob asyncJob)
7425 virDomainDefPtr def = NULL;
7426 qemuDomainObjPrivatePtr priv = vm->privateData;
7427 int fd = -1;
7428 int ret = -1;
7429 char *xmlout = NULL;
7430 virQEMUSaveDataPtr data = NULL;
7431 virFileWrapperFdPtr wrapperFd = NULL;
7433 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7434 bypass_cache, &wrapperFd, false, true);
7435 if (fd < 0) {
7436 if (fd == -3)
7437 ret = 1;
7438 goto cleanup;
7441 if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
7442 int hookret;
7444 if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
7445 VIR_HOOK_QEMU_OP_RESTORE,
7446 VIR_HOOK_SUBOP_BEGIN,
7447 NULL, data->xml, &xmlout)) < 0)
7448 goto cleanup;
7450 if (hookret == 0 && !virStringIsEmpty(xmlout)) {
7451 virDomainDefPtr tmp;
7453 VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
7455 if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, xmlout)))
7456 goto cleanup;
7458 virDomainDefFree(def);
7459 def = tmp;
7460 priv->hookRun = true;
7464 if (STRNEQ(vm->def->name, def->name) ||
7465 memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
7466 char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
7467 char def_uuidstr[VIR_UUID_STRING_BUFLEN];
7468 virUUIDFormat(vm->def->uuid, vm_uuidstr);
7469 virUUIDFormat(def->uuid, def_uuidstr);
7470 virReportError(VIR_ERR_OPERATION_FAILED,
7471 _("cannot restore domain '%s' uuid %s from a file"
7472 " which belongs to domain '%s' uuid %s"),
7473 vm->def->name, vm_uuidstr,
7474 def->name, def_uuidstr);
7475 goto cleanup;
7478 virDomainObjAssignDef(vm, def, true, NULL);
7479 def = NULL;
7481 ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path,
7482 start_paused, asyncJob);
7484 cleanup:
7485 virQEMUSaveDataFree(data);
7486 VIR_FREE(xmlout);
7487 virDomainDefFree(def);
7488 VIR_FORCE_CLOSE(fd);
7489 if (virFileWrapperFdClose(wrapperFd) < 0)
7490 ret = -1;
7491 virFileWrapperFdFree(wrapperFd);
7492 return ret;
7496 static char
7497 *qemuDomainGetXMLDesc(virDomainPtr dom,
7498 unsigned int flags)
7500 virQEMUDriverPtr driver = dom->conn->privateData;
7501 virDomainObjPtr vm;
7502 char *ret = NULL;
7504 virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS | VIR_DOMAIN_XML_UPDATE_CPU |
7505 VIR_DOMAIN_XML_SNAPSHOTS | VIR_DOMAIN_XML_CHECKPOINTS, NULL);
7507 if (!(vm = qemuDomObjFromDomain(dom)))
7508 goto cleanup;
7510 if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
7511 goto cleanup;
7513 qemuDomainUpdateCurrentMemorySize(vm);
7515 if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
7516 flags |= QEMU_DOMAIN_FORMAT_LIVE_FLAGS;
7518 /* The CPU is already updated in the domain's live definition, we need to
7519 * ignore the VIR_DOMAIN_XML_UPDATE_CPU flag.
7521 if (virDomainObjIsActive(vm) &&
7522 !(flags & VIR_DOMAIN_XML_INACTIVE))
7523 flags &= ~VIR_DOMAIN_XML_UPDATE_CPU;
7525 ret = qemuDomainFormatXML(driver, vm, flags);
7527 cleanup:
7528 virDomainObjEndAPI(&vm);
7529 return ret;
7533 static char *qemuConnectDomainXMLFromNative(virConnectPtr conn,
7534 const char *format,
7535 const char *config,
7536 unsigned int flags)
7538 virQEMUDriverPtr driver = conn->privateData;
7539 virDomainDefPtr def = NULL;
7540 char *xml = NULL;
7541 virCapsPtr caps = NULL;
7543 virCheckFlags(0, NULL);
7545 if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
7546 goto cleanup;
7548 if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
7549 virReportError(VIR_ERR_INVALID_ARG,
7550 _("unsupported config type %s"), format);
7551 goto cleanup;
7554 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7555 goto cleanup;
7557 def = qemuParseCommandLineString(driver->qemuCapsCache,
7558 caps, driver->xmlopt, config,
7559 NULL, NULL, NULL);
7560 if (!def)
7561 goto cleanup;
7563 if (!def->name && VIR_STRDUP(def->name, "unnamed") < 0)
7564 goto cleanup;
7566 xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE);
7568 cleanup:
7569 virDomainDefFree(def);
7570 virObjectUnref(caps);
7571 return xml;
7574 static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
7575 const char *format,
7576 const char *xmlData,
7577 unsigned int flags)
7579 virQEMUDriverPtr driver = conn->privateData;
7580 virDomainObjPtr vm = NULL;
7581 virCommandPtr cmd = NULL;
7582 char *ret = NULL;
7583 size_t i;
7584 virQEMUDriverConfigPtr cfg;
7585 virCapsPtr caps = NULL;
7587 virCheckFlags(0, NULL);
7589 cfg = virQEMUDriverGetConfig(driver);
7591 if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
7592 goto cleanup;
7594 if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
7595 virReportError(VIR_ERR_INVALID_ARG,
7596 _("unsupported config type %s"), format);
7597 goto cleanup;
7600 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7601 goto cleanup;
7603 if (!(vm = virDomainObjNew(driver->xmlopt)))
7604 goto cleanup;
7606 if (!(vm->def = virDomainDefParseString(xmlData, caps, driver->xmlopt, NULL,
7607 VIR_DOMAIN_DEF_PARSE_INACTIVE |
7608 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE)))
7609 goto cleanup;
7611 /* Since we're just exporting args, we can't do bridge/network/direct
7612 * setups, since libvirt will normally create TAP/macvtap devices
7613 * directly. We convert those configs into generic 'ethernet'
7614 * config and assume the user has suitable 'ifup-qemu' scripts
7616 for (i = 0; i < vm->def->nnets; i++) {
7617 virDomainNetDefPtr net = vm->def->nets[i];
7618 unsigned int bootIndex = net->info.bootIndex;
7619 char *model = net->model;
7620 virMacAddr mac = net->mac;
7621 char *script = net->script;
7623 net->model = NULL;
7624 net->script = NULL;
7626 virDomainNetDefClear(net);
7628 net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
7629 net->info.bootIndex = bootIndex;
7630 net->model = model;
7631 net->mac = mac;
7632 net->script = script;
7635 if (!(cmd = qemuProcessCreatePretendCmd(driver, vm, NULL,
7636 qemuCheckFips(), true,
7637 VIR_QEMU_PROCESS_START_COLD)))
7638 goto cleanup;
7640 ret = virCommandToString(cmd, false);
7642 cleanup:
7643 virCommandFree(cmd);
7644 virObjectUnref(vm);
7645 virObjectUnref(caps);
7646 virObjectUnref(cfg);
7647 return ret;
7651 static int qemuConnectListDefinedDomains(virConnectPtr conn,
7652 char **const names, int nnames) {
7653 virQEMUDriverPtr driver = conn->privateData;
7654 int ret = -1;
7656 if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
7657 goto cleanup;
7659 ret = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
7660 virConnectListDefinedDomainsCheckACL,
7661 conn);
7663 cleanup:
7664 return ret;
7667 static int qemuConnectNumOfDefinedDomains(virConnectPtr conn)
7669 virQEMUDriverPtr driver = conn->privateData;
7670 int ret = -1;
7672 if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
7673 goto cleanup;
7675 ret = virDomainObjListNumOfDomains(driver->domains, false,
7676 virConnectNumOfDefinedDomainsCheckACL,
7677 conn);
7679 cleanup:
7680 return ret;
7684 static int
7685 qemuDomainObjStart(virConnectPtr conn,
7686 virQEMUDriverPtr driver,
7687 virDomainObjPtr vm,
7688 unsigned int flags,
7689 qemuDomainAsyncJob asyncJob)
7691 int ret = -1;
7692 char *managed_save;
7693 bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
7694 bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
7695 bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
7696 bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
7697 unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
7698 qemuDomainObjPrivatePtr priv = vm->privateData;
7700 start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
7701 start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0;
7704 * If there is a managed saved state restore it instead of starting
7705 * from scratch. The old state is removed once the restoring succeeded.
7707 managed_save = qemuDomainManagedSavePath(driver, vm);
7709 if (!managed_save)
7710 goto cleanup;
7712 if (virFileExists(managed_save)) {
7713 if (force_boot) {
7714 if (unlink(managed_save) < 0) {
7715 virReportSystemError(errno,
7716 _("cannot remove managed save file %s"),
7717 managed_save);
7718 goto cleanup;
7720 vm->hasManagedSave = false;
7721 } else {
7722 virDomainJobOperation op = priv->job.current->operation;
7723 priv->job.current->operation = VIR_DOMAIN_JOB_OPERATION_RESTORE;
7725 ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
7726 start_paused, bypass_cache, asyncJob);
7728 if (ret == 0) {
7729 if (unlink(managed_save) < 0)
7730 VIR_WARN("Failed to remove the managed state %s", managed_save);
7731 else
7732 vm->hasManagedSave = false;
7734 goto cleanup;
7735 } else if (ret < 0) {
7736 VIR_WARN("Unable to restore from managed state %s. "
7737 "Maybe the file is corrupted?", managed_save);
7738 goto cleanup;
7739 } else {
7740 VIR_WARN("Ignoring incomplete managed state %s", managed_save);
7741 priv->job.current->operation = op;
7742 vm->hasManagedSave = false;
7747 ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
7748 NULL, -1, NULL, NULL,
7749 VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
7750 virDomainAuditStart(vm, "booted", ret >= 0);
7751 if (ret >= 0) {
7752 virObjectEventPtr event =
7753 virDomainEventLifecycleNewFromObj(vm,
7754 VIR_DOMAIN_EVENT_STARTED,
7755 VIR_DOMAIN_EVENT_STARTED_BOOTED);
7756 virObjectEventStateQueue(driver->domainEventState, event);
7757 if (start_paused) {
7758 event = virDomainEventLifecycleNewFromObj(vm,
7759 VIR_DOMAIN_EVENT_SUSPENDED,
7760 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
7761 virObjectEventStateQueue(driver->domainEventState, event);
7765 cleanup:
7766 VIR_FREE(managed_save);
7767 return ret;
7770 static int
7771 qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
7773 virQEMUDriverPtr driver = dom->conn->privateData;
7774 virDomainObjPtr vm;
7775 int ret = -1;
7777 virCheckFlags(VIR_DOMAIN_START_PAUSED |
7778 VIR_DOMAIN_START_AUTODESTROY |
7779 VIR_DOMAIN_START_BYPASS_CACHE |
7780 VIR_DOMAIN_START_FORCE_BOOT, -1);
7782 virNWFilterReadLockFilterUpdates();
7784 if (!(vm = qemuDomObjFromDomain(dom)))
7785 goto cleanup;
7787 if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
7788 goto cleanup;
7790 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
7791 flags) < 0)
7792 goto cleanup;
7794 if (virDomainObjIsActive(vm)) {
7795 virReportError(VIR_ERR_OPERATION_INVALID,
7796 "%s", _("domain is already running"));
7797 goto endjob;
7800 if (qemuDomainObjStart(dom->conn, driver, vm, flags,
7801 QEMU_ASYNC_JOB_START) < 0)
7802 goto endjob;
7804 dom->id = vm->def->id;
7805 ret = 0;
7807 endjob:
7808 qemuProcessEndJob(driver, vm);
7810 cleanup:
7811 virDomainObjEndAPI(&vm);
7812 virNWFilterUnlockFilterUpdates();
7813 return ret;
7816 static int
7817 qemuDomainCreate(virDomainPtr dom)
7819 return qemuDomainCreateWithFlags(dom, 0);
7822 static virDomainPtr
7823 qemuDomainDefineXMLFlags(virConnectPtr conn,
7824 const char *xml,
7825 unsigned int flags)
7827 virQEMUDriverPtr driver = conn->privateData;
7828 virDomainDefPtr def = NULL;
7829 virDomainDefPtr oldDef = NULL;
7830 virDomainObjPtr vm = NULL;
7831 virDomainPtr dom = NULL;
7832 virObjectEventPtr event = NULL;
7833 virQEMUDriverConfigPtr cfg;
7834 virCapsPtr caps = NULL;
7835 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
7836 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
7838 virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
7840 if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
7841 parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
7843 cfg = virQEMUDriverGetConfig(driver);
7845 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7846 goto cleanup;
7848 if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
7849 NULL, parse_flags)))
7850 goto cleanup;
7852 if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
7853 goto cleanup;
7855 if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
7856 goto cleanup;
7858 if (!(vm = virDomainObjListAdd(driver->domains, def,
7859 driver->xmlopt,
7860 0, &oldDef)))
7861 goto cleanup;
7862 def = NULL;
7864 vm->persistent = 1;
7866 if (virDomainSaveConfig(cfg->configDir, driver->caps,
7867 vm->newDef ? vm->newDef : vm->def) < 0) {
7868 if (oldDef) {
7869 /* There is backup so this VM was defined before.
7870 * Just restore the backup. */
7871 VIR_INFO("Restoring domain '%s' definition", vm->def->name);
7872 if (virDomainObjIsActive(vm))
7873 vm->newDef = oldDef;
7874 else
7875 vm->def = oldDef;
7876 oldDef = NULL;
7877 } else {
7878 /* Brand new domain. Remove it */
7879 VIR_INFO("Deleting domain '%s'", vm->def->name);
7880 vm->persistent = 0;
7881 qemuDomainRemoveInactiveJob(driver, vm);
7883 goto cleanup;
7886 event = virDomainEventLifecycleNewFromObj(vm,
7887 VIR_DOMAIN_EVENT_DEFINED,
7888 !oldDef ?
7889 VIR_DOMAIN_EVENT_DEFINED_ADDED :
7890 VIR_DOMAIN_EVENT_DEFINED_UPDATED);
7892 VIR_INFO("Creating domain '%s'", vm->def->name);
7893 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
7895 cleanup:
7896 virDomainDefFree(oldDef);
7897 virDomainDefFree(def);
7898 virDomainObjEndAPI(&vm);
7899 virObjectEventStateQueue(driver->domainEventState, event);
7900 virObjectUnref(caps);
7901 virObjectUnref(cfg);
7902 return dom;
7905 static virDomainPtr
7906 qemuDomainDefineXML(virConnectPtr conn, const char *xml)
7908 return qemuDomainDefineXMLFlags(conn, xml, 0);
7911 static int
7912 qemuDomainUndefineFlags(virDomainPtr dom,
7913 unsigned int flags)
7915 virQEMUDriverPtr driver = dom->conn->privateData;
7916 virDomainObjPtr vm;
7917 virObjectEventPtr event = NULL;
7918 char *name = NULL;
7919 int ret = -1;
7920 int nsnapshots;
7921 virQEMUDriverConfigPtr cfg = NULL;
7923 virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
7924 VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
7925 VIR_DOMAIN_UNDEFINE_NVRAM |
7926 VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, -1);
7928 if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM) &&
7929 (flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
7930 virReportError(VIR_ERR_OPERATION_INVALID,
7931 "%s", _("cannot both keep and delete nvram"));
7932 return -1;
7935 if (!(vm = qemuDomObjFromDomain(dom)))
7936 return -1;
7938 cfg = virQEMUDriverGetConfig(driver);
7940 if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
7941 goto cleanup;
7943 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
7944 goto cleanup;
7946 if (!vm->persistent) {
7947 virReportError(VIR_ERR_OPERATION_INVALID,
7948 "%s", _("cannot undefine transient domain"));
7949 goto endjob;
7952 if (!virDomainObjIsActive(vm) &&
7953 (nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0))) {
7954 if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
7955 virReportError(VIR_ERR_OPERATION_INVALID,
7956 _("cannot delete inactive domain with %d "
7957 "snapshots"),
7958 nsnapshots);
7959 goto endjob;
7961 if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
7962 goto endjob;
7964 /* TODO: Restrict deletion if checkpoints exist? */
7966 name = qemuDomainManagedSavePath(driver, vm);
7967 if (name == NULL)
7968 goto endjob;
7970 if (virFileExists(name)) {
7971 if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
7972 if (unlink(name) < 0) {
7973 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7974 _("Failed to remove domain managed "
7975 "save image"));
7976 goto endjob;
7978 } else {
7979 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7980 _("Refusing to undefine while domain managed "
7981 "save image exists"));
7982 goto endjob;
7986 if (vm->def->os.loader &&
7987 vm->def->os.loader->nvram &&
7988 virFileExists(vm->def->os.loader->nvram)) {
7989 if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
7990 if (unlink(vm->def->os.loader->nvram) < 0) {
7991 virReportSystemError(errno,
7992 _("failed to remove nvram: %s"),
7993 vm->def->os.loader->nvram);
7994 goto endjob;
7996 } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
7997 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7998 _("cannot undefine domain with nvram"));
7999 goto endjob;
8003 if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
8004 goto endjob;
8006 event = virDomainEventLifecycleNewFromObj(vm,
8007 VIR_DOMAIN_EVENT_UNDEFINED,
8008 VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
8010 VIR_INFO("Undefining domain '%s'", vm->def->name);
8012 /* If the domain is active, keep it running but set it as transient.
8013 * domainDestroy and domainShutdown will take care of removing the
8014 * domain obj from the hash table.
8016 vm->persistent = 0;
8017 if (!virDomainObjIsActive(vm))
8018 qemuDomainRemoveInactive(driver, vm);
8020 ret = 0;
8021 endjob:
8022 qemuDomainObjEndJob(driver, vm);
8024 cleanup:
8025 VIR_FREE(name);
8026 virDomainObjEndAPI(&vm);
8027 virObjectEventStateQueue(driver->domainEventState, event);
8028 virObjectUnref(cfg);
8029 return ret;
8032 static int
8033 qemuDomainUndefine(virDomainPtr dom)
8035 return qemuDomainUndefineFlags(dom, 0);
8038 static int
8039 qemuDomainAttachDeviceLive(virDomainObjPtr vm,
8040 virDomainDeviceDefPtr dev,
8041 virQEMUDriverPtr driver)
8043 int ret = -1;
8044 const char *alias = NULL;
8046 switch ((virDomainDeviceType)dev->type) {
8047 case VIR_DOMAIN_DEVICE_DISK:
8048 qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
8049 ret = qemuDomainAttachDeviceDiskLive(driver, vm, dev);
8050 if (!ret) {
8051 alias = dev->data.disk->info.alias;
8052 dev->data.disk = NULL;
8054 break;
8056 case VIR_DOMAIN_DEVICE_CONTROLLER:
8057 ret = qemuDomainAttachControllerDevice(driver, vm, dev->data.controller);
8058 if (!ret) {
8059 alias = dev->data.controller->info.alias;
8060 dev->data.controller = NULL;
8062 break;
8064 case VIR_DOMAIN_DEVICE_LEASE:
8065 ret = qemuDomainAttachLease(driver, vm,
8066 dev->data.lease);
8067 if (ret == 0)
8068 dev->data.lease = NULL;
8069 break;
8071 case VIR_DOMAIN_DEVICE_NET:
8072 qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, NULL);
8073 ret = qemuDomainAttachNetDevice(driver, vm, dev->data.net);
8074 if (!ret) {
8075 alias = dev->data.net->info.alias;
8076 dev->data.net = NULL;
8078 break;
8080 case VIR_DOMAIN_DEVICE_HOSTDEV:
8081 qemuDomainObjCheckHostdevTaint(driver, vm, dev->data.hostdev, NULL);
8082 ret = qemuDomainAttachHostDevice(driver, vm,
8083 dev->data.hostdev);
8084 if (!ret) {
8085 alias = dev->data.hostdev->info->alias;
8086 dev->data.hostdev = NULL;
8088 break;
8090 case VIR_DOMAIN_DEVICE_REDIRDEV:
8091 ret = qemuDomainAttachRedirdevDevice(driver, vm,
8092 dev->data.redirdev);
8093 if (!ret) {
8094 alias = dev->data.redirdev->info.alias;
8095 dev->data.redirdev = NULL;
8097 break;
8099 case VIR_DOMAIN_DEVICE_CHR:
8100 ret = qemuDomainAttachChrDevice(driver, vm,
8101 dev->data.chr);
8102 if (!ret) {
8103 alias = dev->data.chr->info.alias;
8104 dev->data.chr = NULL;
8106 break;
8108 case VIR_DOMAIN_DEVICE_RNG:
8109 ret = qemuDomainAttachRNGDevice(driver, vm,
8110 dev->data.rng);
8111 if (!ret) {
8112 alias = dev->data.rng->info.alias;
8113 dev->data.rng = NULL;
8115 break;
8117 case VIR_DOMAIN_DEVICE_MEMORY:
8118 /* note that qemuDomainAttachMemory always consumes dev->data.memory
8119 * and dispatches DeviceAdded event on success */
8120 ret = qemuDomainAttachMemory(driver, vm,
8121 dev->data.memory);
8122 dev->data.memory = NULL;
8123 break;
8125 case VIR_DOMAIN_DEVICE_SHMEM:
8126 ret = qemuDomainAttachShmemDevice(driver, vm,
8127 dev->data.shmem);
8128 if (!ret) {
8129 alias = dev->data.shmem->info.alias;
8130 dev->data.shmem = NULL;
8132 break;
8134 case VIR_DOMAIN_DEVICE_WATCHDOG:
8135 ret = qemuDomainAttachWatchdog(driver, vm,
8136 dev->data.watchdog);
8137 if (!ret) {
8138 alias = dev->data.watchdog->info.alias;
8139 dev->data.watchdog = NULL;
8141 break;
8143 case VIR_DOMAIN_DEVICE_INPUT:
8144 ret = qemuDomainAttachInputDevice(driver, vm, dev->data.input);
8145 if (ret == 0) {
8146 alias = dev->data.input->info.alias;
8147 dev->data.input = NULL;
8149 break;
8151 case VIR_DOMAIN_DEVICE_VSOCK:
8152 ret = qemuDomainAttachVsockDevice(driver, vm, dev->data.vsock);
8153 if (ret == 0) {
8154 alias = dev->data.vsock->info.alias;
8155 dev->data.vsock = NULL;
8157 break;
8159 case VIR_DOMAIN_DEVICE_NONE:
8160 case VIR_DOMAIN_DEVICE_FS:
8161 case VIR_DOMAIN_DEVICE_SOUND:
8162 case VIR_DOMAIN_DEVICE_VIDEO:
8163 case VIR_DOMAIN_DEVICE_GRAPHICS:
8164 case VIR_DOMAIN_DEVICE_HUB:
8165 case VIR_DOMAIN_DEVICE_SMARTCARD:
8166 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8167 case VIR_DOMAIN_DEVICE_NVRAM:
8168 case VIR_DOMAIN_DEVICE_TPM:
8169 case VIR_DOMAIN_DEVICE_PANIC:
8170 case VIR_DOMAIN_DEVICE_IOMMU:
8171 case VIR_DOMAIN_DEVICE_LAST:
8172 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8173 _("live attach of device '%s' is not supported"),
8174 virDomainDeviceTypeToString(dev->type));
8175 break;
8178 if (alias) {
8179 /* queue the event before the alias has a chance to get freed
8180 * if the domain disappears while qemuDomainUpdateDeviceList
8181 * is in monitor */
8182 virObjectEventPtr event;
8183 event = virDomainEventDeviceAddedNewFromObj(vm, alias);
8184 virObjectEventStateQueue(driver->domainEventState, event);
8187 if (ret == 0)
8188 ret = qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE);
8190 return ret;
8193 static int
8194 qemuDomainDetachDeviceControllerLive(virQEMUDriverPtr driver,
8195 virDomainObjPtr vm,
8196 virDomainDeviceDefPtr dev,
8197 bool async)
8199 virDomainControllerDefPtr cont = dev->data.controller;
8200 int ret = -1;
8202 switch (cont->type) {
8203 case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
8204 ret = qemuDomainDetachControllerDevice(driver, vm, dev, async);
8205 break;
8206 default :
8207 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8208 _("'%s' controller cannot be hot unplugged."),
8209 virDomainControllerTypeToString(cont->type));
8211 return ret;
8214 static int
8215 qemuDomainDetachDeviceLive(virDomainObjPtr vm,
8216 virDomainDeviceDefPtr dev,
8217 virQEMUDriverPtr driver,
8218 bool async)
8220 int ret = -1;
8222 switch ((virDomainDeviceType)dev->type) {
8223 case VIR_DOMAIN_DEVICE_DISK:
8224 ret = qemuDomainDetachDeviceDiskLive(driver, vm, dev, async);
8225 break;
8226 case VIR_DOMAIN_DEVICE_CONTROLLER:
8227 ret = qemuDomainDetachDeviceControllerLive(driver, vm, dev, async);
8228 break;
8229 case VIR_DOMAIN_DEVICE_LEASE:
8230 ret = qemuDomainDetachLease(driver, vm, dev->data.lease);
8231 break;
8232 case VIR_DOMAIN_DEVICE_NET:
8233 ret = qemuDomainDetachNetDevice(driver, vm, dev, async);
8234 break;
8235 case VIR_DOMAIN_DEVICE_HOSTDEV:
8236 ret = qemuDomainDetachHostDevice(driver, vm, dev, async);
8237 break;
8238 case VIR_DOMAIN_DEVICE_CHR:
8239 ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr, async);
8240 break;
8241 case VIR_DOMAIN_DEVICE_RNG:
8242 ret = qemuDomainDetachRNGDevice(driver, vm, dev->data.rng, async);
8243 break;
8244 case VIR_DOMAIN_DEVICE_MEMORY:
8245 ret = qemuDomainDetachMemoryDevice(driver, vm, dev->data.memory, async);
8246 break;
8247 case VIR_DOMAIN_DEVICE_SHMEM:
8248 ret = qemuDomainDetachShmemDevice(driver, vm, dev->data.shmem, async);
8249 break;
8250 case VIR_DOMAIN_DEVICE_WATCHDOG:
8251 ret = qemuDomainDetachWatchdog(driver, vm, dev->data.watchdog, async);
8252 break;
8253 case VIR_DOMAIN_DEVICE_INPUT:
8254 ret = qemuDomainDetachInputDevice(vm, dev->data.input, async);
8255 break;
8256 case VIR_DOMAIN_DEVICE_REDIRDEV:
8257 ret = qemuDomainDetachRedirdevDevice(driver, vm, dev->data.redirdev, async);
8258 break;
8260 case VIR_DOMAIN_DEVICE_VSOCK:
8261 ret = qemuDomainDetachVsockDevice(vm, dev->data.vsock, async);
8262 break;
8264 case VIR_DOMAIN_DEVICE_FS:
8265 case VIR_DOMAIN_DEVICE_SOUND:
8266 case VIR_DOMAIN_DEVICE_VIDEO:
8267 case VIR_DOMAIN_DEVICE_GRAPHICS:
8268 case VIR_DOMAIN_DEVICE_HUB:
8269 case VIR_DOMAIN_DEVICE_SMARTCARD:
8270 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8271 case VIR_DOMAIN_DEVICE_NVRAM:
8272 case VIR_DOMAIN_DEVICE_NONE:
8273 case VIR_DOMAIN_DEVICE_TPM:
8274 case VIR_DOMAIN_DEVICE_PANIC:
8275 case VIR_DOMAIN_DEVICE_IOMMU:
8276 case VIR_DOMAIN_DEVICE_LAST:
8277 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8278 _("live detach of device '%s' is not supported"),
8279 virDomainDeviceTypeToString(dev->type));
8280 break;
8283 if (ret == 0)
8284 ret = qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE);
8286 return ret;
8289 static int
8290 qemuDomainChangeDiskLive(virDomainObjPtr vm,
8291 virDomainDeviceDefPtr dev,
8292 virQEMUDriverPtr driver,
8293 bool force)
8295 virDomainDiskDefPtr disk = dev->data.disk;
8296 virDomainDiskDefPtr orig_disk = NULL;
8297 virDomainDeviceDef oldDev = { .type = dev->type };
8298 int ret = -1;
8300 if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
8301 disk->bus, disk->dst))) {
8302 virReportError(VIR_ERR_INTERNAL_ERROR,
8303 _("No device with bus '%s' and target '%s'"),
8304 virDomainDiskBusTypeToString(disk->bus),
8305 disk->dst);
8306 goto cleanup;
8309 oldDev.data.disk = orig_disk;
8310 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8311 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8312 true) < 0)
8313 goto cleanup;
8315 if (!qemuDomainDiskChangeSupported(disk, orig_disk))
8316 goto cleanup;
8318 if (!virStorageSourceIsSameLocation(disk->src, orig_disk->src)) {
8319 /* Disk source can be changed only for removable devices */
8320 if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
8321 disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
8322 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8323 _("disk source can be changed only in removable "
8324 "drives"));
8325 goto cleanup;
8328 if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
8329 dev->data.disk->src, force) < 0)
8330 goto cleanup;
8332 dev->data.disk->src = NULL;
8335 orig_disk->startupPolicy = dev->data.disk->startupPolicy;
8336 orig_disk->snapshot = dev->data.disk->snapshot;
8338 ret = 0;
8339 cleanup:
8340 return ret;
8343 static int
8344 qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
8345 virDomainDeviceDefPtr dev,
8346 virDomainPtr dom,
8347 bool force)
8349 virQEMUDriverPtr driver = dom->conn->privateData;
8350 virDomainDeviceDef oldDev = { .type = dev->type };
8351 int ret = -1;
8352 int idx;
8354 switch ((virDomainDeviceType)dev->type) {
8355 case VIR_DOMAIN_DEVICE_DISK:
8356 qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
8357 ret = qemuDomainChangeDiskLive(vm, dev, driver, force);
8358 break;
8360 case VIR_DOMAIN_DEVICE_GRAPHICS:
8361 if ((idx = qemuDomainFindGraphicsIndex(vm->def, dev->data.graphics)) >= 0) {
8362 oldDev.data.graphics = vm->def->graphics[idx];
8363 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8364 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8365 true) < 0)
8366 return -1;
8369 ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
8370 break;
8372 case VIR_DOMAIN_DEVICE_NET:
8373 if ((idx = virDomainNetFindIdx(vm->def, dev->data.net)) >= 0) {
8374 oldDev.data.net = vm->def->nets[idx];
8375 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8376 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8377 true) < 0)
8378 return -1;
8381 ret = qemuDomainChangeNet(driver, vm, dev);
8382 break;
8384 case VIR_DOMAIN_DEVICE_FS:
8385 case VIR_DOMAIN_DEVICE_INPUT:
8386 case VIR_DOMAIN_DEVICE_SOUND:
8387 case VIR_DOMAIN_DEVICE_VIDEO:
8388 case VIR_DOMAIN_DEVICE_WATCHDOG:
8389 case VIR_DOMAIN_DEVICE_HUB:
8390 case VIR_DOMAIN_DEVICE_SMARTCARD:
8391 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8392 case VIR_DOMAIN_DEVICE_NVRAM:
8393 case VIR_DOMAIN_DEVICE_RNG:
8394 case VIR_DOMAIN_DEVICE_SHMEM:
8395 case VIR_DOMAIN_DEVICE_LEASE:
8396 case VIR_DOMAIN_DEVICE_HOSTDEV:
8397 case VIR_DOMAIN_DEVICE_CONTROLLER:
8398 case VIR_DOMAIN_DEVICE_REDIRDEV:
8399 case VIR_DOMAIN_DEVICE_MEMORY:
8400 case VIR_DOMAIN_DEVICE_CHR:
8401 case VIR_DOMAIN_DEVICE_NONE:
8402 case VIR_DOMAIN_DEVICE_TPM:
8403 case VIR_DOMAIN_DEVICE_PANIC:
8404 case VIR_DOMAIN_DEVICE_IOMMU:
8405 case VIR_DOMAIN_DEVICE_VSOCK:
8406 case VIR_DOMAIN_DEVICE_LAST:
8407 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8408 _("live update of device '%s' is not supported"),
8409 virDomainDeviceTypeToString(dev->type));
8410 break;
8413 return ret;
8416 static int
8417 qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
8418 virDomainDeviceDefPtr dev,
8419 virCapsPtr caps,
8420 unsigned int parse_flags,
8421 virDomainXMLOptionPtr xmlopt)
8423 virDomainDiskDefPtr disk;
8424 virDomainNetDefPtr net;
8425 virDomainHostdevDefPtr hostdev;
8426 virDomainLeaseDefPtr lease;
8427 virDomainControllerDefPtr controller;
8428 virDomainFSDefPtr fs;
8429 virDomainRedirdevDefPtr redirdev;
8430 virDomainShmemDefPtr shmem;
8432 switch ((virDomainDeviceType)dev->type) {
8433 case VIR_DOMAIN_DEVICE_DISK:
8434 disk = dev->data.disk;
8435 if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
8436 virReportError(VIR_ERR_OPERATION_INVALID,
8437 _("target %s already exists"), disk->dst);
8438 return -1;
8440 if (virDomainDiskTranslateSourcePool(disk) < 0)
8441 return -1;
8442 if (qemuCheckDiskConfig(disk, NULL) < 0)
8443 return -1;
8444 if (virDomainDiskInsert(vmdef, disk))
8445 return -1;
8446 /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
8447 dev->data.disk = NULL;
8448 break;
8450 case VIR_DOMAIN_DEVICE_NET:
8451 net = dev->data.net;
8452 if (virDomainNetInsert(vmdef, net))
8453 return -1;
8454 dev->data.net = NULL;
8455 break;
8457 case VIR_DOMAIN_DEVICE_HOSTDEV:
8458 hostdev = dev->data.hostdev;
8459 if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
8460 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8461 _("device is already in the domain configuration"));
8462 return -1;
8464 if (virDomainHostdevInsert(vmdef, hostdev))
8465 return -1;
8466 dev->data.hostdev = NULL;
8467 break;
8469 case VIR_DOMAIN_DEVICE_LEASE:
8470 lease = dev->data.lease;
8471 if (virDomainLeaseIndex(vmdef, lease) >= 0) {
8472 virReportError(VIR_ERR_OPERATION_INVALID,
8473 _("Lease %s in lockspace %s already exists"),
8474 lease->key, NULLSTR(lease->lockspace));
8475 return -1;
8477 if (virDomainLeaseInsert(vmdef, lease) < 0)
8478 return -1;
8480 /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
8481 dev->data.lease = NULL;
8482 break;
8484 case VIR_DOMAIN_DEVICE_CONTROLLER:
8485 controller = dev->data.controller;
8486 if (controller->idx != -1 &&
8487 virDomainControllerFind(vmdef, controller->type,
8488 controller->idx) >= 0) {
8489 virReportError(VIR_ERR_OPERATION_INVALID,
8490 _("controller index='%d' already exists"),
8491 controller->idx);
8492 return -1;
8495 if (virDomainControllerInsert(vmdef, controller) < 0)
8496 return -1;
8497 dev->data.controller = NULL;
8499 break;
8501 case VIR_DOMAIN_DEVICE_CHR:
8502 if (qemuDomainChrInsert(vmdef, dev->data.chr) < 0)
8503 return -1;
8504 dev->data.chr = NULL;
8505 break;
8507 case VIR_DOMAIN_DEVICE_FS:
8508 fs = dev->data.fs;
8509 if (virDomainFSIndexByName(vmdef, fs->dst) >= 0) {
8510 virReportError(VIR_ERR_OPERATION_INVALID,
8511 "%s", _("Target already exists"));
8512 return -1;
8515 if (virDomainFSInsert(vmdef, fs) < 0)
8516 return -1;
8517 dev->data.fs = NULL;
8518 break;
8520 case VIR_DOMAIN_DEVICE_RNG:
8521 if (dev->data.rng->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
8522 virDomainDefHasDeviceAddress(vmdef, &dev->data.rng->info)) {
8523 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8524 _("a device with the same address already exists "));
8525 return -1;
8528 if (VIR_APPEND_ELEMENT(vmdef->rngs, vmdef->nrngs, dev->data.rng) < 0)
8529 return -1;
8530 dev->data.rng = NULL;
8532 break;
8534 case VIR_DOMAIN_DEVICE_MEMORY:
8535 if (vmdef->nmems == vmdef->mem.memory_slots) {
8536 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8537 _("no free memory device slot available"));
8538 return -1;
8541 vmdef->mem.cur_balloon += dev->data.memory->size;
8543 if (virDomainMemoryInsert(vmdef, dev->data.memory) < 0)
8544 return -1;
8545 dev->data.memory = NULL;
8546 break;
8548 case VIR_DOMAIN_DEVICE_REDIRDEV:
8549 redirdev = dev->data.redirdev;
8551 if (VIR_APPEND_ELEMENT(vmdef->redirdevs, vmdef->nredirdevs, redirdev) < 0)
8552 return -1;
8553 dev->data.redirdev = NULL;
8554 break;
8556 case VIR_DOMAIN_DEVICE_SHMEM:
8557 shmem = dev->data.shmem;
8558 if (virDomainShmemDefFind(vmdef, shmem) >= 0) {
8559 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8560 _("device is already in the domain configuration"));
8561 return -1;
8563 if (virDomainShmemDefInsert(vmdef, shmem) < 0)
8564 return -1;
8565 dev->data.shmem = NULL;
8566 break;
8568 case VIR_DOMAIN_DEVICE_WATCHDOG:
8569 if (vmdef->watchdog) {
8570 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8571 _("domain already has a watchdog"));
8572 return -1;
8574 VIR_STEAL_PTR(vmdef->watchdog, dev->data.watchdog);
8575 break;
8577 case VIR_DOMAIN_DEVICE_INPUT:
8578 if (VIR_APPEND_ELEMENT(vmdef->inputs, vmdef->ninputs, dev->data.input) < 0)
8579 return -1;
8580 break;
8582 case VIR_DOMAIN_DEVICE_VSOCK:
8583 if (vmdef->vsock) {
8584 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8585 _("domain already has a vsock device"));
8586 return -1;
8588 VIR_STEAL_PTR(vmdef->vsock, dev->data.vsock);
8589 break;
8591 case VIR_DOMAIN_DEVICE_SOUND:
8592 case VIR_DOMAIN_DEVICE_VIDEO:
8593 case VIR_DOMAIN_DEVICE_GRAPHICS:
8594 case VIR_DOMAIN_DEVICE_HUB:
8595 case VIR_DOMAIN_DEVICE_SMARTCARD:
8596 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8597 case VIR_DOMAIN_DEVICE_NVRAM:
8598 case VIR_DOMAIN_DEVICE_NONE:
8599 case VIR_DOMAIN_DEVICE_TPM:
8600 case VIR_DOMAIN_DEVICE_PANIC:
8601 case VIR_DOMAIN_DEVICE_IOMMU:
8602 case VIR_DOMAIN_DEVICE_LAST:
8603 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8604 _("persistent attach of device '%s' is not supported"),
8605 virDomainDeviceTypeToString(dev->type));
8606 return -1;
8609 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8610 return -1;
8612 return 0;
8616 static int
8617 qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
8618 virDomainDeviceDefPtr dev,
8619 virCapsPtr caps,
8620 unsigned int parse_flags,
8621 virDomainXMLOptionPtr xmlopt)
8623 virDomainDiskDefPtr disk, det_disk;
8624 virDomainNetDefPtr net;
8625 virDomainHostdevDefPtr hostdev, det_hostdev;
8626 virDomainLeaseDefPtr lease, det_lease;
8627 virDomainControllerDefPtr cont, det_cont;
8628 virDomainChrDefPtr chr;
8629 virDomainFSDefPtr fs;
8630 virDomainMemoryDefPtr mem;
8631 int idx;
8633 switch ((virDomainDeviceType)dev->type) {
8634 case VIR_DOMAIN_DEVICE_DISK:
8635 disk = dev->data.disk;
8636 if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
8637 virReportError(VIR_ERR_DEVICE_MISSING,
8638 _("no target device %s"), disk->dst);
8639 return -1;
8641 virDomainDiskDefFree(det_disk);
8642 break;
8644 case VIR_DOMAIN_DEVICE_NET:
8645 net = dev->data.net;
8646 if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
8647 return -1;
8649 /* this is guaranteed to succeed */
8650 virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
8651 break;
8653 case VIR_DOMAIN_DEVICE_HOSTDEV: {
8654 hostdev = dev->data.hostdev;
8655 if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
8656 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8657 _("device not present in domain configuration"));
8658 return -1;
8660 virDomainHostdevRemove(vmdef, idx);
8661 virDomainHostdevDefFree(det_hostdev);
8662 break;
8665 case VIR_DOMAIN_DEVICE_LEASE:
8666 lease = dev->data.lease;
8667 if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
8668 virReportError(VIR_ERR_DEVICE_MISSING,
8669 _("Lease %s in lockspace %s does not exist"),
8670 lease->key, NULLSTR(lease->lockspace));
8671 return -1;
8673 virDomainLeaseDefFree(det_lease);
8674 break;
8676 case VIR_DOMAIN_DEVICE_CONTROLLER:
8677 cont = dev->data.controller;
8678 if ((idx = virDomainControllerFind(vmdef, cont->type,
8679 cont->idx)) < 0) {
8680 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8681 _("device not present in domain configuration"));
8682 return -1;
8684 det_cont = virDomainControllerRemove(vmdef, idx);
8685 virDomainControllerDefFree(det_cont);
8687 break;
8689 case VIR_DOMAIN_DEVICE_CHR:
8690 if (!(chr = qemuDomainChrRemove(vmdef, dev->data.chr)))
8691 return -1;
8693 virDomainChrDefFree(chr);
8694 break;
8696 case VIR_DOMAIN_DEVICE_FS:
8697 fs = dev->data.fs;
8698 idx = virDomainFSIndexByName(vmdef, fs->dst);
8699 if (idx < 0) {
8700 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8701 _("no matching filesystem device was found"));
8702 return -1;
8705 fs = virDomainFSRemove(vmdef, idx);
8706 virDomainFSDefFree(fs);
8707 break;
8709 case VIR_DOMAIN_DEVICE_RNG:
8710 if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
8711 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8712 _("no matching RNG device was found"));
8713 return -1;
8716 virDomainRNGDefFree(virDomainRNGRemove(vmdef, idx));
8717 break;
8719 case VIR_DOMAIN_DEVICE_MEMORY:
8720 if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
8721 dev->data.memory)) < 0) {
8722 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8723 _("matching memory device was not found"));
8724 return -1;
8726 mem = virDomainMemoryRemove(vmdef, idx);
8727 vmdef->mem.cur_balloon -= mem->size;
8728 virDomainMemoryDefFree(mem);
8729 break;
8731 case VIR_DOMAIN_DEVICE_REDIRDEV:
8732 if ((idx = virDomainRedirdevDefFind(vmdef,
8733 dev->data.redirdev)) < 0) {
8734 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8735 _("no matching redirdev was not found"));
8736 return -1;
8739 virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx));
8740 break;
8742 case VIR_DOMAIN_DEVICE_SHMEM:
8743 if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) {
8744 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8745 _("matching shmem device was not found"));
8746 return -1;
8749 virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx));
8750 break;
8753 case VIR_DOMAIN_DEVICE_WATCHDOG:
8754 if (!vmdef->watchdog) {
8755 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8756 _("domain has no watchdog"));
8757 return -1;
8759 virDomainWatchdogDefFree(vmdef->watchdog);
8760 vmdef->watchdog = NULL;
8761 break;
8763 case VIR_DOMAIN_DEVICE_INPUT:
8764 if ((idx = virDomainInputDefFind(vmdef, dev->data.input)) < 0) {
8765 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8766 _("matching input device not found"));
8767 return -1;
8769 VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
8770 break;
8772 case VIR_DOMAIN_DEVICE_VSOCK:
8773 if (!vmdef->vsock ||
8774 !virDomainVsockDefEquals(dev->data.vsock, vmdef->vsock)) {
8775 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
8776 _("matching vsock device not found"));
8777 return -1;
8779 virDomainVsockDefFree(vmdef->vsock);
8780 vmdef->vsock = NULL;
8781 break;
8783 case VIR_DOMAIN_DEVICE_SOUND:
8784 case VIR_DOMAIN_DEVICE_VIDEO:
8785 case VIR_DOMAIN_DEVICE_GRAPHICS:
8786 case VIR_DOMAIN_DEVICE_HUB:
8787 case VIR_DOMAIN_DEVICE_SMARTCARD:
8788 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8789 case VIR_DOMAIN_DEVICE_NVRAM:
8790 case VIR_DOMAIN_DEVICE_NONE:
8791 case VIR_DOMAIN_DEVICE_TPM:
8792 case VIR_DOMAIN_DEVICE_PANIC:
8793 case VIR_DOMAIN_DEVICE_IOMMU:
8794 case VIR_DOMAIN_DEVICE_LAST:
8795 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8796 _("persistent detach of device '%s' is not supported"),
8797 virDomainDeviceTypeToString(dev->type));
8798 return -1;
8801 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8802 return -1;
8804 return 0;
8807 static int
8808 qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
8809 virDomainDeviceDefPtr dev,
8810 virCapsPtr caps,
8811 unsigned int parse_flags,
8812 virDomainXMLOptionPtr xmlopt)
8814 virDomainDiskDefPtr newDisk;
8815 virDomainGraphicsDefPtr newGraphics;
8816 virDomainNetDefPtr net;
8817 virDomainDeviceDef oldDev = { .type = dev->type };
8818 int pos;
8820 switch ((virDomainDeviceType)dev->type) {
8821 case VIR_DOMAIN_DEVICE_DISK:
8822 newDisk = dev->data.disk;
8823 if ((pos = virDomainDiskIndexByName(vmdef, newDisk->dst, false)) < 0) {
8824 virReportError(VIR_ERR_INVALID_ARG,
8825 _("target %s doesn't exist."), newDisk->dst);
8826 return -1;
8829 oldDev.data.disk = vmdef->disks[pos];
8830 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8831 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8832 false) < 0)
8833 return -1;
8835 virDomainDiskDefFree(vmdef->disks[pos]);
8836 vmdef->disks[pos] = newDisk;
8837 dev->data.disk = NULL;
8838 break;
8840 case VIR_DOMAIN_DEVICE_GRAPHICS:
8841 newGraphics = dev->data.graphics;
8842 pos = qemuDomainFindGraphicsIndex(vmdef, newGraphics);
8843 if (pos < 0) {
8844 virReportError(VIR_ERR_INVALID_ARG,
8845 _("cannot find existing graphics type '%s' device to modify"),
8846 virDomainGraphicsTypeToString(newGraphics->type));
8847 return -1;
8850 oldDev.data.graphics = vmdef->graphics[pos];
8851 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8852 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8853 false) < 0)
8854 return -1;
8856 virDomainGraphicsDefFree(vmdef->graphics[pos]);
8857 vmdef->graphics[pos] = newGraphics;
8858 dev->data.graphics = NULL;
8859 break;
8861 case VIR_DOMAIN_DEVICE_NET:
8862 net = dev->data.net;
8863 if ((pos = virDomainNetFindIdx(vmdef, net)) < 0)
8864 return -1;
8866 oldDev.data.net = vmdef->nets[pos];
8867 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8868 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8869 false) < 0)
8870 return -1;
8872 virDomainNetDefFree(vmdef->nets[pos]);
8873 vmdef->nets[pos] = net;
8874 dev->data.net = NULL;
8875 break;
8877 case VIR_DOMAIN_DEVICE_FS:
8878 case VIR_DOMAIN_DEVICE_INPUT:
8879 case VIR_DOMAIN_DEVICE_SOUND:
8880 case VIR_DOMAIN_DEVICE_VIDEO:
8881 case VIR_DOMAIN_DEVICE_WATCHDOG:
8882 case VIR_DOMAIN_DEVICE_HUB:
8883 case VIR_DOMAIN_DEVICE_SMARTCARD:
8884 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8885 case VIR_DOMAIN_DEVICE_NVRAM:
8886 case VIR_DOMAIN_DEVICE_RNG:
8887 case VIR_DOMAIN_DEVICE_SHMEM:
8888 case VIR_DOMAIN_DEVICE_LEASE:
8889 case VIR_DOMAIN_DEVICE_HOSTDEV:
8890 case VIR_DOMAIN_DEVICE_CONTROLLER:
8891 case VIR_DOMAIN_DEVICE_REDIRDEV:
8892 case VIR_DOMAIN_DEVICE_CHR:
8893 case VIR_DOMAIN_DEVICE_MEMORY:
8894 case VIR_DOMAIN_DEVICE_NONE:
8895 case VIR_DOMAIN_DEVICE_TPM:
8896 case VIR_DOMAIN_DEVICE_PANIC:
8897 case VIR_DOMAIN_DEVICE_IOMMU:
8898 case VIR_DOMAIN_DEVICE_VSOCK:
8899 case VIR_DOMAIN_DEVICE_LAST:
8900 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8901 _("persistent update of device '%s' is not supported"),
8902 virDomainDeviceTypeToString(dev->type));
8903 return -1;
8906 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8907 return -1;
8909 return 0;
8912 static int
8913 qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
8914 virQEMUDriverPtr driver,
8915 const char *xml,
8916 unsigned int flags)
8918 virDomainDefPtr vmdef = NULL;
8919 virQEMUDriverConfigPtr cfg = NULL;
8920 virDomainDeviceDefPtr devConf = NULL;
8921 virDomainDeviceDefPtr devLive = NULL;
8922 int ret = -1;
8923 virCapsPtr caps = NULL;
8924 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
8925 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
8927 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8928 VIR_DOMAIN_AFFECT_CONFIG, -1);
8930 cfg = virQEMUDriverGetConfig(driver);
8932 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
8933 goto cleanup;
8935 /* The config and live post processing address auto-generation algorithms
8936 * rely on the correct vm->def or vm->newDef being passed, so call the
8937 * device parse based on which definition is in use */
8938 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8939 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
8940 if (!vmdef)
8941 goto cleanup;
8943 if (!(devConf = virDomainDeviceDefParse(xml, vmdef, caps,
8944 driver->xmlopt, parse_flags)))
8945 goto cleanup;
8947 if (virDomainDefCompatibleDevice(vmdef, devConf, NULL,
8948 VIR_DOMAIN_DEVICE_ACTION_ATTACH,
8949 false) < 0)
8950 goto cleanup;
8952 if ((ret = qemuDomainAttachDeviceConfig(vmdef, devConf, caps,
8953 parse_flags,
8954 driver->xmlopt)) < 0)
8955 goto cleanup;
8958 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8959 if (!(devLive = virDomainDeviceDefParse(xml, vm->def, caps,
8960 driver->xmlopt, parse_flags)))
8961 goto cleanup;
8963 if (virDomainDeviceValidateAliasForHotplug(vm, devLive, flags) < 0)
8964 goto cleanup;
8966 if (virDomainDefCompatibleDevice(vm->def, devLive, NULL,
8967 VIR_DOMAIN_DEVICE_ACTION_ATTACH,
8968 true) < 0)
8969 goto cleanup;
8971 if ((ret = qemuDomainAttachDeviceLive(vm, devLive, driver)) < 0)
8972 goto cleanup;
8974 * update domain status forcibly because the domain status may be
8975 * changed even if we failed to attach the device. For example,
8976 * a new controller may be created.
8978 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
8979 ret = -1;
8980 goto cleanup;
8984 /* Finally, if no error until here, we can save config. */
8985 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8986 ret = virDomainSaveConfig(cfg->configDir, driver->caps, vmdef);
8987 if (!ret) {
8988 virDomainObjAssignDef(vm, vmdef, false, NULL);
8989 vmdef = NULL;
8993 cleanup:
8994 virDomainDefFree(vmdef);
8995 virDomainDeviceDefFree(devConf);
8996 virDomainDeviceDefFree(devLive);
8997 virObjectUnref(cfg);
8998 virObjectUnref(caps);
9000 return ret;
9003 static int
9004 qemuDomainAttachDeviceFlags(virDomainPtr dom,
9005 const char *xml,
9006 unsigned int flags)
9008 virQEMUDriverPtr driver = dom->conn->privateData;
9009 virDomainObjPtr vm = NULL;
9010 int ret = -1;
9012 virNWFilterReadLockFilterUpdates();
9014 if (!(vm = qemuDomObjFromDomain(dom)))
9015 goto cleanup;
9017 if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
9018 goto cleanup;
9020 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9021 goto cleanup;
9023 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9024 goto endjob;
9026 if (qemuDomainAttachDeviceLiveAndConfig(vm, driver, xml, flags) < 0)
9027 goto endjob;
9029 ret = 0;
9031 endjob:
9032 qemuDomainObjEndJob(driver, vm);
9034 cleanup:
9035 virDomainObjEndAPI(&vm);
9036 virNWFilterUnlockFilterUpdates();
9037 return ret;
9040 static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
9042 return qemuDomainAttachDeviceFlags(dom, xml,
9043 VIR_DOMAIN_AFFECT_LIVE);
9047 static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
9048 const char *xml,
9049 unsigned int flags)
9051 virQEMUDriverPtr driver = dom->conn->privateData;
9052 virDomainObjPtr vm = NULL;
9053 virDomainDefPtr vmdef = NULL;
9054 virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
9055 bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
9056 int ret = -1;
9057 virQEMUDriverConfigPtr cfg = NULL;
9058 virCapsPtr caps = NULL;
9059 unsigned int parse_flags = 0;
9061 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9062 VIR_DOMAIN_AFFECT_CONFIG |
9063 VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);
9065 virNWFilterReadLockFilterUpdates();
9067 cfg = virQEMUDriverGetConfig(driver);
9069 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
9070 goto cleanup;
9072 if (!(vm = qemuDomObjFromDomain(dom)))
9073 goto cleanup;
9075 if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
9076 goto cleanup;
9078 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9079 goto cleanup;
9081 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9082 goto endjob;
9084 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
9085 !(flags & VIR_DOMAIN_AFFECT_LIVE))
9086 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
9088 dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
9089 caps, driver->xmlopt,
9090 parse_flags);
9091 if (dev == NULL)
9092 goto endjob;
9094 if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
9095 flags & VIR_DOMAIN_AFFECT_LIVE) {
9096 /* If we are affecting both CONFIG and LIVE
9097 * create a deep copy of device as adding
9098 * to CONFIG takes one instance.
9100 dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
9101 if (!dev_copy)
9102 goto endjob;
9105 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9106 /* Make a copy for updated domain. */
9107 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
9108 if (!vmdef)
9109 goto endjob;
9111 /* virDomainDefCompatibleDevice call is delayed until we know the
9112 * device we're going to update. */
9113 if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps,
9114 parse_flags,
9115 driver->xmlopt)) < 0)
9116 goto endjob;
9119 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9120 /* virDomainDefCompatibleDevice call is delayed until we know the
9121 * device we're going to update. */
9122 if ((ret = qemuDomainUpdateDeviceLive(vm, dev_copy, dom, force)) < 0)
9123 goto endjob;
9125 * update domain status forcibly because the domain status may be
9126 * changed even if we failed to attach the device. For example,
9127 * a new controller may be created.
9129 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
9130 ret = -1;
9131 goto endjob;
9135 /* Finally, if no error until here, we can save config. */
9136 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9137 ret = virDomainSaveConfig(cfg->configDir, driver->caps, vmdef);
9138 if (!ret) {
9139 virDomainObjAssignDef(vm, vmdef, false, NULL);
9140 vmdef = NULL;
9144 endjob:
9145 qemuDomainObjEndJob(driver, vm);
9147 cleanup:
9148 virDomainDefFree(vmdef);
9149 if (dev != dev_copy)
9150 virDomainDeviceDefFree(dev_copy);
9151 virDomainDeviceDefFree(dev);
9152 virDomainObjEndAPI(&vm);
9153 virObjectUnref(caps);
9154 virObjectUnref(cfg);
9155 virNWFilterUnlockFilterUpdates();
9156 return ret;
9159 static int
9160 qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
9161 virDomainObjPtr vm,
9162 const char *xml,
9163 unsigned int flags)
9165 virCapsPtr caps = NULL;
9166 virQEMUDriverConfigPtr cfg = NULL;
9167 virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
9168 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
9169 virDomainDefPtr vmdef = NULL;
9170 int ret = -1;
9172 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9173 VIR_DOMAIN_AFFECT_CONFIG, -1);
9175 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
9176 goto cleanup;
9178 cfg = virQEMUDriverGetConfig(driver);
9180 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
9181 !(flags & VIR_DOMAIN_AFFECT_LIVE))
9182 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
9184 dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
9185 caps, driver->xmlopt,
9186 parse_flags);
9187 if (dev == NULL)
9188 goto cleanup;
9190 if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
9191 flags & VIR_DOMAIN_AFFECT_LIVE) {
9192 /* If we are affecting both CONFIG and LIVE
9193 * create a deep copy of device as adding
9194 * to CONFIG takes one instance.
9196 dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
9197 if (!dev_copy)
9198 goto cleanup;
9201 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9202 /* Make a copy for updated domain. */
9203 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
9204 if (!vmdef)
9205 goto cleanup;
9207 if (qemuDomainDetachDeviceConfig(vmdef, dev, caps,
9208 parse_flags,
9209 driver->xmlopt) < 0)
9210 goto cleanup;
9213 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9214 if (qemuDomainDetachDeviceLive(vm, dev_copy, driver, false) < 0)
9215 goto cleanup;
9217 * update domain status forcibly because the domain status may be
9218 * changed even if we failed to attach the device. For example,
9219 * a new controller may be created.
9221 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, caps) < 0)
9222 goto cleanup;
9225 /* Finally, if no error until here, we can save config. */
9226 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9227 if (virDomainSaveConfig(cfg->configDir, caps, vmdef) < 0)
9228 goto cleanup;
9230 virDomainObjAssignDef(vm, vmdef, false, NULL);
9231 vmdef = NULL;
9234 ret = 0;
9236 cleanup:
9237 virObjectUnref(caps);
9238 virObjectUnref(cfg);
9239 if (dev != dev_copy)
9240 virDomainDeviceDefFree(dev_copy);
9241 virDomainDeviceDefFree(dev);
9242 virDomainDefFree(vmdef);
9243 return ret;
9247 static int
9248 qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
9249 virDomainObjPtr vm,
9250 const char *alias,
9251 unsigned int flags)
9253 virCapsPtr caps = NULL;
9254 virQEMUDriverConfigPtr cfg = NULL;
9255 virDomainDefPtr def = NULL;
9256 virDomainDefPtr persistentDef = NULL;
9257 virDomainDefPtr vmdef = NULL;
9258 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
9259 int ret = -1;
9261 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9262 VIR_DOMAIN_AFFECT_CONFIG, -1);
9264 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
9265 goto cleanup;
9267 cfg = virQEMUDriverGetConfig(driver);
9269 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
9270 !(flags & VIR_DOMAIN_AFFECT_LIVE))
9271 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
9273 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9274 goto cleanup;
9276 if (persistentDef) {
9277 virDomainDeviceDef dev;
9279 if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt)))
9280 goto cleanup;
9282 if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0)
9283 goto cleanup;
9285 if (qemuDomainDetachDeviceConfig(vmdef, &dev, caps,
9286 parse_flags, driver->xmlopt) < 0)
9287 goto cleanup;
9290 if (def) {
9291 virDomainDeviceDef dev;
9293 if (virDomainDefFindDevice(def, alias, &dev, true) < 0)
9294 goto cleanup;
9296 if (qemuDomainDetachDeviceLive(vm, &dev, driver, true) < 0)
9297 goto cleanup;
9300 if (vmdef) {
9301 if (virDomainSaveConfig(cfg->configDir, caps, vmdef) < 0)
9302 goto cleanup;
9303 virDomainObjAssignDef(vm, vmdef, false, NULL);
9304 vmdef = NULL;
9307 ret = 0;
9308 cleanup:
9309 virDomainDefFree(vmdef);
9310 virObjectUnref(cfg);
9311 virObjectUnref(caps);
9312 return ret;
9316 static int
9317 qemuDomainDetachDeviceFlags(virDomainPtr dom,
9318 const char *xml,
9319 unsigned int flags)
9321 virQEMUDriverPtr driver = dom->conn->privateData;
9322 virDomainObjPtr vm = NULL;
9323 int ret = -1;
9325 if (!(vm = qemuDomObjFromDomain(dom)))
9326 goto cleanup;
9328 if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
9329 goto cleanup;
9331 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9332 goto cleanup;
9334 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9335 goto endjob;
9337 if (qemuDomainDetachDeviceLiveAndConfig(driver, vm, xml, flags) < 0)
9338 goto endjob;
9340 ret = 0;
9342 endjob:
9343 qemuDomainObjEndJob(driver, vm);
9345 cleanup:
9346 virDomainObjEndAPI(&vm);
9347 return ret;
9351 static int
9352 qemuDomainDetachDeviceAlias(virDomainPtr dom,
9353 const char *alias,
9354 unsigned int flags)
9356 virQEMUDriverPtr driver = dom->conn->privateData;
9357 virDomainObjPtr vm = NULL;
9358 int ret = -1;
9360 if (!(vm = qemuDomObjFromDomain(dom)))
9361 goto cleanup;
9363 if (virDomainDetachDeviceAliasEnsureACL(dom->conn, vm->def, flags) < 0)
9364 goto cleanup;
9366 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9367 goto cleanup;
9369 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9370 goto endjob;
9372 if (qemuDomainDetachDeviceAliasLiveAndConfig(driver, vm, alias, flags) < 0)
9373 goto endjob;
9375 ret = 0;
9377 endjob:
9378 qemuDomainObjEndJob(driver, vm);
9380 cleanup:
9381 virDomainObjEndAPI(&vm);
9382 return ret;
9386 static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
9388 return qemuDomainDetachDeviceFlags(dom, xml,
9389 VIR_DOMAIN_AFFECT_LIVE);
9392 static int qemuDomainGetAutostart(virDomainPtr dom,
9393 int *autostart)
9395 virDomainObjPtr vm;
9396 int ret = -1;
9398 if (!(vm = qemuDomObjFromDomain(dom)))
9399 goto cleanup;
9401 if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
9402 goto cleanup;
9404 *autostart = vm->autostart;
9405 ret = 0;
9407 cleanup:
9408 virDomainObjEndAPI(&vm);
9409 return ret;
9412 static int qemuDomainSetAutostart(virDomainPtr dom,
9413 int autostart)
9415 virQEMUDriverPtr driver = dom->conn->privateData;
9416 virDomainObjPtr vm;
9417 char *configFile = NULL, *autostartLink = NULL;
9418 int ret = -1;
9419 virQEMUDriverConfigPtr cfg = NULL;
9421 if (!(vm = qemuDomObjFromDomain(dom)))
9422 return -1;
9424 cfg = virQEMUDriverGetConfig(driver);
9426 if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
9427 goto cleanup;
9429 if (!vm->persistent) {
9430 virReportError(VIR_ERR_OPERATION_INVALID,
9431 "%s", _("cannot set autostart for transient domain"));
9432 goto cleanup;
9435 autostart = (autostart != 0);
9437 if (vm->autostart != autostart) {
9438 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9439 goto cleanup;
9441 if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
9442 goto endjob;
9444 if (!(autostartLink = virDomainConfigFile(cfg->autostartDir,
9445 vm->def->name)))
9446 goto endjob;
9448 if (autostart) {
9449 if (virFileMakePath(cfg->autostartDir) < 0) {
9450 virReportSystemError(errno,
9451 _("cannot create autostart directory %s"),
9452 cfg->autostartDir);
9453 goto endjob;
9456 if (symlink(configFile, autostartLink) < 0) {
9457 virReportSystemError(errno,
9458 _("Failed to create symlink '%s to '%s'"),
9459 autostartLink, configFile);
9460 goto endjob;
9462 } else {
9463 if (unlink(autostartLink) < 0 &&
9464 errno != ENOENT &&
9465 errno != ENOTDIR) {
9466 virReportSystemError(errno,
9467 _("Failed to delete symlink '%s'"),
9468 autostartLink);
9469 goto endjob;
9473 vm->autostart = autostart;
9475 endjob:
9476 qemuDomainObjEndJob(driver, vm);
9478 ret = 0;
9480 cleanup:
9481 VIR_FREE(configFile);
9482 VIR_FREE(autostartLink);
9483 virDomainObjEndAPI(&vm);
9484 virObjectUnref(cfg);
9485 return ret;
9489 static char *qemuDomainGetSchedulerType(virDomainPtr dom,
9490 int *nparams)
9492 char *ret = NULL;
9493 virDomainObjPtr vm = NULL;
9494 qemuDomainObjPrivatePtr priv;
9495 virQEMUDriverPtr driver = dom->conn->privateData;
9497 if (!(vm = qemuDomObjFromDomain(dom)))
9498 goto cleanup;
9500 priv = vm->privateData;
9502 if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
9503 goto cleanup;
9505 if (!virQEMUDriverIsPrivileged(driver)) {
9506 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9507 _("CPU tuning is not available in session mode"));
9508 goto cleanup;
9511 /* Domain not running, thus no cgroups - return defaults */
9512 if (!virDomainObjIsActive(vm)) {
9513 if (nparams)
9514 *nparams = 9;
9515 ignore_value(VIR_STRDUP(ret, "posix"));
9516 goto cleanup;
9519 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
9520 virReportError(VIR_ERR_OPERATION_INVALID,
9521 "%s", _("cgroup CPU controller is not mounted"));
9522 goto cleanup;
9525 if (nparams) {
9526 if (virCgroupSupportsCpuBW(priv->cgroup))
9527 *nparams = 9;
9528 else
9529 *nparams = 1;
9532 ignore_value(VIR_STRDUP(ret, "posix"));
9534 cleanup:
9535 virDomainObjEndAPI(&vm);
9536 return ret;
9539 /* blkioDeviceStr in the form of /device/path,weight,/device/path,weight
9540 * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
9542 static int
9543 qemuDomainParseBlkioDeviceStr(char *blkioDeviceStr, const char *type,
9544 virBlkioDevicePtr *dev, size_t *size)
9546 char *temp;
9547 int ndevices = 0;
9548 int nsep = 0;
9549 size_t i;
9550 virBlkioDevicePtr result = NULL;
9552 *dev = NULL;
9553 *size = 0;
9555 if (STREQ(blkioDeviceStr, ""))
9556 return 0;
9558 temp = blkioDeviceStr;
9559 while (temp) {
9560 temp = strchr(temp, ',');
9561 if (temp) {
9562 temp++;
9563 nsep++;
9567 /* A valid string must have even number of fields, hence an odd
9568 * number of commas. */
9569 if (!(nsep & 1))
9570 goto parse_error;
9572 ndevices = (nsep + 1) / 2;
9574 if (VIR_ALLOC_N(result, ndevices) < 0)
9575 return -1;
9577 i = 0;
9578 temp = blkioDeviceStr;
9579 while (temp) {
9580 char *p = temp;
9582 /* device path */
9583 p = strchr(p, ',');
9584 if (!p)
9585 goto parse_error;
9587 if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0)
9588 goto cleanup;
9590 /* value */
9591 temp = p + 1;
9593 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9594 if (virStrToLong_uip(temp, &p, 10, &result[i].weight) < 0)
9595 goto number_error;
9596 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9597 if (virStrToLong_uip(temp, &p, 10, &result[i].riops) < 0)
9598 goto number_error;
9599 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9600 if (virStrToLong_uip(temp, &p, 10, &result[i].wiops) < 0)
9601 goto number_error;
9602 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9603 if (virStrToLong_ullp(temp, &p, 10, &result[i].rbps) < 0)
9604 goto number_error;
9605 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9606 if (virStrToLong_ullp(temp, &p, 10, &result[i].wbps) < 0)
9607 goto number_error;
9608 } else {
9609 virReportError(VIR_ERR_INVALID_ARG,
9610 _("unknown parameter '%s'"), type);
9611 goto cleanup;
9614 i++;
9616 if (*p == '\0')
9617 break;
9618 else if (*p != ',')
9619 goto parse_error;
9620 temp = p + 1;
9623 if (!i)
9624 VIR_FREE(result);
9626 *dev = result;
9627 *size = i;
9629 return 0;
9631 parse_error:
9632 virReportError(VIR_ERR_INVALID_ARG,
9633 _("unable to parse blkio device '%s' '%s'"),
9634 type, blkioDeviceStr);
9635 goto cleanup;
9637 number_error:
9638 virReportError(VIR_ERR_INVALID_ARG,
9639 _("invalid value '%s' for parameter '%s' of device '%s'"),
9640 temp, type, result[i].path);
9642 cleanup:
9643 if (result) {
9644 virBlkioDeviceArrayClear(result, ndevices);
9645 VIR_FREE(result);
9647 return -1;
9650 /* Modify dest_array to reflect all blkio device changes described in
9651 * src_array. */
9652 static int
9653 qemuDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
9654 size_t *dest_size,
9655 virBlkioDevicePtr src_array,
9656 size_t src_size,
9657 const char *type)
9659 size_t i, j;
9660 virBlkioDevicePtr dest, src;
9662 for (i = 0; i < src_size; i++) {
9663 bool found = false;
9665 src = &src_array[i];
9666 for (j = 0; j < *dest_size; j++) {
9667 dest = &(*dest_array)[j];
9668 if (STREQ(src->path, dest->path)) {
9669 found = true;
9671 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9672 dest->weight = src->weight;
9673 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9674 dest->riops = src->riops;
9675 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9676 dest->wiops = src->wiops;
9677 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9678 dest->rbps = src->rbps;
9679 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9680 dest->wbps = src->wbps;
9681 } else {
9682 virReportError(VIR_ERR_INVALID_ARG, _("Unknown parameter %s"),
9683 type);
9684 return -1;
9686 break;
9689 if (!found) {
9690 if (!src->weight && !src->riops && !src->wiops && !src->rbps && !src->wbps)
9691 continue;
9692 if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0)
9693 return -1;
9694 dest = &(*dest_array)[*dest_size - 1];
9696 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9697 dest->weight = src->weight;
9698 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9699 dest->riops = src->riops;
9700 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9701 dest->wiops = src->wiops;
9702 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9703 dest->rbps = src->rbps;
9704 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9705 dest->wbps = src->wbps;
9706 } else {
9707 *dest_size = *dest_size - 1;
9708 return -1;
9711 dest->path = src->path;
9712 src->path = NULL;
9716 return 0;
9719 static int
9720 qemuDomainSetBlkioParameters(virDomainPtr dom,
9721 virTypedParameterPtr params,
9722 int nparams,
9723 unsigned int flags)
9725 virQEMUDriverPtr driver = dom->conn->privateData;
9726 size_t i;
9727 virDomainObjPtr vm = NULL;
9728 virDomainDefPtr def;
9729 virDomainDefPtr persistentDef;
9730 int ret = -1;
9731 virQEMUDriverConfigPtr cfg = NULL;
9732 qemuDomainObjPrivatePtr priv;
9734 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9735 VIR_DOMAIN_AFFECT_CONFIG, -1);
9736 if (virTypedParamsValidate(params, nparams,
9737 VIR_DOMAIN_BLKIO_WEIGHT,
9738 VIR_TYPED_PARAM_UINT,
9739 VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
9740 VIR_TYPED_PARAM_STRING,
9741 VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS,
9742 VIR_TYPED_PARAM_STRING,
9743 VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS,
9744 VIR_TYPED_PARAM_STRING,
9745 VIR_DOMAIN_BLKIO_DEVICE_READ_BPS,
9746 VIR_TYPED_PARAM_STRING,
9747 VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS,
9748 VIR_TYPED_PARAM_STRING,
9749 NULL) < 0)
9750 return -1;
9752 if (!(vm = qemuDomObjFromDomain(dom)))
9753 return -1;
9755 priv = vm->privateData;
9756 cfg = virQEMUDriverGetConfig(driver);
9758 if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0)
9759 goto cleanup;
9761 if (!virQEMUDriverIsPrivileged(driver)) {
9762 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9763 _("Block I/O tuning is not available in session mode"));
9764 goto cleanup;
9767 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9768 goto cleanup;
9770 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9771 goto endjob;
9773 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9774 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
9775 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9776 _("blkio cgroup isn't mounted"));
9777 goto endjob;
9781 ret = 0;
9782 if (def) {
9783 for (i = 0; i < nparams; i++) {
9784 virTypedParameterPtr param = &params[i];
9786 if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
9787 if (virCgroupSetBlkioWeight(priv->cgroup, param->value.ui) < 0 ||
9788 virCgroupGetBlkioWeight(priv->cgroup, &def->blkio.weight) < 0)
9789 ret = -1;
9790 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) ||
9791 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) ||
9792 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) ||
9793 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) ||
9794 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9795 size_t ndevices;
9796 virBlkioDevicePtr devices = NULL;
9797 size_t j;
9799 if (qemuDomainParseBlkioDeviceStr(param->value.s,
9800 param->field,
9801 &devices,
9802 &ndevices) < 0) {
9803 ret = -1;
9804 continue;
9807 if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9808 for (j = 0; j < ndevices; j++) {
9809 if (virCgroupSetBlkioDeviceWeight(priv->cgroup,
9810 devices[j].path,
9811 devices[j].weight) < 0 ||
9812 virCgroupGetBlkioDeviceWeight(priv->cgroup,
9813 devices[j].path,
9814 &devices[j].weight) < 0) {
9815 ret = -1;
9816 break;
9819 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9820 for (j = 0; j < ndevices; j++) {
9821 if (virCgroupSetBlkioDeviceReadIops(priv->cgroup,
9822 devices[j].path,
9823 devices[j].riops) < 0 ||
9824 virCgroupGetBlkioDeviceReadIops(priv->cgroup,
9825 devices[j].path,
9826 &devices[j].riops) < 0) {
9827 ret = -1;
9828 break;
9831 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9832 for (j = 0; j < ndevices; j++) {
9833 if (virCgroupSetBlkioDeviceWriteIops(priv->cgroup,
9834 devices[j].path,
9835 devices[j].wiops) < 0 ||
9836 virCgroupGetBlkioDeviceWriteIops(priv->cgroup,
9837 devices[j].path,
9838 &devices[j].wiops) < 0) {
9839 ret = -1;
9840 break;
9843 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9844 for (j = 0; j < ndevices; j++) {
9845 if (virCgroupSetBlkioDeviceReadBps(priv->cgroup,
9846 devices[j].path,
9847 devices[j].rbps) < 0 ||
9848 virCgroupGetBlkioDeviceReadBps(priv->cgroup,
9849 devices[j].path,
9850 &devices[j].rbps) < 0) {
9851 ret = -1;
9852 break;
9855 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9856 for (j = 0; j < ndevices; j++) {
9857 if (virCgroupSetBlkioDeviceWriteBps(priv->cgroup,
9858 devices[j].path,
9859 devices[j].wbps) < 0 ||
9860 virCgroupGetBlkioDeviceWriteBps(priv->cgroup,
9861 devices[j].path,
9862 &devices[j].wbps) < 0) {
9863 ret = -1;
9864 break;
9867 } else {
9868 virReportError(VIR_ERR_INVALID_ARG, _("Unknown blkio parameter %s"),
9869 param->field);
9870 ret = -1;
9871 virBlkioDeviceArrayClear(devices, ndevices);
9872 VIR_FREE(devices);
9874 continue;
9877 if (j != ndevices ||
9878 qemuDomainMergeBlkioDevice(&def->blkio.devices,
9879 &def->blkio.ndevices,
9880 devices, ndevices, param->field) < 0)
9881 ret = -1;
9882 virBlkioDeviceArrayClear(devices, ndevices);
9883 VIR_FREE(devices);
9887 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
9888 goto endjob;
9890 if (ret < 0)
9891 goto endjob;
9892 if (persistentDef) {
9893 for (i = 0; i < nparams; i++) {
9894 virTypedParameterPtr param = &params[i];
9896 if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
9897 persistentDef->blkio.weight = param->value.ui;
9898 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) ||
9899 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) ||
9900 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) ||
9901 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) ||
9902 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9903 virBlkioDevicePtr devices = NULL;
9904 size_t ndevices;
9906 if (qemuDomainParseBlkioDeviceStr(param->value.s,
9907 param->field,
9908 &devices,
9909 &ndevices) < 0) {
9910 ret = -1;
9911 continue;
9913 if (qemuDomainMergeBlkioDevice(&persistentDef->blkio.devices,
9914 &persistentDef->blkio.ndevices,
9915 devices, ndevices, param->field) < 0)
9916 ret = -1;
9917 virBlkioDeviceArrayClear(devices, ndevices);
9918 VIR_FREE(devices);
9922 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
9923 ret = -1;
9926 endjob:
9927 qemuDomainObjEndJob(driver, vm);
9929 cleanup:
9930 virDomainObjEndAPI(&vm);
9931 virObjectUnref(cfg);
9932 return ret;
9936 static int
9937 qemuDomainGetBlkioParameters(virDomainPtr dom,
9938 virTypedParameterPtr params,
9939 int *nparams,
9940 unsigned int flags)
9942 virQEMUDriverPtr driver = dom->conn->privateData;
9943 virDomainObjPtr vm = NULL;
9944 virDomainDefPtr def = NULL;
9945 virDomainDefPtr persistentDef = NULL;
9946 int maxparams = QEMU_NB_BLKIO_PARAM;
9947 unsigned int val;
9948 int ret = -1;
9949 qemuDomainObjPrivatePtr priv;
9951 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9952 VIR_DOMAIN_AFFECT_CONFIG |
9953 VIR_TYPED_PARAM_STRING_OKAY, -1);
9955 /* We blindly return a string, and let libvirt.c and
9956 * remote_driver.c do the filtering on behalf of older clients
9957 * that can't parse it. */
9958 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
9960 if (!(vm = qemuDomObjFromDomain(dom)))
9961 return -1;
9963 priv = vm->privateData;
9965 if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0)
9966 goto cleanup;
9968 if (!virQEMUDriverIsPrivileged(driver)) {
9969 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9970 _("Block I/O tuning is not available in session mode"));
9971 goto cleanup;
9974 if ((*nparams) == 0) {
9975 /* Current number of blkio parameters supported by cgroups */
9976 *nparams = QEMU_NB_BLKIO_PARAM;
9977 ret = 0;
9978 goto cleanup;
9979 } else if (*nparams < maxparams) {
9980 maxparams = *nparams;
9983 *nparams = 0;
9985 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9986 goto cleanup;
9988 if (def) {
9989 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
9990 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9991 _("blkio cgroup isn't mounted"));
9992 goto cleanup;
9995 /* fill blkio weight here */
9996 if (virCgroupGetBlkioWeight(priv->cgroup, &val) < 0)
9997 goto cleanup;
9998 if (virTypedParameterAssign(&(params[(*nparams)++]),
9999 VIR_DOMAIN_BLKIO_WEIGHT,
10000 VIR_TYPED_PARAM_UINT, val) < 0)
10001 goto cleanup;
10003 if (virDomainGetBlkioParametersAssignFromDef(def, params, nparams,
10004 maxparams) < 0)
10005 goto cleanup;
10007 } else if (persistentDef) {
10008 /* fill blkio weight here */
10009 if (virTypedParameterAssign(&(params[(*nparams)++]),
10010 VIR_DOMAIN_BLKIO_WEIGHT,
10011 VIR_TYPED_PARAM_UINT,
10012 persistentDef->blkio.weight) < 0)
10013 goto cleanup;
10015 if (virDomainGetBlkioParametersAssignFromDef(persistentDef, params,
10016 nparams, maxparams) < 0)
10017 goto cleanup;
10020 ret = 0;
10022 cleanup:
10023 virDomainObjEndAPI(&vm);
10024 return ret;
10027 static int
10028 qemuDomainSetMemoryParameters(virDomainPtr dom,
10029 virTypedParameterPtr params,
10030 int nparams,
10031 unsigned int flags)
10033 virQEMUDriverPtr driver = dom->conn->privateData;
10034 virDomainDefPtr def = NULL;
10035 virDomainDefPtr persistentDef = NULL;
10036 virDomainObjPtr vm = NULL;
10037 unsigned long long swap_hard_limit;
10038 unsigned long long hard_limit = 0;
10039 unsigned long long soft_limit = 0;
10040 bool set_swap_hard_limit = false;
10041 bool set_hard_limit = false;
10042 bool set_soft_limit = false;
10043 virQEMUDriverConfigPtr cfg = NULL;
10044 int rc;
10045 int ret = -1;
10046 qemuDomainObjPrivatePtr priv;
10048 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10049 VIR_DOMAIN_AFFECT_CONFIG, -1);
10051 if (virTypedParamsValidate(params, nparams,
10052 VIR_DOMAIN_MEMORY_HARD_LIMIT,
10053 VIR_TYPED_PARAM_ULLONG,
10054 VIR_DOMAIN_MEMORY_SOFT_LIMIT,
10055 VIR_TYPED_PARAM_ULLONG,
10056 VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
10057 VIR_TYPED_PARAM_ULLONG,
10058 NULL) < 0)
10059 return -1;
10062 if (!(vm = qemuDomObjFromDomain(dom)))
10063 return -1;
10065 priv = vm->privateData;
10066 cfg = virQEMUDriverGetConfig(driver);
10068 if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0)
10069 goto cleanup;
10071 if (!virQEMUDriverIsPrivileged(driver)) {
10072 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10073 _("Memory tuning is not available in session mode"));
10074 goto cleanup;
10077 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10078 goto cleanup;
10080 /* QEMU and LXC implementation are identical */
10081 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10082 goto endjob;
10084 if (def &&
10085 !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
10086 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10087 _("cgroup memory controller is not mounted"));
10088 goto endjob;
10091 #define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE) \
10092 if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0) \
10093 goto endjob; \
10095 if (rc == 1) \
10096 set_ ## VALUE = true;
10098 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
10099 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
10100 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)
10102 #undef VIR_GET_LIMIT_PARAMETER
10104 /* Swap hard limit must be greater than hard limit. */
10105 if (set_swap_hard_limit || set_hard_limit) {
10106 unsigned long long mem_limit = vm->def->mem.hard_limit;
10107 unsigned long long swap_limit = vm->def->mem.swap_hard_limit;
10109 if (set_swap_hard_limit)
10110 swap_limit = swap_hard_limit;
10112 if (set_hard_limit)
10113 mem_limit = hard_limit;
10115 if (mem_limit > swap_limit) {
10116 virReportError(VIR_ERR_INVALID_ARG, "%s",
10117 _("memory hard_limit tunable value must be lower "
10118 "than or equal to swap_hard_limit"));
10119 goto endjob;
10123 #define VIR_SET_MEM_PARAMETER(FUNC, VALUE) \
10124 if (set_ ## VALUE) { \
10125 if (def) { \
10126 if ((rc = FUNC(priv->cgroup, VALUE)) < 0) \
10127 goto endjob; \
10128 def->mem.VALUE = VALUE; \
10131 if (persistentDef) \
10132 persistentDef->mem.VALUE = VALUE; \
10135 /* Soft limit doesn't clash with the others */
10136 VIR_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
10138 /* set hard limit before swap hard limit if decreasing it */
10139 if (def && def->mem.hard_limit > hard_limit) {
10140 VIR_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
10141 /* inhibit changing the limit a second time */
10142 set_hard_limit = false;
10145 VIR_SET_MEM_PARAMETER(virCgroupSetMemSwapHardLimit, swap_hard_limit);
10147 /* otherwise increase it after swap hard limit */
10148 VIR_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
10150 #undef VIR_SET_MEM_PARAMETER
10152 if (def &&
10153 virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10154 goto endjob;
10156 if (persistentDef &&
10157 virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10158 goto endjob;
10159 /* QEMU and LXC implementations are identical */
10161 ret = 0;
10163 endjob:
10164 qemuDomainObjEndJob(driver, vm);
10166 cleanup:
10167 virDomainObjEndAPI(&vm);
10168 virObjectUnref(cfg);
10169 return ret;
10173 #define QEMU_ASSIGN_MEM_PARAM(index, name, value) \
10174 if (index < *nparams && \
10175 virTypedParameterAssign(&params[index], name, VIR_TYPED_PARAM_ULLONG, \
10176 value) < 0) \
10177 goto cleanup
10179 static int
10180 qemuDomainGetMemoryParameters(virDomainPtr dom,
10181 virTypedParameterPtr params,
10182 int *nparams,
10183 unsigned int flags)
10185 virQEMUDriverPtr driver = dom->conn->privateData;
10186 virDomainObjPtr vm = NULL;
10187 virDomainDefPtr persistentDef = NULL;
10188 int ret = -1;
10189 qemuDomainObjPrivatePtr priv;
10190 unsigned long long swap_hard_limit, mem_hard_limit, mem_soft_limit;
10192 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10193 VIR_DOMAIN_AFFECT_CONFIG |
10194 VIR_TYPED_PARAM_STRING_OKAY, -1);
10196 if (!(vm = qemuDomObjFromDomain(dom)))
10197 return -1;
10199 priv = vm->privateData;
10201 if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0)
10202 goto cleanup;
10204 if (!virQEMUDriverIsPrivileged(driver)) {
10205 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10206 _("Memory tuning is not available in session mode"));
10207 goto cleanup;
10210 if (virDomainObjGetDefs(vm, flags, NULL, &persistentDef) < 0)
10211 goto cleanup;
10213 if ((*nparams) == 0) {
10214 /* Current number of memory parameters supported by cgroups */
10215 *nparams = QEMU_NB_MEM_PARAM;
10216 ret = 0;
10217 goto cleanup;
10220 if (persistentDef) {
10221 mem_hard_limit = persistentDef->mem.hard_limit;
10222 mem_soft_limit = persistentDef->mem.soft_limit;
10223 swap_hard_limit = persistentDef->mem.swap_hard_limit;
10224 } else {
10225 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
10226 virReportError(VIR_ERR_OPERATION_INVALID,
10227 "%s", _("cgroup memory controller is not mounted"));
10228 goto cleanup;
10231 if (virCgroupGetMemoryHardLimit(priv->cgroup, &mem_hard_limit) < 0)
10232 goto cleanup;
10234 if (virCgroupGetMemorySoftLimit(priv->cgroup, &mem_soft_limit) < 0)
10235 goto cleanup;
10237 if (virCgroupGetMemSwapHardLimit(priv->cgroup, &swap_hard_limit) < 0) {
10238 if (!virLastErrorIsSystemErrno(ENOENT) &&
10239 !virLastErrorIsSystemErrno(EOPNOTSUPP))
10240 goto cleanup;
10241 swap_hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
10245 QEMU_ASSIGN_MEM_PARAM(0, VIR_DOMAIN_MEMORY_HARD_LIMIT, mem_hard_limit);
10246 QEMU_ASSIGN_MEM_PARAM(1, VIR_DOMAIN_MEMORY_SOFT_LIMIT, mem_soft_limit);
10247 QEMU_ASSIGN_MEM_PARAM(2, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit);
10249 if (QEMU_NB_MEM_PARAM < *nparams)
10250 *nparams = QEMU_NB_MEM_PARAM;
10251 ret = 0;
10253 cleanup:
10254 virDomainObjEndAPI(&vm);
10255 return ret;
10257 #undef QEMU_ASSIGN_MEM_PARAM
10259 static int
10260 qemuDomainSetNumaParamsLive(virDomainObjPtr vm,
10261 virBitmapPtr nodeset)
10263 virCgroupPtr cgroup_temp = NULL;
10264 qemuDomainObjPrivatePtr priv = vm->privateData;
10265 char *nodeset_str = NULL;
10266 virDomainNumatuneMemMode mode;
10267 size_t i = 0;
10268 int ret = -1;
10270 if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
10271 mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
10272 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10273 _("change of nodeset for running domain "
10274 "requires strict numa mode"));
10275 goto cleanup;
10278 if (!virNumaNodesetIsAvailable(nodeset))
10279 goto cleanup;
10281 /* Ensure the cpuset string is formatted before passing to cgroup */
10282 if (!(nodeset_str = virBitmapFormat(nodeset)))
10283 goto cleanup;
10285 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
10286 false, &cgroup_temp) < 0 ||
10287 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10288 goto cleanup;
10289 virCgroupFree(&cgroup_temp);
10291 for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
10292 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
10294 if (!vcpu->online)
10295 continue;
10297 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
10298 false, &cgroup_temp) < 0 ||
10299 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10300 goto cleanup;
10301 virCgroupFree(&cgroup_temp);
10304 for (i = 0; i < vm->def->niothreadids; i++) {
10305 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
10306 vm->def->iothreadids[i]->iothread_id,
10307 false, &cgroup_temp) < 0 ||
10308 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10309 goto cleanup;
10310 virCgroupFree(&cgroup_temp);
10313 ret = 0;
10314 cleanup:
10315 VIR_FREE(nodeset_str);
10316 virCgroupFree(&cgroup_temp);
10318 return ret;
10321 static int
10322 qemuDomainSetNumaParameters(virDomainPtr dom,
10323 virTypedParameterPtr params,
10324 int nparams,
10325 unsigned int flags)
10327 virQEMUDriverPtr driver = dom->conn->privateData;
10328 size_t i;
10329 virDomainDefPtr def;
10330 virDomainDefPtr persistentDef;
10331 virDomainObjPtr vm = NULL;
10332 int ret = -1;
10333 virQEMUDriverConfigPtr cfg = NULL;
10334 qemuDomainObjPrivatePtr priv;
10335 virBitmapPtr nodeset = NULL;
10336 virDomainNumatuneMemMode config_mode;
10337 int mode = -1;
10339 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10340 VIR_DOMAIN_AFFECT_CONFIG, -1);
10342 if (virTypedParamsValidate(params, nparams,
10343 VIR_DOMAIN_NUMA_MODE,
10344 VIR_TYPED_PARAM_INT,
10345 VIR_DOMAIN_NUMA_NODESET,
10346 VIR_TYPED_PARAM_STRING,
10347 NULL) < 0)
10348 return -1;
10350 if (!(vm = qemuDomObjFromDomain(dom)))
10351 return -1;
10353 priv = vm->privateData;
10354 cfg = virQEMUDriverGetConfig(driver);
10356 if (virDomainSetNumaParametersEnsureACL(dom->conn, vm->def, flags) < 0)
10357 goto cleanup;
10359 for (i = 0; i < nparams; i++) {
10360 virTypedParameterPtr param = &params[i];
10362 if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
10363 mode = param->value.i;
10365 if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) {
10366 virReportError(VIR_ERR_INVALID_ARG,
10367 _("unsupported numatune mode: '%d'"), mode);
10368 goto cleanup;
10371 } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
10372 if (virBitmapParse(param->value.s, &nodeset,
10373 VIR_DOMAIN_CPUMASK_LEN) < 0)
10374 goto cleanup;
10376 if (virBitmapIsAllClear(nodeset)) {
10377 virReportError(VIR_ERR_OPERATION_INVALID,
10378 _("Invalid nodeset of 'numatune': %s"),
10379 param->value.s);
10380 goto cleanup;
10385 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10386 goto cleanup;
10388 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10389 goto endjob;
10391 if (def) {
10392 if (!virQEMUDriverIsPrivileged(driver)) {
10393 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10394 _("NUMA tuning is not available in session mode"));
10395 goto endjob;
10398 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
10399 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10400 _("cgroup cpuset controller is not mounted"));
10401 goto endjob;
10404 if (mode != -1 &&
10405 virDomainNumatuneGetMode(def->numa, -1, &config_mode) == 0 &&
10406 config_mode != mode) {
10407 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10408 _("can't change numatune mode for running domain"));
10409 goto endjob;
10412 if (nodeset &&
10413 qemuDomainSetNumaParamsLive(vm, nodeset) < 0)
10414 goto endjob;
10416 if (virDomainNumatuneSet(def->numa,
10417 def->placement_mode ==
10418 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
10419 -1, mode, nodeset) < 0)
10420 goto endjob;
10422 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10423 goto endjob;
10426 if (persistentDef) {
10427 if (virDomainNumatuneSet(persistentDef->numa,
10428 persistentDef->placement_mode ==
10429 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
10430 -1, mode, nodeset) < 0)
10431 goto endjob;
10433 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10434 goto endjob;
10437 ret = 0;
10439 endjob:
10440 qemuDomainObjEndJob(driver, vm);
10442 cleanup:
10443 virBitmapFree(nodeset);
10444 virDomainObjEndAPI(&vm);
10445 virObjectUnref(cfg);
10446 return ret;
10449 static int
10450 qemuDomainGetNumaParameters(virDomainPtr dom,
10451 virTypedParameterPtr params,
10452 int *nparams,
10453 unsigned int flags)
10455 size_t i;
10456 virDomainObjPtr vm = NULL;
10457 virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
10458 qemuDomainObjPrivatePtr priv;
10459 char *nodeset = NULL;
10460 int ret = -1;
10461 virDomainDefPtr def = NULL;
10462 bool live = false;
10463 virBitmapPtr autoNodeset = NULL;
10465 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10466 VIR_DOMAIN_AFFECT_CONFIG |
10467 VIR_TYPED_PARAM_STRING_OKAY, -1);
10469 if (!(vm = qemuDomObjFromDomain(dom)))
10470 return -1;
10471 priv = vm->privateData;
10473 if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
10474 goto cleanup;
10476 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
10477 goto cleanup;
10479 if (live)
10480 autoNodeset = priv->autoNodeset;
10482 if ((*nparams) == 0) {
10483 *nparams = QEMU_NB_NUMA_PARAM;
10484 ret = 0;
10485 goto cleanup;
10488 for (i = 0; i < QEMU_NB_NUMA_PARAM && i < *nparams; i++) {
10489 virMemoryParameterPtr param = &params[i];
10491 switch (i) {
10492 case 0: /* fill numa mode here */
10493 ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
10495 if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
10496 VIR_TYPED_PARAM_INT, tmpmode) < 0)
10497 goto cleanup;
10499 break;
10501 case 1: /* fill numa nodeset here */
10502 nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, -1);
10503 if (!nodeset ||
10504 virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
10505 VIR_TYPED_PARAM_STRING, nodeset) < 0)
10506 goto cleanup;
10508 nodeset = NULL;
10509 break;
10511 /* coverity[dead_error_begin] */
10512 default:
10513 break;
10514 /* should not hit here */
10518 if (*nparams > QEMU_NB_NUMA_PARAM)
10519 *nparams = QEMU_NB_NUMA_PARAM;
10520 ret = 0;
10522 cleanup:
10523 VIR_FREE(nodeset);
10524 virDomainObjEndAPI(&vm);
10525 return ret;
10528 static int
10529 qemuSetGlobalBWLive(virCgroupPtr cgroup, unsigned long long period,
10530 long long quota)
10532 if (period == 0 && quota == 0)
10533 return 0;
10535 if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
10536 return -1;
10538 return 0;
10541 static int
10542 qemuDomainSetPerfEvents(virDomainPtr dom,
10543 virTypedParameterPtr params,
10544 int nparams,
10545 unsigned int flags)
10547 virQEMUDriverPtr driver = dom->conn->privateData;
10548 size_t i;
10549 virDomainObjPtr vm = NULL;
10550 virQEMUDriverConfigPtr cfg = NULL;
10551 qemuDomainObjPrivatePtr priv;
10552 virDomainDefPtr def;
10553 virDomainDefPtr persistentDef;
10554 int ret = -1;
10555 virPerfEventType type;
10556 bool enabled;
10558 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10559 VIR_DOMAIN_AFFECT_CONFIG, -1);
10561 if (virTypedParamsValidate(params, nparams,
10562 VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
10563 VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
10564 VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
10565 VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10566 VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
10567 VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_BOOLEAN,
10568 VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_BOOLEAN,
10569 VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
10570 VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_BOOLEAN,
10571 VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10572 VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_BOOLEAN,
10573 VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_BOOLEAN,
10574 VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10575 VIR_PERF_PARAM_CPU_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
10576 VIR_PERF_PARAM_TASK_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
10577 VIR_PERF_PARAM_PAGE_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10578 VIR_PERF_PARAM_CONTEXT_SWITCHES, VIR_TYPED_PARAM_BOOLEAN,
10579 VIR_PERF_PARAM_CPU_MIGRATIONS, VIR_TYPED_PARAM_BOOLEAN,
10580 VIR_PERF_PARAM_PAGE_FAULTS_MIN, VIR_TYPED_PARAM_BOOLEAN,
10581 VIR_PERF_PARAM_PAGE_FAULTS_MAJ, VIR_TYPED_PARAM_BOOLEAN,
10582 VIR_PERF_PARAM_ALIGNMENT_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10583 VIR_PERF_PARAM_EMULATION_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10584 NULL) < 0)
10585 return -1;
10587 if (!(vm = qemuDomObjFromDomain(dom)))
10588 return -1;
10590 cfg = virQEMUDriverGetConfig(driver);
10591 priv = vm->privateData;
10593 if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
10594 goto cleanup;
10596 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10597 goto cleanup;
10599 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10600 goto endjob;
10602 if (def) {
10603 for (i = 0; i < nparams; i++) {
10604 virTypedParameterPtr param = &params[i];
10605 enabled = param->value.b;
10606 type = virPerfEventTypeFromString(param->field);
10608 if (!enabled && virPerfEventDisable(priv->perf, type) < 0)
10609 goto endjob;
10610 if (enabled && virPerfEventEnable(priv->perf, type, vm->pid) < 0)
10611 goto endjob;
10613 def->perf.events[type] = enabled ?
10614 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
10617 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10618 goto endjob;
10621 if (persistentDef) {
10622 for (i = 0; i < nparams; i++) {
10623 virTypedParameterPtr param = &params[i];
10624 enabled = param->value.b;
10625 type = virPerfEventTypeFromString(param->field);
10627 persistentDef->perf.events[type] = enabled ?
10628 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
10631 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10632 goto endjob;
10635 ret = 0;
10637 endjob:
10638 qemuDomainObjEndJob(driver, vm);
10640 cleanup:
10641 virDomainObjEndAPI(&vm);
10642 virObjectUnref(cfg);
10643 return ret;
10646 static int
10647 qemuDomainGetPerfEvents(virDomainPtr dom,
10648 virTypedParameterPtr *params,
10649 int *nparams,
10650 unsigned int flags)
10652 virQEMUDriverPtr driver = dom->conn->privateData;
10653 virDomainObjPtr vm = NULL;
10654 qemuDomainObjPrivatePtr priv;
10655 virDomainDefPtr def;
10656 virTypedParameterPtr par = NULL;
10657 int maxpar = 0;
10658 int npar = 0;
10659 size_t i;
10660 int ret = -1;
10662 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10663 VIR_DOMAIN_AFFECT_CONFIG |
10664 VIR_TYPED_PARAM_STRING_OKAY, -1);
10666 if (!(vm = qemuDomObjFromDomain(dom)))
10667 goto cleanup;
10669 if (virDomainGetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
10670 goto cleanup;
10672 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10673 goto cleanup;
10675 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
10676 goto endjob;
10678 if (!(def = virDomainObjGetOneDef(vm, flags)))
10679 goto endjob;
10681 priv = vm->privateData;
10683 for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
10684 bool perf_enabled;
10686 if (flags & VIR_DOMAIN_AFFECT_CONFIG)
10687 perf_enabled = def->perf.events[i] == VIR_TRISTATE_BOOL_YES;
10688 else
10689 perf_enabled = virPerfEventIsEnabled(priv->perf, i);
10691 if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
10692 virPerfEventTypeToString(i),
10693 perf_enabled) < 0)
10694 goto endjob;
10697 *params = par;
10698 *nparams = npar;
10699 par = NULL;
10700 npar = 0;
10701 ret = 0;
10703 endjob:
10704 qemuDomainObjEndJob(driver, vm);
10706 cleanup:
10707 virDomainObjEndAPI(&vm);
10708 virTypedParamsFree(par, npar);
10709 return ret;
10712 static int
10713 qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
10714 unsigned long long period, long long quota)
10716 size_t i;
10717 virCgroupPtr cgroup_vcpu = NULL;
10719 if (period == 0 && quota == 0)
10720 return 0;
10722 if (!qemuDomainHasVcpuPids(vm))
10723 return 0;
10725 for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
10726 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
10728 if (!vcpu->online)
10729 continue;
10731 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_VCPU, i,
10732 false, &cgroup_vcpu) < 0)
10733 goto cleanup;
10735 if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
10736 goto cleanup;
10738 virCgroupFree(&cgroup_vcpu);
10741 return 0;
10743 cleanup:
10744 virCgroupFree(&cgroup_vcpu);
10745 return -1;
10748 static int
10749 qemuSetEmulatorBandwidthLive(virCgroupPtr cgroup,
10750 unsigned long long period,
10751 long long quota)
10753 virCgroupPtr cgroup_emulator = NULL;
10755 if (period == 0 && quota == 0)
10756 return 0;
10758 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
10759 false, &cgroup_emulator) < 0)
10760 goto cleanup;
10762 if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
10763 goto cleanup;
10765 virCgroupFree(&cgroup_emulator);
10766 return 0;
10768 cleanup:
10769 virCgroupFree(&cgroup_emulator);
10770 return -1;
10774 static int
10775 qemuSetIOThreadsBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
10776 unsigned long long period, long long quota)
10778 size_t i;
10779 virCgroupPtr cgroup_iothread = NULL;
10781 if (period == 0 && quota == 0)
10782 return 0;
10784 if (!vm->def->niothreadids)
10785 return 0;
10787 for (i = 0; i < vm->def->niothreadids; i++) {
10788 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_IOTHREAD,
10789 vm->def->iothreadids[i]->iothread_id,
10790 false, &cgroup_iothread) < 0)
10791 goto cleanup;
10793 if (qemuSetupCgroupVcpuBW(cgroup_iothread, period, quota) < 0)
10794 goto cleanup;
10796 virCgroupFree(&cgroup_iothread);
10799 return 0;
10801 cleanup:
10802 virCgroupFree(&cgroup_iothread);
10803 return -1;
10807 #define SCHED_RANGE_CHECK(VAR, NAME, MIN, MAX) \
10808 if (((VAR) > 0 && (VAR) < (MIN)) || (VAR) > (MAX)) { \
10809 virReportError(VIR_ERR_INVALID_ARG, \
10810 _("value of '%s' is out of range [%lld, %lld]"), \
10811 NAME, MIN, MAX); \
10812 rc = -1; \
10813 goto endjob; \
10816 static int
10817 qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,
10818 virTypedParameterPtr params,
10819 int nparams,
10820 unsigned int flags)
10822 virQEMUDriverPtr driver = dom->conn->privateData;
10823 size_t i;
10824 virDomainObjPtr vm = NULL;
10825 virDomainDefPtr def = NULL;
10826 virDomainDefPtr persistentDef = NULL;
10827 virDomainDefPtr persistentDefCopy = NULL;
10828 unsigned long long value_ul;
10829 long long value_l;
10830 int ret = -1;
10831 int rc;
10832 virQEMUDriverConfigPtr cfg = NULL;
10833 virCapsPtr caps = NULL;
10834 qemuDomainObjPrivatePtr priv;
10835 virObjectEventPtr event = NULL;
10836 virTypedParameterPtr eventParams = NULL;
10837 int eventNparams = 0;
10838 int eventMaxNparams = 0;
10840 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10841 VIR_DOMAIN_AFFECT_CONFIG, -1);
10842 if (virTypedParamsValidate(params, nparams,
10843 VIR_DOMAIN_SCHEDULER_CPU_SHARES,
10844 VIR_TYPED_PARAM_ULLONG,
10845 VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
10846 VIR_TYPED_PARAM_ULLONG,
10847 VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
10848 VIR_TYPED_PARAM_LLONG,
10849 VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
10850 VIR_TYPED_PARAM_ULLONG,
10851 VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
10852 VIR_TYPED_PARAM_LLONG,
10853 VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
10854 VIR_TYPED_PARAM_ULLONG,
10855 VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
10856 VIR_TYPED_PARAM_LLONG,
10857 VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
10858 VIR_TYPED_PARAM_ULLONG,
10859 VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
10860 VIR_TYPED_PARAM_LLONG,
10861 NULL) < 0)
10862 return -1;
10864 if (!(vm = qemuDomObjFromDomain(dom)))
10865 return -1;
10867 priv = vm->privateData;
10868 cfg = virQEMUDriverGetConfig(driver);
10870 if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
10871 goto cleanup;
10873 if (!virQEMUDriverIsPrivileged(driver)) {
10874 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10875 _("CPU tuning is not available in session mode"));
10876 goto cleanup;
10879 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
10880 goto cleanup;
10882 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10883 goto cleanup;
10885 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10886 goto endjob;
10888 if (persistentDef) {
10889 /* Make a copy for updated domain. */
10890 if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps,
10891 driver->xmlopt)))
10892 goto endjob;
10895 if (def &&
10896 !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
10897 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10898 _("cgroup CPU controller is not mounted"));
10899 goto endjob;
10902 for (i = 0; i < nparams; i++) {
10903 virTypedParameterPtr param = &params[i];
10904 value_ul = param->value.ul;
10905 value_l = param->value.l;
10907 if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
10908 if (def) {
10909 unsigned long long val;
10910 if (virCgroupSetCpuShares(priv->cgroup, value_ul) < 0)
10911 goto endjob;
10913 if (virCgroupGetCpuShares(priv->cgroup, &val) < 0)
10914 goto endjob;
10916 def->cputune.shares = val;
10917 def->cputune.sharesSpecified = true;
10919 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10920 &eventMaxNparams,
10921 VIR_DOMAIN_TUNABLE_CPU_CPU_SHARES,
10922 val) < 0)
10923 goto endjob;
10926 if (persistentDef) {
10927 persistentDefCopy->cputune.shares = value_ul;
10928 persistentDefCopy->cputune.sharesSpecified = true;
10932 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
10933 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
10934 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10936 if (def && value_ul) {
10937 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, value_ul, 0)))
10938 goto endjob;
10940 def->cputune.period = value_ul;
10942 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10943 &eventMaxNparams,
10944 VIR_DOMAIN_TUNABLE_CPU_VCPU_PERIOD,
10945 value_ul) < 0)
10946 goto endjob;
10949 if (persistentDef)
10950 persistentDefCopy->cputune.period = value_ul;
10952 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
10953 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
10954 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10956 if (def && value_l) {
10957 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, 0, value_l)))
10958 goto endjob;
10960 def->cputune.quota = value_l;
10962 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
10963 &eventMaxNparams,
10964 VIR_DOMAIN_TUNABLE_CPU_VCPU_QUOTA,
10965 value_l) < 0)
10966 goto endjob;
10969 if (persistentDef)
10970 persistentDefCopy->cputune.quota = value_l;
10972 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD)) {
10973 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
10974 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10976 if (def && value_ul) {
10977 if ((rc = qemuSetGlobalBWLive(priv->cgroup, value_ul, 0)))
10978 goto endjob;
10980 def->cputune.global_period = value_ul;
10982 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10983 &eventMaxNparams,
10984 VIR_DOMAIN_TUNABLE_CPU_GLOBAL_PERIOD,
10985 value_ul) < 0)
10986 goto endjob;
10989 if (persistentDef)
10990 persistentDefCopy->cputune.global_period = value_ul;
10992 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA)) {
10993 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
10994 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10996 if (def && value_l) {
10997 if ((rc = qemuSetGlobalBWLive(priv->cgroup, 0, value_l)))
10998 goto endjob;
11000 def->cputune.global_quota = value_l;
11002 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
11003 &eventMaxNparams,
11004 VIR_DOMAIN_TUNABLE_CPU_GLOBAL_QUOTA,
11005 value_l) < 0)
11006 goto endjob;
11009 if (persistentDef)
11010 persistentDefCopy->cputune.global_quota = value_l;
11012 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD)) {
11013 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
11014 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
11016 if (def && value_ul) {
11017 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
11018 value_ul, 0)))
11019 goto endjob;
11021 def->cputune.emulator_period = value_ul;
11023 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
11024 &eventMaxNparams,
11025 VIR_DOMAIN_TUNABLE_CPU_EMULATOR_PERIOD,
11026 value_ul) < 0)
11027 goto endjob;
11030 if (persistentDef)
11031 persistentDefCopy->cputune.emulator_period = value_ul;
11033 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA)) {
11034 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
11035 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
11037 if (def && value_l) {
11038 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
11039 0, value_l)))
11040 goto endjob;
11042 def->cputune.emulator_quota = value_l;
11044 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
11045 &eventMaxNparams,
11046 VIR_DOMAIN_TUNABLE_CPU_EMULATOR_QUOTA,
11047 value_l) < 0)
11048 goto endjob;
11051 if (persistentDef)
11052 persistentDefCopy->cputune.emulator_quota = value_l;
11054 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD)) {
11055 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
11056 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
11058 if (def && value_ul) {
11059 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, value_ul, 0)))
11060 goto endjob;
11062 def->cputune.iothread_period = value_ul;
11064 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
11065 &eventMaxNparams,
11066 VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_PERIOD,
11067 value_ul) < 0)
11068 goto endjob;
11071 if (persistentDef)
11072 persistentDefCopy->cputune.iothread_period = value_ul;
11074 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA)) {
11075 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
11076 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
11078 if (def && value_l) {
11079 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, 0, value_l)))
11080 goto endjob;
11082 def->cputune.iothread_quota = value_l;
11084 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
11085 &eventMaxNparams,
11086 VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_QUOTA,
11087 value_l) < 0)
11088 goto endjob;
11091 if (persistentDef)
11092 persistentDefCopy->cputune.iothread_quota = value_l;
11096 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
11097 goto endjob;
11099 if (eventNparams) {
11100 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
11101 eventNparams = 0;
11102 virObjectEventStateQueue(driver->domainEventState, event);
11105 if (persistentDef) {
11106 rc = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDefCopy);
11107 if (rc < 0)
11108 goto endjob;
11110 virDomainObjAssignDef(vm, persistentDefCopy, false, NULL);
11111 persistentDefCopy = NULL;
11114 ret = 0;
11116 endjob:
11117 qemuDomainObjEndJob(driver, vm);
11119 cleanup:
11120 virDomainDefFree(persistentDefCopy);
11121 virDomainObjEndAPI(&vm);
11122 if (eventNparams)
11123 virTypedParamsFree(eventParams, eventNparams);
11124 virObjectUnref(caps);
11125 virObjectUnref(cfg);
11126 return ret;
11128 #undef SCHED_RANGE_CHECK
11130 static int
11131 qemuDomainSetSchedulerParameters(virDomainPtr dom,
11132 virTypedParameterPtr params,
11133 int nparams)
11135 return qemuDomainSetSchedulerParametersFlags(dom,
11136 params,
11137 nparams,
11138 VIR_DOMAIN_AFFECT_CURRENT);
11141 static int
11142 qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
11143 long long *quota)
11145 if (virCgroupGetCpuCfsPeriod(cgroup, period) < 0)
11146 return -1;
11148 if (virCgroupGetCpuCfsQuota(cgroup, quota) < 0)
11149 return -1;
11151 return 0;
11154 static int
11155 qemuGetVcpusBWLive(virDomainObjPtr vm,
11156 unsigned long long *period, long long *quota)
11158 virCgroupPtr cgroup_vcpu = NULL;
11159 qemuDomainObjPrivatePtr priv = NULL;
11160 int rc;
11161 int ret = -1;
11163 priv = vm->privateData;
11164 if (!qemuDomainHasVcpuPids(vm)) {
11165 /* We do not create sub dir for each vcpu */
11166 rc = qemuGetVcpuBWLive(priv->cgroup, period, quota);
11167 if (rc < 0)
11168 goto cleanup;
11170 if (*quota > 0)
11171 *quota /= virDomainDefGetVcpus(vm->def);
11172 goto out;
11175 /* get period and quota for vcpu0 */
11176 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, 0,
11177 false, &cgroup_vcpu) < 0)
11178 goto cleanup;
11180 rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
11181 if (rc < 0)
11182 goto cleanup;
11184 out:
11185 ret = 0;
11187 cleanup:
11188 virCgroupFree(&cgroup_vcpu);
11189 return ret;
11192 static int
11193 qemuGetEmulatorBandwidthLive(virCgroupPtr cgroup,
11194 unsigned long long *period,
11195 long long *quota)
11197 virCgroupPtr cgroup_emulator = NULL;
11198 int ret = -1;
11200 /* get period and quota for emulator */
11201 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
11202 false, &cgroup_emulator) < 0)
11203 goto cleanup;
11205 if (qemuGetVcpuBWLive(cgroup_emulator, period, quota) < 0)
11206 goto cleanup;
11208 ret = 0;
11210 cleanup:
11211 virCgroupFree(&cgroup_emulator);
11212 return ret;
11215 static int
11216 qemuGetIOThreadsBWLive(virDomainObjPtr vm,
11217 unsigned long long *period, long long *quota)
11219 virCgroupPtr cgroup_iothread = NULL;
11220 qemuDomainObjPrivatePtr priv = NULL;
11221 int rc;
11222 int ret = -1;
11224 priv = vm->privateData;
11225 if (!vm->def->niothreadids) {
11226 /* We do not create sub dir for each iothread */
11227 if ((rc = qemuGetVcpuBWLive(priv->cgroup, period, quota)) < 0)
11228 goto cleanup;
11230 goto out;
11233 /* get period and quota for the "first" IOThread */
11234 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
11235 vm->def->iothreadids[0]->iothread_id,
11236 false, &cgroup_iothread) < 0)
11237 goto cleanup;
11239 rc = qemuGetVcpuBWLive(cgroup_iothread, period, quota);
11240 if (rc < 0)
11241 goto cleanup;
11243 out:
11244 ret = 0;
11246 cleanup:
11247 virCgroupFree(&cgroup_iothread);
11248 return ret;
11252 static int
11253 qemuGetGlobalBWLive(virCgroupPtr cgroup, unsigned long long *period,
11254 long long *quota)
11256 if (qemuGetVcpuBWLive(cgroup, period, quota) < 0)
11257 return -1;
11259 return 0;
11262 static int
11263 qemuDomainGetSchedulerParametersFlags(virDomainPtr dom,
11264 virTypedParameterPtr params,
11265 int *nparams,
11266 unsigned int flags)
11268 virQEMUDriverPtr driver = dom->conn->privateData;
11269 virDomainObjPtr vm = NULL;
11270 virDomainCputune data = {0};
11271 int ret = -1;
11272 bool cpu_bw_status = true;
11273 virDomainDefPtr persistentDef;
11274 virDomainDefPtr def;
11275 qemuDomainObjPrivatePtr priv;
11276 int maxparams = *nparams;
11278 *nparams = 0;
11280 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11281 VIR_DOMAIN_AFFECT_CONFIG |
11282 VIR_TYPED_PARAM_STRING_OKAY, -1);
11284 if (!(vm = qemuDomObjFromDomain(dom)))
11285 goto cleanup;
11287 priv = vm->privateData;
11289 if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
11290 goto cleanup;
11292 if (!virQEMUDriverIsPrivileged(driver)) {
11293 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
11294 _("CPU tuning is not available in session mode"));
11295 goto cleanup;
11298 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
11299 goto cleanup;
11301 if (persistentDef) {
11302 data = persistentDef->cputune;
11303 } else if (def) {
11304 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
11305 virReportError(VIR_ERR_OPERATION_INVALID,
11306 "%s", _("cgroup CPU controller is not mounted"));
11307 goto cleanup;
11310 if (virCgroupGetCpuShares(priv->cgroup, &data.shares) < 0)
11311 goto cleanup;
11313 if (virCgroupSupportsCpuBW(priv->cgroup)) {
11314 if (maxparams > 1 &&
11315 qemuGetVcpusBWLive(vm, &data.period, &data.quota) < 0)
11316 goto cleanup;
11318 if (maxparams > 3 &&
11319 qemuGetEmulatorBandwidthLive(priv->cgroup, &data.emulator_period,
11320 &data.emulator_quota) < 0)
11321 goto cleanup;
11323 if (maxparams > 5 &&
11324 qemuGetGlobalBWLive(priv->cgroup, &data.global_period,
11325 &data.global_quota) < 0)
11326 goto cleanup;
11328 if (maxparams > 7 &&
11329 qemuGetIOThreadsBWLive(vm, &data.iothread_period,
11330 &data.iothread_quota) < 0)
11331 goto cleanup;
11332 } else {
11333 cpu_bw_status = false;
11337 #define QEMU_SCHED_ASSIGN(param, name, type) \
11338 if (*nparams < maxparams && \
11339 virTypedParameterAssign(&(params[(*nparams)++]), \
11340 VIR_DOMAIN_SCHEDULER_ ## name, \
11341 VIR_TYPED_PARAM_ ## type, \
11342 data.param) < 0) \
11343 goto cleanup
11345 QEMU_SCHED_ASSIGN(shares, CPU_SHARES, ULLONG);
11347 if (cpu_bw_status) {
11348 QEMU_SCHED_ASSIGN(period, VCPU_PERIOD, ULLONG);
11349 QEMU_SCHED_ASSIGN(quota, VCPU_QUOTA, LLONG);
11351 QEMU_SCHED_ASSIGN(emulator_period, EMULATOR_PERIOD, ULLONG);
11352 QEMU_SCHED_ASSIGN(emulator_quota, EMULATOR_QUOTA, LLONG);
11354 QEMU_SCHED_ASSIGN(global_period, GLOBAL_PERIOD, ULLONG);
11355 QEMU_SCHED_ASSIGN(global_quota, GLOBAL_QUOTA, LLONG);
11357 QEMU_SCHED_ASSIGN(iothread_period, IOTHREAD_PERIOD, ULLONG);
11358 QEMU_SCHED_ASSIGN(iothread_quota, IOTHREAD_QUOTA, LLONG);
11361 #undef QEMU_SCHED_ASSIGN
11363 ret = 0;
11365 cleanup:
11366 virDomainObjEndAPI(&vm);
11367 return ret;
11370 static int
11371 qemuDomainGetSchedulerParameters(virDomainPtr dom,
11372 virTypedParameterPtr params,
11373 int *nparams)
11375 return qemuDomainGetSchedulerParametersFlags(dom, params, nparams,
11376 VIR_DOMAIN_AFFECT_CURRENT);
11380 * Resize a block device while a guest is running. Resize to a lower size
11381 * is supported, but should be used with extreme caution. Note that it
11382 * only supports to resize image files, it can't resize block devices
11383 * like LVM volumes.
11385 static int
11386 qemuDomainBlockResize(virDomainPtr dom,
11387 const char *path,
11388 unsigned long long size,
11389 unsigned int flags)
11391 virQEMUDriverPtr driver = dom->conn->privateData;
11392 virDomainObjPtr vm;
11393 qemuDomainObjPrivatePtr priv;
11394 int ret = -1;
11395 char *device = NULL;
11396 const char *nodename = NULL;
11397 virDomainDiskDefPtr disk = NULL;
11399 virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
11401 /* We prefer operating on bytes. */
11402 if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
11403 if (size > ULLONG_MAX / 1024) {
11404 virReportError(VIR_ERR_OVERFLOW,
11405 _("size must be less than %llu"),
11406 ULLONG_MAX / 1024);
11407 return -1;
11409 size *= 1024;
11412 if (!(vm = qemuDomObjFromDomain(dom)))
11413 goto cleanup;
11415 priv = vm->privateData;
11417 if (virDomainBlockResizeEnsureACL(dom->conn, vm->def) < 0)
11418 goto cleanup;
11420 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
11421 goto cleanup;
11423 if (virDomainObjCheckActive(vm) < 0)
11424 goto endjob;
11426 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
11427 virReportError(VIR_ERR_INVALID_ARG,
11428 _("disk '%s' was not found in the domain config"), path);
11429 goto endjob;
11432 /* qcow2 and qed must be sized on 512 byte blocks/sectors,
11433 * so adjust size if necessary to round up.
11435 if (disk->src->format == VIR_STORAGE_FILE_QCOW2 ||
11436 disk->src->format == VIR_STORAGE_FILE_QED)
11437 size = VIR_ROUND_UP(size, 512);
11439 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
11440 if (virStorageSourceIsEmpty(disk->src) || disk->src->readonly) {
11441 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
11442 _("can't resize empty or readonly disk '%s'"),
11443 disk->dst);
11444 goto endjob;
11447 nodename = disk->src->nodeformat;
11448 } else {
11449 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
11450 goto endjob;
11453 qemuDomainObjEnterMonitor(driver, vm);
11454 if (qemuMonitorBlockResize(priv->mon, device, nodename, size) < 0) {
11455 ignore_value(qemuDomainObjExitMonitor(driver, vm));
11456 goto endjob;
11458 if (qemuDomainObjExitMonitor(driver, vm) < 0)
11459 goto endjob;
11461 ret = 0;
11463 endjob:
11464 qemuDomainObjEndJob(driver, vm);
11466 cleanup:
11467 VIR_FREE(device);
11468 virDomainObjEndAPI(&vm);
11469 return ret;
11473 static int
11474 qemuDomainBlockStatsGatherTotals(qemuBlockStatsPtr data,
11475 qemuBlockStatsPtr total)
11477 #define QEMU_BLOCK_STAT_TOTAL(NAME) \
11478 if (data->NAME > 0) \
11479 total->NAME += data->NAME
11481 QEMU_BLOCK_STAT_TOTAL(wr_bytes);
11482 QEMU_BLOCK_STAT_TOTAL(wr_req);
11483 QEMU_BLOCK_STAT_TOTAL(rd_bytes);
11484 QEMU_BLOCK_STAT_TOTAL(rd_req);
11485 QEMU_BLOCK_STAT_TOTAL(flush_req);
11486 QEMU_BLOCK_STAT_TOTAL(wr_total_times);
11487 QEMU_BLOCK_STAT_TOTAL(rd_total_times);
11488 QEMU_BLOCK_STAT_TOTAL(flush_total_times);
11489 #undef QEMU_BLOCK_STAT_TOTAL
11490 return 0;
11495 * qemuDomainBlocksStatsGather:
11496 * @driver: driver object
11497 * @vm: domain object
11498 * @path: to gather the statistics for
11499 * @capacity: refresh capacity of the backing image
11500 * @retstats: returns pointer to structure holding the stats
11502 * Gathers the block statistics for use in qemuDomainBlockStats* APIs.
11504 * Returns -1 on error; number of filled block statistics on success.
11506 static int
11507 qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
11508 virDomainObjPtr vm,
11509 const char *path,
11510 bool capacity,
11511 qemuBlockStatsPtr *retstats)
11513 qemuDomainObjPrivatePtr priv = vm->privateData;
11514 bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
11515 virDomainDiskDefPtr disk = NULL;
11516 virHashTablePtr blockstats = NULL;
11517 qemuBlockStatsPtr stats;
11518 size_t i;
11519 int nstats;
11520 int rc = 0;
11521 const char *entryname = NULL;
11522 int ret = -1;
11524 if (*path) {
11525 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
11526 virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
11527 goto cleanup;
11530 if (blockdev) {
11531 entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
11532 } else {
11533 if (!disk->info.alias) {
11534 virReportError(VIR_ERR_INTERNAL_ERROR,
11535 _("missing disk device alias name for %s"), disk->dst);
11536 goto cleanup;
11539 entryname = disk->info.alias;
11543 qemuDomainObjEnterMonitor(driver, vm);
11544 nstats = qemuMonitorGetAllBlockStatsInfo(priv->mon, &blockstats, false);
11546 if (capacity && nstats >= 0) {
11547 if (blockdev)
11548 rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, blockstats);
11549 else
11550 rc = qemuMonitorBlockStatsUpdateCapacity(priv->mon, blockstats, false);
11553 if (qemuDomainObjExitMonitor(driver, vm) < 0 || nstats < 0 || rc < 0)
11554 goto cleanup;
11556 if (VIR_ALLOC(*retstats) < 0)
11557 goto cleanup;
11559 if (entryname) {
11560 if (!(stats = virHashLookup(blockstats, entryname))) {
11561 virReportError(VIR_ERR_INTERNAL_ERROR,
11562 _("cannot find statistics for device '%s'"), entryname);
11563 goto cleanup;
11566 **retstats = *stats;
11568 if (blockdev) {
11569 /* capacity are reported only per node-name so we need to transfer them */
11570 qemuBlockStatsPtr capstats;
11572 if (disk && disk->src &&
11573 (capstats = virHashLookup(blockstats, disk->src->nodeformat))) {
11574 (*retstats)->capacity = capstats->capacity;
11575 (*retstats)->physical = capstats->physical;
11576 (*retstats)->wr_highest_offset = capstats->wr_highest_offset;
11577 (*retstats)->wr_highest_offset_valid = capstats->wr_highest_offset_valid;
11578 (*retstats)->write_threshold = capstats->write_threshold;
11581 } else {
11582 for (i = 0; i < vm->def->ndisks; i++) {
11583 disk = vm->def->disks[i];
11584 entryname = disk->info.alias;
11586 if (blockdev)
11587 entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
11589 if (!entryname)
11590 continue;
11592 if (!(stats = virHashLookup(blockstats, entryname))) {
11593 virReportError(VIR_ERR_INTERNAL_ERROR,
11594 _("cannot find statistics for device '%s'"), entryname);
11595 goto cleanup;
11598 qemuDomainBlockStatsGatherTotals(stats, *retstats);
11602 ret = nstats;
11604 cleanup:
11605 virHashFree(blockstats);
11606 return ret;
11610 /* This uses the 'info blockstats' monitor command which was
11611 * integrated into both qemu & kvm in late 2007. If the command is
11612 * not supported we detect this and return the appropriate error.
11614 static int
11615 qemuDomainBlockStats(virDomainPtr dom,
11616 const char *path,
11617 virDomainBlockStatsPtr stats)
11619 virQEMUDriverPtr driver = dom->conn->privateData;
11620 qemuBlockStatsPtr blockstats = NULL;
11621 int ret = -1;
11622 virDomainObjPtr vm;
11624 if (!(vm = qemuDomObjFromDomain(dom)))
11625 goto cleanup;
11627 if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
11628 goto cleanup;
11630 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
11631 goto cleanup;
11633 if (virDomainObjCheckActive(vm) < 0)
11634 goto endjob;
11636 if (qemuDomainBlocksStatsGather(driver, vm, path, false, &blockstats) < 0)
11637 goto endjob;
11639 stats->rd_req = blockstats->rd_req;
11640 stats->rd_bytes = blockstats->rd_bytes;
11641 stats->wr_req = blockstats->wr_req;
11642 stats->wr_bytes = blockstats->wr_bytes;
11643 /* qemu doesn't report the error count */
11644 stats->errs = -1;
11646 ret = 0;
11648 endjob:
11649 qemuDomainObjEndJob(driver, vm);
11651 cleanup:
11652 virDomainObjEndAPI(&vm);
11653 VIR_FREE(blockstats);
11654 return ret;
11658 static int
11659 qemuDomainBlockStatsFlags(virDomainPtr dom,
11660 const char *path,
11661 virTypedParameterPtr params,
11662 int *nparams,
11663 unsigned int flags)
11665 virQEMUDriverPtr driver = dom->conn->privateData;
11666 virDomainObjPtr vm;
11667 qemuBlockStatsPtr blockstats = NULL;
11668 int nstats;
11669 int ret = -1;
11671 VIR_DEBUG("params=%p, flags=0x%x", params, flags);
11673 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
11675 /* We don't return strings, and thus trivially support this flag. */
11676 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
11678 if (!(vm = qemuDomObjFromDomain(dom)))
11679 goto cleanup;
11681 if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
11682 goto cleanup;
11684 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
11685 goto cleanup;
11687 if (virDomainObjCheckActive(vm) < 0)
11688 goto endjob;
11690 if ((nstats = qemuDomainBlocksStatsGather(driver, vm, path, false,
11691 &blockstats)) < 0)
11692 goto endjob;
11694 /* return count of supported stats */
11695 if (*nparams == 0) {
11696 *nparams = nstats;
11697 ret = 0;
11698 goto endjob;
11701 nstats = 0;
11703 #define QEMU_BLOCK_STATS_ASSIGN_PARAM(VAR, NAME) \
11704 if (nstats < *nparams && (blockstats->VAR) != -1) { \
11705 if (virTypedParameterAssign(params + nstats, NAME, \
11706 VIR_TYPED_PARAM_LLONG, (blockstats->VAR)) < 0) \
11707 goto endjob; \
11708 nstats++; \
11711 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
11712 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);
11714 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
11715 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ);
11717 QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_req, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);
11719 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_total_times,
11720 VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES);
11721 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_total_times,
11722 VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES);
11723 QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_total_times,
11724 VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES);
11725 #undef QEMU_BLOCK_STATS_ASSIGN_PARAM
11727 ret = 0;
11728 *nparams = nstats;
11730 endjob:
11731 qemuDomainObjEndJob(driver, vm);
11733 cleanup:
11734 VIR_FREE(blockstats);
11735 virDomainObjEndAPI(&vm);
11736 return ret;
11739 static int
11740 qemuDomainInterfaceStats(virDomainPtr dom,
11741 const char *device,
11742 virDomainInterfaceStatsPtr stats)
11744 virDomainObjPtr vm;
11745 virDomainNetDefPtr net = NULL;
11746 int ret = -1;
11748 if (!(vm = qemuDomObjFromDomain(dom)))
11749 goto cleanup;
11751 if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0)
11752 goto cleanup;
11754 if (virDomainObjCheckActive(vm) < 0)
11755 goto cleanup;
11757 if (!(net = virDomainNetFind(vm->def, device)))
11758 goto cleanup;
11760 if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
11761 if (virNetDevOpenvswitchInterfaceStats(net->ifname, stats) < 0)
11762 goto cleanup;
11763 } else {
11764 if (virNetDevTapInterfaceStats(net->ifname, stats,
11765 !virDomainNetTypeSharesHostView(net)) < 0)
11766 goto cleanup;
11769 ret = 0;
11770 cleanup:
11771 virDomainObjEndAPI(&vm);
11772 return ret;
11775 static int
11776 qemuDomainSetInterfaceParameters(virDomainPtr dom,
11777 const char *device,
11778 virTypedParameterPtr params,
11779 int nparams,
11780 unsigned int flags)
11782 virQEMUDriverPtr driver = dom->conn->privateData;
11783 size_t i;
11784 virDomainObjPtr vm = NULL;
11785 virDomainDefPtr def;
11786 virDomainDefPtr persistentDef;
11787 int ret = -1;
11788 virDomainNetDefPtr net = NULL, persistentNet = NULL;
11789 virNetDevBandwidthPtr bandwidth = NULL, newBandwidth = NULL;
11790 virQEMUDriverConfigPtr cfg = NULL;
11791 bool inboundSpecified = false, outboundSpecified = false;
11792 int actualType;
11793 bool qosSupported = true;
11795 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11796 VIR_DOMAIN_AFFECT_CONFIG, -1);
11797 if (virTypedParamsValidate(params, nparams,
11798 VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
11799 VIR_TYPED_PARAM_UINT,
11800 VIR_DOMAIN_BANDWIDTH_IN_PEAK,
11801 VIR_TYPED_PARAM_UINT,
11802 VIR_DOMAIN_BANDWIDTH_IN_BURST,
11803 VIR_TYPED_PARAM_UINT,
11804 VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
11805 VIR_TYPED_PARAM_UINT,
11806 VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
11807 VIR_TYPED_PARAM_UINT,
11808 VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
11809 VIR_TYPED_PARAM_UINT,
11810 VIR_DOMAIN_BANDWIDTH_OUT_BURST,
11811 VIR_TYPED_PARAM_UINT,
11812 NULL) < 0)
11813 return -1;
11815 if (!(vm = qemuDomObjFromDomain(dom)))
11816 return -1;
11818 cfg = virQEMUDriverGetConfig(driver);
11820 if (virDomainSetInterfaceParametersEnsureACL(dom->conn, vm->def, flags) < 0)
11821 goto cleanup;
11823 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
11824 goto cleanup;
11826 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
11827 goto endjob;
11829 if (def &&
11830 !(net = virDomainNetFind(vm->def, device)))
11831 goto endjob;
11833 if (persistentDef &&
11834 !(persistentNet = virDomainNetFind(persistentDef, device)))
11835 goto endjob;
11837 if (net) {
11838 actualType = virDomainNetGetActualType(net);
11839 qosSupported = virNetDevSupportBandwidth(actualType);
11842 if (qosSupported && persistentNet) {
11843 actualType = virDomainNetGetActualType(persistentNet);
11844 qosSupported = virNetDevSupportBandwidth(actualType);
11847 if (!qosSupported) {
11848 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11849 _("setting bandwidth on interfaces of "
11850 "type '%s' is not implemented yet"),
11851 virDomainNetTypeToString(actualType));
11852 goto endjob;
11855 if ((VIR_ALLOC(bandwidth) < 0) ||
11856 (VIR_ALLOC(bandwidth->in) < 0) ||
11857 (VIR_ALLOC(bandwidth->out) < 0))
11858 goto endjob;
11860 for (i = 0; i < nparams; i++) {
11861 virTypedParameterPtr param = &params[i];
11863 if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) {
11864 bandwidth->in->average = param->value.ui;
11865 inboundSpecified = true;
11866 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) {
11867 bandwidth->in->peak = param->value.ui;
11868 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) {
11869 bandwidth->in->burst = param->value.ui;
11870 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_FLOOR)) {
11871 bandwidth->in->floor = param->value.ui;
11872 inboundSpecified = true;
11873 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) {
11874 bandwidth->out->average = param->value.ui;
11875 outboundSpecified = true;
11876 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) {
11877 bandwidth->out->peak = param->value.ui;
11878 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) {
11879 bandwidth->out->burst = param->value.ui;
11883 /* average or floor are mandatory, peak and burst are optional.
11884 * So if no average or floor is given, we free inbound/outbound
11885 * here which causes inbound/outbound to not be set. */
11886 if (!bandwidth->in->average && !bandwidth->in->floor)
11887 VIR_FREE(bandwidth->in);
11888 if (!bandwidth->out->average)
11889 VIR_FREE(bandwidth->out);
11891 if (net) {
11892 if (VIR_ALLOC(newBandwidth) < 0)
11893 goto endjob;
11895 /* virNetDevBandwidthSet() will clear any previous value of
11896 * bandwidth parameters, so merge with old bandwidth parameters
11897 * here to prevent them from being lost. */
11898 if (bandwidth->in ||
11899 (!inboundSpecified && net->bandwidth && net->bandwidth->in)) {
11900 if (VIR_ALLOC(newBandwidth->in) < 0)
11901 goto endjob;
11903 memcpy(newBandwidth->in,
11904 bandwidth->in ? bandwidth->in : net->bandwidth->in,
11905 sizeof(*newBandwidth->in));
11907 if (bandwidth->out ||
11908 (!outboundSpecified && net->bandwidth && net->bandwidth->out)) {
11909 if (VIR_ALLOC(newBandwidth->out) < 0)
11910 goto endjob;
11912 memcpy(newBandwidth->out,
11913 bandwidth->out ? bandwidth->out : net->bandwidth->out,
11914 sizeof(*newBandwidth->out));
11917 if (!virDomainNetBandwidthChangeAllowed(net, newBandwidth))
11918 goto endjob;
11920 if (virNetDevBandwidthSet(net->ifname, newBandwidth, false,
11921 !virDomainNetTypeSharesHostView(net)) < 0 ||
11922 virDomainNetBandwidthUpdate(net, newBandwidth) < 0) {
11923 ignore_value(virNetDevBandwidthSet(net->ifname,
11924 net->bandwidth,
11925 false,
11926 !virDomainNetTypeSharesHostView(net)));
11927 goto endjob;
11930 virNetDevBandwidthFree(net->bandwidth);
11931 if (newBandwidth->in || newBandwidth->out) {
11932 net->bandwidth = newBandwidth;
11933 newBandwidth = NULL;
11934 } else {
11935 net->bandwidth = NULL;
11938 if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
11939 virNetDevBandwidthFree(net->data.network.actual->bandwidth);
11940 if (virNetDevBandwidthCopy(&net->data.network.actual->bandwidth,
11941 net->bandwidth) < 0)
11942 goto endjob;
11945 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
11946 goto endjob;
11949 if (persistentNet) {
11950 if (!persistentNet->bandwidth) {
11951 persistentNet->bandwidth = bandwidth;
11952 bandwidth = NULL;
11953 } else {
11954 if (bandwidth->in) {
11955 VIR_FREE(persistentNet->bandwidth->in);
11956 persistentNet->bandwidth->in = bandwidth->in;
11957 bandwidth->in = NULL;
11958 } else if (inboundSpecified) {
11959 VIR_FREE(persistentNet->bandwidth->in);
11961 if (bandwidth->out) {
11962 VIR_FREE(persistentNet->bandwidth->out);
11963 persistentNet->bandwidth->out = bandwidth->out;
11964 bandwidth->out = NULL;
11965 } else if (outboundSpecified) {
11966 VIR_FREE(persistentNet->bandwidth->out);
11970 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
11971 goto endjob;
11974 ret = 0;
11976 endjob:
11977 qemuDomainObjEndJob(driver, vm);
11979 cleanup:
11980 virNetDevBandwidthFree(bandwidth);
11981 virNetDevBandwidthFree(newBandwidth);
11982 virDomainObjEndAPI(&vm);
11983 virObjectUnref(cfg);
11984 return ret;
11987 static int
11988 qemuDomainGetInterfaceParameters(virDomainPtr dom,
11989 const char *device,
11990 virTypedParameterPtr params,
11991 int *nparams,
11992 unsigned int flags)
11994 size_t i;
11995 virDomainObjPtr vm = NULL;
11996 virDomainDefPtr def = NULL;
11997 virDomainNetDefPtr net = NULL;
11998 int ret = -1;
12000 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
12001 VIR_DOMAIN_AFFECT_CONFIG |
12002 VIR_TYPED_PARAM_STRING_OKAY, -1);
12004 if (!(vm = qemuDomObjFromDomain(dom)))
12005 return -1;
12007 if (virDomainGetInterfaceParametersEnsureACL(dom->conn, vm->def) < 0)
12008 goto cleanup;
12010 if (!(def = virDomainObjGetOneDef(vm, flags)))
12011 goto cleanup;
12013 if ((*nparams) == 0) {
12014 *nparams = QEMU_NB_BANDWIDTH_PARAM;
12015 ret = 0;
12016 goto cleanup;
12019 if (!(net = virDomainNetFind(def, device)))
12020 goto cleanup;
12022 for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) {
12023 switch (i) {
12024 case 0: /* inbound.average */
12025 if (virTypedParameterAssign(&params[i],
12026 VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
12027 VIR_TYPED_PARAM_UINT, 0) < 0)
12028 goto cleanup;
12029 if (net->bandwidth && net->bandwidth->in)
12030 params[i].value.ui = net->bandwidth->in->average;
12031 break;
12032 case 1: /* inbound.peak */
12033 if (virTypedParameterAssign(&params[i],
12034 VIR_DOMAIN_BANDWIDTH_IN_PEAK,
12035 VIR_TYPED_PARAM_UINT, 0) < 0)
12036 goto cleanup;
12037 if (net->bandwidth && net->bandwidth->in)
12038 params[i].value.ui = net->bandwidth->in->peak;
12039 break;
12040 case 2: /* inbound.burst */
12041 if (virTypedParameterAssign(&params[i],
12042 VIR_DOMAIN_BANDWIDTH_IN_BURST,
12043 VIR_TYPED_PARAM_UINT, 0) < 0)
12044 goto cleanup;
12045 if (net->bandwidth && net->bandwidth->in)
12046 params[i].value.ui = net->bandwidth->in->burst;
12047 break;
12048 case 3: /* inbound.floor */
12049 if (virTypedParameterAssign(&params[i],
12050 VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
12051 VIR_TYPED_PARAM_UINT, 0) < 0)
12052 goto cleanup;
12053 if (net->bandwidth && net->bandwidth->in)
12054 params[i].value.ui = net->bandwidth->in->floor;
12055 break;
12056 case 4: /* outbound.average */
12057 if (virTypedParameterAssign(&params[i],
12058 VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
12059 VIR_TYPED_PARAM_UINT, 0) < 0)
12060 goto cleanup;
12061 if (net->bandwidth && net->bandwidth->out)
12062 params[i].value.ui = net->bandwidth->out->average;
12063 break;
12064 case 5: /* outbound.peak */
12065 if (virTypedParameterAssign(&params[i],
12066 VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
12067 VIR_TYPED_PARAM_UINT, 0) < 0)
12068 goto cleanup;
12069 if (net->bandwidth && net->bandwidth->out)
12070 params[i].value.ui = net->bandwidth->out->peak;
12071 break;
12072 case 6: /* outbound.burst */
12073 if (virTypedParameterAssign(&params[i],
12074 VIR_DOMAIN_BANDWIDTH_OUT_BURST,
12075 VIR_TYPED_PARAM_UINT, 0) < 0)
12076 goto cleanup;
12077 if (net->bandwidth && net->bandwidth->out)
12078 params[i].value.ui = net->bandwidth->out->burst;
12079 break;
12080 /* coverity[dead_error_begin] */
12081 default:
12082 break;
12083 /* should not hit here */
12087 if (*nparams > QEMU_NB_BANDWIDTH_PARAM)
12088 *nparams = QEMU_NB_BANDWIDTH_PARAM;
12089 ret = 0;
12091 cleanup:
12092 virDomainObjEndAPI(&vm);
12093 return ret;
12096 /* This functions assumes that job QEMU_JOB_QUERY is started by a caller */
12097 static int
12098 qemuDomainMemoryStatsInternal(virQEMUDriverPtr driver,
12099 virDomainObjPtr vm,
12100 virDomainMemoryStatPtr stats,
12101 unsigned int nr_stats)
12104 int ret = -1;
12105 long rss;
12107 if (virDomainObjCheckActive(vm) < 0)
12108 return -1;
12110 if (virDomainDefHasMemballoon(vm->def)) {
12111 qemuDomainObjEnterMonitor(driver, vm);
12112 ret = qemuMonitorGetMemoryStats(qemuDomainGetMonitor(vm),
12113 vm->def->memballoon, stats, nr_stats);
12114 if (qemuDomainObjExitMonitor(driver, vm) < 0)
12115 ret = -1;
12117 if (ret < 0 || ret >= nr_stats)
12118 return ret;
12119 } else {
12120 ret = 0;
12123 if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) {
12124 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
12125 _("cannot get RSS for domain"));
12126 } else {
12127 stats[ret].tag = VIR_DOMAIN_MEMORY_STAT_RSS;
12128 stats[ret].val = rss;
12129 ret++;
12132 return ret;
12135 static int
12136 qemuDomainMemoryStats(virDomainPtr dom,
12137 virDomainMemoryStatPtr stats,
12138 unsigned int nr_stats,
12139 unsigned int flags)
12141 virQEMUDriverPtr driver = dom->conn->privateData;
12142 virDomainObjPtr vm;
12143 int ret = -1;
12145 virCheckFlags(0, -1);
12147 if (!(vm = qemuDomObjFromDomain(dom)))
12148 goto cleanup;
12150 if (virDomainMemoryStatsEnsureACL(dom->conn, vm->def) < 0)
12151 goto cleanup;
12153 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12154 goto cleanup;
12156 ret = qemuDomainMemoryStatsInternal(driver, vm, stats, nr_stats);
12158 qemuDomainObjEndJob(driver, vm);
12160 cleanup:
12161 virDomainObjEndAPI(&vm);
12162 return ret;
12165 static int
12166 qemuDomainBlockPeek(virDomainPtr dom,
12167 const char *path,
12168 unsigned long long offset, size_t size,
12169 void *buffer,
12170 unsigned int flags)
12172 virQEMUDriverPtr driver = dom->conn->privateData;
12173 virDomainDiskDefPtr disk = NULL;
12174 virDomainObjPtr vm;
12175 char *tmpbuf = NULL;
12176 ssize_t nread;
12177 int ret = -1;
12179 virCheckFlags(0, -1);
12181 if (!(vm = qemuDomObjFromDomain(dom)))
12182 goto cleanup;
12184 if (virDomainBlockPeekEnsureACL(dom->conn, vm->def) < 0)
12185 goto cleanup;
12187 /* Check the path belongs to this domain. */
12188 if (!(disk = virDomainDiskByName(vm->def, path, true))) {
12189 virReportError(VIR_ERR_INVALID_ARG,
12190 _("invalid disk or path '%s'"), path);
12191 goto cleanup;
12194 if (disk->src->format != VIR_STORAGE_FILE_RAW) {
12195 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12196 _("peeking is only supported for disk with 'raw' format not '%s'"),
12197 virStorageFileFormatTypeToString(disk->src->format));
12198 goto cleanup;
12201 if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) < 0)
12202 goto cleanup;
12204 if ((nread = virStorageFileRead(disk->src, offset, size, &tmpbuf)) < 0) {
12205 if (nread == -2) {
12206 virReportError(VIR_ERR_INTERNAL_ERROR,
12207 _("storage file reading is not supported for "
12208 "storage type %s (protocol: %s)"),
12209 virStorageTypeToString(disk->src->type),
12210 virStorageNetProtocolTypeToString(disk->src->protocol));
12212 goto cleanup;
12215 if (nread < size) {
12216 virReportError(VIR_ERR_INVALID_ARG,
12217 _("'%s' starting from %llu has only %zd bytes available"),
12218 path, offset, nread);
12219 goto cleanup;
12222 memcpy(buffer, tmpbuf, size);
12224 ret = 0;
12226 cleanup:
12227 if (disk)
12228 virStorageFileDeinit(disk->src);
12229 virDomainObjEndAPI(&vm);
12230 VIR_FREE(tmpbuf);
12231 return ret;
12234 static int
12235 qemuDomainMemoryPeek(virDomainPtr dom,
12236 unsigned long long offset, size_t size,
12237 void *buffer,
12238 unsigned int flags)
12240 virQEMUDriverPtr driver = dom->conn->privateData;
12241 virDomainObjPtr vm;
12242 char *tmp = NULL;
12243 int fd = -1, ret = -1;
12244 qemuDomainObjPrivatePtr priv;
12245 virQEMUDriverConfigPtr cfg = NULL;
12247 virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);
12249 if (!(vm = qemuDomObjFromDomain(dom)))
12250 goto cleanup;
12252 cfg = virQEMUDriverGetConfig(driver);
12254 if (virDomainMemoryPeekEnsureACL(dom->conn, vm->def) < 0)
12255 goto cleanup;
12257 if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
12258 virReportError(VIR_ERR_INVALID_ARG,
12259 "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
12260 goto cleanup;
12263 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12264 goto cleanup;
12266 if (virDomainObjCheckActive(vm) < 0)
12267 goto endjob;
12269 if (virAsprintf(&tmp, "%s/qemu.mem.XXXXXX", cfg->cacheDir) < 0)
12270 goto endjob;
12272 /* Create a temporary filename. */
12273 if ((fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
12274 virReportSystemError(errno,
12275 _("mkostemp(\"%s\") failed"), tmp);
12276 goto endjob;
12279 qemuSecuritySetSavedStateLabel(driver, vm, tmp);
12281 priv = vm->privateData;
12282 qemuDomainObjEnterMonitor(driver, vm);
12283 if (flags == VIR_MEMORY_VIRTUAL) {
12284 if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
12285 ignore_value(qemuDomainObjExitMonitor(driver, vm));
12286 goto endjob;
12288 } else {
12289 if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
12290 ignore_value(qemuDomainObjExitMonitor(driver, vm));
12291 goto endjob;
12294 if (qemuDomainObjExitMonitor(driver, vm) < 0)
12295 goto endjob;
12297 /* Read the memory file into buffer. */
12298 if (saferead(fd, buffer, size) == (ssize_t)-1) {
12299 virReportSystemError(errno,
12300 _("failed to read temporary file "
12301 "created with template %s"), tmp);
12302 goto endjob;
12305 ret = 0;
12307 endjob:
12308 qemuDomainObjEndJob(driver, vm);
12310 cleanup:
12311 VIR_FORCE_CLOSE(fd);
12312 if (tmp)
12313 unlink(tmp);
12314 VIR_FREE(tmp);
12315 virDomainObjEndAPI(&vm);
12316 virObjectUnref(cfg);
12317 return ret;
12322 * @driver: qemu driver data
12323 * @cfg: driver configuration data
12324 * @vm: domain object
12325 * @src: storage source data
12326 * @ret_fd: pointer to return open'd file descriptor
12327 * @ret_sb: pointer to return stat buffer (local or remote)
12329 * For local storage, open the file using qemuOpenFile and then use
12330 * fstat() to grab the stat struct data for the caller.
12332 * For remote storage, attempt to access the file and grab the stat
12333 * struct data if the remote connection supports it.
12335 * Returns 0 on success with @ret_fd and @ret_sb populated, -1 on failure
12337 static int
12338 qemuDomainStorageOpenStat(virQEMUDriverPtr driver,
12339 virQEMUDriverConfigPtr cfg,
12340 virDomainObjPtr vm,
12341 virStorageSourcePtr src,
12342 int *ret_fd,
12343 struct stat *ret_sb)
12345 if (virStorageSourceIsLocalStorage(src)) {
12346 if ((*ret_fd = qemuOpenFile(driver, vm, src->path, O_RDONLY,
12347 NULL)) < 0)
12348 return -1;
12350 if (fstat(*ret_fd, ret_sb) < 0) {
12351 virReportSystemError(errno, _("cannot stat file '%s'"), src->path);
12352 VIR_FORCE_CLOSE(*ret_fd);
12353 return -1;
12355 } else {
12356 if (virStorageFileInitAs(src, cfg->user, cfg->group) < 0)
12357 return -1;
12359 if (virStorageFileStat(src, ret_sb) < 0) {
12360 virStorageFileDeinit(src);
12361 virReportSystemError(errno, _("failed to stat remote file '%s'"),
12362 NULLSTR(src->path));
12363 return -1;
12367 return 0;
12372 * @src: storage source data
12373 * @fd: file descriptor to close for local
12375 * If local, then just close the file descriptor.
12376 * else remote, then tear down the storage driver backend connection.
12378 static void
12379 qemuDomainStorageCloseStat(virStorageSourcePtr src,
12380 int *fd)
12382 if (virStorageSourceIsLocalStorage(src))
12383 VIR_FORCE_CLOSE(*fd);
12384 else
12385 virStorageFileDeinit(src);
12389 static int
12390 qemuDomainStorageUpdatePhysical(virQEMUDriverPtr driver,
12391 virQEMUDriverConfigPtr cfg,
12392 virDomainObjPtr vm,
12393 virStorageSourcePtr src)
12395 int ret;
12396 int fd = -1;
12397 struct stat sb;
12399 if (virStorageSourceIsEmpty(src))
12400 return 0;
12402 if (qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb) < 0)
12403 return -1;
12405 ret = virStorageSourceUpdatePhysicalSize(src, fd, &sb);
12407 qemuDomainStorageCloseStat(src, &fd);
12409 return ret;
12414 * @driver: qemu driver data
12415 * @cfg: driver configuration data
12416 * @vm: domain object
12417 * @src: storage source data
12419 * Refresh the capacity and allocation limits of a given storage source.
12421 * Assumes that the caller has already obtained a domain job and only
12422 * called for an offline domain. Being offline is particularly important
12423 * since reading a file while qemu is writing it risks the reader seeing
12424 * bogus data or avoiding opening a file in order to get stat data.
12426 * We always want to check current on-disk statistics (as users have been
12427 * known to change offline images behind our backs).
12429 * For read-only disks, nothing should be changing unless the user has
12430 * requested a block-commit action. For read-write disks, we know some
12431 * special cases: capacity should not change without a block-resize (where
12432 * capacity is the only stat that requires reading a file, and even then,
12433 * only for non-raw files); and physical size of a raw image or of a
12434 * block device should likewise not be changing without block-resize.
12435 * On the other hand, allocation of a raw file can change (if the file
12436 * is sparse, but the amount of sparseness changes due to writes or
12437 * punching holes), and physical size of a non-raw file can change.
12439 * Returns 0 on success, -1 on failure
12441 static int
12442 qemuStorageLimitsRefresh(virQEMUDriverPtr driver,
12443 virQEMUDriverConfigPtr cfg,
12444 virDomainObjPtr vm,
12445 virStorageSourcePtr src)
12447 int ret = -1;
12448 int fd = -1;
12449 struct stat sb;
12450 char *buf = NULL;
12451 ssize_t len;
12453 if (qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb) < 0)
12454 goto cleanup;
12456 if (virStorageSourceIsLocalStorage(src)) {
12457 if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
12458 virReportSystemError(errno, _("cannot read header '%s'"),
12459 src->path);
12460 goto cleanup;
12462 } else {
12463 if ((len = virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, &buf)) < 0)
12464 goto cleanup;
12467 if (virStorageSourceUpdateBackingSizes(src, fd, &sb) < 0)
12468 goto cleanup;
12470 if (virStorageSourceUpdateCapacity(src, buf, len, false) < 0)
12471 goto cleanup;
12473 /* If guest is not using raw disk format and is on a host block
12474 * device, then leave the value unspecified, so caller knows to
12475 * query the highest allocated extent from QEMU
12477 if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK &&
12478 src->format != VIR_STORAGE_FILE_RAW &&
12479 S_ISBLK(sb.st_mode))
12480 src->allocation = 0;
12482 ret = 0;
12484 cleanup:
12485 VIR_FREE(buf);
12486 qemuDomainStorageCloseStat(src, &fd);
12487 return ret;
12491 static int
12492 qemuDomainGetBlockInfo(virDomainPtr dom,
12493 const char *path,
12494 virDomainBlockInfoPtr info,
12495 unsigned int flags)
12497 virQEMUDriverPtr driver = dom->conn->privateData;
12498 virDomainObjPtr vm;
12499 int ret = -1;
12500 virDomainDiskDefPtr disk;
12501 virQEMUDriverConfigPtr cfg = NULL;
12502 qemuBlockStatsPtr entry = NULL;
12504 virCheckFlags(0, -1);
12506 if (!(vm = qemuDomObjFromDomain(dom)))
12507 return -1;
12509 cfg = virQEMUDriverGetConfig(driver);
12511 if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0)
12512 goto cleanup;
12514 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12515 goto cleanup;
12517 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
12518 virReportError(VIR_ERR_INVALID_ARG,
12519 _("invalid path %s not assigned to domain"), path);
12520 goto endjob;
12523 if (virStorageSourceIsEmpty(disk->src)) {
12524 virReportError(VIR_ERR_INVALID_ARG,
12525 _("disk '%s' does not currently have a source assigned"),
12526 path);
12527 goto endjob;
12530 /* for inactive domains we have to peek into the files */
12531 if (!virDomainObjIsActive(vm)) {
12532 if ((qemuStorageLimitsRefresh(driver, cfg, vm, disk->src)) < 0)
12533 goto endjob;
12535 info->capacity = disk->src->capacity;
12536 info->allocation = disk->src->allocation;
12537 info->physical = disk->src->physical;
12539 ret = 0;
12540 goto endjob;
12543 if (qemuDomainBlocksStatsGather(driver, vm, path, true, &entry) < 0)
12544 goto endjob;
12546 if (!entry->wr_highest_offset_valid) {
12547 info->allocation = entry->physical;
12548 } else {
12549 if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_FILE &&
12550 disk->src->format == VIR_STORAGE_FILE_QCOW2)
12551 info->allocation = entry->physical;
12552 else
12553 info->allocation = entry->wr_highest_offset;
12556 /* Unlike GetStatsBlock, this API has defined the expected return values
12557 * for allocation and physical slightly differently.
12559 * Having a zero for either or if they're the same is an indication that
12560 * there's a sparse file backing this device. In this case, we'll force
12561 * the setting of physical based on the on disk file size.
12563 * Additionally, if qemu hasn't written to the file yet, then set the
12564 * allocation to whatever qemu returned for physical (e.g. the "actual-
12565 * size" from the json query) as that will match the expected allocation
12566 * value for this API. NB: May still be 0 for block. */
12567 if (entry->physical == 0 || info->allocation == 0 ||
12568 info->allocation == entry->physical) {
12569 if (info->allocation == 0)
12570 info->allocation = entry->physical;
12572 if (qemuDomainStorageUpdatePhysical(driver, cfg, vm, disk->src) == 0) {
12573 info->physical = disk->src->physical;
12574 } else {
12575 virResetLastError();
12576 info->physical = entry->physical;
12578 } else {
12579 info->physical = entry->physical;
12582 info->capacity = entry->capacity;
12584 ret = 0;
12586 endjob:
12587 qemuDomainObjEndJob(driver, vm);
12588 cleanup:
12589 VIR_FREE(entry);
12590 virDomainObjEndAPI(&vm);
12591 virObjectUnref(cfg);
12592 return ret;
12596 static int
12597 qemuConnectDomainEventRegister(virConnectPtr conn,
12598 virConnectDomainEventCallback callback,
12599 void *opaque,
12600 virFreeCallback freecb)
12602 virQEMUDriverPtr driver = conn->privateData;
12603 int ret = -1;
12605 if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
12606 goto cleanup;
12608 if (virDomainEventStateRegister(conn,
12609 driver->domainEventState,
12610 callback, opaque, freecb) < 0)
12611 goto cleanup;
12613 ret = 0;
12615 cleanup:
12616 return ret;
12620 static int
12621 qemuConnectDomainEventDeregister(virConnectPtr conn,
12622 virConnectDomainEventCallback callback)
12624 virQEMUDriverPtr driver = conn->privateData;
12625 int ret = -1;
12627 if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
12628 goto cleanup;
12630 if (virDomainEventStateDeregister(conn,
12631 driver->domainEventState,
12632 callback) < 0)
12633 goto cleanup;
12635 ret = 0;
12637 cleanup:
12638 return ret;
12642 static int
12643 qemuConnectDomainEventRegisterAny(virConnectPtr conn,
12644 virDomainPtr dom,
12645 int eventID,
12646 virConnectDomainEventGenericCallback callback,
12647 void *opaque,
12648 virFreeCallback freecb)
12650 virQEMUDriverPtr driver = conn->privateData;
12651 int ret = -1;
12653 if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
12654 goto cleanup;
12656 if (virDomainEventStateRegisterID(conn,
12657 driver->domainEventState,
12658 dom, eventID,
12659 callback, opaque, freecb, &ret) < 0)
12660 ret = -1;
12662 cleanup:
12663 return ret;
12667 static int
12668 qemuConnectDomainEventDeregisterAny(virConnectPtr conn,
12669 int callbackID)
12671 virQEMUDriverPtr driver = conn->privateData;
12672 int ret = -1;
12674 if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
12675 goto cleanup;
12677 if (virObjectEventStateDeregisterID(conn,
12678 driver->domainEventState,
12679 callbackID, true) < 0)
12680 goto cleanup;
12682 ret = 0;
12684 cleanup:
12685 return ret;
12689 /*******************************************************************
12690 * Migration Protocol Version 2
12691 *******************************************************************/
12693 /* Prepare is the first step, and it runs on the destination host.
12695 * This version starts an empty VM listening on a localhost TCP port, and
12696 * sets up the corresponding virStream to handle the incoming data.
12698 static int
12699 qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
12700 virStreamPtr st,
12701 unsigned long flags,
12702 const char *dname,
12703 unsigned long resource ATTRIBUTE_UNUSED,
12704 const char *dom_xml)
12706 virQEMUDriverPtr driver = dconn->privateData;
12707 virDomainDefPtr def = NULL;
12708 char *origname = NULL;
12709 qemuMigrationParamsPtr migParams = NULL;
12710 int ret = -1;
12712 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12714 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
12715 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12716 _("PrepareTunnel called but no TUNNELLED flag set"));
12717 goto cleanup;
12720 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12721 QEMU_MIGRATION_DESTINATION)))
12722 goto cleanup;
12724 if (virLockManagerPluginUsesState(driver->lockManager)) {
12725 virReportError(VIR_ERR_INTERNAL_ERROR,
12726 _("Cannot use migrate v2 protocol with lock manager %s"),
12727 virLockManagerPluginGetName(driver->lockManager));
12728 goto cleanup;
12731 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
12732 goto cleanup;
12734 if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0)
12735 goto cleanup;
12737 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
12738 NULL, 0, NULL, NULL, /* No cookies in v2 */
12739 st, &def, origname, migParams, flags);
12741 cleanup:
12742 qemuMigrationParamsFree(migParams);
12743 VIR_FREE(origname);
12744 virDomainDefFree(def);
12745 return ret;
12748 /* Prepare is the first step, and it runs on the destination host.
12750 * This starts an empty VM listening on a TCP port.
12752 static int ATTRIBUTE_NONNULL(5)
12753 qemuDomainMigratePrepare2(virConnectPtr dconn,
12754 char **cookie ATTRIBUTE_UNUSED,
12755 int *cookielen ATTRIBUTE_UNUSED,
12756 const char *uri_in,
12757 char **uri_out,
12758 unsigned long flags,
12759 const char *dname,
12760 unsigned long resource ATTRIBUTE_UNUSED,
12761 const char *dom_xml)
12763 virQEMUDriverPtr driver = dconn->privateData;
12764 virDomainDefPtr def = NULL;
12765 char *origname = NULL;
12766 qemuMigrationParamsPtr migParams = NULL;
12767 int ret = -1;
12769 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12771 if (flags & VIR_MIGRATE_TUNNELLED) {
12772 /* this is a logical error; we never should have gotten here with
12773 * VIR_MIGRATE_TUNNELLED set
12775 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12776 _("Tunnelled migration requested but invalid "
12777 "RPC method called"));
12778 goto cleanup;
12781 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12782 QEMU_MIGRATION_DESTINATION)))
12783 goto cleanup;
12785 if (virLockManagerPluginUsesState(driver->lockManager)) {
12786 virReportError(VIR_ERR_INTERNAL_ERROR,
12787 _("Cannot use migrate v2 protocol with lock manager %s"),
12788 virLockManagerPluginGetName(driver->lockManager));
12789 goto cleanup;
12792 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
12793 goto cleanup;
12795 if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0)
12796 goto cleanup;
12798 /* Do not use cookies in v2 protocol, since the cookie
12799 * length was not sufficiently large, causing failures
12800 * migrating between old & new libvirtd
12802 ret = qemuMigrationDstPrepareDirect(driver, dconn,
12803 NULL, 0, NULL, NULL, /* No cookies */
12804 uri_in, uri_out,
12805 &def, origname, NULL, 0, NULL, 0,
12806 migParams, flags);
12808 cleanup:
12809 qemuMigrationParamsFree(migParams);
12810 VIR_FREE(origname);
12811 virDomainDefFree(def);
12812 return ret;
12816 /* Perform is the second step, and it runs on the source host. */
12817 static int
12818 qemuDomainMigratePerform(virDomainPtr dom,
12819 const char *cookie,
12820 int cookielen,
12821 const char *uri,
12822 unsigned long flags,
12823 const char *dname,
12824 unsigned long resource)
12826 virQEMUDriverPtr driver = dom->conn->privateData;
12827 virDomainObjPtr vm;
12828 int ret = -1;
12829 const char *dconnuri = NULL;
12830 qemuMigrationParamsPtr migParams = NULL;
12832 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12834 if (virLockManagerPluginUsesState(driver->lockManager)) {
12835 virReportError(VIR_ERR_INTERNAL_ERROR,
12836 _("Cannot use migrate v2 protocol with lock manager %s"),
12837 virLockManagerPluginGetName(driver->lockManager));
12838 goto cleanup;
12841 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12842 QEMU_MIGRATION_SOURCE)))
12843 goto cleanup;
12845 if (!(vm = qemuDomObjFromDomain(dom)))
12846 goto cleanup;
12848 if (virDomainMigratePerformEnsureACL(dom->conn, vm->def) < 0) {
12849 virDomainObjEndAPI(&vm);
12850 goto cleanup;
12853 if (flags & VIR_MIGRATE_PEER2PEER)
12854 VIR_STEAL_PTR(dconnuri, uri);
12856 /* Do not output cookies in v2 protocol, since the cookie
12857 * length was not sufficiently large, causing failures
12858 * migrating between old & new libvirtd.
12860 * Consume any cookie we were able to decode though
12862 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, NULL,
12863 NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0,
12864 migParams, cookie, cookielen,
12865 NULL, NULL, /* No output cookies in v2 */
12866 flags, dname, resource, false);
12868 cleanup:
12869 qemuMigrationParamsFree(migParams);
12870 return ret;
12874 /* Finish is the third and final step, and it runs on the destination host. */
12875 static virDomainPtr
12876 qemuDomainMigrateFinish2(virConnectPtr dconn,
12877 const char *dname,
12878 const char *cookie ATTRIBUTE_UNUSED,
12879 int cookielen ATTRIBUTE_UNUSED,
12880 const char *uri ATTRIBUTE_UNUSED,
12881 unsigned long flags,
12882 int retcode)
12884 virQEMUDriverPtr driver = dconn->privateData;
12885 virDomainObjPtr vm;
12886 virDomainPtr dom = NULL;
12888 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12890 vm = virDomainObjListFindByName(driver->domains, dname);
12891 if (!vm) {
12892 virReportError(VIR_ERR_NO_DOMAIN,
12893 _("no domain with matching name '%s'"), dname);
12894 qemuMigrationDstErrorReport(driver, dname);
12895 goto cleanup;
12898 if (virDomainMigrateFinish2EnsureACL(dconn, vm->def) < 0) {
12899 virDomainObjEndAPI(&vm);
12900 goto cleanup;
12903 /* Do not use cookies in v2 protocol, since the cookie
12904 * length was not sufficiently large, causing failures
12905 * migrating between old & new libvirtd
12907 dom = qemuMigrationDstFinish(driver, dconn, vm,
12908 NULL, 0, NULL, NULL, /* No cookies */
12909 flags, retcode, false);
12911 cleanup:
12912 return dom;
12916 /*******************************************************************
12917 * Migration Protocol Version 3
12918 *******************************************************************/
12920 static char *
12921 qemuDomainMigrateBegin3(virDomainPtr domain,
12922 const char *xmlin,
12923 char **cookieout,
12924 int *cookieoutlen,
12925 unsigned long flags,
12926 const char *dname,
12927 unsigned long resource ATTRIBUTE_UNUSED)
12929 virDomainObjPtr vm;
12931 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12933 if (!(vm = qemuDomObjFromDomain(domain)))
12934 return NULL;
12936 if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) {
12937 virDomainObjEndAPI(&vm);
12938 return NULL;
12941 return qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
12942 cookieout, cookieoutlen, 0, NULL, flags);
12945 static char *
12946 qemuDomainMigrateBegin3Params(virDomainPtr domain,
12947 virTypedParameterPtr params,
12948 int nparams,
12949 char **cookieout,
12950 int *cookieoutlen,
12951 unsigned int flags)
12953 const char *xmlin = NULL;
12954 const char *dname = NULL;
12955 const char **migrate_disks = NULL;
12956 int nmigrate_disks;
12957 char *ret = NULL;
12958 virDomainObjPtr vm;
12960 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12961 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
12962 goto cleanup;
12964 if (virTypedParamsGetString(params, nparams,
12965 VIR_MIGRATE_PARAM_DEST_XML,
12966 &xmlin) < 0 ||
12967 virTypedParamsGetString(params, nparams,
12968 VIR_MIGRATE_PARAM_DEST_NAME,
12969 &dname) < 0)
12970 goto cleanup;
12972 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
12973 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
12974 &migrate_disks);
12976 if (nmigrate_disks < 0)
12977 goto cleanup;
12979 if (!(vm = qemuDomObjFromDomain(domain)))
12980 goto cleanup;
12982 if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
12983 virDomainObjEndAPI(&vm);
12984 goto cleanup;
12987 ret = qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
12988 cookieout, cookieoutlen,
12989 nmigrate_disks, migrate_disks, flags);
12991 cleanup:
12992 VIR_FREE(migrate_disks);
12993 return ret;
12997 static int
12998 qemuDomainMigratePrepare3(virConnectPtr dconn,
12999 const char *cookiein,
13000 int cookieinlen,
13001 char **cookieout,
13002 int *cookieoutlen,
13003 const char *uri_in,
13004 char **uri_out,
13005 unsigned long flags,
13006 const char *dname,
13007 unsigned long resource ATTRIBUTE_UNUSED,
13008 const char *dom_xml)
13010 virQEMUDriverPtr driver = dconn->privateData;
13011 virDomainDefPtr def = NULL;
13012 char *origname = NULL;
13013 qemuMigrationParamsPtr migParams = NULL;
13014 int ret = -1;
13016 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13018 if (flags & VIR_MIGRATE_TUNNELLED) {
13019 /* this is a logical error; we never should have gotten here with
13020 * VIR_MIGRATE_TUNNELLED set
13022 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13023 _("Tunnelled migration requested but invalid "
13024 "RPC method called"));
13025 goto cleanup;
13028 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
13029 QEMU_MIGRATION_DESTINATION)))
13030 goto cleanup;
13032 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13033 goto cleanup;
13035 if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0)
13036 goto cleanup;
13038 ret = qemuMigrationDstPrepareDirect(driver, dconn,
13039 cookiein, cookieinlen,
13040 cookieout, cookieoutlen,
13041 uri_in, uri_out,
13042 &def, origname, NULL, 0, NULL, 0,
13043 migParams, flags);
13045 cleanup:
13046 qemuMigrationParamsFree(migParams);
13047 VIR_FREE(origname);
13048 virDomainDefFree(def);
13049 return ret;
13052 static int
13053 qemuDomainMigratePrepare3Params(virConnectPtr dconn,
13054 virTypedParameterPtr params,
13055 int nparams,
13056 const char *cookiein,
13057 int cookieinlen,
13058 char **cookieout,
13059 int *cookieoutlen,
13060 char **uri_out,
13061 unsigned int flags)
13063 virQEMUDriverPtr driver = dconn->privateData;
13064 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
13065 virDomainDefPtr def = NULL;
13066 const char *dom_xml = NULL;
13067 const char *dname = NULL;
13068 const char *uri_in = NULL;
13069 const char *listenAddress = cfg->migrationAddress;
13070 int nbdPort = 0;
13071 int nmigrate_disks;
13072 const char **migrate_disks = NULL;
13073 char *origname = NULL;
13074 qemuMigrationParamsPtr migParams = NULL;
13075 int ret = -1;
13077 virCheckFlagsGoto(QEMU_MIGRATION_FLAGS, cleanup);
13078 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13079 goto cleanup;
13081 if (virTypedParamsGetString(params, nparams,
13082 VIR_MIGRATE_PARAM_DEST_XML,
13083 &dom_xml) < 0 ||
13084 virTypedParamsGetString(params, nparams,
13085 VIR_MIGRATE_PARAM_DEST_NAME,
13086 &dname) < 0 ||
13087 virTypedParamsGetString(params, nparams,
13088 VIR_MIGRATE_PARAM_URI,
13089 &uri_in) < 0 ||
13090 virTypedParamsGetString(params, nparams,
13091 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
13092 &listenAddress) < 0 ||
13093 virTypedParamsGetInt(params, nparams,
13094 VIR_MIGRATE_PARAM_DISKS_PORT,
13095 &nbdPort) < 0)
13096 goto cleanup;
13098 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
13099 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
13100 &migrate_disks);
13102 if (nmigrate_disks < 0)
13103 goto cleanup;
13105 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13106 QEMU_MIGRATION_DESTINATION)))
13107 goto cleanup;
13109 if (flags & VIR_MIGRATE_TUNNELLED) {
13110 /* this is a logical error; we never should have gotten here with
13111 * VIR_MIGRATE_TUNNELLED set
13113 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13114 _("Tunnelled migration requested but invalid "
13115 "RPC method called"));
13116 goto cleanup;
13119 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13120 goto cleanup;
13122 if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
13123 goto cleanup;
13125 ret = qemuMigrationDstPrepareDirect(driver, dconn,
13126 cookiein, cookieinlen,
13127 cookieout, cookieoutlen,
13128 uri_in, uri_out,
13129 &def, origname, listenAddress,
13130 nmigrate_disks, migrate_disks, nbdPort,
13131 migParams, flags);
13133 cleanup:
13134 qemuMigrationParamsFree(migParams);
13135 VIR_FREE(migrate_disks);
13136 VIR_FREE(origname);
13137 virDomainDefFree(def);
13138 virObjectUnref(cfg);
13139 return ret;
13143 static int
13144 qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
13145 virStreamPtr st,
13146 const char *cookiein,
13147 int cookieinlen,
13148 char **cookieout,
13149 int *cookieoutlen,
13150 unsigned long flags,
13151 const char *dname,
13152 unsigned long resource ATTRIBUTE_UNUSED,
13153 const char *dom_xml)
13155 virQEMUDriverPtr driver = dconn->privateData;
13156 virDomainDefPtr def = NULL;
13157 char *origname = NULL;
13158 qemuMigrationParamsPtr migParams = NULL;
13159 int ret = -1;
13161 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13163 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
13164 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13165 _("PrepareTunnel called but no TUNNELLED flag set"));
13166 goto cleanup;
13169 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
13170 QEMU_MIGRATION_DESTINATION)))
13171 goto cleanup;
13173 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13174 goto cleanup;
13176 if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0)
13177 goto cleanup;
13179 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
13180 cookiein, cookieinlen,
13181 cookieout, cookieoutlen,
13182 st, &def, origname, migParams, flags);
13184 cleanup:
13185 qemuMigrationParamsFree(migParams);
13186 VIR_FREE(origname);
13187 virDomainDefFree(def);
13188 return ret;
13191 static int
13192 qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
13193 virStreamPtr st,
13194 virTypedParameterPtr params,
13195 int nparams,
13196 const char *cookiein,
13197 int cookieinlen,
13198 char **cookieout,
13199 int *cookieoutlen,
13200 unsigned int flags)
13202 virQEMUDriverPtr driver = dconn->privateData;
13203 virDomainDefPtr def = NULL;
13204 const char *dom_xml = NULL;
13205 const char *dname = NULL;
13206 char *origname = NULL;
13207 qemuMigrationParamsPtr migParams = NULL;
13208 int ret = -1;
13210 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13211 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13212 return -1;
13214 if (virTypedParamsGetString(params, nparams,
13215 VIR_MIGRATE_PARAM_DEST_XML,
13216 &dom_xml) < 0 ||
13217 virTypedParamsGetString(params, nparams,
13218 VIR_MIGRATE_PARAM_DEST_NAME,
13219 &dname) < 0)
13220 return -1;
13222 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
13223 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13224 _("PrepareTunnel called but no TUNNELLED flag set"));
13225 goto cleanup;
13228 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13229 QEMU_MIGRATION_DESTINATION)))
13230 goto cleanup;
13232 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13233 goto cleanup;
13235 if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
13236 goto cleanup;
13238 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
13239 cookiein, cookieinlen,
13240 cookieout, cookieoutlen,
13241 st, &def, origname, migParams, flags);
13243 cleanup:
13244 qemuMigrationParamsFree(migParams);
13245 VIR_FREE(origname);
13246 virDomainDefFree(def);
13247 return ret;
13251 static int
13252 qemuDomainMigratePerform3(virDomainPtr dom,
13253 const char *xmlin,
13254 const char *cookiein,
13255 int cookieinlen,
13256 char **cookieout,
13257 int *cookieoutlen,
13258 const char *dconnuri,
13259 const char *uri,
13260 unsigned long flags,
13261 const char *dname,
13262 unsigned long resource)
13264 virQEMUDriverPtr driver = dom->conn->privateData;
13265 virDomainObjPtr vm;
13266 qemuMigrationParamsPtr migParams = NULL;
13267 int ret = -1;
13269 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13271 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
13272 QEMU_MIGRATION_SOURCE)))
13273 goto cleanup;
13275 if (!(vm = qemuDomObjFromDomain(dom)))
13276 goto cleanup;
13278 if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) {
13279 virDomainObjEndAPI(&vm);
13280 goto cleanup;
13283 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, xmlin, NULL,
13284 dconnuri, uri, NULL, NULL, 0, NULL, 0,
13285 migParams,
13286 cookiein, cookieinlen,
13287 cookieout, cookieoutlen,
13288 flags, dname, resource, true);
13290 cleanup:
13291 qemuMigrationParamsFree(migParams);
13292 return ret;
13295 static int
13296 qemuDomainMigratePerform3Params(virDomainPtr dom,
13297 const char *dconnuri,
13298 virTypedParameterPtr params,
13299 int nparams,
13300 const char *cookiein,
13301 int cookieinlen,
13302 char **cookieout,
13303 int *cookieoutlen,
13304 unsigned int flags)
13306 virQEMUDriverPtr driver = dom->conn->privateData;
13307 virDomainObjPtr vm;
13308 const char *dom_xml = NULL;
13309 const char *persist_xml = NULL;
13310 const char *dname = NULL;
13311 const char *uri = NULL;
13312 const char *graphicsuri = NULL;
13313 const char *listenAddress = NULL;
13314 int nmigrate_disks;
13315 const char **migrate_disks = NULL;
13316 unsigned long long bandwidth = 0;
13317 int nbdPort = 0;
13318 qemuMigrationParamsPtr migParams = NULL;
13319 int ret = -1;
13321 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13322 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13323 return ret;
13325 if (virTypedParamsGetString(params, nparams,
13326 VIR_MIGRATE_PARAM_DEST_XML,
13327 &dom_xml) < 0 ||
13328 virTypedParamsGetString(params, nparams,
13329 VIR_MIGRATE_PARAM_DEST_NAME,
13330 &dname) < 0 ||
13331 virTypedParamsGetString(params, nparams,
13332 VIR_MIGRATE_PARAM_URI,
13333 &uri) < 0 ||
13334 virTypedParamsGetULLong(params, nparams,
13335 VIR_MIGRATE_PARAM_BANDWIDTH,
13336 &bandwidth) < 0 ||
13337 virTypedParamsGetString(params, nparams,
13338 VIR_MIGRATE_PARAM_GRAPHICS_URI,
13339 &graphicsuri) < 0 ||
13340 virTypedParamsGetString(params, nparams,
13341 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
13342 &listenAddress) < 0 ||
13343 virTypedParamsGetInt(params, nparams,
13344 VIR_MIGRATE_PARAM_DISKS_PORT,
13345 &nbdPort) < 0 ||
13346 virTypedParamsGetString(params, nparams,
13347 VIR_MIGRATE_PARAM_PERSIST_XML,
13348 &persist_xml) < 0)
13349 goto cleanup;
13351 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
13352 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
13353 &migrate_disks);
13355 if (nmigrate_disks < 0)
13356 goto cleanup;
13358 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13359 QEMU_MIGRATION_SOURCE)))
13360 goto cleanup;
13362 if (!(vm = qemuDomObjFromDomain(dom)))
13363 goto cleanup;
13365 if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0) {
13366 virDomainObjEndAPI(&vm);
13367 goto cleanup;
13370 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, dom_xml, persist_xml,
13371 dconnuri, uri, graphicsuri, listenAddress,
13372 nmigrate_disks, migrate_disks, nbdPort,
13373 migParams,
13374 cookiein, cookieinlen, cookieout, cookieoutlen,
13375 flags, dname, bandwidth, true);
13376 cleanup:
13377 qemuMigrationParamsFree(migParams);
13378 VIR_FREE(migrate_disks);
13379 return ret;
13383 static virDomainPtr
13384 qemuDomainMigrateFinish3(virConnectPtr dconn,
13385 const char *dname,
13386 const char *cookiein,
13387 int cookieinlen,
13388 char **cookieout,
13389 int *cookieoutlen,
13390 const char *dconnuri ATTRIBUTE_UNUSED,
13391 const char *uri ATTRIBUTE_UNUSED,
13392 unsigned long flags,
13393 int cancelled)
13395 virQEMUDriverPtr driver = dconn->privateData;
13396 virDomainObjPtr vm;
13398 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
13400 if (!dname) {
13401 virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
13402 return NULL;
13405 vm = virDomainObjListFindByName(driver->domains, dname);
13406 if (!vm) {
13407 virReportError(VIR_ERR_NO_DOMAIN,
13408 _("no domain with matching name '%s'"), dname);
13409 qemuMigrationDstErrorReport(driver, dname);
13410 return NULL;
13413 if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) {
13414 virDomainObjEndAPI(&vm);
13415 return NULL;
13418 return qemuMigrationDstFinish(driver, dconn, vm,
13419 cookiein, cookieinlen,
13420 cookieout, cookieoutlen,
13421 flags, cancelled, true);
13424 static virDomainPtr
13425 qemuDomainMigrateFinish3Params(virConnectPtr dconn,
13426 virTypedParameterPtr params,
13427 int nparams,
13428 const char *cookiein,
13429 int cookieinlen,
13430 char **cookieout,
13431 int *cookieoutlen,
13432 unsigned int flags,
13433 int cancelled)
13435 virQEMUDriverPtr driver = dconn->privateData;
13436 virDomainObjPtr vm;
13437 const char *dname = NULL;
13439 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
13440 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13441 return NULL;
13443 if (virTypedParamsGetString(params, nparams,
13444 VIR_MIGRATE_PARAM_DEST_NAME,
13445 &dname) < 0)
13446 return NULL;
13448 if (!dname) {
13449 virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
13450 return NULL;
13453 vm = virDomainObjListFindByName(driver->domains, dname);
13454 if (!vm) {
13455 virReportError(VIR_ERR_NO_DOMAIN,
13456 _("no domain with matching name '%s'"), dname);
13457 qemuMigrationDstErrorReport(driver, dname);
13458 return NULL;
13461 if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
13462 virDomainObjEndAPI(&vm);
13463 return NULL;
13466 return qemuMigrationDstFinish(driver, dconn, vm,
13467 cookiein, cookieinlen,
13468 cookieout, cookieoutlen,
13469 flags, cancelled, true);
13473 static int
13474 qemuDomainMigrateConfirm3(virDomainPtr domain,
13475 const char *cookiein,
13476 int cookieinlen,
13477 unsigned long flags,
13478 int cancelled)
13480 virDomainObjPtr vm;
13482 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13484 if (!(vm = qemuDomObjFromDomain(domain)))
13485 return -1;
13487 if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) {
13488 virDomainObjEndAPI(&vm);
13489 return -1;
13492 return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
13493 flags, cancelled);
13496 static int
13497 qemuDomainMigrateConfirm3Params(virDomainPtr domain,
13498 virTypedParameterPtr params,
13499 int nparams,
13500 const char *cookiein,
13501 int cookieinlen,
13502 unsigned int flags,
13503 int cancelled)
13505 virDomainObjPtr vm;
13507 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13509 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13510 return -1;
13512 if (!(vm = qemuDomObjFromDomain(domain)))
13513 return -1;
13515 if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
13516 virDomainObjEndAPI(&vm);
13517 return -1;
13520 return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
13521 flags, cancelled);
13525 static int
13526 qemuNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
13527 unsigned *domain,
13528 unsigned *bus,
13529 unsigned *slot,
13530 unsigned *function)
13532 virNodeDevCapsDefPtr cap;
13533 int ret = -1;
13535 cap = def->caps;
13536 while (cap) {
13537 if (cap->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
13538 *domain = cap->data.pci_dev.domain;
13539 *bus = cap->data.pci_dev.bus;
13540 *slot = cap->data.pci_dev.slot;
13541 *function = cap->data.pci_dev.function;
13542 break;
13545 cap = cap->next;
13548 if (!cap) {
13549 virReportError(VIR_ERR_INVALID_ARG,
13550 _("device %s is not a PCI device"), def->name);
13551 goto out;
13554 ret = 0;
13555 out:
13556 return ret;
13559 static int
13560 qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
13561 const char *driverName,
13562 unsigned int flags)
13564 virQEMUDriverPtr driver = dev->conn->privateData;
13565 virPCIDevicePtr pci = NULL;
13566 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13567 int ret = -1;
13568 virNodeDeviceDefPtr def = NULL;
13569 char *xml = NULL;
13570 bool legacy = qemuHostdevHostSupportsPassthroughLegacy();
13571 bool vfio = qemuHostdevHostSupportsPassthroughVFIO();
13572 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13574 virCheckFlags(0, -1);
13576 xml = virNodeDeviceGetXMLDesc(dev, 0);
13577 if (!xml)
13578 goto cleanup;
13580 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13581 if (!def)
13582 goto cleanup;
13584 if (virNodeDeviceDetachFlagsEnsureACL(dev->conn, def) < 0)
13585 goto cleanup;
13587 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13588 goto cleanup;
13590 pci = virPCIDeviceNew(domain, bus, slot, function);
13591 if (!pci)
13592 goto cleanup;
13594 if (!driverName) {
13595 if (vfio) {
13596 driverName = "vfio";
13597 } else if (legacy) {
13598 driverName = "kvm";
13599 } else {
13600 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
13601 _("neither VFIO nor KVM device assignment is "
13602 "currently supported on this system"));
13603 goto cleanup;
13607 if (STREQ(driverName, "vfio")) {
13608 if (!vfio) {
13609 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13610 _("VFIO device assignment is currently not "
13611 "supported on this system"));
13612 goto cleanup;
13614 virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_VFIO);
13615 } else if (STREQ(driverName, "kvm")) {
13616 if (!legacy) {
13617 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13618 _("KVM device assignment is currently not "
13619 "supported on this system"));
13620 goto cleanup;
13622 virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_KVM);
13623 } else {
13624 virReportError(VIR_ERR_INVALID_ARG,
13625 _("unknown driver name '%s'"), driverName);
13626 goto cleanup;
13629 ret = virHostdevPCINodeDeviceDetach(hostdev_mgr, pci);
13630 cleanup:
13631 virPCIDeviceFree(pci);
13632 virNodeDeviceDefFree(def);
13633 VIR_FREE(xml);
13634 return ret;
13637 static int
13638 qemuNodeDeviceDettach(virNodeDevicePtr dev)
13640 return qemuNodeDeviceDetachFlags(dev, NULL, 0);
13643 static int
13644 qemuNodeDeviceReAttach(virNodeDevicePtr dev)
13646 virQEMUDriverPtr driver = dev->conn->privateData;
13647 virPCIDevicePtr pci = NULL;
13648 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13649 int ret = -1;
13650 virNodeDeviceDefPtr def = NULL;
13651 char *xml = NULL;
13652 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13654 xml = virNodeDeviceGetXMLDesc(dev, 0);
13655 if (!xml)
13656 goto cleanup;
13658 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13659 if (!def)
13660 goto cleanup;
13662 if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0)
13663 goto cleanup;
13665 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13666 goto cleanup;
13668 pci = virPCIDeviceNew(domain, bus, slot, function);
13669 if (!pci)
13670 goto cleanup;
13672 ret = virHostdevPCINodeDeviceReAttach(hostdev_mgr, pci);
13674 virPCIDeviceFree(pci);
13675 cleanup:
13676 virNodeDeviceDefFree(def);
13677 VIR_FREE(xml);
13678 return ret;
13681 static int
13682 qemuNodeDeviceReset(virNodeDevicePtr dev)
13684 virQEMUDriverPtr driver = dev->conn->privateData;
13685 virPCIDevicePtr pci;
13686 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13687 int ret = -1;
13688 virNodeDeviceDefPtr def = NULL;
13689 char *xml = NULL;
13690 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13692 xml = virNodeDeviceGetXMLDesc(dev, 0);
13693 if (!xml)
13694 goto cleanup;
13696 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13697 if (!def)
13698 goto cleanup;
13700 if (virNodeDeviceResetEnsureACL(dev->conn, def) < 0)
13701 goto cleanup;
13703 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13704 goto cleanup;
13706 pci = virPCIDeviceNew(domain, bus, slot, function);
13707 if (!pci)
13708 goto cleanup;
13710 ret = virHostdevPCINodeDeviceReset(hostdev_mgr, pci);
13712 virPCIDeviceFree(pci);
13713 cleanup:
13714 virNodeDeviceDefFree(def);
13715 VIR_FREE(xml);
13716 return ret;
13719 static int
13720 qemuConnectCompareCPU(virConnectPtr conn,
13721 const char *xmlDesc,
13722 unsigned int flags)
13724 virQEMUDriverPtr driver = conn->privateData;
13725 int ret = VIR_CPU_COMPARE_ERROR;
13726 virCapsPtr caps = NULL;
13727 bool failIncompatible;
13729 virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
13730 VIR_CPU_COMPARE_ERROR);
13732 if (virConnectCompareCPUEnsureACL(conn) < 0)
13733 goto cleanup;
13735 failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
13737 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
13738 goto cleanup;
13740 ret = virCPUCompareXML(caps->host.arch, caps->host.cpu,
13741 xmlDesc, failIncompatible);
13743 cleanup:
13744 virObjectUnref(caps);
13745 return ret;
13749 static int
13750 qemuConnectCompareHypervisorCPU(virConnectPtr conn,
13751 const char *emulator,
13752 const char *archStr,
13753 const char *machine,
13754 const char *virttypeStr,
13755 const char *xmlCPU,
13756 unsigned int flags)
13758 int ret = VIR_CPU_COMPARE_ERROR;
13759 virQEMUDriverPtr driver = conn->privateData;
13760 virQEMUCapsPtr qemuCaps = NULL;
13761 bool failIncompatible;
13762 virCPUDefPtr hvCPU;
13763 virArch arch;
13764 virDomainVirtType virttype;
13766 virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
13767 VIR_CPU_COMPARE_ERROR);
13769 if (virConnectCompareHypervisorCPUEnsureACL(conn) < 0)
13770 goto cleanup;
13772 failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
13774 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
13775 emulator,
13776 archStr,
13777 virttypeStr,
13778 machine,
13779 &arch, &virttype, NULL);
13780 if (!qemuCaps)
13781 goto cleanup;
13783 hvCPU = virQEMUCapsGetHostModel(qemuCaps, virttype,
13784 VIR_QEMU_CAPS_HOST_CPU_REPORTED);
13786 if (!hvCPU || hvCPU->fallback != VIR_CPU_FALLBACK_FORBID) {
13787 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13788 _("QEMU '%s' does not support reporting CPU model for "
13789 "virttype '%s'"),
13790 virQEMUCapsGetBinary(qemuCaps),
13791 virDomainVirtTypeToString(virttype));
13792 goto cleanup;
13795 if (ARCH_IS_X86(arch)) {
13796 ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible);
13797 } else {
13798 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13799 _("comparing with the hypervisor CPU is not supported "
13800 "for arch %s"), virArchToString(arch));
13803 cleanup:
13804 virObjectUnref(qemuCaps);
13805 return ret;
13809 static char *
13810 qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
13811 const char **xmlCPUs,
13812 unsigned int ncpus,
13813 unsigned int flags)
13815 virCPUDefPtr *cpus = NULL;
13816 virCPUDefPtr baseline = NULL;
13817 virCPUDefPtr cpu = NULL;
13818 char *cpustr = NULL;
13820 virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
13821 VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
13823 if (virConnectBaselineCPUEnsureACL(conn) < 0)
13824 goto cleanup;
13826 if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
13827 goto cleanup;
13829 if (!(baseline = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL,
13830 !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE))))
13831 goto cleanup;
13833 if (!(cpu = virCPUDefCopyWithoutModel(baseline)))
13834 goto cleanup;
13836 if (virCPUDefCopyModelFilter(cpu, baseline, false,
13837 virQEMUCapsCPUFilterFeatures,
13838 &cpus[0]->arch) < 0)
13839 goto cleanup;
13841 if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
13842 virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
13843 goto cleanup;
13845 cpustr = virCPUDefFormat(cpu, NULL);
13847 cleanup:
13848 virCPUDefListFree(cpus);
13849 virCPUDefFree(baseline);
13850 virCPUDefFree(cpu);
13852 return cpustr;
13856 static char *
13857 qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
13858 const char *emulator,
13859 const char *archStr,
13860 const char *machine,
13861 const char *virttypeStr,
13862 const char **xmlCPUs,
13863 unsigned int ncpus,
13864 unsigned int flags)
13866 virQEMUDriverPtr driver = conn->privateData;
13867 virCPUDefPtr *cpus = NULL;
13868 virQEMUCapsPtr qemuCaps = NULL;
13869 virArch arch;
13870 virDomainVirtType virttype;
13871 virDomainCapsCPUModelsPtr cpuModels;
13872 bool migratable;
13873 virCPUDefPtr cpu = NULL;
13874 char *cpustr = NULL;
13875 char **features = NULL;
13877 virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
13878 VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
13880 if (virConnectBaselineHypervisorCPUEnsureACL(conn) < 0)
13881 goto cleanup;
13883 migratable = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
13885 if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_AUTO)))
13886 goto cleanup;
13888 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
13889 emulator,
13890 archStr,
13891 virttypeStr,
13892 machine,
13893 &arch, &virttype, NULL);
13894 if (!qemuCaps)
13895 goto cleanup;
13897 if (!(cpuModels = virQEMUCapsGetCPUDefinitions(qemuCaps, virttype)) ||
13898 cpuModels->nmodels == 0) {
13899 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13900 _("QEMU '%s' does not support any CPU models for "
13901 "virttype '%s'"),
13902 virQEMUCapsGetBinary(qemuCaps),
13903 virDomainVirtTypeToString(virttype));
13904 goto cleanup;
13907 if (ARCH_IS_X86(arch)) {
13908 int rc = virQEMUCapsGetCPUFeatures(qemuCaps, virttype,
13909 migratable, &features);
13910 if (rc < 0)
13911 goto cleanup;
13912 if (features && rc == 0) {
13913 /* We got only migratable features from QEMU if we asked for them,
13914 * no further filtering in virCPUBaseline is desired. */
13915 migratable = false;
13918 if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
13919 (const char **)features, migratable)))
13920 goto cleanup;
13921 } else {
13922 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13923 _("computing baseline hypervisor CPU is not supported "
13924 "for arch %s"), virArchToString(arch));
13925 goto cleanup;
13928 cpu->fallback = VIR_CPU_FALLBACK_FORBID;
13930 if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
13931 virCPUExpandFeatures(arch, cpu) < 0)
13932 goto cleanup;
13934 cpustr = virCPUDefFormat(cpu, NULL);
13936 cleanup:
13937 virCPUDefListFree(cpus);
13938 virCPUDefFree(cpu);
13939 virObjectUnref(qemuCaps);
13940 virStringListFree(features);
13942 return cpustr;
13946 static int
13947 qemuDomainGetJobInfoMigrationStats(virQEMUDriverPtr driver,
13948 virDomainObjPtr vm,
13949 qemuDomainJobInfoPtr jobInfo)
13951 qemuDomainObjPrivatePtr priv = vm->privateData;
13952 bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
13954 if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE ||
13955 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_MIGRATING ||
13956 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED ||
13957 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
13958 if (events &&
13959 jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
13960 qemuMigrationAnyFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE,
13961 jobInfo, NULL) < 0)
13962 return -1;
13964 if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
13965 jobInfo->statsType == QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION &&
13966 qemuMigrationSrcFetchMirrorStats(driver, vm, QEMU_ASYNC_JOB_NONE,
13967 jobInfo) < 0)
13968 return -1;
13970 if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
13971 return -1;
13974 return 0;
13978 static int
13979 qemuDomainGetJobInfoDumpStats(virQEMUDriverPtr driver,
13980 virDomainObjPtr vm,
13981 qemuDomainJobInfoPtr jobInfo)
13983 qemuDomainObjPrivatePtr priv = vm->privateData;
13984 qemuMonitorDumpStats stats = { 0 };
13985 int rc;
13987 if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
13988 return -1;
13990 rc = qemuMonitorQueryDump(priv->mon, &stats);
13992 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
13993 return -1;
13995 jobInfo->stats.dump = stats;
13997 if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
13998 return -1;
14000 switch (jobInfo->stats.dump.status) {
14001 case QEMU_MONITOR_DUMP_STATUS_NONE:
14002 case QEMU_MONITOR_DUMP_STATUS_FAILED:
14003 case QEMU_MONITOR_DUMP_STATUS_LAST:
14004 virReportError(VIR_ERR_OPERATION_FAILED,
14005 _("dump query failed, status=%d"),
14006 jobInfo->stats.dump.status);
14007 return -1;
14008 break;
14010 case QEMU_MONITOR_DUMP_STATUS_ACTIVE:
14011 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE;
14012 VIR_DEBUG("dump active, bytes written='%llu' remaining='%llu'",
14013 jobInfo->stats.dump.completed,
14014 jobInfo->stats.dump.total -
14015 jobInfo->stats.dump.completed);
14016 break;
14018 case QEMU_MONITOR_DUMP_STATUS_COMPLETED:
14019 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED;
14020 VIR_DEBUG("dump completed, bytes written='%llu'",
14021 jobInfo->stats.dump.completed);
14022 break;
14025 return 0;
14029 static int
14030 qemuDomainGetJobStatsInternal(virQEMUDriverPtr driver,
14031 virDomainObjPtr vm,
14032 bool completed,
14033 qemuDomainJobInfoPtr jobInfo)
14035 qemuDomainObjPrivatePtr priv = vm->privateData;
14036 int ret = -1;
14038 if (completed) {
14039 if (priv->job.completed && !priv->job.current)
14040 *jobInfo = *priv->job.completed;
14041 else
14042 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_NONE;
14044 return 0;
14047 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
14048 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
14049 _("migration statistics are available only on "
14050 "the source host"));
14051 return -1;
14054 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14055 return -1;
14057 if (virDomainObjCheckActive(vm) < 0)
14058 goto cleanup;
14060 if (!priv->job.current) {
14061 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_NONE;
14062 ret = 0;
14063 goto cleanup;
14065 *jobInfo = *priv->job.current;
14067 switch (jobInfo->statsType) {
14068 case QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION:
14069 case QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP:
14070 if (qemuDomainGetJobInfoMigrationStats(driver, vm, jobInfo) < 0)
14071 goto cleanup;
14072 break;
14074 case QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP:
14075 if (qemuDomainGetJobInfoDumpStats(driver, vm, jobInfo) < 0)
14076 goto cleanup;
14077 break;
14079 case QEMU_DOMAIN_JOB_STATS_TYPE_NONE:
14080 break;
14083 ret = 0;
14085 cleanup:
14086 qemuDomainObjEndJob(driver, vm);
14087 return ret;
14091 static int
14092 qemuDomainGetJobInfo(virDomainPtr dom,
14093 virDomainJobInfoPtr info)
14095 virQEMUDriverPtr driver = dom->conn->privateData;
14096 qemuDomainJobInfo jobInfo;
14097 virDomainObjPtr vm;
14098 int ret = -1;
14100 if (!(vm = qemuDomObjFromDomain(dom)))
14101 goto cleanup;
14103 if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0)
14104 goto cleanup;
14106 if (qemuDomainGetJobStatsInternal(driver, vm, false, &jobInfo) < 0)
14107 goto cleanup;
14109 if (jobInfo.status == QEMU_DOMAIN_JOB_STATUS_NONE) {
14110 memset(info, 0, sizeof(*info));
14111 info->type = VIR_DOMAIN_JOB_NONE;
14112 ret = 0;
14113 goto cleanup;
14116 ret = qemuDomainJobInfoToInfo(&jobInfo, info);
14118 cleanup:
14119 virDomainObjEndAPI(&vm);
14120 return ret;
14124 static int
14125 qemuDomainGetJobStats(virDomainPtr dom,
14126 int *type,
14127 virTypedParameterPtr *params,
14128 int *nparams,
14129 unsigned int flags)
14131 virQEMUDriverPtr driver = dom->conn->privateData;
14132 virDomainObjPtr vm;
14133 qemuDomainObjPrivatePtr priv;
14134 qemuDomainJobInfo jobInfo;
14135 bool completed = !!(flags & VIR_DOMAIN_JOB_STATS_COMPLETED);
14136 int ret = -1;
14138 virCheckFlags(VIR_DOMAIN_JOB_STATS_COMPLETED, -1);
14140 if (!(vm = qemuDomObjFromDomain(dom)))
14141 goto cleanup;
14143 if (virDomainGetJobStatsEnsureACL(dom->conn, vm->def) < 0)
14144 goto cleanup;
14146 priv = vm->privateData;
14147 if (qemuDomainGetJobStatsInternal(driver, vm, completed, &jobInfo) < 0)
14148 goto cleanup;
14150 if (jobInfo.status == QEMU_DOMAIN_JOB_STATUS_NONE) {
14151 *type = VIR_DOMAIN_JOB_NONE;
14152 *params = NULL;
14153 *nparams = 0;
14154 ret = 0;
14155 goto cleanup;
14158 ret = qemuDomainJobInfoToParams(&jobInfo, type, params, nparams);
14160 if (completed && ret == 0)
14161 VIR_FREE(priv->job.completed);
14163 cleanup:
14164 virDomainObjEndAPI(&vm);
14165 return ret;
14169 static int qemuDomainAbortJob(virDomainPtr dom)
14171 virQEMUDriverPtr driver = dom->conn->privateData;
14172 virDomainObjPtr vm;
14173 int ret = -1;
14174 qemuDomainObjPrivatePtr priv;
14175 int reason;
14177 if (!(vm = qemuDomObjFromDomain(dom)))
14178 goto cleanup;
14180 if (virDomainAbortJobEnsureACL(dom->conn, vm->def) < 0)
14181 goto cleanup;
14183 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
14184 goto cleanup;
14186 if (virDomainObjCheckActive(vm) < 0)
14187 goto endjob;
14189 priv = vm->privateData;
14191 if (!priv->job.asyncJob) {
14192 virReportError(VIR_ERR_OPERATION_INVALID,
14193 "%s", _("no job is active on the domain"));
14194 goto endjob;
14197 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
14198 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14199 _("cannot abort incoming migration;"
14200 " use virDomainDestroy instead"));
14201 goto endjob;
14204 if (priv->job.asyncJob == QEMU_ASYNC_JOB_DUMP &&
14205 priv->job.apiFlags & VIR_DUMP_MEMORY_ONLY) {
14206 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14207 _("cannot abort memory-only dump"));
14208 goto endjob;
14211 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT &&
14212 (priv->job.current->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY ||
14213 (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
14214 reason == VIR_DOMAIN_PAUSED_POSTCOPY))) {
14215 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14216 _("cannot abort migration in post-copy mode"));
14217 goto endjob;
14220 VIR_DEBUG("Cancelling job at client request");
14221 qemuDomainObjAbortAsyncJob(vm);
14222 qemuDomainObjEnterMonitor(driver, vm);
14223 ret = qemuMonitorMigrateCancel(priv->mon);
14224 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14225 ret = -1;
14227 endjob:
14228 qemuDomainObjEndJob(driver, vm);
14230 cleanup:
14231 virDomainObjEndAPI(&vm);
14232 return ret;
14236 static int
14237 qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
14238 unsigned long long downtime,
14239 unsigned int flags)
14241 virQEMUDriverPtr driver = dom->conn->privateData;
14242 virDomainObjPtr vm;
14243 qemuDomainObjPrivatePtr priv;
14244 int ret = -1;
14246 virCheckFlags(0, -1);
14248 if (!(vm = qemuDomObjFromDomain(dom)))
14249 goto cleanup;
14251 if (virDomainMigrateSetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
14252 goto cleanup;
14254 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14255 goto cleanup;
14257 if (virDomainObjCheckActive(vm) < 0)
14258 goto endjob;
14260 priv = vm->privateData;
14262 VIR_DEBUG("Setting migration downtime to %llums", downtime);
14263 qemuDomainObjEnterMonitor(driver, vm);
14264 ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
14265 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14266 ret = -1;
14268 endjob:
14269 qemuDomainObjEndJob(driver, vm);
14271 cleanup:
14272 virDomainObjEndAPI(&vm);
14273 return ret;
14277 static int
14278 qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
14279 unsigned long long *downtime,
14280 unsigned int flags)
14282 virQEMUDriverPtr driver = dom->conn->privateData;
14283 virDomainObjPtr vm;
14284 qemuMigrationParamsPtr migParams = NULL;
14285 int ret = -1;
14286 int rc;
14288 virCheckFlags(0, -1);
14290 if (!(vm = qemuDomObjFromDomain(dom)))
14291 return -1;
14293 if (virDomainMigrateGetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
14294 goto cleanup;
14296 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14297 goto cleanup;
14299 if (virDomainObjCheckActive(vm) < 0)
14300 goto endjob;
14302 if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
14303 &migParams) < 0)
14304 goto endjob;
14306 if ((rc = qemuMigrationParamsGetULL(migParams,
14307 QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT,
14308 downtime)) < 0) {
14309 goto endjob;
14312 if (rc == 1) {
14313 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14314 _("Querying migration downtime is not supported by "
14315 "QEMU binary"));
14316 goto endjob;
14319 ret = 0;
14321 endjob:
14322 qemuDomainObjEndJob(driver, vm);
14324 cleanup:
14325 qemuMigrationParamsFree(migParams);
14326 virDomainObjEndAPI(&vm);
14327 return ret;
14331 static int
14332 qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
14333 unsigned long long *cacheSize,
14334 unsigned int flags)
14336 virQEMUDriverPtr driver = dom->conn->privateData;
14337 virDomainObjPtr vm;
14338 qemuDomainObjPrivatePtr priv;
14339 int ret = -1;
14341 virCheckFlags(0, -1);
14343 if (!(vm = qemuDomObjFromDomain(dom)))
14344 goto cleanup;
14346 if (virDomainMigrateGetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
14347 goto cleanup;
14349 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14350 goto cleanup;
14352 if (virDomainObjCheckActive(vm) < 0)
14353 goto endjob;
14355 priv = vm->privateData;
14357 if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
14358 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
14359 _("Compressed migration is not supported by "
14360 "QEMU binary"));
14361 goto endjob;
14364 qemuDomainObjEnterMonitor(driver, vm);
14366 ret = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize);
14368 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14369 ret = -1;
14371 endjob:
14372 qemuDomainObjEndJob(driver, vm);
14374 cleanup:
14375 virDomainObjEndAPI(&vm);
14376 return ret;
14379 static int
14380 qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
14381 unsigned long long cacheSize,
14382 unsigned int flags)
14384 virQEMUDriverPtr driver = dom->conn->privateData;
14385 virDomainObjPtr vm;
14386 qemuDomainObjPrivatePtr priv;
14387 int ret = -1;
14389 virCheckFlags(0, -1);
14391 if (!(vm = qemuDomObjFromDomain(dom)))
14392 goto cleanup;
14394 if (virDomainMigrateSetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
14395 goto cleanup;
14397 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14398 goto cleanup;
14400 if (virDomainObjCheckActive(vm) < 0)
14401 goto endjob;
14403 priv = vm->privateData;
14405 if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
14406 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
14407 _("Compressed migration is not supported by "
14408 "QEMU binary"));
14409 goto endjob;
14412 qemuDomainObjEnterMonitor(driver, vm);
14414 VIR_DEBUG("Setting compression cache to %llu B", cacheSize);
14415 ret = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize);
14417 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14418 ret = -1;
14420 endjob:
14421 qemuDomainObjEndJob(driver, vm);
14423 cleanup:
14424 virDomainObjEndAPI(&vm);
14425 return ret;
14428 static int
14429 qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
14430 unsigned long bandwidth,
14431 unsigned int flags)
14433 virQEMUDriverPtr driver = dom->conn->privateData;
14434 virDomainObjPtr vm;
14435 qemuDomainObjPrivatePtr priv;
14436 bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
14437 VIR_AUTOPTR(qemuMigrationParams) migParams = NULL;
14438 unsigned long long max;
14439 int ret = -1;
14441 virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
14443 if (!(vm = qemuDomObjFromDomain(dom)))
14444 goto cleanup;
14446 priv = vm->privateData;
14448 if (virDomainMigrateSetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
14449 goto cleanup;
14451 if (postcopy)
14452 max = ULLONG_MAX / 1024 / 1024;
14453 else
14454 max = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
14456 if (bandwidth > max) {
14457 virReportError(VIR_ERR_OVERFLOW,
14458 _("bandwidth must be less than %llu"), max + 1);
14459 goto cleanup;
14462 if (!postcopy && !virDomainObjIsActive(vm)) {
14463 priv->migMaxBandwidth = bandwidth;
14464 ret = 0;
14465 goto cleanup;
14468 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14469 goto cleanup;
14471 if (virDomainObjCheckActive(vm) < 0)
14472 goto endjob;
14474 VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
14476 if (postcopy) {
14477 if (!(migParams = qemuMigrationParamsNew()))
14478 goto endjob;
14480 if (qemuMigrationParamsSetULL(migParams,
14481 QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
14482 bandwidth * 1024 * 1024) < 0)
14483 goto endjob;
14485 if (qemuMigrationParamsApply(driver, vm, QEMU_ASYNC_JOB_NONE,
14486 migParams) < 0)
14487 goto endjob;
14488 } else {
14489 int rc;
14491 qemuDomainObjEnterMonitor(driver, vm);
14492 rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
14493 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
14494 goto endjob;
14496 priv->migMaxBandwidth = bandwidth;
14499 ret = 0;
14501 endjob:
14502 qemuDomainObjEndJob(driver, vm);
14504 cleanup:
14505 virDomainObjEndAPI(&vm);
14506 return ret;
14510 static int
14511 qemuDomainMigrationGetPostcopyBandwidth(virQEMUDriverPtr driver,
14512 virDomainObjPtr vm,
14513 unsigned long *bandwidth)
14515 VIR_AUTOPTR(qemuMigrationParams) migParams = NULL;
14516 unsigned long long bw;
14517 int rc;
14518 int ret = -1;
14520 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14521 return -1;
14523 if (virDomainObjCheckActive(vm) < 0)
14524 goto cleanup;
14526 if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
14527 &migParams) < 0)
14528 goto cleanup;
14530 if ((rc = qemuMigrationParamsGetULL(migParams,
14531 QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
14532 &bw)) < 0)
14533 goto cleanup;
14535 if (rc == 1) {
14536 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14537 _("querying maximum post-copy migration speed is "
14538 "not supported by QEMU binary"));
14539 goto cleanup;
14542 /* QEMU reports B/s while we use MiB/s */
14543 bw /= 1024 * 1024;
14545 if (bw > ULONG_MAX) {
14546 virReportError(VIR_ERR_OVERFLOW,
14547 _("bandwidth %llu is greater than %lu which is the "
14548 "maximum value supported by this API"),
14549 bw, ULONG_MAX);
14550 goto cleanup;
14553 *bandwidth = bw;
14554 ret = 0;
14556 cleanup:
14557 qemuDomainObjEndJob(driver, vm);
14558 return ret;
14562 static int
14563 qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
14564 unsigned long *bandwidth,
14565 unsigned int flags)
14567 virQEMUDriverPtr driver = dom->conn->privateData;
14568 virDomainObjPtr vm;
14569 qemuDomainObjPrivatePtr priv;
14570 bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
14571 int ret = -1;
14573 virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
14575 if (!(vm = qemuDomObjFromDomain(dom)))
14576 goto cleanup;
14578 priv = vm->privateData;
14580 if (virDomainMigrateGetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
14581 goto cleanup;
14583 if (postcopy) {
14584 if (qemuDomainMigrationGetPostcopyBandwidth(driver, vm, bandwidth) < 0)
14585 goto cleanup;
14586 } else {
14587 *bandwidth = priv->migMaxBandwidth;
14590 ret = 0;
14592 cleanup:
14593 virDomainObjEndAPI(&vm);
14594 return ret;
14598 static int
14599 qemuDomainMigrateStartPostCopy(virDomainPtr dom,
14600 unsigned int flags)
14602 virQEMUDriverPtr driver = dom->conn->privateData;
14603 virDomainObjPtr vm;
14604 qemuDomainObjPrivatePtr priv;
14605 int ret = -1;
14607 virCheckFlags(0, -1);
14609 if (!(vm = qemuDomObjFromDomain(dom)))
14610 goto cleanup;
14612 if (virDomainMigrateStartPostCopyEnsureACL(dom->conn, vm->def) < 0)
14613 goto cleanup;
14615 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14616 goto cleanup;
14618 if (virDomainObjCheckActive(vm) < 0)
14619 goto endjob;
14621 priv = vm->privateData;
14623 if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
14624 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14625 _("post-copy can only be started while "
14626 "outgoing migration is in progress"));
14627 goto endjob;
14630 if (!(priv->job.apiFlags & VIR_MIGRATE_POSTCOPY)) {
14631 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14632 _("switching to post-copy requires migration to be "
14633 "started with VIR_MIGRATE_POSTCOPY flag"));
14634 goto endjob;
14637 VIR_DEBUG("Starting post-copy");
14638 qemuDomainObjEnterMonitor(driver, vm);
14639 ret = qemuMonitorMigrateStartPostCopy(priv->mon);
14640 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14641 ret = -1;
14643 endjob:
14644 qemuDomainObjEndJob(driver, vm);
14646 cleanup:
14647 virDomainObjEndAPI(&vm);
14648 return ret;
14652 /* Return -1 if request is not sent to agent due to misconfig, -2 if request
14653 * is sent but failed, and number of frozen filesystems on success. If -2 is
14654 * returned, FSThaw should be called revert the quiesced status. */
14655 static int
14656 qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
14657 virDomainObjPtr vm,
14658 const char **mountpoints,
14659 unsigned int nmountpoints)
14661 qemuAgentPtr agent;
14662 int frozen;
14664 if (!qemuDomainAgentAvailable(vm, true))
14665 return -1;
14667 agent = qemuDomainObjEnterAgent(vm);
14668 frozen = qemuAgentFSFreeze(agent, mountpoints, nmountpoints);
14669 qemuDomainObjExitAgent(vm, agent);
14670 return frozen < 0 ? -2 : frozen;
14674 /* Return -1 on error, otherwise number of thawed filesystems. */
14675 static int
14676 qemuDomainSnapshotFSThaw(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
14677 virDomainObjPtr vm,
14678 bool report)
14680 qemuAgentPtr agent;
14681 int thawed;
14682 virErrorPtr err = NULL;
14684 if (!qemuDomainAgentAvailable(vm, report))
14685 return -1;
14687 agent = qemuDomainObjEnterAgent(vm);
14688 if (!report)
14689 err = virSaveLastError();
14690 thawed = qemuAgentFSThaw(agent);
14691 if (!report)
14692 virSetError(err);
14693 qemuDomainObjExitAgent(vm, agent);
14695 virFreeError(err);
14697 return thawed;
14701 /* The domain is expected to be locked and inactive. */
14702 static int
14703 qemuDomainSnapshotCreateInactiveInternal(virQEMUDriverPtr driver,
14704 virDomainObjPtr vm,
14705 virDomainSnapshotObjPtr snap)
14707 return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
14711 /* The domain is expected to be locked and inactive. */
14712 static int
14713 qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
14714 virDomainObjPtr vm,
14715 virDomainSnapshotObjPtr snap,
14716 bool reuse)
14718 size_t i;
14719 virDomainSnapshotDiskDefPtr snapdisk;
14720 virDomainDiskDefPtr defdisk;
14721 virCommandPtr cmd = NULL;
14722 const char *qemuImgPath;
14723 virBitmapPtr created = NULL;
14724 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
14725 int ret = -1;
14726 virBuffer buf = VIR_BUFFER_INITIALIZER;
14728 if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
14729 goto cleanup;
14731 if (!(created = virBitmapNew(snap->def->ndisks)))
14732 goto cleanup;
14734 /* If reuse is true, then qemuDomainSnapshotPrepare already
14735 * ensured that the new files exist, and it was up to the user to
14736 * create them correctly. */
14737 for (i = 0; i < snap->def->ndisks && !reuse; i++) {
14738 snapdisk = &(snap->def->disks[i]);
14739 defdisk = snap->def->dom->disks[snapdisk->idx];
14740 if (snapdisk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)
14741 continue;
14743 if (!snapdisk->src->format)
14744 snapdisk->src->format = VIR_STORAGE_FILE_QCOW2;
14746 /* creates cmd line args: qemu-img create -f qcow2 -o */
14747 if (!(cmd = virCommandNewArgList(qemuImgPath,
14748 "create",
14749 "-f",
14750 virStorageFileFormatTypeToString(snapdisk->src->format),
14751 "-o",
14752 NULL)))
14753 goto cleanup;
14755 /* adds cmd line arg: backing_fmt=format,backing_file=/path/to/backing/file */
14756 virBufferAsprintf(&buf, "backing_fmt=%s,backing_file=",
14757 virStorageFileFormatTypeToString(defdisk->src->format));
14758 virQEMUBuildBufferEscapeComma(&buf, defdisk->src->path);
14759 virCommandAddArgBuffer(cmd, &buf);
14761 /* adds cmd line args: /path/to/target/file */
14762 virQEMUBuildBufferEscapeComma(&buf, snapdisk->src->path);
14763 virCommandAddArgBuffer(cmd, &buf);
14765 /* If the target does not exist, we're going to create it possibly */
14766 if (!virFileExists(snapdisk->src->path))
14767 ignore_value(virBitmapSetBit(created, i));
14769 if (virCommandRun(cmd, NULL) < 0)
14770 goto cleanup;
14772 virCommandFree(cmd);
14773 cmd = NULL;
14776 /* update disk definitions */
14777 for (i = 0; i < snap->def->ndisks; i++) {
14778 snapdisk = &(snap->def->disks[i]);
14779 defdisk = vm->def->disks[snapdisk->idx];
14781 if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
14782 VIR_FREE(defdisk->src->path);
14783 if (VIR_STRDUP(defdisk->src->path, snapdisk->src->path) < 0) {
14784 /* we cannot rollback here in a sane way */
14785 goto cleanup;
14787 defdisk->src->format = snapdisk->src->format;
14789 if (virDomainSaveConfig(cfg->configDir, driver->caps, vm->def) < 0)
14790 goto cleanup;
14794 ret = 0;
14796 cleanup:
14797 virBufferFreeAndReset(&buf);
14798 virCommandFree(cmd);
14800 /* unlink images if creation has failed */
14801 if (ret < 0 && created) {
14802 ssize_t bit = -1;
14803 while ((bit = virBitmapNextSetBit(created, bit)) >= 0) {
14804 snapdisk = &(snap->def->disks[bit]);
14805 if (unlink(snapdisk->src->path) < 0)
14806 VIR_WARN("Failed to remove snapshot image '%s'",
14807 snapdisk->src->path);
14810 virBitmapFree(created);
14811 virObjectUnref(cfg);
14813 return ret;
14817 /* The domain is expected to be locked and active. */
14818 static int
14819 qemuDomainSnapshotCreateActiveInternal(virQEMUDriverPtr driver,
14820 virDomainObjPtr vm,
14821 virDomainSnapshotObjPtr snap,
14822 unsigned int flags)
14824 qemuDomainObjPrivatePtr priv = vm->privateData;
14825 virObjectEventPtr event = NULL;
14826 bool resume = false;
14827 int ret = -1;
14829 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
14830 goto cleanup;
14832 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
14833 /* savevm monitor command pauses the domain emitting an event which
14834 * confuses libvirt since it's not notified when qemu resumes the
14835 * domain. Thus we stop and start CPUs ourselves.
14837 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
14838 QEMU_ASYNC_JOB_SNAPSHOT) < 0)
14839 goto cleanup;
14841 resume = true;
14842 if (!virDomainObjIsActive(vm)) {
14843 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
14844 _("guest unexpectedly quit"));
14845 goto cleanup;
14849 if (qemuDomainObjEnterMonitorAsync(driver, vm,
14850 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
14851 resume = false;
14852 goto cleanup;
14855 ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
14856 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14857 ret = -1;
14858 if (ret < 0)
14859 goto cleanup;
14861 if (!(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
14862 goto cleanup;
14864 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
14865 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
14866 VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
14867 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
14868 QEMU_ASYNC_JOB_SNAPSHOT, 0);
14869 virDomainAuditStop(vm, "from-snapshot");
14870 resume = false;
14873 cleanup:
14874 if (resume && virDomainObjIsActive(vm) &&
14875 qemuProcessStartCPUs(driver, vm,
14876 VIR_DOMAIN_RUNNING_UNPAUSED,
14877 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
14878 event = virDomainEventLifecycleNewFromObj(vm,
14879 VIR_DOMAIN_EVENT_SUSPENDED,
14880 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
14881 if (virGetLastErrorCode() == VIR_ERR_OK) {
14882 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
14883 _("resuming after snapshot failed"));
14887 virObjectEventStateQueue(driver->domainEventState, event);
14889 return ret;
14893 static int
14894 qemuDomainSnapshotPrepareDiskShared(virDomainSnapshotDiskDefPtr snapdisk,
14895 virDomainDiskDefPtr domdisk)
14897 if (!domdisk->src->shared || domdisk->src->readonly)
14898 return 0;
14900 if (!qemuBlockStorageSourceSupportsConcurrentAccess(snapdisk->src)) {
14901 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14902 _("shared access for disk '%s' requires use of "
14903 "supported storage format"), domdisk->dst);
14904 return -1;
14907 return 0;
14911 static int
14912 qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
14913 virDomainDiskDefPtr domdisk)
14915 int domDiskType = virStorageSourceGetActualType(domdisk->src);
14916 int snapDiskType = virStorageSourceGetActualType(snapdisk->src);
14918 switch ((virStorageType)domDiskType) {
14919 case VIR_STORAGE_TYPE_BLOCK:
14920 case VIR_STORAGE_TYPE_FILE:
14921 break;
14923 case VIR_STORAGE_TYPE_NETWORK:
14924 switch ((virStorageNetProtocol) domdisk->src->protocol) {
14925 case VIR_STORAGE_NET_PROTOCOL_NONE:
14926 case VIR_STORAGE_NET_PROTOCOL_NBD:
14927 case VIR_STORAGE_NET_PROTOCOL_RBD:
14928 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
14929 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
14930 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
14931 case VIR_STORAGE_NET_PROTOCOL_HTTP:
14932 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
14933 case VIR_STORAGE_NET_PROTOCOL_FTP:
14934 case VIR_STORAGE_NET_PROTOCOL_FTPS:
14935 case VIR_STORAGE_NET_PROTOCOL_TFTP:
14936 case VIR_STORAGE_NET_PROTOCOL_SSH:
14937 case VIR_STORAGE_NET_PROTOCOL_VXHS:
14938 case VIR_STORAGE_NET_PROTOCOL_LAST:
14939 virReportError(VIR_ERR_INTERNAL_ERROR,
14940 _("external inactive snapshots are not supported on "
14941 "'network' disks using '%s' protocol"),
14942 virStorageNetProtocolTypeToString(domdisk->src->protocol));
14943 return -1;
14945 break;
14947 case VIR_STORAGE_TYPE_DIR:
14948 case VIR_STORAGE_TYPE_VOLUME:
14949 case VIR_STORAGE_TYPE_NONE:
14950 case VIR_STORAGE_TYPE_LAST:
14951 virReportError(VIR_ERR_INTERNAL_ERROR,
14952 _("external inactive snapshots are not supported on "
14953 "'%s' disks"), virStorageTypeToString(domDiskType));
14954 return -1;
14957 switch ((virStorageType)snapDiskType) {
14958 case VIR_STORAGE_TYPE_BLOCK:
14959 case VIR_STORAGE_TYPE_FILE:
14960 break;
14962 case VIR_STORAGE_TYPE_NETWORK:
14963 case VIR_STORAGE_TYPE_DIR:
14964 case VIR_STORAGE_TYPE_VOLUME:
14965 case VIR_STORAGE_TYPE_NONE:
14966 case VIR_STORAGE_TYPE_LAST:
14967 virReportError(VIR_ERR_INTERNAL_ERROR,
14968 _("external inactive snapshots are not supported on "
14969 "'%s' disks"), virStorageTypeToString(snapDiskType));
14970 return -1;
14973 if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
14974 return -1;
14976 return 0;
14980 static int
14981 qemuDomainSnapshotPrepareDiskExternalActive(virDomainSnapshotDiskDefPtr snapdisk,
14982 virDomainDiskDefPtr domdisk)
14984 int actualType = virStorageSourceGetActualType(snapdisk->src);
14986 if (domdisk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
14987 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
14988 _("external active snapshots are not supported on scsi "
14989 "passthrough devices"));
14990 return -1;
14993 switch ((virStorageType)actualType) {
14994 case VIR_STORAGE_TYPE_BLOCK:
14995 case VIR_STORAGE_TYPE_FILE:
14996 break;
14998 case VIR_STORAGE_TYPE_NETWORK:
14999 switch ((virStorageNetProtocol) snapdisk->src->protocol) {
15000 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
15001 break;
15003 case VIR_STORAGE_NET_PROTOCOL_NONE:
15004 case VIR_STORAGE_NET_PROTOCOL_NBD:
15005 case VIR_STORAGE_NET_PROTOCOL_RBD:
15006 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
15007 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
15008 case VIR_STORAGE_NET_PROTOCOL_HTTP:
15009 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
15010 case VIR_STORAGE_NET_PROTOCOL_FTP:
15011 case VIR_STORAGE_NET_PROTOCOL_FTPS:
15012 case VIR_STORAGE_NET_PROTOCOL_TFTP:
15013 case VIR_STORAGE_NET_PROTOCOL_SSH:
15014 case VIR_STORAGE_NET_PROTOCOL_VXHS:
15015 case VIR_STORAGE_NET_PROTOCOL_LAST:
15016 virReportError(VIR_ERR_INTERNAL_ERROR,
15017 _("external active snapshots are not supported on "
15018 "'network' disks using '%s' protocol"),
15019 virStorageNetProtocolTypeToString(snapdisk->src->protocol));
15020 return -1;
15023 break;
15025 case VIR_STORAGE_TYPE_DIR:
15026 case VIR_STORAGE_TYPE_VOLUME:
15027 case VIR_STORAGE_TYPE_NONE:
15028 case VIR_STORAGE_TYPE_LAST:
15029 virReportError(VIR_ERR_INTERNAL_ERROR,
15030 _("external active snapshots are not supported on "
15031 "'%s' disks"), virStorageTypeToString(actualType));
15032 return -1;
15035 if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
15036 return -1;
15038 return 0;
15042 static int
15043 qemuDomainSnapshotPrepareDiskExternal(virDomainDiskDefPtr disk,
15044 virDomainSnapshotDiskDefPtr snapdisk,
15045 bool active,
15046 bool reuse)
15048 int ret = -1;
15049 struct stat st;
15051 if (disk->src->readonly) {
15052 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15053 _("external snapshot for readonly disk %s "
15054 "is not supported"), disk->dst);
15055 return -1;
15058 if (qemuTranslateSnapshotDiskSourcePool(snapdisk) < 0)
15059 return -1;
15061 if (!active) {
15062 if (virDomainDiskTranslateSourcePool(disk) < 0)
15063 return -1;
15065 if (qemuDomainSnapshotPrepareDiskExternalInactive(snapdisk, disk) < 0)
15066 return -1;
15067 } else {
15068 if (qemuDomainSnapshotPrepareDiskExternalActive(snapdisk, disk) < 0)
15069 return -1;
15072 if (virStorageFileInit(snapdisk->src) < 0)
15073 return -1;
15075 if (virStorageFileStat(snapdisk->src, &st) < 0) {
15076 if (errno != ENOENT) {
15077 virReportSystemError(errno,
15078 _("unable to stat for disk %s: %s"),
15079 snapdisk->name, snapdisk->src->path);
15080 goto cleanup;
15081 } else if (reuse) {
15082 virReportSystemError(errno,
15083 _("missing existing file for disk %s: %s"),
15084 snapdisk->name, snapdisk->src->path);
15085 goto cleanup;
15087 } else if (!S_ISBLK(st.st_mode) && st.st_size && !reuse) {
15088 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15089 _("external snapshot file for disk %s already "
15090 "exists and is not a block device: %s"),
15091 snapdisk->name, snapdisk->src->path);
15092 goto cleanup;
15095 ret = 0;
15097 cleanup:
15098 virStorageFileDeinit(snapdisk->src);
15099 return ret;
15103 static int
15104 qemuDomainSnapshotPrepareDiskInternal(virDomainDiskDefPtr disk,
15105 bool active)
15107 int actualType;
15109 /* active disks are handled by qemu itself so no need to worry about those */
15110 if (active)
15111 return 0;
15113 if (virDomainDiskTranslateSourcePool(disk) < 0)
15114 return -1;
15116 actualType = virStorageSourceGetActualType(disk->src);
15118 switch ((virStorageType)actualType) {
15119 case VIR_STORAGE_TYPE_BLOCK:
15120 case VIR_STORAGE_TYPE_FILE:
15121 return 0;
15123 case VIR_STORAGE_TYPE_NETWORK:
15124 switch ((virStorageNetProtocol) disk->src->protocol) {
15125 case VIR_STORAGE_NET_PROTOCOL_NONE:
15126 case VIR_STORAGE_NET_PROTOCOL_NBD:
15127 case VIR_STORAGE_NET_PROTOCOL_RBD:
15128 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
15129 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
15130 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
15131 case VIR_STORAGE_NET_PROTOCOL_HTTP:
15132 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
15133 case VIR_STORAGE_NET_PROTOCOL_FTP:
15134 case VIR_STORAGE_NET_PROTOCOL_FTPS:
15135 case VIR_STORAGE_NET_PROTOCOL_TFTP:
15136 case VIR_STORAGE_NET_PROTOCOL_SSH:
15137 case VIR_STORAGE_NET_PROTOCOL_VXHS:
15138 case VIR_STORAGE_NET_PROTOCOL_LAST:
15139 virReportError(VIR_ERR_INTERNAL_ERROR,
15140 _("internal inactive snapshots are not supported on "
15141 "'network' disks using '%s' protocol"),
15142 virStorageNetProtocolTypeToString(disk->src->protocol));
15143 return -1;
15145 break;
15147 case VIR_STORAGE_TYPE_DIR:
15148 case VIR_STORAGE_TYPE_VOLUME:
15149 case VIR_STORAGE_TYPE_NONE:
15150 case VIR_STORAGE_TYPE_LAST:
15151 virReportError(VIR_ERR_INTERNAL_ERROR,
15152 _("internal inactive snapshots are not supported on "
15153 "'%s' disks"), virStorageTypeToString(actualType));
15154 return -1;
15157 return 0;
15161 static int
15162 qemuDomainSnapshotPrepare(virDomainObjPtr vm,
15163 virDomainSnapshotDefPtr def,
15164 unsigned int *flags)
15166 int ret = -1;
15167 size_t i;
15168 bool active = virDomainObjIsActive(vm);
15169 bool reuse = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
15170 bool found_internal = false;
15171 bool forbid_internal = false;
15172 int external = 0;
15174 for (i = 0; i < def->ndisks; i++) {
15175 virDomainSnapshotDiskDefPtr disk = &def->disks[i];
15176 virDomainDiskDefPtr dom_disk = vm->def->disks[i];
15178 if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
15179 qemuDomainDiskBlockJobIsActive(dom_disk))
15180 goto cleanup;
15182 switch ((virDomainSnapshotLocation) disk->snapshot) {
15183 case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL:
15184 found_internal = true;
15186 if (def->state == VIR_SNAP_STATE_DISK_SNAPSHOT && active) {
15187 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15188 _("active qemu domains require external disk "
15189 "snapshots; disk %s requested internal"),
15190 disk->name);
15191 goto cleanup;
15194 if (qemuDomainSnapshotPrepareDiskInternal(dom_disk,
15195 active) < 0)
15196 goto cleanup;
15198 if (vm->def->disks[i]->src->format > 0 &&
15199 vm->def->disks[i]->src->format != VIR_STORAGE_FILE_QCOW2) {
15200 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15201 _("internal snapshot for disk %s unsupported "
15202 "for storage type %s"),
15203 disk->name,
15204 virStorageFileFormatTypeToString(
15205 vm->def->disks[i]->src->format));
15206 goto cleanup;
15208 break;
15210 case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:
15211 if (!disk->src->format) {
15212 disk->src->format = VIR_STORAGE_FILE_QCOW2;
15213 } else if (disk->src->format != VIR_STORAGE_FILE_QCOW2 &&
15214 disk->src->format != VIR_STORAGE_FILE_QED) {
15215 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15216 _("external snapshot format for disk %s "
15217 "is unsupported: %s"),
15218 disk->name,
15219 virStorageFileFormatTypeToString(disk->src->format));
15220 goto cleanup;
15223 if (qemuDomainSnapshotPrepareDiskExternal(dom_disk, disk,
15224 active, reuse) < 0)
15225 goto cleanup;
15227 external++;
15228 break;
15230 case VIR_DOMAIN_SNAPSHOT_LOCATION_NONE:
15231 /* Remember seeing a disk that has snapshot disabled */
15232 if (!virStorageSourceIsEmpty(dom_disk->src) &&
15233 !dom_disk->src->readonly)
15234 forbid_internal = true;
15235 break;
15237 case VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT:
15238 case VIR_DOMAIN_SNAPSHOT_LOCATION_LAST:
15239 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
15240 _("unexpected code path"));
15241 goto cleanup;
15245 if (!found_internal && !external &&
15246 def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
15247 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15248 _("nothing selected for snapshot"));
15249 goto cleanup;
15252 /* internal snapshot requires a disk image to store the memory image to, and
15253 * also disks can't be excluded from an internal snapshot*/
15254 if ((def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL && !found_internal) ||
15255 (found_internal && forbid_internal)) {
15256 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15257 _("internal and full system snapshots require all "
15258 "disks to be selected for snapshot"));
15259 goto cleanup;
15262 /* disk snapshot requires at least one disk */
15263 if (def->state == VIR_SNAP_STATE_DISK_SNAPSHOT && !external) {
15264 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15265 _("disk-only snapshots require at least "
15266 "one disk to be selected for snapshot"));
15267 goto cleanup;
15270 /* For now, we don't allow mixing internal and external disks.
15271 * XXX technically, we could mix internal and external disks for
15272 * offline snapshots */
15273 if ((found_internal && external) ||
15274 (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL && external) ||
15275 (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL && found_internal)) {
15276 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15277 _("mixing internal and external targets for a snapshot "
15278 "is not yet supported"));
15279 goto cleanup;
15282 /* internal snapshots + pflash based loader have the following problems:
15283 * - if the variable store is raw, the snapshot fails
15284 * - allowing a qcow2 image as the varstore would make it eligible to receive
15285 * the vmstate dump, which would make it huge
15286 * - offline snapshot would not snapshot the varstore at all
15288 * Avoid the issues by forbidding internal snapshot with pflash completely.
15290 if (found_internal &&
15291 vm->def->os.loader &&
15292 vm->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) {
15293 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15294 _("internal snapshots of a VM with pflash based "
15295 "firmware are not supported"));
15296 goto cleanup;
15299 /* Alter flags to let later users know what we learned. */
15300 if (external && !active)
15301 *flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY;
15303 ret = 0;
15305 cleanup:
15306 return ret;
15310 struct _qemuDomainSnapshotDiskData {
15311 virStorageSourcePtr src;
15312 bool initialized; /* @src was initialized in the storage driver */
15313 bool created; /* @src was created by the snapshot code */
15314 bool prepared; /* @src was prepared using qemuDomainDiskChainElementPrepare */
15315 virDomainDiskDefPtr disk;
15316 char *relPath; /* relative path component to fill into original disk */
15318 virStorageSourcePtr persistsrc;
15319 virDomainDiskDefPtr persistdisk;
15322 typedef struct _qemuDomainSnapshotDiskData qemuDomainSnapshotDiskData;
15323 typedef qemuDomainSnapshotDiskData *qemuDomainSnapshotDiskDataPtr;
15326 static void
15327 qemuDomainSnapshotDiskDataFree(qemuDomainSnapshotDiskDataPtr data,
15328 size_t ndata,
15329 virQEMUDriverPtr driver,
15330 virDomainObjPtr vm)
15332 size_t i;
15334 if (!data)
15335 return;
15337 for (i = 0; i < ndata; i++) {
15338 /* on success of the snapshot the 'src' and 'persistsrc' properties will
15339 * be set to NULL by qemuDomainSnapshotUpdateDiskSources */
15340 if (data[i].src) {
15341 if (data[i].initialized)
15342 virStorageFileDeinit(data[i].src);
15344 if (data[i].prepared)
15345 qemuDomainDiskChainElementRevoke(driver, vm, data[i].src);
15347 virObjectUnref(data[i].src);
15349 virObjectUnref(data[i].persistsrc);
15350 VIR_FREE(data[i].relPath);
15353 VIR_FREE(data);
15358 * qemuDomainSnapshotDiskDataCollect:
15360 * Collects and prepares a list of structures that hold information about disks
15361 * that are selected for the snapshot.
15363 static qemuDomainSnapshotDiskDataPtr
15364 qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver,
15365 virDomainObjPtr vm,
15366 virDomainSnapshotObjPtr snap,
15367 bool reuse)
15369 size_t i;
15370 qemuDomainSnapshotDiskDataPtr ret;
15371 qemuDomainSnapshotDiskDataPtr dd;
15372 char *backingStoreStr;
15374 if (VIR_ALLOC_N(ret, snap->def->ndisks) < 0)
15375 return NULL;
15377 for (i = 0; i < snap->def->ndisks; i++) {
15378 if (snap->def->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
15379 continue;
15381 dd = ret + i;
15383 dd->disk = vm->def->disks[i];
15385 if (!(dd->src = virStorageSourceCopy(snap->def->disks[i].src, false)))
15386 goto error;
15388 if (virStorageSourceInitChainElement(dd->src, dd->disk->src, false) < 0)
15389 goto error;
15391 if (qemuDomainStorageFileInit(driver, vm, dd->src, NULL) < 0)
15392 goto error;
15394 dd->initialized = true;
15396 /* relative backing store paths need to be updated so that relative
15397 * block commit still works */
15398 if (reuse) {
15399 if (virStorageFileGetBackingStoreStr(dd->src, &backingStoreStr) < 0)
15400 goto error;
15401 if (backingStoreStr != NULL) {
15402 if (virStorageIsRelative(backingStoreStr))
15403 VIR_STEAL_PTR(dd->relPath, backingStoreStr);
15404 else
15405 VIR_FREE(backingStoreStr);
15409 /* Note that it's unsafe to assume that the disks in the persistent
15410 * definition match up with the disks in the live definition just by
15411 * checking that the target name is the same. We've done that
15412 * historically this way though. */
15413 if (vm->newDef &&
15414 (dd->persistdisk = virDomainDiskByName(vm->newDef, dd->disk->dst,
15415 false))) {
15417 if (!(dd->persistsrc = virStorageSourceCopy(dd->src, false)))
15418 goto error;
15420 if (virStorageSourceInitChainElement(dd->persistsrc,
15421 dd->persistdisk->src, false) < 0)
15422 goto error;
15426 return ret;
15428 error:
15429 qemuDomainSnapshotDiskDataFree(ret, snap->def->ndisks, driver, vm);
15430 return NULL;
15434 static void
15435 qemuDomainSnapshotUpdateDiskSourcesRenumber(virStorageSourcePtr src)
15437 virStorageSourcePtr next;
15438 unsigned int idx = 1;
15440 for (next = src->backingStore; virStorageSourceIsBacking(next); next = next->backingStore)
15441 next->id = idx++;
15446 * qemuDomainSnapshotUpdateDiskSources:
15447 * @dd: snapshot disk data object
15448 * @persist: set to true if persistent config of the VM was changed
15450 * Updates disk definition after a successful snapshot.
15452 static void
15453 qemuDomainSnapshotUpdateDiskSources(qemuDomainSnapshotDiskDataPtr dd,
15454 bool *persist)
15456 if (!dd->src)
15457 return;
15459 /* storage driver access won'd be needed */
15460 if (dd->initialized)
15461 virStorageFileDeinit(dd->src);
15463 /* the old disk image is now readonly */
15464 dd->disk->src->readonly = true;
15466 VIR_STEAL_PTR(dd->disk->src->relPath, dd->relPath);
15467 VIR_STEAL_PTR(dd->src->backingStore, dd->disk->src);
15468 VIR_STEAL_PTR(dd->disk->src, dd->src);
15470 /* fix numbering of disks */
15471 qemuDomainSnapshotUpdateDiskSourcesRenumber(dd->disk->src);
15473 if (dd->persistdisk) {
15474 VIR_STEAL_PTR(dd->persistsrc->backingStore, dd->persistdisk->src);
15475 VIR_STEAL_PTR(dd->persistdisk->src, dd->persistsrc);
15476 *persist = true;
15481 static int
15482 qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
15483 virDomainObjPtr vm,
15484 qemuDomainSnapshotDiskDataPtr dd,
15485 virJSONValuePtr actions,
15486 bool reuse)
15488 int ret = -1;
15490 if (qemuBlockSnapshotAddLegacy(actions, dd->disk, dd->src, reuse) < 0)
15491 goto cleanup;
15493 /* pre-create the image file so that we can label it before handing it to qemu */
15494 if (!reuse && dd->src->type != VIR_STORAGE_TYPE_BLOCK) {
15495 if (virStorageFileCreate(dd->src) < 0) {
15496 virReportSystemError(errno, _("failed to create image file '%s'"),
15497 NULLSTR(dd->src->path));
15498 goto cleanup;
15500 dd->created = true;
15503 /* set correct security, cgroup and locking options on the new image */
15504 if (qemuDomainDiskChainElementPrepare(driver, vm, dd->src, false, true) < 0) {
15505 qemuDomainDiskChainElementRevoke(driver, vm, dd->src);
15506 goto cleanup;
15509 dd->prepared = true;
15511 ret = 0;
15513 cleanup:
15514 return ret;
15518 /* The domain is expected to be locked and active. */
15519 static int
15520 qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
15521 virDomainObjPtr vm,
15522 virDomainSnapshotObjPtr snap,
15523 unsigned int flags,
15524 qemuDomainAsyncJob asyncJob)
15526 qemuDomainObjPrivatePtr priv = vm->privateData;
15527 virJSONValuePtr actions = NULL;
15528 bool do_transaction = false;
15529 int ret = 0;
15530 size_t i;
15531 bool persist = false;
15532 bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
15533 virQEMUDriverConfigPtr cfg = NULL;
15534 qemuDomainSnapshotDiskDataPtr diskdata = NULL;
15535 virErrorPtr orig_err = NULL;
15537 if (virDomainObjCheckActive(vm) < 0)
15538 return -1;
15540 if (!(actions = virJSONValueNewArray()))
15541 return -1;
15543 /* prepare a list of objects to use in the vm definition so that we don't
15544 * have to roll back later */
15545 if (!(diskdata = qemuDomainSnapshotDiskDataCollect(driver, vm, snap, reuse)))
15546 goto cleanup;
15548 cfg = virQEMUDriverGetConfig(driver);
15550 /* Based on earlier qemuDomainSnapshotPrepare, all disks in this list are
15551 * now either VIR_DOMAIN_SNAPSHOT_LOCATION_NONE, or
15552 * VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL with a valid file name and
15553 * qcow2 format. */
15554 for (i = 0; i < snap->def->ndisks; i++) {
15555 if (!diskdata[i].src)
15556 continue;
15558 ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
15559 &diskdata[i],
15560 actions, reuse);
15562 if (ret < 0)
15563 goto error;
15565 do_transaction = true;
15568 if (do_transaction) {
15569 if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
15570 goto cleanup;
15572 ret = qemuMonitorTransaction(priv->mon, &actions);
15574 if (qemuDomainObjExitMonitor(driver, vm) < 0)
15575 ret = -1;
15577 for (i = 0; i < snap->def->ndisks; i++) {
15578 qemuDomainSnapshotDiskDataPtr dd = &diskdata[i];
15580 if (!dd->src)
15581 continue;
15583 virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", ret >= 0);
15585 if (ret == 0)
15586 qemuDomainSnapshotUpdateDiskSources(dd, &persist);
15589 if (ret < 0)
15590 goto error;
15593 error:
15594 if (ret < 0) {
15595 orig_err = virSaveLastError();
15596 for (i = 0; i < snap->def->ndisks; i++) {
15597 if (!diskdata[i].src)
15598 continue;
15600 if (diskdata[i].prepared)
15601 qemuDomainDiskChainElementRevoke(driver, vm, diskdata[i].src);
15603 if (diskdata[i].created &&
15604 virStorageFileUnlink(diskdata[i].src) < 0)
15605 VIR_WARN("Unable to remove just-created %s", diskdata[i].src->path);
15607 } else {
15608 /* on successful snapshot we need to remove locks from the now-old
15609 * disks and if the VM is paused release locks on the images since qemu
15610 * stopped using them*/
15611 bool paused = virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING;
15613 for (i = 0; i < snap->def->ndisks; i++) {
15614 if (!diskdata[i].disk)
15615 continue;
15617 if (paused)
15618 virDomainLockImageDetach(driver->lockManager, vm,
15619 diskdata[i].disk->src);
15621 virDomainLockImageDetach(driver->lockManager, vm,
15622 diskdata[i].disk->src->backingStore);
15626 if (ret == 0 || !do_transaction) {
15627 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0 ||
15628 (persist && virDomainSaveConfig(cfg->configDir, driver->caps,
15629 vm->newDef) < 0))
15630 ret = -1;
15633 cleanup:
15634 qemuDomainSnapshotDiskDataFree(diskdata, snap->def->ndisks, driver, vm);
15635 virJSONValueFree(actions);
15636 virObjectUnref(cfg);
15638 if (orig_err) {
15639 virSetError(orig_err);
15640 virFreeError(orig_err);
15643 return ret;
15647 static int
15648 qemuDomainSnapshotCreateActiveExternal(virQEMUDriverPtr driver,
15649 virDomainObjPtr vm,
15650 virDomainSnapshotObjPtr snap,
15651 unsigned int flags)
15653 virObjectEventPtr event;
15654 bool resume = false;
15655 int ret = -1;
15656 qemuDomainObjPrivatePtr priv = vm->privateData;
15657 char *xml = NULL;
15658 bool memory = snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
15659 bool memory_unlink = false;
15660 int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
15661 bool pmsuspended = false;
15662 virQEMUDriverConfigPtr cfg = NULL;
15663 int compressed;
15664 char *compressedpath = NULL;
15665 virQEMUSaveDataPtr data = NULL;
15667 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DISK_SNAPSHOT) ||
15668 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
15669 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15670 _("live disk snapshot not supported with this "
15671 "QEMU binary"));
15672 return -1;
15675 /* If quiesce was requested, then issue a freeze command, and a
15676 * counterpart thaw command when it is actually sent to agent.
15677 * The command will fail if the guest is paused or the guest agent
15678 * is not running, or is already quiesced. */
15679 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
15680 int freeze;
15682 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
15683 goto cleanup;
15685 if (virDomainObjCheckActive(vm) < 0) {
15686 qemuDomainObjEndAgentJob(vm);
15687 goto cleanup;
15690 freeze = qemuDomainSnapshotFSFreeze(driver, vm, NULL, 0);
15691 qemuDomainObjEndAgentJob(vm);
15693 if (freeze < 0) {
15694 /* the helper reported the error */
15695 if (freeze == -2)
15696 thaw = -1; /* the command is sent but agent failed */
15697 goto cleanup;
15699 thaw = 1;
15702 /* We need to track what state the guest is in, since taking the
15703 * snapshot may alter that state and we must restore it later. */
15704 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PMSUSPENDED) {
15705 pmsuspended = true;
15706 } else if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
15707 /* For full system external snapshots (those with memory), the guest
15708 * must pause (either by libvirt up front, or by qemu after
15709 * _LIVE converges). */
15710 if (memory)
15711 resume = true;
15713 if (memory && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE)) {
15714 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SNAPSHOT,
15715 QEMU_ASYNC_JOB_SNAPSHOT) < 0)
15716 goto cleanup;
15718 if (!virDomainObjIsActive(vm)) {
15719 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
15720 _("guest unexpectedly quit"));
15721 goto cleanup;
15724 resume = true;
15728 /* do the memory snapshot if necessary */
15729 if (memory) {
15730 /* check if migration is possible */
15731 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
15732 goto cleanup;
15734 /* allow the migration job to be cancelled or the domain to be paused */
15735 qemuDomainObjSetAsyncJobMask(vm, (QEMU_JOB_DEFAULT_MASK |
15736 JOB_MASK(QEMU_JOB_SUSPEND) |
15737 JOB_MASK(QEMU_JOB_MIGRATION_OP)));
15739 cfg = virQEMUDriverGetConfig(driver);
15740 if ((compressed = qemuGetCompressionProgram(cfg->snapshotImageFormat,
15741 &compressedpath,
15742 "snapshot", false)) < 0)
15743 goto cleanup;
15745 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
15746 true, true)) ||
15747 !(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
15748 goto cleanup;
15750 if (!(data = virQEMUSaveDataNew(xml,
15751 (qemuDomainSaveCookiePtr) snap->def->cookie,
15752 resume, compressed, driver->xmlopt)))
15753 goto cleanup;
15754 xml = NULL;
15756 if ((ret = qemuDomainSaveMemory(driver, vm, snap->def->file, data,
15757 compressedpath, 0,
15758 QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
15759 goto cleanup;
15761 /* the memory image was created, remove it on errors */
15762 memory_unlink = true;
15764 /* forbid any further manipulation */
15765 qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_DEFAULT_MASK);
15768 /* the domain is now paused if a memory snapshot was requested */
15770 if ((ret = qemuDomainSnapshotCreateDiskActive(driver, vm, snap, flags,
15771 QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
15772 goto cleanup;
15774 /* the snapshot is complete now */
15775 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
15776 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
15777 VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
15778 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
15779 QEMU_ASYNC_JOB_SNAPSHOT, 0);
15780 virDomainAuditStop(vm, "from-snapshot");
15781 resume = false;
15782 thaw = 0;
15783 virObjectEventStateQueue(driver->domainEventState, event);
15784 } else if (memory && pmsuspended) {
15785 /* qemu 1.3 is unable to save a domain in pm-suspended (S3)
15786 * state; so we must emit an event stating that it was
15787 * converted to paused. */
15788 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
15789 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
15790 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
15791 VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
15792 virObjectEventStateQueue(driver->domainEventState, event);
15795 ret = 0;
15797 cleanup:
15798 if (resume && virDomainObjIsActive(vm) &&
15799 qemuProcessStartCPUs(driver, vm,
15800 VIR_DOMAIN_RUNNING_UNPAUSED,
15801 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
15802 event = virDomainEventLifecycleNewFromObj(vm,
15803 VIR_DOMAIN_EVENT_SUSPENDED,
15804 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
15805 virObjectEventStateQueue(driver->domainEventState, event);
15806 if (virGetLastErrorCode() == VIR_ERR_OK) {
15807 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
15808 _("resuming after snapshot failed"));
15811 ret = -1;
15814 if (thaw != 0 &&
15815 qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) >= 0 &&
15816 virDomainObjIsActive(vm)) {
15817 if (qemuDomainSnapshotFSThaw(driver, vm, ret == 0 && thaw > 0) < 0) {
15818 /* helper reported the error, if it was needed */
15819 if (thaw > 0)
15820 ret = -1;
15823 qemuDomainObjEndAgentJob(vm);
15826 virQEMUSaveDataFree(data);
15827 VIR_FREE(xml);
15828 VIR_FREE(compressedpath);
15829 virObjectUnref(cfg);
15830 if (memory_unlink && ret < 0)
15831 unlink(snap->def->file);
15833 return ret;
15837 /* Validate that a snapshot object does not violate any qemu-specific
15838 * constraints. */
15839 static int
15840 qemuDomainSnapshotValidate(virDomainSnapshotDefPtr def,
15841 virDomainSnapshotState state,
15842 unsigned int flags)
15844 /* reject snapshot names containing slashes or starting with dot as
15845 * snapshot definitions are saved in files named by the snapshot name */
15846 if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
15847 if (strchr(def->name, '/')) {
15848 virReportError(VIR_ERR_XML_DETAIL,
15849 _("invalid snapshot name '%s': "
15850 "name can't contain '/'"),
15851 def->name);
15852 return -1;
15855 if (def->name[0] == '.') {
15856 virReportError(VIR_ERR_XML_DETAIL,
15857 _("invalid snapshot name '%s': "
15858 "name can't start with '.'"),
15859 def->name);
15860 return -1;
15864 /* allow snapshots only in certain states */
15865 switch (state) {
15866 /* valid states */
15867 case VIR_SNAP_STATE_RUNNING:
15868 case VIR_SNAP_STATE_PAUSED:
15869 case VIR_SNAP_STATE_SHUTDOWN:
15870 case VIR_SNAP_STATE_SHUTOFF:
15871 case VIR_SNAP_STATE_CRASHED:
15872 break;
15874 case VIR_SNAP_STATE_DISK_SNAPSHOT:
15875 if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
15876 virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"),
15877 virDomainSnapshotStateTypeToString(state));
15878 return -1;
15880 break;
15882 case VIR_SNAP_STATE_PMSUSPENDED:
15883 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15884 _("qemu doesn't support taking snapshots of "
15885 "PMSUSPENDED guests"));
15886 return -1;
15888 /* invalid states */
15889 case VIR_SNAP_STATE_NOSTATE:
15890 case VIR_SNAP_STATE_BLOCKED: /* invalid state, unused in qemu */
15891 case VIR_SNAP_STATE_LAST:
15892 virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"),
15893 virDomainSnapshotStateTypeToString(state));
15894 return -1;
15896 return 0;
15900 /* Struct and hash-iterator callback used when bulk redefining snapshots */
15901 struct qemuDomainSnapshotBulk {
15902 virDomainObjPtr vm;
15903 virQEMUDriverPtr driver;
15904 const char *snapshotDir;
15905 unsigned int flags;
15908 static int
15909 qemuDomainSnapshotBulkRedefine(void *payload,
15910 const void *name ATTRIBUTE_UNUSED,
15911 void *opaque)
15913 virDomainSnapshotObjPtr snap = payload;
15914 struct qemuDomainSnapshotBulk *data = opaque;
15916 if (qemuDomainSnapshotValidate(snap->def, snap->def->state,
15917 data->flags) < 0)
15918 return -1;
15919 if (qemuDomainSnapshotWriteMetadata(data->vm, snap, data->driver->caps,
15920 data->driver->xmlopt,
15921 data->snapshotDir) < 0)
15922 return -1;
15923 return 0;
15927 static virDomainSnapshotPtr
15928 qemuDomainSnapshotCreateXML(virDomainPtr domain,
15929 const char *xmlDesc,
15930 unsigned int flags)
15932 virQEMUDriverPtr driver = domain->conn->privateData;
15933 virDomainObjPtr vm = NULL;
15934 char *xml = NULL;
15935 virDomainSnapshotObjPtr snap = NULL;
15936 virDomainSnapshotPtr snapshot = NULL;
15937 virDomainSnapshotDefPtr def = NULL;
15938 bool update_current = true;
15939 bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
15940 unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
15941 virDomainSnapshotObjPtr other = NULL;
15942 int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
15943 bool align_match = true;
15944 virQEMUDriverConfigPtr cfg = NULL;
15945 virCapsPtr caps = NULL;
15946 qemuDomainObjPrivatePtr priv;
15948 virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
15949 VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
15950 VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
15951 VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
15952 VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
15953 VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
15954 VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
15955 VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
15956 VIR_DOMAIN_SNAPSHOT_CREATE_LIVE |
15957 VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE_LIST, NULL);
15959 VIR_REQUIRE_FLAG_RET(VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE,
15960 VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY,
15961 NULL);
15962 VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_SNAPSHOT_CREATE_LIVE,
15963 VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE,
15964 NULL);
15966 if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
15967 (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA))
15968 update_current = false;
15969 if (redefine)
15970 parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
15972 if (!(vm = qemuDomObjFromDomain(domain)))
15973 goto cleanup;
15975 cfg = virQEMUDriverGetConfig(driver);
15977 if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0)
15978 goto cleanup;
15980 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
15981 goto cleanup;
15983 if (qemuProcessAutoDestroyActive(driver, vm)) {
15984 virReportError(VIR_ERR_OPERATION_INVALID,
15985 "%s", _("domain is marked for auto destroy"));
15986 goto cleanup;
15989 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE_LIST) {
15990 struct qemuDomainSnapshotBulk bulk = {
15991 .vm = vm,
15992 .driver = driver,
15993 .snapshotDir = cfg->snapshotDir,
15994 .flags = flags,
15997 if (virDomainSnapshotObjListParse(xmlDesc, vm->def->uuid,
15998 vm->snapshots, &vm->current_snapshot,
15999 caps, driver->xmlopt,
16000 parse_flags) < 0)
16001 goto cleanup;
16002 /* Validate and save the snapshots to disk. Since we don't get
16003 * here unless there were no snapshots beforehand, just delete
16004 * everything if anything failed, ignoring further errors. */
16005 if (virDomainSnapshotForEach(vm->snapshots,
16006 qemuDomainSnapshotBulkRedefine,
16007 &bulk) < 0) {
16008 virErrorPtr orig_err = virSaveLastError();
16010 qemuDomainSnapshotDiscardAllMetadata(driver, vm);
16011 virSetError(orig_err);
16012 virFreeError(orig_err);
16013 goto cleanup;
16015 /* Return is arbitrary, so use the first root */
16016 snap = virDomainSnapshotFindByName(vm->snapshots, NULL);
16017 snapshot = virGetDomainSnapshot(domain, snap->first_child->def->name);
16018 goto cleanup;
16021 if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
16022 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16023 _("cannot halt after transient domain snapshot"));
16024 goto cleanup;
16026 if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) ||
16027 !virDomainObjIsActive(vm))
16028 parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE;
16030 if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt,
16031 parse_flags)))
16032 goto cleanup;
16034 if (qemuDomainSnapshotValidate(def, redefine ? def->state : vm->state.state,
16035 flags) < 0)
16036 goto cleanup;
16038 /* reject the VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag where not supported */
16039 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE &&
16040 (!virDomainObjIsActive(vm) ||
16041 def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)) {
16042 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
16043 _("live snapshot creation is supported only "
16044 "during full system snapshots"));
16045 goto cleanup;
16048 /* We are going to modify the domain below. Internal snapshots would use
16049 * a regular job, so we need to set the job mask to disallow query as
16050 * 'savevm' blocks the monitor. External snapshot will then modify the
16051 * job mask appropriately. */
16052 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SNAPSHOT,
16053 VIR_DOMAIN_JOB_OPERATION_SNAPSHOT, flags) < 0)
16054 goto cleanup;
16056 qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
16058 priv = vm->privateData;
16060 if (redefine) {
16061 if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
16062 driver->xmlopt,
16063 &update_current, flags) < 0)
16064 goto endjob;
16065 } else {
16066 /* Easiest way to clone inactive portion of vm->def is via
16067 * conversion in and back out of xml. */
16068 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
16069 true, true)) ||
16070 !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL,
16071 VIR_DOMAIN_DEF_PARSE_INACTIVE |
16072 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
16073 goto endjob;
16075 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
16076 align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
16077 align_match = false;
16078 if (virDomainObjIsActive(vm))
16079 def->state = VIR_SNAP_STATE_DISK_SNAPSHOT;
16080 else
16081 def->state = VIR_SNAP_STATE_SHUTOFF;
16082 def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
16083 } else if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
16084 def->state = virDomainObjGetState(vm, NULL);
16085 align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
16086 align_match = false;
16087 } else {
16088 def->state = virDomainObjGetState(vm, NULL);
16090 if (virDomainObjIsActive(vm) &&
16091 def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
16092 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
16093 _("internal snapshot of a running VM "
16094 "must include the memory state"));
16095 goto endjob;
16098 def->memory = (def->state == VIR_SNAP_STATE_SHUTOFF ?
16099 VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
16100 VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL);
16102 if (virDomainSnapshotAlignDisks(def, align_location,
16103 align_match) < 0 ||
16104 qemuDomainSnapshotPrepare(vm, def, &flags) < 0)
16105 goto endjob;
16108 if (!snap) {
16109 if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
16110 goto endjob;
16112 def = NULL;
16115 if (update_current)
16116 snap->def->current = true;
16117 if (vm->current_snapshot) {
16118 if (!redefine &&
16119 VIR_STRDUP(snap->def->parent, vm->current_snapshot->def->name) < 0)
16120 goto endjob;
16121 if (update_current) {
16122 vm->current_snapshot->def->current = false;
16123 if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
16124 driver->caps, driver->xmlopt,
16125 cfg->snapshotDir) < 0)
16126 goto endjob;
16127 vm->current_snapshot = NULL;
16131 /* actually do the snapshot */
16132 if (redefine) {
16133 /* XXX Should we validate that the redefined snapshot even
16134 * makes sense, such as checking that qemu-img recognizes the
16135 * snapshot name in at least one of the domain's disks? */
16136 } else if (virDomainObjIsActive(vm)) {
16137 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ||
16138 snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
16139 /* external full system or disk snapshot */
16140 if (qemuDomainSnapshotCreateActiveExternal(driver,
16141 vm, snap, flags) < 0)
16142 goto endjob;
16143 } else {
16144 /* internal full system */
16145 if (qemuDomainSnapshotCreateActiveInternal(driver,
16146 vm, snap, flags) < 0)
16147 goto endjob;
16149 } else {
16150 /* inactive; qemuDomainSnapshotPrepare guaranteed that we
16151 * aren't mixing internal and external, and altered flags to
16152 * contain DISK_ONLY if there is an external disk. */
16153 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
16154 bool reuse = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
16156 if (qemuDomainSnapshotCreateInactiveExternal(driver, vm, snap,
16157 reuse) < 0)
16158 goto endjob;
16159 } else {
16160 if (qemuDomainSnapshotCreateInactiveInternal(driver, vm, snap) < 0)
16161 goto endjob;
16165 /* If we fail after this point, there's not a whole lot we can
16166 * do; we've successfully taken the snapshot, and we are now running
16167 * on it, so we have to go forward the best we can
16169 snapshot = virGetDomainSnapshot(domain, snap->def->name);
16171 endjob:
16172 if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
16173 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
16174 driver->xmlopt,
16175 cfg->snapshotDir) < 0) {
16176 /* if writing of metadata fails, error out rather than trying
16177 * to silently carry on without completing the snapshot */
16178 virObjectUnref(snapshot);
16179 snapshot = NULL;
16180 virReportError(VIR_ERR_INTERNAL_ERROR,
16181 _("unable to save metadata for snapshot %s"),
16182 snap->def->name);
16183 virDomainSnapshotObjListRemove(vm->snapshots, snap);
16184 } else {
16185 if (update_current)
16186 vm->current_snapshot = snap;
16187 other = virDomainSnapshotFindByName(vm->snapshots,
16188 snap->def->parent);
16189 snap->parent = other;
16190 other->nchildren++;
16191 snap->sibling = other->first_child;
16192 other->first_child = snap;
16194 } else if (snap) {
16195 virDomainSnapshotObjListRemove(vm->snapshots, snap);
16198 qemuDomainObjEndAsyncJob(driver, vm);
16200 cleanup:
16201 virDomainObjEndAPI(&vm);
16202 virDomainSnapshotDefFree(def);
16203 VIR_FREE(xml);
16204 virObjectUnref(caps);
16205 virObjectUnref(cfg);
16206 return snapshot;
16210 static int
16211 qemuDomainSnapshotListNames(virDomainPtr domain,
16212 char **names,
16213 int nameslen,
16214 unsigned int flags)
16216 virDomainObjPtr vm = NULL;
16217 int n = -1;
16219 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16220 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16222 if (!(vm = qemuDomObjFromDomain(domain)))
16223 return -1;
16225 if (virDomainSnapshotListNamesEnsureACL(domain->conn, vm->def) < 0)
16226 goto cleanup;
16228 n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
16229 flags);
16231 cleanup:
16232 virDomainObjEndAPI(&vm);
16233 return n;
16237 static int
16238 qemuDomainSnapshotNum(virDomainPtr domain,
16239 unsigned int flags)
16241 virDomainObjPtr vm = NULL;
16242 int n = -1;
16244 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16245 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16247 if (!(vm = qemuDomObjFromDomain(domain)))
16248 return -1;
16250 if (virDomainSnapshotNumEnsureACL(domain->conn, vm->def) < 0)
16251 goto cleanup;
16253 n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);
16255 cleanup:
16256 virDomainObjEndAPI(&vm);
16257 return n;
16261 static int
16262 qemuDomainListAllSnapshots(virDomainPtr domain,
16263 virDomainSnapshotPtr **snaps,
16264 unsigned int flags)
16266 virDomainObjPtr vm = NULL;
16267 int n = -1;
16269 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16270 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16272 if (!(vm = qemuDomObjFromDomain(domain)))
16273 return -1;
16275 if (virDomainListAllSnapshotsEnsureACL(domain->conn, vm->def) < 0)
16276 goto cleanup;
16278 n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);
16280 cleanup:
16281 virDomainObjEndAPI(&vm);
16282 return n;
16286 static int
16287 qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
16288 char **names,
16289 int nameslen,
16290 unsigned int flags)
16292 virDomainObjPtr vm = NULL;
16293 virDomainSnapshotObjPtr snap = NULL;
16294 int n = -1;
16296 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16297 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16299 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16300 return -1;
16302 if (virDomainSnapshotListChildrenNamesEnsureACL(snapshot->domain->conn, vm->def) < 0)
16303 goto cleanup;
16305 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16306 goto cleanup;
16308 n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
16309 flags);
16311 cleanup:
16312 virDomainObjEndAPI(&vm);
16313 return n;
16317 static int
16318 qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
16319 unsigned int flags)
16321 virDomainObjPtr vm = NULL;
16322 virDomainSnapshotObjPtr snap = NULL;
16323 int n = -1;
16325 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16326 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16328 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16329 return -1;
16331 if (virDomainSnapshotNumChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
16332 goto cleanup;
16334 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16335 goto cleanup;
16337 n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);
16339 cleanup:
16340 virDomainObjEndAPI(&vm);
16341 return n;
16345 static int
16346 qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
16347 virDomainSnapshotPtr **snaps,
16348 unsigned int flags)
16350 virDomainObjPtr vm = NULL;
16351 virDomainSnapshotObjPtr snap = NULL;
16352 int n = -1;
16354 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16355 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16357 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16358 return -1;
16360 if (virDomainSnapshotListAllChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
16361 goto cleanup;
16363 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16364 goto cleanup;
16366 n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
16367 flags);
16369 cleanup:
16370 virDomainObjEndAPI(&vm);
16371 return n;
16375 static virDomainSnapshotPtr
16376 qemuDomainSnapshotLookupByName(virDomainPtr domain,
16377 const char *name,
16378 unsigned int flags)
16380 virDomainObjPtr vm;
16381 virDomainSnapshotObjPtr snap = NULL;
16382 virDomainSnapshotPtr snapshot = NULL;
16384 virCheckFlags(0, NULL);
16386 if (!(vm = qemuDomObjFromDomain(domain)))
16387 return NULL;
16389 if (virDomainSnapshotLookupByNameEnsureACL(domain->conn, vm->def) < 0)
16390 goto cleanup;
16392 if (!(snap = qemuSnapObjFromName(vm, name)))
16393 goto cleanup;
16395 snapshot = virGetDomainSnapshot(domain, snap->def->name);
16397 cleanup:
16398 virDomainObjEndAPI(&vm);
16399 return snapshot;
16403 static int
16404 qemuDomainHasCurrentSnapshot(virDomainPtr domain,
16405 unsigned int flags)
16407 virDomainObjPtr vm;
16408 int ret = -1;
16410 virCheckFlags(0, -1);
16412 if (!(vm = qemuDomObjFromDomain(domain)))
16413 return -1;
16415 if (virDomainHasCurrentSnapshotEnsureACL(domain->conn, vm->def) < 0)
16416 goto cleanup;
16418 ret = (vm->current_snapshot != NULL);
16420 cleanup:
16421 virDomainObjEndAPI(&vm);
16422 return ret;
16426 static virDomainSnapshotPtr
16427 qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
16428 unsigned int flags)
16430 virDomainObjPtr vm;
16431 virDomainSnapshotObjPtr snap = NULL;
16432 virDomainSnapshotPtr parent = NULL;
16434 virCheckFlags(0, NULL);
16436 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16437 return NULL;
16439 if (virDomainSnapshotGetParentEnsureACL(snapshot->domain->conn, vm->def) < 0)
16440 goto cleanup;
16442 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16443 goto cleanup;
16445 if (!snap->def->parent) {
16446 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
16447 _("snapshot '%s' does not have a parent"),
16448 snap->def->name);
16449 goto cleanup;
16452 parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);
16454 cleanup:
16455 virDomainObjEndAPI(&vm);
16456 return parent;
16460 static virDomainSnapshotPtr
16461 qemuDomainSnapshotCurrent(virDomainPtr domain,
16462 unsigned int flags)
16464 virDomainObjPtr vm;
16465 virDomainSnapshotPtr snapshot = NULL;
16467 virCheckFlags(0, NULL);
16469 if (!(vm = qemuDomObjFromDomain(domain)))
16470 return NULL;
16472 if (virDomainSnapshotCurrentEnsureACL(domain->conn, vm->def) < 0)
16473 goto cleanup;
16475 if (!vm->current_snapshot) {
16476 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
16477 _("the domain does not have a current snapshot"));
16478 goto cleanup;
16481 snapshot = virGetDomainSnapshot(domain, vm->current_snapshot->def->name);
16483 cleanup:
16484 virDomainObjEndAPI(&vm);
16485 return snapshot;
16489 static char *
16490 qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
16491 unsigned int flags)
16493 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
16494 virDomainObjPtr vm = NULL;
16495 char *xml = NULL;
16496 virDomainSnapshotObjPtr snap = NULL;
16497 char uuidstr[VIR_UUID_STRING_BUFLEN];
16499 virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
16501 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16502 return NULL;
16504 if (virDomainSnapshotGetXMLDescEnsureACL(snapshot->domain->conn, vm->def, flags) < 0)
16505 goto cleanup;
16507 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16508 goto cleanup;
16510 virUUIDFormat(snapshot->domain->uuid, uuidstr);
16512 xml = virDomainSnapshotDefFormat(uuidstr, snap->def,
16513 driver->caps, driver->xmlopt,
16514 virDomainSnapshotFormatConvertXMLFlags(flags));
16516 cleanup:
16517 virDomainObjEndAPI(&vm);
16518 return xml;
16522 static int
16523 qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
16524 unsigned int flags)
16526 virDomainObjPtr vm = NULL;
16527 int ret = -1;
16528 virDomainSnapshotObjPtr snap = NULL;
16530 virCheckFlags(0, -1);
16532 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16533 return -1;
16535 if (virDomainSnapshotIsCurrentEnsureACL(snapshot->domain->conn, vm->def) < 0)
16536 goto cleanup;
16538 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16539 goto cleanup;
16541 ret = (vm->current_snapshot &&
16542 STREQ(snapshot->name, vm->current_snapshot->def->name));
16544 cleanup:
16545 virDomainObjEndAPI(&vm);
16546 return ret;
16550 static int
16551 qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
16552 unsigned int flags)
16554 virDomainObjPtr vm = NULL;
16555 int ret = -1;
16556 virDomainSnapshotObjPtr snap = NULL;
16558 virCheckFlags(0, -1);
16560 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16561 return -1;
16563 if (virDomainSnapshotHasMetadataEnsureACL(snapshot->domain->conn, vm->def) < 0)
16564 goto cleanup;
16566 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16567 goto cleanup;
16569 /* XXX Someday, we should recognize internal snapshots in qcow2
16570 * images that are not tied to a libvirt snapshot; if we ever do
16571 * that, then we would have a reason to return 0 here. */
16572 ret = 1;
16574 cleanup:
16575 virDomainObjEndAPI(&vm);
16576 return ret;
16580 /* The domain is expected to be locked and inactive. */
16581 static int
16582 qemuDomainSnapshotRevertInactive(virQEMUDriverPtr driver,
16583 virDomainObjPtr vm,
16584 virDomainSnapshotObjPtr snap)
16586 /* Try all disks, but report failure if we skipped any. */
16587 int ret = qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-a", true);
16588 return ret > 0 ? -1 : ret;
16592 static int
16593 qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
16594 unsigned int flags)
16596 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
16597 virDomainObjPtr vm = NULL;
16598 int ret = -1;
16599 virDomainSnapshotObjPtr snap = NULL;
16600 virObjectEventPtr event = NULL;
16601 virObjectEventPtr event2 = NULL;
16602 int detail;
16603 qemuDomainObjPrivatePtr priv;
16604 int rc;
16605 virDomainDefPtr config = NULL;
16606 virQEMUDriverConfigPtr cfg = NULL;
16607 virCapsPtr caps = NULL;
16608 bool was_stopped = false;
16609 qemuDomainSaveCookiePtr cookie;
16610 virCPUDefPtr origCPU = NULL;
16611 unsigned int start_flags = VIR_QEMU_PROCESS_START_GEN_VMID;
16612 qemuDomainAsyncJob jobType = QEMU_ASYNC_JOB_START;
16614 virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16615 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
16616 VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);
16618 /* We have the following transitions, which create the following events:
16619 * 1. inactive -> inactive: none
16620 * 2. inactive -> running: EVENT_STARTED
16621 * 3. inactive -> paused: EVENT_STARTED, EVENT_PAUSED
16622 * 4. running -> inactive: EVENT_STOPPED
16623 * 5. running -> running: none
16624 * 6. running -> paused: EVENT_PAUSED
16625 * 7. paused -> inactive: EVENT_STOPPED
16626 * 8. paused -> running: EVENT_RESUMED
16627 * 9. paused -> paused: none
16628 * Also, several transitions occur even if we fail partway through,
16629 * and use of FORCE can cause multiple transitions.
16632 virNWFilterReadLockFilterUpdates();
16634 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16635 goto cleanup;
16637 cfg = virQEMUDriverGetConfig(driver);
16639 if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0)
16640 goto cleanup;
16642 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
16643 goto cleanup;
16645 if (qemuDomainHasBlockjob(vm, false)) {
16646 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16647 _("domain has active block job"));
16648 goto cleanup;
16651 if (qemuProcessBeginJob(driver, vm,
16652 VIR_DOMAIN_JOB_OPERATION_SNAPSHOT_REVERT,
16653 flags) < 0)
16654 goto cleanup;
16656 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16657 goto endjob;
16659 if (!vm->persistent &&
16660 snap->def->state != VIR_SNAP_STATE_RUNNING &&
16661 snap->def->state != VIR_SNAP_STATE_PAUSED &&
16662 (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16663 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) == 0) {
16664 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16665 _("transient domain needs to request run or pause "
16666 "to revert to inactive snapshot"));
16667 goto endjob;
16670 if (virDomainSnapshotIsExternal(snap)) {
16671 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
16672 _("revert to external snapshot not supported yet"));
16673 goto endjob;
16676 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
16677 if (!snap->def->dom) {
16678 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
16679 _("snapshot '%s' lacks domain '%s' rollback info"),
16680 snap->def->name, vm->def->name);
16681 goto endjob;
16683 if (virDomainObjIsActive(vm) &&
16684 !(snap->def->state == VIR_SNAP_STATE_RUNNING ||
16685 snap->def->state == VIR_SNAP_STATE_PAUSED) &&
16686 (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16687 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
16688 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
16689 _("must respawn qemu to start inactive snapshot"));
16690 goto endjob;
16695 if (vm->current_snapshot) {
16696 vm->current_snapshot->def->current = false;
16697 if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
16698 driver->caps, driver->xmlopt,
16699 cfg->snapshotDir) < 0)
16700 goto endjob;
16701 vm->current_snapshot = NULL;
16702 /* XXX Should we restore vm->current_snapshot after this point
16703 * in the failure cases where we know there was no change? */
16706 /* Prepare to copy the snapshot inactive xml as the config of this
16707 * domain.
16709 * XXX Should domain snapshots track live xml rather
16710 * than inactive xml? */
16711 snap->def->current = true;
16712 if (snap->def->dom) {
16713 config = virDomainDefCopy(snap->def->dom, caps,
16714 driver->xmlopt, NULL, true);
16715 if (!config)
16716 goto endjob;
16719 cookie = (qemuDomainSaveCookiePtr) snap->def->cookie;
16721 switch ((virDomainSnapshotState) snap->def->state) {
16722 case VIR_SNAP_STATE_RUNNING:
16723 case VIR_SNAP_STATE_PAUSED:
16725 start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
16727 /* Transitions 2, 3, 5, 6, 8, 9 */
16728 /* When using the loadvm monitor command, qemu does not know
16729 * whether to pause or run the reverted domain, and just stays
16730 * in the same state as before the monitor command, whether
16731 * that is paused or running. We always pause before loadvm,
16732 * to have finer control. */
16733 if (virDomainObjIsActive(vm)) {
16734 /* Transitions 5, 6, 8, 9 */
16735 /* Check for ABI compatibility. We need to do this check against
16736 * the migratable XML or it will always fail otherwise */
16737 if (config) {
16738 bool compatible;
16740 /* Replace the CPU in config and put the original one in priv
16741 * once we're done. When we have the updated CPU def in the
16742 * cookie, we don't want to replace the CPU in migratable def
16743 * when doing ABI checks to make sure the current CPU exactly
16744 * matches the one used at the time the snapshot was taken.
16746 if (cookie && cookie->cpu && config->cpu) {
16747 origCPU = config->cpu;
16748 if (!(config->cpu = virCPUDefCopy(cookie->cpu)))
16749 goto endjob;
16751 compatible = qemuDomainDefCheckABIStability(driver, vm->def,
16752 config);
16753 } else {
16754 compatible = qemuDomainCheckABIStability(driver, vm, config);
16757 /* If using VM GenID, there is no way currently to change
16758 * the genid for the running guest, so set an error,
16759 * mark as incompatible, and don't allow change of genid
16760 * if the revert force flag would start the guest again. */
16761 if (compatible && config->genidRequested) {
16762 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
16763 _("domain genid update requires restart"));
16764 compatible = false;
16765 start_flags &= ~VIR_QEMU_PROCESS_START_GEN_VMID;
16768 if (!compatible) {
16769 virErrorPtr err = virGetLastError();
16771 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
16772 /* Re-spawn error using correct category. */
16773 if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
16774 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
16775 err->str2);
16776 goto endjob;
16778 virResetError(err);
16779 qemuProcessStop(driver, vm,
16780 VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
16781 QEMU_ASYNC_JOB_START, 0);
16782 virDomainAuditStop(vm, "from-snapshot");
16783 detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
16784 event = virDomainEventLifecycleNewFromObj(vm,
16785 VIR_DOMAIN_EVENT_STOPPED,
16786 detail);
16787 virObjectEventStateQueue(driver->domainEventState, event);
16788 /* Start after stop won't be an async start job, so
16789 * reset to none */
16790 jobType = QEMU_ASYNC_JOB_NONE;
16791 goto load;
16795 priv = vm->privateData;
16796 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
16797 /* Transitions 5, 6 */
16798 if (qemuProcessStopCPUs(driver, vm,
16799 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
16800 QEMU_ASYNC_JOB_START) < 0)
16801 goto endjob;
16802 /* Create an event now in case the restore fails, so
16803 * that user will be alerted that they are now paused.
16804 * If restore later succeeds, we might replace this. */
16805 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16806 event = virDomainEventLifecycleNewFromObj(vm,
16807 VIR_DOMAIN_EVENT_SUSPENDED,
16808 detail);
16809 if (!virDomainObjIsActive(vm)) {
16810 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16811 _("guest unexpectedly quit"));
16812 goto endjob;
16816 if (qemuDomainObjEnterMonitorAsync(driver, vm,
16817 QEMU_ASYNC_JOB_START) < 0)
16818 goto endjob;
16819 rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
16820 if (qemuDomainObjExitMonitor(driver, vm) < 0)
16821 goto endjob;
16822 if (rc < 0) {
16823 /* XXX resume domain if it was running before the
16824 * failed loadvm attempt? */
16825 goto endjob;
16827 if (config) {
16828 virDomainObjAssignDef(vm, config, false, NULL);
16829 virCPUDefFree(priv->origCPU);
16830 VIR_STEAL_PTR(priv->origCPU, origCPU);
16832 } else {
16833 /* Transitions 2, 3 */
16834 load:
16835 was_stopped = true;
16836 if (config)
16837 virDomainObjAssignDef(vm, config, false, NULL);
16839 /* No cookie means libvirt which saved the domain was too old to
16840 * mess up the CPU definitions.
16842 if (cookie &&
16843 qemuDomainFixupCPUs(vm, &cookie->cpu) < 0)
16844 goto cleanup;
16846 rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
16847 cookie ? cookie->cpu : NULL,
16848 jobType, NULL, -1, NULL, snap,
16849 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
16850 start_flags);
16851 virDomainAuditStart(vm, "from-snapshot", rc >= 0);
16852 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16853 event = virDomainEventLifecycleNewFromObj(vm,
16854 VIR_DOMAIN_EVENT_STARTED,
16855 detail);
16856 if (rc < 0)
16857 goto endjob;
16860 /* Touch up domain state. */
16861 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
16862 (snap->def->state == VIR_SNAP_STATE_PAUSED ||
16863 (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
16864 /* Transitions 3, 6, 9 */
16865 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
16866 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
16867 if (was_stopped) {
16868 /* Transition 3, use event as-is and add event2 */
16869 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16870 event2 = virDomainEventLifecycleNewFromObj(vm,
16871 VIR_DOMAIN_EVENT_SUSPENDED,
16872 detail);
16873 } /* else transition 6 and 9 use event as-is */
16874 } else {
16875 /* Transitions 2, 5, 8 */
16876 if (!virDomainObjIsActive(vm)) {
16877 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16878 _("guest unexpectedly quit"));
16879 goto endjob;
16881 rc = qemuProcessStartCPUs(driver, vm,
16882 VIR_DOMAIN_RUNNING_FROM_SNAPSHOT,
16883 jobType);
16884 if (rc < 0)
16885 goto endjob;
16886 virObjectUnref(event);
16887 event = NULL;
16888 if (was_stopped) {
16889 /* Transition 2 */
16890 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16891 event = virDomainEventLifecycleNewFromObj(vm,
16892 VIR_DOMAIN_EVENT_STARTED,
16893 detail);
16896 break;
16898 case VIR_SNAP_STATE_SHUTDOWN:
16899 case VIR_SNAP_STATE_SHUTOFF:
16900 case VIR_SNAP_STATE_CRASHED:
16901 /* Transitions 1, 4, 7 */
16902 /* Newer qemu -loadvm refuses to revert to the state of a snapshot
16903 * created by qemu-img snapshot -c. If the domain is running, we
16904 * must take it offline; then do the revert using qemu-img.
16907 if (virDomainObjIsActive(vm)) {
16908 /* Transitions 4, 7 */
16909 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
16910 QEMU_ASYNC_JOB_START, 0);
16911 virDomainAuditStop(vm, "from-snapshot");
16912 detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
16913 event = virDomainEventLifecycleNewFromObj(vm,
16914 VIR_DOMAIN_EVENT_STOPPED,
16915 detail);
16918 if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) {
16919 qemuDomainRemoveInactive(driver, vm);
16920 qemuProcessEndJob(driver, vm);
16921 goto cleanup;
16923 if (config)
16924 virDomainObjAssignDef(vm, config, false, NULL);
16926 if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16927 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
16928 /* Flush first event, now do transition 2 or 3 */
16929 bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;
16931 start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
16933 virObjectEventStateQueue(driver->domainEventState, event);
16934 rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
16935 QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL,
16936 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
16937 start_flags);
16938 virDomainAuditStart(vm, "from-snapshot", rc >= 0);
16939 if (rc < 0) {
16940 qemuDomainRemoveInactive(driver, vm);
16941 qemuProcessEndJob(driver, vm);
16942 goto cleanup;
16944 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16945 event = virDomainEventLifecycleNewFromObj(vm,
16946 VIR_DOMAIN_EVENT_STARTED,
16947 detail);
16948 if (paused) {
16949 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16950 event2 = virDomainEventLifecycleNewFromObj(vm,
16951 VIR_DOMAIN_EVENT_SUSPENDED,
16952 detail);
16955 break;
16957 case VIR_SNAP_STATE_PMSUSPENDED:
16958 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
16959 _("qemu doesn't support reversion of snapshot taken in "
16960 "PMSUSPENDED state"));
16961 goto endjob;
16963 case VIR_SNAP_STATE_DISK_SNAPSHOT:
16964 /* Rejected earlier as an external snapshot */
16965 case VIR_SNAP_STATE_NOSTATE:
16966 case VIR_SNAP_STATE_BLOCKED:
16967 case VIR_SNAP_STATE_LAST:
16968 virReportError(VIR_ERR_INTERNAL_ERROR,
16969 _("Invalid target domain state '%s'. Refusing "
16970 "snapshot reversion"),
16971 virDomainSnapshotStateTypeToString(snap->def->state));
16972 goto endjob;
16975 ret = 0;
16977 endjob:
16978 qemuProcessEndJob(driver, vm);
16980 cleanup:
16981 if (ret == 0) {
16982 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
16983 driver->xmlopt,
16984 cfg->snapshotDir) < 0)
16985 ret = -1;
16986 else
16987 vm->current_snapshot = snap;
16988 } else if (snap) {
16989 snap->def->current = false;
16991 if (ret == 0 && config && vm->persistent &&
16992 !(ret = virDomainSaveConfig(cfg->configDir, driver->caps,
16993 vm->newDef ? vm->newDef : vm->def))) {
16994 detail = VIR_DOMAIN_EVENT_DEFINED_FROM_SNAPSHOT;
16995 virObjectEventStateQueue(driver->domainEventState,
16996 virDomainEventLifecycleNewFromObj(vm,
16997 VIR_DOMAIN_EVENT_DEFINED,
16998 detail));
17000 virObjectEventStateQueue(driver->domainEventState, event);
17001 virObjectEventStateQueue(driver->domainEventState, event2);
17002 virDomainObjEndAPI(&vm);
17003 virObjectUnref(caps);
17004 virObjectUnref(cfg);
17005 virNWFilterUnlockFilterUpdates();
17006 virCPUDefFree(origCPU);
17008 return ret;
17012 typedef struct _virQEMUSnapReparent virQEMUSnapReparent;
17013 typedef virQEMUSnapReparent *virQEMUSnapReparentPtr;
17014 struct _virQEMUSnapReparent {
17015 virQEMUDriverConfigPtr cfg;
17016 virDomainSnapshotObjPtr parent;
17017 virDomainObjPtr vm;
17018 virCapsPtr caps;
17019 virDomainXMLOptionPtr xmlopt;
17020 int err;
17021 virDomainSnapshotObjPtr last;
17025 static int
17026 qemuDomainSnapshotReparentChildren(void *payload,
17027 const void *name ATTRIBUTE_UNUSED,
17028 void *data)
17030 virDomainSnapshotObjPtr snap = payload;
17031 virQEMUSnapReparentPtr rep = data;
17033 if (rep->err < 0)
17034 return 0;
17036 VIR_FREE(snap->def->parent);
17037 snap->parent = rep->parent;
17039 if (rep->parent->def &&
17040 VIR_STRDUP(snap->def->parent, rep->parent->def->name) < 0) {
17041 rep->err = -1;
17042 return 0;
17045 if (!snap->sibling)
17046 rep->last = snap;
17048 rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
17049 rep->caps, rep->xmlopt,
17050 rep->cfg->snapshotDir);
17051 return 0;
17055 static int
17056 qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
17057 unsigned int flags)
17059 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
17060 virDomainObjPtr vm = NULL;
17061 int ret = -1;
17062 virDomainSnapshotObjPtr snap = NULL;
17063 virQEMUDependentRemove rem;
17064 virQEMUSnapReparent rep;
17065 bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
17066 int external = 0;
17067 virQEMUDriverConfigPtr cfg = NULL;
17069 virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
17070 VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
17071 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);
17073 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
17074 return -1;
17076 cfg = virQEMUDriverGetConfig(driver);
17078 if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, vm->def) < 0)
17079 goto cleanup;
17081 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17082 goto cleanup;
17084 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
17085 goto endjob;
17087 if (!metadata_only) {
17088 if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
17089 virDomainSnapshotIsExternal(snap))
17090 external++;
17091 if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
17092 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY))
17093 virDomainSnapshotForEachDescendant(snap,
17094 qemuDomainSnapshotCountExternal,
17095 &external);
17096 if (external) {
17097 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17098 _("deletion of %d external disk snapshots not "
17099 "supported yet"), external);
17100 goto endjob;
17104 if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
17105 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
17106 rem.driver = driver;
17107 rem.vm = vm;
17108 rem.metadata_only = metadata_only;
17109 rem.err = 0;
17110 rem.current = false;
17111 virDomainSnapshotForEachDescendant(snap,
17112 qemuDomainSnapshotDiscardAll,
17113 &rem);
17114 if (rem.err < 0)
17115 goto endjob;
17116 if (rem.current) {
17117 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
17118 snap->def->current = true;
17119 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
17120 driver->xmlopt,
17121 cfg->snapshotDir) < 0) {
17122 virReportError(VIR_ERR_INTERNAL_ERROR,
17123 _("failed to set snapshot '%s' as current"),
17124 snap->def->name);
17125 snap->def->current = false;
17126 goto endjob;
17129 vm->current_snapshot = snap;
17131 } else if (snap->nchildren) {
17132 rep.cfg = cfg;
17133 rep.parent = snap->parent;
17134 rep.vm = vm;
17135 rep.err = 0;
17136 rep.last = NULL;
17137 rep.caps = driver->caps;
17138 rep.xmlopt = driver->xmlopt;
17139 virDomainSnapshotForEachChild(snap,
17140 qemuDomainSnapshotReparentChildren,
17141 &rep);
17142 if (rep.err < 0)
17143 goto endjob;
17144 /* Can't modify siblings during ForEachChild, so do it now. */
17145 snap->parent->nchildren += snap->nchildren;
17146 rep.last->sibling = snap->parent->first_child;
17147 snap->parent->first_child = snap->first_child;
17150 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
17151 snap->nchildren = 0;
17152 snap->first_child = NULL;
17153 ret = 0;
17154 } else {
17155 ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
17158 endjob:
17159 qemuDomainObjEndJob(driver, vm);
17161 cleanup:
17162 virDomainObjEndAPI(&vm);
17163 virObjectUnref(cfg);
17164 return ret;
17168 /* Called prior to job lock */
17169 static virDomainCheckpointDefPtr
17170 qemuDomainCheckpointDefParseString(virQEMUDriverPtr driver, virCapsPtr caps,
17171 const char *xmlDesc, unsigned int flags)
17173 virDomainCheckpointDefPtr def = NULL;
17174 virDomainCheckpointDefPtr ret = NULL;
17175 unsigned int parse_flags = VIR_DOMAIN_CHECKPOINT_PARSE_DISKS;
17177 if (flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE)
17178 parse_flags |= VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
17179 if (!(def = virDomainCheckpointDefParseString(xmlDesc, caps, driver->xmlopt,
17180 parse_flags)))
17181 goto cleanup;
17183 /* reject checkpoint names containing slashes or starting with dot as
17184 * checkpoint definitions are saved in files named by the checkpoint name */
17185 if (!(flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA)) {
17186 if (strchr(def->name, '/')) {
17187 virReportError(VIR_ERR_XML_DETAIL,
17188 _("invalid checkpoint name '%s': "
17189 "name can't contain '/'"),
17190 def->name);
17191 goto cleanup;
17194 if (def->name[0] == '.') {
17195 virReportError(VIR_ERR_XML_DETAIL,
17196 _("invalid checkpoint name '%s': "
17197 "name can't start with '.'"),
17198 def->name);
17199 goto cleanup;
17203 VIR_STEAL_PTR(ret, def);
17205 cleanup:
17206 virDomainCheckpointDefFree(def);
17207 return ret;
17211 /* Called inside job lock */
17212 static int
17213 qemuDomainCheckpointPrepare(virQEMUDriverPtr driver, virCapsPtr caps,
17214 virDomainObjPtr vm,
17215 virDomainCheckpointDefPtr def)
17217 int ret = -1;
17218 size_t i;
17219 char *xml = NULL;
17220 qemuDomainObjPrivatePtr priv = vm->privateData;
17222 /* Easiest way to clone inactive portion of vm->def is via
17223 * conversion in and back out of xml. */
17224 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
17225 true, true)) ||
17226 !(def->dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL,
17227 VIR_DOMAIN_DEF_PARSE_INACTIVE |
17228 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
17229 goto cleanup;
17231 if (virDomainCheckpointAlignDisks(def) < 0 ||
17232 qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
17233 goto cleanup;
17235 for (i = 0; i < def->ndisks; i++) {
17236 virDomainCheckpointDiskDefPtr disk = &def->disks[i];
17238 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17239 continue;
17241 /* We want to name temporary bitmap after disk name during
17242 * incremental backup, which is not possible if that is a
17243 * persistent bitmap name. We can also make life easier by
17244 * enforcing bitmap names match checkpoint name, although this
17245 * is not technically necessary. */
17246 if (STREQ(disk->name, disk->bitmap)) {
17247 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17248 _("checkpoint for disk %s must have distinct bitmap name"),
17249 disk->name);
17250 goto cleanup;
17252 if (STRNEQ(disk->bitmap, def->name)) {
17253 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17254 _("disk %s bitmap should match checkpoint name %s"),
17255 disk->name, def->name);
17256 goto cleanup;
17259 if (vm->def->disks[i]->src->format > 0 &&
17260 vm->def->disks[i]->src->format != VIR_STORAGE_FILE_QCOW2) {
17261 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17262 _("checkpoint for disk %s unsupported "
17263 "for storage type %s"),
17264 disk->name,
17265 virStorageFileFormatTypeToString(
17266 vm->def->disks[i]->src->format));
17267 goto cleanup;
17271 ret = 0;
17273 cleanup:
17274 VIR_FREE(xml);
17275 return ret;
17278 static int
17279 qemuDomainCheckpointAddActions(virDomainObjPtr vm,
17280 virJSONValuePtr actions,
17281 virDomainCheckpointObjPtr old_current,
17282 virDomainCheckpointDefPtr def)
17284 size_t i, j;
17285 int ret = -1;
17287 for (i = 0; i < def->ndisks; i++) {
17288 virDomainCheckpointDiskDef *disk = &def->disks[i];
17289 const char *node;
17291 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17292 continue;
17293 node = qemuBlockNodeLookup(vm, disk->name);
17294 if (qemuMonitorJSONTransactionAdd(actions,
17295 "block-dirty-bitmap-add",
17296 "s:node", node,
17297 "s:name", disk->bitmap,
17298 "b:persistent", true,
17299 NULL) < 0)
17300 goto cleanup;
17301 if (old_current) {
17302 for (j = 0; j < old_current->def->ndisks; j++) {
17303 virDomainCheckpointDiskDef *disk2;
17305 disk2 = &old_current->def->disks[j];
17306 if (STRNEQ(disk->name, disk2->name))
17307 continue;
17308 if (disk2->type == VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP &&
17309 qemuMonitorJSONTransactionAdd(actions,
17310 "block-dirty-bitmap-disable",
17311 "s:node", node,
17312 "s:name", disk2->bitmap,
17313 NULL) < 0)
17314 goto cleanup;
17318 ret = 0;
17320 cleanup:
17321 return ret;
17325 /* Struct and hash-iterator callback used when bulk redefining checkpoints */
17326 struct qemuDomainCheckpointBulk {
17327 virDomainObjPtr vm;
17328 virQEMUDriverPtr driver;
17329 const char *checkpointDir;
17330 unsigned int flags;
17333 static int
17334 qemuDomainCheckpointBulkRedefine(void *payload,
17335 const void *name ATTRIBUTE_UNUSED,
17336 void *opaque)
17338 virDomainCheckpointObjPtr chk = payload;
17339 struct qemuDomainCheckpointBulk *data = opaque;
17341 return qemuDomainCheckpointWriteMetadata(data->vm, chk, data->driver->caps,
17342 data->driver->xmlopt,
17343 data->checkpointDir);
17347 static virDomainCheckpointPtr
17348 qemuDomainCheckpointCreateXML(virDomainPtr domain,
17349 const char *xmlDesc,
17350 unsigned int flags)
17352 virQEMUDriverPtr driver = domain->conn->privateData;
17353 virDomainObjPtr vm = NULL;
17354 char *xml = NULL;
17355 virDomainCheckpointObjPtr chk = NULL;
17356 virDomainCheckpointPtr checkpoint = NULL;
17357 virDomainCheckpointDefPtr def = NULL;
17358 bool update_current = true;
17359 bool redefine = flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE;
17360 unsigned int parse_flags = VIR_DOMAIN_CHECKPOINT_PARSE_DISKS;
17361 virDomainCheckpointObjPtr other = NULL;
17362 virQEMUDriverConfigPtr cfg = NULL;
17363 virCapsPtr caps = NULL;
17364 qemuDomainObjPrivatePtr priv;
17365 virJSONValuePtr actions = NULL;
17366 int ret;
17368 virCheckFlags(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE |
17369 VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT |
17370 VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA |
17371 VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE_LIST, NULL);
17372 /* TODO: VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE */
17374 if (redefine)
17375 parse_flags |= VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
17376 if ((redefine && !(flags & VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT)) ||
17377 (flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA))
17378 update_current = false;
17380 if (!(vm = qemuDomObjFromDomain(domain)))
17381 goto cleanup;
17383 priv = vm->privateData;
17384 cfg = virQEMUDriverGetConfig(driver);
17386 if (virDomainCheckpointCreateXMLEnsureACL(domain->conn, vm->def) < 0)
17387 goto cleanup;
17389 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17390 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17391 _("qemu binary lacks persistent bitmaps support"));
17392 goto cleanup;
17395 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
17396 goto cleanup;
17398 if (qemuProcessAutoDestroyActive(driver, vm)) {
17399 virReportError(VIR_ERR_OPERATION_INVALID,
17400 "%s", _("domain is marked for auto destroy"));
17401 goto cleanup;
17404 if (!virDomainObjIsActive(vm)) {
17405 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17406 _("cannot create checkpoint for inactive domain"));
17407 goto cleanup;
17410 if (flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE_LIST) {
17411 struct qemuDomainCheckpointBulk bulk = {
17412 .vm = vm,
17413 .driver = driver,
17414 .checkpointDir = cfg->checkpointDir,
17415 .flags = flags,
17418 if (virDomainCheckpointObjListParse(xmlDesc, vm->def->uuid,
17419 vm->checkpoints,
17420 &vm->current_checkpoint,
17421 caps, driver->xmlopt,
17422 parse_flags) < 0)
17423 goto cleanup;
17424 /* Validate and save the checkpoints to disk. Since we don't get
17425 * here unless there were no checkpoints beforehand, just delete
17426 * everything if anything failed, ignoring further errors. */
17427 if (virDomainCheckpointForEach(vm->checkpoints,
17428 qemuDomainCheckpointBulkRedefine,
17429 &bulk) < 0) {
17430 virErrorPtr orig_err = virSaveLastError();
17432 qemuDomainCheckpointDiscardAllMetadata(driver, vm);
17433 virSetError(orig_err);
17434 virFreeError(orig_err);
17435 goto cleanup;
17437 /* Return is arbitrary, so use the first root */
17438 chk = virDomainCheckpointFindByName(vm->checkpoints, NULL);
17439 checkpoint = virGetDomainCheckpoint(domain,
17440 chk->first_child->def->name);
17441 goto cleanup;
17444 if (!(def = qemuDomainCheckpointDefParseString(driver, caps, xmlDesc,
17445 parse_flags)))
17446 goto cleanup;
17448 /* We are going to modify the domain below. */
17449 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17450 goto cleanup;
17452 if (redefine) {
17453 if (virDomainCheckpointRedefinePrep(domain, vm, &def, &chk,
17454 driver->xmlopt,
17455 &update_current) < 0)
17456 goto endjob;
17457 } else if (qemuDomainCheckpointPrepare(driver, caps, vm, def) < 0) {
17458 goto endjob;
17461 if (!chk) {
17462 if (!(chk = virDomainCheckpointAssignDef(vm->checkpoints, def)))
17463 goto endjob;
17465 def = NULL;
17468 if (update_current)
17469 chk->def->current = true;
17470 if (vm->current_checkpoint) {
17471 other = vm->current_checkpoint;
17472 if (!redefine &&
17473 VIR_STRDUP(chk->def->parent, vm->current_checkpoint->def->name) < 0)
17474 goto endjob;
17475 if (update_current) {
17476 vm->current_checkpoint->def->current = false;
17477 if (qemuDomainCheckpointWriteMetadata(vm, vm->current_checkpoint,
17478 driver->caps, driver->xmlopt,
17479 cfg->checkpointDir) < 0)
17480 goto endjob;
17481 vm->current_checkpoint = NULL;
17485 /* actually do the checkpoint */
17486 if (redefine) {
17487 /* XXX Should we validate that the redefined checkpoint even
17488 * makes sense, such as checking that qemu-img recognizes the
17489 * checkpoint bitmap name in at least one of the domain's disks? */
17490 } else {
17491 if (!(actions = virJSONValueNewArray()))
17492 goto endjob;
17493 if (qemuDomainCheckpointAddActions(vm, actions, other, chk->def) < 0)
17494 goto endjob;
17495 qemuDomainObjEnterMonitor(driver, vm);
17496 ret = qemuMonitorTransaction(priv->mon, &actions);
17497 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
17498 goto endjob;
17501 /* If we fail after this point, there's not a whole lot we can do;
17502 * we've successfully created the checkpoint, so we have to go
17503 * forward the best we can.
17505 checkpoint = virGetDomainCheckpoint(domain, chk->def->name);
17507 endjob:
17508 if (checkpoint && !(flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA)) {
17509 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
17510 driver->xmlopt,
17511 cfg->checkpointDir) < 0) {
17512 /* if writing of metadata fails, error out rather than trying
17513 * to silently carry on without completing the checkpoint */
17514 virObjectUnref(checkpoint);
17515 checkpoint = NULL;
17516 virReportError(VIR_ERR_INTERNAL_ERROR,
17517 _("unable to save metadata for checkpoint %s"),
17518 chk->def->name);
17519 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
17520 } else {
17521 if (update_current)
17522 vm->current_checkpoint = chk;
17523 other = virDomainCheckpointFindByName(vm->checkpoints,
17524 chk->def->parent);
17525 chk->parent = other;
17526 other->nchildren++;
17527 chk->sibling = other->first_child;
17528 other->first_child = chk;
17530 } else if (chk) {
17531 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
17534 qemuDomainObjEndJob(driver, vm);
17536 cleanup:
17537 virJSONValueFree(actions);
17538 virDomainObjEndAPI(&vm);
17539 virDomainCheckpointDefFree(def);
17540 VIR_FREE(xml);
17541 virObjectUnref(caps);
17542 virObjectUnref(cfg);
17543 return checkpoint;
17547 static int
17548 qemuDomainListCheckpoints(virDomainPtr domain,
17549 virDomainCheckpointPtr **chks,
17550 unsigned int flags)
17552 virDomainObjPtr vm = NULL;
17553 int n = -1;
17555 virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS |
17556 VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
17558 if (!(vm = qemuDomObjFromDomain(domain)))
17559 return -1;
17561 if (virDomainListCheckpointsEnsureACL(domain->conn, vm->def) < 0)
17562 goto cleanup;
17564 n = virDomainListAllCheckpoints(vm->checkpoints, NULL, domain, chks, flags);
17566 cleanup:
17567 virDomainObjEndAPI(&vm);
17568 return n;
17572 static int
17573 qemuDomainCheckpointListChildren(virDomainCheckpointPtr checkpoint,
17574 virDomainCheckpointPtr **chks,
17575 unsigned int flags)
17577 virDomainObjPtr vm = NULL;
17578 virDomainCheckpointObjPtr chk = NULL;
17579 int n = -1;
17581 virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS |
17582 VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
17584 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17585 return -1;
17587 if (virDomainCheckpointListChildrenEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17588 goto cleanup;
17590 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17591 goto cleanup;
17593 n = virDomainListAllCheckpoints(vm->checkpoints, chk, checkpoint->domain, chks, flags);
17595 cleanup:
17596 virDomainObjEndAPI(&vm);
17597 return n;
17601 static virDomainCheckpointPtr
17602 qemuDomainCheckpointLookupByName(virDomainPtr domain,
17603 const char *name,
17604 unsigned int flags)
17606 virDomainObjPtr vm;
17607 virDomainCheckpointObjPtr chk = NULL;
17608 virDomainCheckpointPtr checkpoint = NULL;
17610 virCheckFlags(0, NULL);
17612 if (!(vm = qemuDomObjFromDomain(domain)))
17613 return NULL;
17615 if (virDomainCheckpointLookupByNameEnsureACL(domain->conn, vm->def) < 0)
17616 goto cleanup;
17618 if (!(chk = qemuCheckObjFromName(vm, name)))
17619 goto cleanup;
17621 checkpoint = virGetDomainCheckpoint(domain, chk->def->name);
17623 cleanup:
17624 virDomainObjEndAPI(&vm);
17625 return checkpoint;
17629 static int
17630 qemuDomainHasCurrentCheckpoint(virDomainPtr domain,
17631 unsigned int flags)
17633 virDomainObjPtr vm;
17634 int ret = -1;
17636 virCheckFlags(0, -1);
17638 if (!(vm = qemuDomObjFromDomain(domain)))
17639 return -1;
17641 if (virDomainHasCurrentCheckpointEnsureACL(domain->conn, vm->def) < 0)
17642 goto cleanup;
17644 ret = (vm->current_checkpoint != NULL);
17646 cleanup:
17647 virDomainObjEndAPI(&vm);
17648 return ret;
17652 static virDomainCheckpointPtr
17653 qemuDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
17654 unsigned int flags)
17656 virDomainObjPtr vm;
17657 virDomainCheckpointObjPtr chk = NULL;
17658 virDomainCheckpointPtr parent = NULL;
17660 virCheckFlags(0, NULL);
17662 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17663 return NULL;
17665 if (virDomainCheckpointGetParentEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17666 goto cleanup;
17668 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17669 goto cleanup;
17671 if (!chk->def->parent) {
17672 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
17673 _("checkpoint '%s' does not have a parent"),
17674 chk->def->name);
17675 goto cleanup;
17678 parent = virGetDomainCheckpoint(checkpoint->domain, chk->def->parent);
17680 cleanup:
17681 virDomainObjEndAPI(&vm);
17682 return parent;
17686 static virDomainCheckpointPtr
17687 qemuDomainCheckpointCurrent(virDomainPtr domain,
17688 unsigned int flags)
17690 virDomainObjPtr vm;
17691 virDomainCheckpointPtr checkpoint = NULL;
17693 virCheckFlags(0, NULL);
17695 if (!(vm = qemuDomObjFromDomain(domain)))
17696 return NULL;
17698 if (virDomainCheckpointCurrentEnsureACL(domain->conn, vm->def) < 0)
17699 goto cleanup;
17701 if (!vm->current_checkpoint) {
17702 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT, "%s",
17703 _("the domain does not have a current checkpoint"));
17704 goto cleanup;
17707 checkpoint = virGetDomainCheckpoint(domain, vm->current_checkpoint->def->name);
17709 cleanup:
17710 virDomainObjEndAPI(&vm);
17711 return checkpoint;
17715 static char *
17716 qemuDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
17717 unsigned int flags)
17719 virQEMUDriverPtr driver = checkpoint->domain->conn->privateData;
17720 virDomainObjPtr vm = NULL;
17721 char *xml = NULL;
17722 virDomainCheckpointObjPtr chk = NULL;
17723 qemuDomainObjPrivatePtr priv;
17724 int rc;
17725 size_t i;
17727 virCheckFlags(VIR_DOMAIN_CHECKPOINT_XML_SECURE |
17728 VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN |
17729 VIR_DOMAIN_CHECKPOINT_XML_SIZE, NULL);
17731 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17732 return NULL;
17734 if (virDomainCheckpointGetXMLDescEnsureACL(checkpoint->domain->conn, vm->def, flags) < 0)
17735 goto cleanup;
17737 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17738 goto cleanup;
17740 if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE) {
17741 /* TODO: for non-current checkpoint, this requires a QMP sequence per
17742 disk, since the stat of one bitmap in isolation is too low,
17743 and merely adding bitmap sizes may be too high:
17744 block-dirty-bitmap-create tmp
17745 for each bitmap from checkpoint to current:
17746 add bitmap to src_list
17747 block-dirty-bitmap-merge dst=tmp src_list
17748 query-block and read tmp size
17749 block-dirty-bitmap-remove tmp
17750 So for now, go with simpler query-blocks only for current.
17752 if (!vm->current_checkpoint ||
17753 STRNEQ(checkpoint->name, vm->current_checkpoint->def->name)) {
17754 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
17755 _("cannot compute size for non-current checkpoint '%s'"),
17756 checkpoint->name);
17757 goto cleanup;
17760 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
17761 goto cleanup;
17763 if (virDomainObjCheckActive(vm) < 0)
17764 goto endjob;
17766 if (qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
17767 goto endjob;
17769 /* TODO: Shouldn't need to recompute node names. */
17770 for (i = 0; i < chk->def->ndisks; i++) {
17771 virDomainCheckpointDiskDef *disk = &chk->def->disks[i];
17773 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17774 continue;
17775 VIR_FREE(chk->def->dom->disks[disk->idx]->src->nodeformat);
17776 if (VIR_STRDUP(chk->def->dom->disks[disk->idx]->src->nodeformat,
17777 qemuBlockNodeLookup(vm, disk->name)) < 0)
17778 goto endjob;
17781 priv = vm->privateData;
17782 qemuDomainObjEnterMonitor(driver, vm);
17783 rc = qemuMonitorUpdateCheckpointSize(priv->mon, chk->def);
17784 if (qemuDomainObjExitMonitor(driver, vm) < 0)
17785 goto endjob;
17786 if (rc < 0)
17787 goto endjob;
17790 xml = virDomainCheckpointDefFormat(chk->def, driver->caps, driver->xmlopt,
17791 flags);
17793 endjob:
17794 if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE)
17795 qemuDomainObjEndJob(driver, vm);
17797 cleanup:
17798 virDomainObjEndAPI(&vm);
17799 return xml;
17803 static int
17804 qemuDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint,
17805 unsigned int flags)
17807 virDomainObjPtr vm = NULL;
17808 int ret = -1;
17809 virDomainCheckpointObjPtr chk = NULL;
17811 virCheckFlags(0, -1);
17813 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17814 return -1;
17816 if (virDomainCheckpointIsCurrentEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17817 goto cleanup;
17819 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17820 goto cleanup;
17822 ret = (vm->current_checkpoint &&
17823 STREQ(checkpoint->name, vm->current_checkpoint->def->name));
17825 cleanup:
17826 virDomainObjEndAPI(&vm);
17827 return ret;
17831 static int
17832 qemuDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint,
17833 unsigned int flags)
17835 virDomainObjPtr vm = NULL;
17836 int ret = -1;
17837 virDomainCheckpointObjPtr chk = NULL;
17839 virCheckFlags(0, -1);
17841 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17842 return -1;
17844 if (virDomainCheckpointHasMetadataEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17845 goto cleanup;
17847 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17848 goto cleanup;
17850 /* XXX Someday, we should recognize internal bitmaps in qcow2
17851 * images that are not tied to a libvirt checkpoint; if we ever do
17852 * that, then we would have a reason to return 0 here. */
17853 ret = 1;
17855 cleanup:
17856 virDomainObjEndAPI(&vm);
17857 return ret;
17861 typedef struct _virQEMUCheckReparent virQEMUCheckReparent;
17862 typedef virQEMUCheckReparent *virQEMUCheckReparentPtr;
17863 struct _virQEMUCheckReparent {
17864 virQEMUDriverConfigPtr cfg;
17865 virDomainCheckpointObjPtr parent;
17866 virDomainObjPtr vm;
17867 virCapsPtr caps;
17868 virDomainXMLOptionPtr xmlopt;
17869 int err;
17870 virDomainCheckpointObjPtr last;
17874 static int
17875 qemuDomainCheckpointReparentChildren(void *payload,
17876 const void *name ATTRIBUTE_UNUSED,
17877 void *data)
17879 virDomainCheckpointObjPtr chk = payload;
17880 virQEMUCheckReparentPtr rep = data;
17882 if (rep->err < 0)
17883 return 0;
17885 VIR_FREE(chk->def->parent);
17886 chk->parent = rep->parent;
17888 if (rep->parent->def &&
17889 VIR_STRDUP(chk->def->parent, rep->parent->def->name) < 0) {
17890 rep->err = -1;
17891 return 0;
17894 if (!chk->sibling)
17895 rep->last = chk;
17897 rep->err = qemuDomainCheckpointWriteMetadata(rep->vm, chk,
17898 rep->caps, rep->xmlopt,
17899 rep->cfg->checkpointDir);
17900 return 0;
17904 static int
17905 qemuDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
17906 unsigned int flags)
17908 virQEMUDriverPtr driver = checkpoint->domain->conn->privateData;
17909 virDomainObjPtr vm = NULL;
17910 qemuDomainObjPrivatePtr priv;
17911 int ret = -1;
17912 virDomainCheckpointObjPtr chk = NULL;
17913 virQEMUDependentRemove rem;
17914 virQEMUCheckReparent rep;
17915 bool metadata_only = !!(flags & VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY);
17916 virQEMUDriverConfigPtr cfg = NULL;
17918 virCheckFlags(VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
17919 VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY |
17920 VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY, -1);
17922 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17923 return -1;
17925 cfg = virQEMUDriverGetConfig(driver);
17927 if (virDomainCheckpointDeleteEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17928 goto cleanup;
17930 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17931 goto cleanup;
17933 priv = vm->privateData;
17934 if (!metadata_only) {
17935 /* Until qemu-img supports offline bitmap deletion, we are stuck
17936 * with requiring a running guest */
17937 if (!virDomainObjIsActive(vm)) {
17938 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17939 _("cannot delete checkpoint for inactive domain"));
17940 goto endjob;
17942 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17943 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17944 _("qemu binary lacks persistent bitmaps support"));
17945 goto endjob;
17949 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17950 goto endjob;
17952 if (flags & (VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
17953 VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY)) {
17954 rem.driver = driver;
17955 rem.vm = vm;
17956 rem.metadata_only = metadata_only;
17957 rem.err = 0;
17958 rem.current = false;
17959 virDomainCheckpointForEachDescendant(chk,
17960 qemuDomainCheckpointDiscardAll,
17961 &rem);
17962 if (rem.err < 0)
17963 goto endjob;
17964 if (rem.current) {
17965 if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
17966 chk->def->current = true;
17967 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
17968 driver->xmlopt,
17969 cfg->checkpointDir) < 0) {
17970 virReportError(VIR_ERR_INTERNAL_ERROR,
17971 _("failed to set checkpoint '%s' as current"),
17972 chk->def->name);
17973 chk->def->current = false;
17974 goto endjob;
17977 vm->current_checkpoint = chk;
17979 } else if (chk->nchildren) {
17980 rep.cfg = cfg;
17981 rep.parent = chk->parent;
17982 rep.vm = vm;
17983 rep.err = 0;
17984 rep.last = NULL;
17985 rep.caps = driver->caps;
17986 rep.xmlopt = driver->xmlopt;
17987 virDomainCheckpointForEachChild(chk,
17988 qemuDomainCheckpointReparentChildren,
17989 &rep);
17990 if (rep.err < 0)
17991 goto endjob;
17992 /* Can't modify siblings during ForEachChild, so do it now. */
17993 chk->parent->nchildren += chk->nchildren;
17994 rep.last->sibling = chk->parent->first_child;
17995 chk->parent->first_child = chk->first_child;
17998 if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
17999 chk->nchildren = 0;
18000 chk->first_child = NULL;
18001 ret = 0;
18002 } else {
18003 ret = qemuDomainCheckpointDiscard(driver, vm, chk, true, metadata_only);
18006 endjob:
18007 qemuDomainObjEndJob(driver, vm);
18009 cleanup:
18010 virDomainObjEndAPI(&vm);
18011 virObjectUnref(cfg);
18012 return ret;
18015 static int
18016 qemuDomainBackupPrepare(virQEMUDriverPtr driver, virDomainObjPtr vm,
18017 virDomainBackupDefPtr def,
18018 virDomainCheckpointObjPtr chk)
18020 int ret = -1;
18021 size_t i;
18023 if (chk && def->ndisks != chk->def->ndisks) {
18024 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
18025 _("inconsistency between backup and checkpoint disks"));
18026 goto cleanup;
18028 if (qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
18029 goto cleanup;
18030 for (i = 0; i < def->ndisks; i++) {
18031 virDomainBackupDiskDef *disk = &def->disks[i];
18032 virStorageSourcePtr src = vm->def->disks[disk->idx]->src;
18034 /* For now, insist that atomic checkpoint affect same disks as
18035 * those being backed up. */
18036 if (!disk->store) {
18037 if (chk &&
18038 chk->def->disks[i].type != VIR_DOMAIN_CHECKPOINT_TYPE_NONE) {
18039 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
18040 _("disk %s requested checkpoint without backup"),
18041 disk->name);
18042 goto cleanup;
18044 continue;
18046 if (chk &&
18047 chk->def->disks[i].type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP) {
18048 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
18049 _("disk %s requested backup without checkpoint"),
18050 disk->name);
18051 goto cleanup;
18053 if (virAsprintf(&disk->store->nodeformat, "tmp-%s", disk->name) < 0)
18054 goto cleanup;
18055 if (!disk->store->format)
18056 disk->store->format = VIR_STORAGE_FILE_QCOW2;
18057 if (def->incremental) {
18058 if (src->format != VIR_STORAGE_FILE_QCOW2) {
18059 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
18060 _("incremental backup of %s requires qcow2"),
18061 disk->name);
18062 goto cleanup;
18066 ret = 0;
18067 cleanup:
18068 return ret;
18071 /* Called while monitor lock is held. Best-effort cleanup. */
18072 static int
18073 qemuDomainBackupDiskCleanup(virQEMUDriverPtr driver, virDomainObjPtr vm,
18074 virDomainBackupDiskDef *disk, bool push,
18075 bool incremental, bool completed)
18077 qemuDomainObjPrivatePtr priv = vm->privateData;
18078 const char *node = vm->def->disks[disk->idx]->src->nodeformat;
18079 int ret = 0;
18081 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_EXPORT) {
18082 /* No real need to use nbd-server-remove, since we will
18083 * shortly be calling nbd-server-stop. */
18085 if (incremental && disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_BITMAP &&
18086 qemuMonitorDeleteBitmap(priv->mon, node, disk->name) < 0) {
18087 VIR_WARN("Unable to remove temp bitmap for disk %s after backup",
18088 disk->name);
18089 ret = -1;
18091 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_READY &&
18092 qemuMonitorBlockdevDel(priv->mon, disk->store->nodeformat) < 0) {
18093 VIR_WARN("Unable to remove %s disk %s after backup",
18094 push ? "target" : "scratch", disk->name);
18095 ret = -1;
18097 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_LABEL)
18098 qemuDomainDiskChainElementRevoke(driver, vm, disk->store);
18099 if ((!push || !completed) &&
18100 disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_CREATED &&
18101 disk->store->detected && unlink(disk->store->path) < 0) {
18102 VIR_WARN("Unable to unlink %s disk %s after backup",
18103 push ? "failed target" : "scratch", disk->store->path);
18104 ret = -1;
18106 return ret;
18109 static int
18110 qemuDomainBackupBegin(virDomainPtr domain, const char *diskXml,
18111 const char *checkpointXml, unsigned int flags)
18113 virQEMUDriverPtr driver = domain->conn->privateData;
18114 virDomainObjPtr vm = NULL;
18115 virDomainBackupDefPtr def = NULL;
18116 virQEMUDriverConfigPtr cfg = NULL;
18117 virCapsPtr caps = NULL;
18118 qemuDomainObjPrivatePtr priv;
18119 int ret = -1;
18120 virJSONValuePtr json = NULL;
18121 bool job_started = false;
18122 bool nbd_running = false;
18123 bool push;
18124 const char *mode;
18125 size_t i;
18126 struct timeval tv;
18127 char *suffix = NULL;
18128 virCommandPtr cmd = NULL;
18129 const char *qemuImgPath;
18130 virDomainCheckpointDefPtr chkdef = NULL;
18131 virDomainCheckpointObjPtr chk = NULL;
18132 virDomainCheckpointObjPtr other = NULL;
18133 virDomainCheckpointObjPtr parent = NULL;
18134 virJSONValuePtr arr = NULL;
18136 virCheckFlags(VIR_DOMAIN_BACKUP_BEGIN_NO_METADATA, -1);
18137 /* TODO: VIR_DOMAIN_BACKUP_BEGIN_QUIESCE */
18139 if (!(vm = qemuDomObjFromDomain(domain)))
18140 goto cleanup;
18142 priv = vm->privateData;
18143 cfg = virQEMUDriverGetConfig(driver);
18145 if (virDomainBackupBeginEnsureACL(domain->conn, vm->def) < 0)
18146 goto cleanup;
18148 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
18149 goto cleanup;
18151 if (qemuProcessAutoDestroyActive(driver, vm)) {
18152 virReportError(VIR_ERR_OPERATION_INVALID,
18153 "%s", _("domain is marked for auto destroy"));
18154 goto cleanup;
18157 if (!virDomainObjIsActive(vm)) {
18158 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
18159 _("cannot perform disk backup for inactive domain"));
18160 goto cleanup;
18162 if (!(def = virDomainBackupDefParseString(diskXml, driver->xmlopt, 0)))
18163 goto cleanup;
18165 if (checkpointXml) {
18166 if (!(chkdef = qemuDomainCheckpointDefParseString(driver, caps,
18167 checkpointXml, 0)) ||
18168 VIR_STRDUP(suffix, chkdef->name) < 0)
18169 goto cleanup;
18170 } else {
18171 gettimeofday(&tv, NULL);
18172 if (virAsprintf(&suffix, "%lld", (long long)tv.tv_sec) < 0)
18173 goto cleanup;
18176 push = def->type == VIR_DOMAIN_BACKUP_TYPE_PUSH;
18177 if (!push) {
18178 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_BITMAP)) {
18179 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
18180 _("qemu binary lacks pull-mode backup support"));
18181 goto cleanup;
18183 if (!def->server ||
18184 def->server->transport != VIR_STORAGE_NET_HOST_TRANS_TCP) {
18185 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
18186 _("<domainbackup> must specify TCP server for now"));
18187 goto cleanup;
18190 if (def->incremental) {
18191 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
18192 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
18193 _("qemu binary lacks persistent bitmaps support"));
18194 goto cleanup;
18196 for (other = vm->current_checkpoint; other;
18197 other = other->def->parent ?
18198 virDomainCheckpointFindByName(vm->checkpoints,
18199 other->def->parent) : NULL)
18200 if (STREQ(other->def->name, def->incremental))
18201 break;
18202 if (!other) {
18203 virReportError(VIR_ERR_OPERATION_INVALID,
18204 _("could not locate checkpoint '%s' for incremental backup"),
18205 def->incremental);
18206 goto cleanup;
18210 if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
18211 goto cleanup;
18213 /* We are going to modify the domain below. */
18214 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18215 goto cleanup;
18217 if (priv->backup) {
18218 virReportError(VIR_ERR_OPERATION_INVALID,
18219 "%s", _("another backup job is already running"));
18220 goto endjob;
18223 if (chkdef) {
18224 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
18225 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
18226 _("qemu binary lacks persistent bitmaps support"));
18227 goto endjob;
18230 if (qemuDomainCheckpointPrepare(driver, caps, vm, chkdef) < 0)
18231 goto endjob;
18232 if (!(chk = virDomainCheckpointAssignDef(vm->checkpoints, chkdef)))
18233 goto endjob;
18234 chkdef = NULL;
18235 chk->def->current = true;
18236 if (vm->current_checkpoint) {
18237 parent = vm->current_checkpoint;
18238 if (VIR_STRDUP(chk->def->parent, parent->def->name) < 0)
18239 goto endjob;
18240 if (qemuDomainCheckpointWriteMetadata(vm, parent, driver->caps,
18241 driver->xmlopt,
18242 cfg->checkpointDir) < 0)
18243 goto endjob;
18244 vm->current_checkpoint = NULL;
18248 if (virDomainBackupAlignDisks(def, vm->def, suffix) < 0 ||
18249 qemuDomainBackupPrepare(driver, vm, def, chk) < 0)
18250 goto endjob;
18252 /* actually start the checkpoint. 2x2 array of push/pull, full/incr,
18253 plus additional tweak if checkpoint requested */
18254 qemuDomainObjEnterMonitor(driver, vm);
18255 /* - push/pull: blockdev-add per <disk>
18256 - incr: bitmap-add of tmp, bitmap-merge per <disk> */
18257 for (i = 0; i < def->ndisks; i++) {
18258 virDomainBackupDiskDef *disk = &def->disks[i];
18259 virJSONValuePtr file;
18260 virStorageSourcePtr src = vm->def->disks[disk->idx]->src;
18261 const char *node = src->nodeformat;
18263 if (!disk->store)
18264 continue;
18265 if (qemuDomainStorageFileInit(driver, vm, disk->store, src) < 0)
18266 goto endmon;
18267 if (disk->store->detected) {
18268 if (virStorageFileCreate(disk->store) < 0) {
18269 virReportSystemError(errno,
18270 _("failed to create image file '%s'"),
18271 NULLSTR(disk->store->path));
18272 goto endmon;
18274 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_CREATED;
18276 if (qemuDomainDiskChainElementPrepare(driver, vm, disk->store, false,
18277 true) < 0)
18278 goto endmon;
18279 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_LABEL;
18280 if (disk->store->detected) {
18281 virBuffer buf = VIR_BUFFER_INITIALIZER;
18283 /* Force initialization of scratch/target file to new qcow2 */
18284 if (!(cmd = virCommandNewArgList(qemuImgPath,
18285 "create",
18286 "-f",
18287 virStorageFileFormatTypeToString(disk->store->format),
18288 "-o",
18289 NULL)))
18290 goto endmon;
18291 virBufferAsprintf(&buf, "backing_fmt=%s,backing_file=",
18292 virStorageFileFormatTypeToString(src->format));
18293 virQEMUBuildBufferEscapeComma(&buf, src->path);
18294 virCommandAddArgBuffer(cmd, &buf);
18296 virQEMUBuildBufferEscapeComma(&buf, disk->store->path);
18297 virCommandAddArgBuffer(cmd, &buf);
18298 if (virCommandRun(cmd, NULL) < 0)
18299 goto endmon;
18300 virCommandFree(cmd);
18301 cmd = NULL;
18304 /* FIXME: allow non-local files for push destinations */
18305 if (virJSONValueObjectCreate(&file,
18306 "s:driver", "file",
18307 "s:filename", disk->store->path,
18308 NULL) < 0)
18309 goto endmon;
18310 if (virJSONValueObjectCreate(&json,
18311 "s:driver", virStorageFileFormatTypeToString(disk->store->format),
18312 "s:node-name", disk->store->nodeformat,
18313 "a:file", &file,
18314 "s:backing", node, NULL) < 0) {
18315 virJSONValueFree(file);
18316 goto endmon;
18318 if (qemuMonitorBlockdevAdd(priv->mon, json) < 0)
18319 goto endmon;
18320 json = NULL;
18321 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_READY;
18323 if (def->incremental) {
18324 if (!(arr = virJSONValueNewArray()))
18325 goto endmon;
18326 if (qemuMonitorAddBitmap(priv->mon, node, disk->name, false) < 0) {
18327 virJSONValueFree(arr);
18328 goto endmon;
18330 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_BITMAP;
18331 for (other = parent ? parent : vm->current_checkpoint; other;
18332 other = other->def->parent ?
18333 virDomainCheckpointFindByName(vm->checkpoints,
18334 other->def->parent) : NULL) {
18335 if (virJSONValueArrayAppendString(arr, other->def->name) < 0) {
18336 virJSONValueFree(arr);
18337 goto endmon;
18339 if (STREQ(other->def->name, def->incremental))
18340 break;
18342 if (qemuMonitorMergeBitmaps(priv->mon, node, disk->name, &arr) < 0)
18343 goto endmon;
18347 /* - transaction, containing:
18348 - push+full: blockdev-backup sync:full
18349 - push+incr: blockdev-backup sync:incremental bitmap:tmp
18350 - pull+full: blockdev-backup sync:none
18351 - pull+incr: blockdev-backup sync:none, bitmap-disable of tmp
18352 - if checkpoint: bitmap-disable of old, bitmap-add of new
18354 if (!(json = virJSONValueNewArray()))
18355 goto endmon;
18356 if (push)
18357 mode = def->incremental ? "incremental" : "full";
18358 else
18359 mode = "none";
18360 for (i = 0; i < def->ndisks; i++) {
18361 virDomainBackupDiskDef *disk = &def->disks[i];
18362 const char *node;
18363 const char *push_bitmap = NULL;
18365 if (!disk->store)
18366 continue;
18367 node = qemuBlockNodeLookup(vm, disk->name);
18368 if (push && def->incremental)
18369 push_bitmap = disk->name;
18370 if (qemuMonitorJSONTransactionAdd(json,
18371 "blockdev-backup",
18372 "s:device", node,
18373 "s:target", disk->store->nodeformat,
18374 "s:sync", mode,
18375 "S:bitmap", push_bitmap,
18376 "s:job-id", disk->name,
18377 NULL) < 0)
18378 goto endmon;
18379 if (def->incremental && !push &&
18380 qemuMonitorJSONTransactionAdd(json,
18381 "block-dirty-bitmap-disable",
18382 "s:node", node,
18383 "s:name", disk->name,
18384 NULL) < 0)
18385 goto endmon;
18387 if (chk && qemuDomainCheckpointAddActions(vm, json, parent, chk->def) < 0)
18388 goto endmon;
18389 if (qemuMonitorTransaction(priv->mon, &json) < 0)
18390 goto endmon;
18391 job_started = true;
18392 if (chk) {
18393 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
18394 driver->xmlopt,
18395 cfg->checkpointDir) < 0) {
18396 virReportError(VIR_ERR_INTERNAL_ERROR,
18397 _("unable to save metadata for checkpoint %s"),
18398 chk->def->name);
18399 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
18400 goto endmon;
18402 vm->current_checkpoint = chk;
18403 other = virDomainCheckpointFindByName(vm->checkpoints,
18404 chk->def->parent);
18405 chk->parent = other;
18406 other->nchildren++;
18407 chk->sibling = other->first_child;
18408 other->first_child = chk;
18412 - pull: nbd-server-start with <server> from user (or autogenerate server)
18413 - pull: nbd-server-add per <disk>, including bitmap for incr
18415 if (!push) {
18416 if (qemuMonitorNBDServerStart(priv->mon, def->server->name,
18417 def->server->port, NULL) < 0)
18418 goto endmon;
18419 nbd_running = true;
18420 for (i = 0; i < def->ndisks; i++) {
18421 virDomainBackupDiskDef *disk = &def->disks[i];
18423 if (!disk->store)
18424 continue;
18425 if (qemuMonitorNBDServerAdd(priv->mon, disk->store->nodeformat,
18426 disk->name, false,
18427 def->incremental ? disk->name :
18428 NULL) < 0)
18429 goto endmon;
18430 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_EXPORT;
18434 ret = 0;
18435 endmon:
18436 /* Best effort cleanup if we fail partway through */
18437 if (ret < 0) {
18438 virErrorPtr save_err = virSaveLastError();
18440 if (nbd_running &&
18441 qemuMonitorNBDServerStop(priv->mon) < 0)
18442 VIR_WARN("Unable to stop NBD server on vm %s after backup job",
18443 vm->def->name);
18444 for (i = 0; i < def->ndisks; i++) {
18445 virDomainBackupDiskDef *disk = &def->disks[i];
18447 if (!disk->store)
18448 continue;
18449 if (job_started &&
18450 qemuMonitorBlockJobCancel(priv->mon, disk->name) < 0)
18451 VIR_WARN("Unable to stop backup job %s on vm %s after failure",
18452 disk->name, vm->def->name);
18453 qemuDomainBackupDiskCleanup(driver, vm, disk, push,
18454 !!def->incremental, false);
18456 virSetError(save_err);
18457 virFreeError(save_err);
18459 if (qemuDomainObjExitMonitor(driver, vm) < 0)
18460 ret = -1;
18461 if (ret < 0)
18462 goto endjob;
18464 VIR_STEAL_PTR(priv->backup, def);
18465 ret = priv->backup->id = 1; /* Hard-coded job id for now */
18466 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm,
18467 driver->caps) < 0)
18468 VIR_WARN("Unable to save status on vm %s after backup job",
18469 vm->def->name);
18471 endjob:
18472 qemuDomainObjEndJob(driver, vm);
18474 cleanup:
18475 virJSONValueFree(arr);
18476 virDomainCheckpointDefFree(chkdef);
18477 virCommandFree(cmd);
18478 VIR_FREE(suffix);
18479 virJSONValueFree(json);
18480 virDomainObjEndAPI(&vm);
18481 virDomainBackupDefFree(def);
18482 virObjectUnref(caps);
18483 virObjectUnref(cfg);
18484 return ret;
18487 static char *qemuDomainBackupGetXMLDesc(virDomainPtr domain, int id,
18488 unsigned int flags)
18490 virDomainObjPtr vm = NULL;
18491 char *xml = NULL;
18492 qemuDomainObjPrivatePtr priv;
18493 virBuffer buf = VIR_BUFFER_INITIALIZER;
18495 virCheckFlags(0, NULL);
18497 if (!(vm = qemuDomObjFromDomain(domain)))
18498 return NULL;
18500 if (virDomainBackupGetXMLDescEnsureACL(domain->conn, vm->def) < 0)
18501 goto cleanup;
18503 /* TODO: Allow more than one hard-coded job id */
18504 priv = vm->privateData;
18505 if (id != 1 || !priv->backup) {
18506 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
18507 _("no domain backup job with id '%d'"), id);
18508 goto cleanup;
18511 if (virDomainBackupDefFormat(&buf, priv->backup, false) < 0)
18512 goto cleanup;
18513 xml = virBufferContentAndReset(&buf);
18515 cleanup:
18516 virDomainObjEndAPI(&vm);
18517 return xml;
18520 static int qemuDomainBackupEnd(virDomainPtr domain, int id, unsigned int flags)
18522 virQEMUDriverPtr driver = domain->conn->privateData;
18523 virQEMUDriverConfigPtr cfg = NULL;
18524 virDomainObjPtr vm = NULL;
18525 int ret = -1;
18526 virDomainBackupDefPtr backup = NULL;
18527 qemuDomainObjPrivatePtr priv;
18528 bool want_abort = flags & VIR_DOMAIN_BACKUP_END_ABORT;
18529 virDomainBackupDefPtr def;
18530 size_t i;
18531 bool push = true;
18532 bool completed = true;
18534 virCheckFlags(VIR_DOMAIN_BACKUP_END_ABORT, -1);
18536 if (!(vm = qemuDomObjFromDomain(domain)))
18537 return -1;
18539 cfg = virQEMUDriverGetConfig(driver);
18540 if (virDomainBackupEndEnsureACL(domain->conn, vm->def) < 0)
18541 goto cleanup;
18543 /* TODO: Allow more than one hard-coded job id */
18544 priv = vm->privateData;
18545 if (id != 1 || !priv->backup) {
18546 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
18547 _("no domain backup job with id '%d'"), id);
18548 goto cleanup;
18551 def = priv->backup;
18552 if (def->type != VIR_DOMAIN_BACKUP_TYPE_PUSH) {
18553 want_abort = false;
18554 push = false;
18557 /* We are going to modify the domain below. */
18558 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18559 goto cleanup;
18561 qemuDomainObjEnterMonitor(driver, vm);
18562 if (push) {
18563 for (i = 0; i < def->ndisks; i++) {
18564 virDomainBackupDiskDef *disk = &def->disks[i];
18566 if (!disk->store)
18567 continue;
18568 if (disk->state != VIR_DOMAIN_BACKUP_DISK_STATE_COMPLETE)
18569 completed = false;
18571 } else {
18572 ret = qemuMonitorNBDServerStop(priv->mon);
18574 if (!completed && !want_abort) {
18575 virReportError(VIR_ERR_OPERATION_INVALID,
18576 _("backup job id '%d' not complete yet"), id);
18577 } else {
18578 for (i = 0; i < def->ndisks; i++) {
18579 virDomainBackupDiskDef *disk = &def->disks[i];
18581 if (!disk->store)
18582 continue;
18583 if (!push || disk->state < VIR_DOMAIN_BACKUP_DISK_STATE_COMPLETE) {
18584 if (qemuMonitorBlockJobCancel(priv->mon,
18585 disk->name) < 0 &&
18586 !want_abort) {
18587 ret = -1;
18588 continue;
18591 if (qemuDomainBackupDiskCleanup(driver, vm, disk, push,
18592 !!def->incremental, completed) < 0)
18593 ret = -1;
18596 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
18597 ret = -1;
18598 goto endjob;
18601 VIR_STEAL_PTR(backup, priv->backup);
18602 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm,
18603 driver->caps) < 0)
18604 VIR_WARN("Unable to save status on vm %s after backup job",
18605 vm->def->name);
18607 ret = want_abort ? 0 : 1;
18609 endjob:
18610 qemuDomainObjEndJob(driver, vm);
18612 cleanup:
18613 virDomainBackupDefFree(backup);
18614 virDomainObjEndAPI(&vm);
18615 return ret;
18618 static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
18619 char **result, unsigned int flags)
18621 virQEMUDriverPtr driver = domain->conn->privateData;
18622 virDomainObjPtr vm = NULL;
18623 int ret = -1;
18624 qemuDomainObjPrivatePtr priv;
18625 bool hmp;
18627 virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
18629 if (!(vm = qemuDomObjFromDomain(domain)))
18630 goto cleanup;
18632 if (virDomainQemuMonitorCommandEnsureACL(domain->conn, vm->def) < 0)
18633 goto cleanup;
18635 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
18636 goto cleanup;
18638 if (virDomainObjCheckActive(vm) < 0)
18639 goto endjob;
18641 priv = vm->privateData;
18643 qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, NULL);
18645 hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
18647 qemuDomainObjEnterMonitor(driver, vm);
18648 ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
18649 if (qemuDomainObjExitMonitor(driver, vm) < 0)
18650 ret = -1;
18652 endjob:
18653 qemuDomainObjEndJob(driver, vm);
18655 cleanup:
18656 virDomainObjEndAPI(&vm);
18657 return ret;
18661 static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn,
18662 unsigned int pid_value,
18663 unsigned int flags)
18665 virQEMUDriverPtr driver = conn->privateData;
18666 virDomainObjPtr vm = NULL;
18667 virDomainDefPtr def = NULL;
18668 virDomainPtr dom = NULL;
18669 virDomainChrSourceDefPtr monConfig = NULL;
18670 bool monJSON = false;
18671 pid_t pid = pid_value;
18672 char *pidfile = NULL;
18673 virQEMUCapsPtr qemuCaps = NULL;
18674 virCapsPtr caps = NULL;
18676 virCheckFlags(0, NULL);
18678 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
18679 goto cleanup;
18681 if (!(def = qemuParseCommandLinePid(driver->qemuCapsCache,
18682 caps, driver->xmlopt, pid,
18683 &pidfile, &monConfig, &monJSON)))
18684 goto cleanup;
18686 if (virDomainQemuAttachEnsureACL(conn, def) < 0)
18687 goto cleanup;
18689 if (!monConfig) {
18690 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18691 _("No monitor connection for pid %u"), pid_value);
18692 goto cleanup;
18694 if (monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
18695 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18696 _("Cannot connect to monitor connection of type '%s' "
18697 "for pid %u"),
18698 virDomainChrTypeToString(monConfig->type),
18699 pid_value);
18700 goto cleanup;
18703 if (!(def->name) &&
18704 virAsprintf(&def->name, "attach-pid-%u", pid_value) < 0)
18705 goto cleanup;
18707 if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
18708 def->emulator)))
18709 goto cleanup;
18711 if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
18712 goto cleanup;
18714 if (!(vm = virDomainObjListAdd(driver->domains, def,
18715 driver->xmlopt,
18716 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
18717 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
18718 NULL)))
18719 goto cleanup;
18721 def = NULL;
18723 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
18724 qemuDomainRemoveInactive(driver, vm);
18725 goto cleanup;
18728 if (qemuProcessAttach(conn, driver, vm, pid,
18729 pidfile, monConfig, monJSON) < 0) {
18730 monConfig = NULL;
18731 qemuDomainRemoveInactive(driver, vm);
18732 qemuDomainObjEndJob(driver, vm);
18733 goto cleanup;
18736 monConfig = NULL;
18738 if (qemuProcessAttach(conn, driver, vm, pid,
18739 pidfile, monConfig, monJSON) < 0) {
18740 qemuDomainRemoveInactive(driver, vm);
18741 qemuDomainObjEndJob(driver, vm);
18742 goto cleanup;
18745 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
18747 qemuDomainObjEndJob(driver, vm);
18749 cleanup:
18750 virDomainDefFree(def);
18751 virObjectUnref(monConfig);
18752 virDomainObjEndAPI(&vm);
18753 VIR_FREE(pidfile);
18754 virObjectUnref(caps);
18755 virObjectUnref(qemuCaps);
18756 return dom;
18760 static int
18761 qemuDomainOpenConsole(virDomainPtr dom,
18762 const char *dev_name,
18763 virStreamPtr st,
18764 unsigned int flags)
18766 virDomainObjPtr vm = NULL;
18767 int ret = -1;
18768 size_t i;
18769 virDomainChrDefPtr chr = NULL;
18770 qemuDomainObjPrivatePtr priv;
18772 virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
18773 VIR_DOMAIN_CONSOLE_FORCE, -1);
18775 if (!(vm = qemuDomObjFromDomain(dom)))
18776 goto cleanup;
18778 if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
18779 goto cleanup;
18781 if (virDomainObjCheckActive(vm) < 0)
18782 goto cleanup;
18784 priv = vm->privateData;
18786 if (dev_name) {
18787 for (i = 0; !chr && i < vm->def->nconsoles; i++) {
18788 if (vm->def->consoles[i]->info.alias &&
18789 STREQ(dev_name, vm->def->consoles[i]->info.alias))
18790 chr = vm->def->consoles[i];
18792 for (i = 0; !chr && i < vm->def->nserials; i++) {
18793 if (STREQ(dev_name, vm->def->serials[i]->info.alias))
18794 chr = vm->def->serials[i];
18796 for (i = 0; !chr && i < vm->def->nparallels; i++) {
18797 if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
18798 chr = vm->def->parallels[i];
18800 } else {
18801 if (vm->def->nconsoles)
18802 chr = vm->def->consoles[0];
18803 else if (vm->def->nserials)
18804 chr = vm->def->serials[0];
18807 if (!chr) {
18808 virReportError(VIR_ERR_INTERNAL_ERROR,
18809 _("cannot find character device %s"),
18810 NULLSTR(dev_name));
18811 goto cleanup;
18814 if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
18815 virReportError(VIR_ERR_INTERNAL_ERROR,
18816 _("character device %s is not using a PTY"),
18817 dev_name ? dev_name : NULLSTR(chr->info.alias));
18818 goto cleanup;
18821 /* handle mutually exclusive access to console devices */
18822 ret = virChrdevOpen(priv->devs,
18823 chr->source,
18825 (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
18827 if (ret == 1) {
18828 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
18829 _("Active console session exists for this domain"));
18830 ret = -1;
18833 cleanup:
18834 virDomainObjEndAPI(&vm);
18835 return ret;
18838 static int
18839 qemuDomainOpenChannel(virDomainPtr dom,
18840 const char *name,
18841 virStreamPtr st,
18842 unsigned int flags)
18844 virDomainObjPtr vm = NULL;
18845 int ret = -1;
18846 size_t i;
18847 virDomainChrDefPtr chr = NULL;
18848 qemuDomainObjPrivatePtr priv;
18850 virCheckFlags(VIR_DOMAIN_CHANNEL_FORCE, -1);
18852 if (!(vm = qemuDomObjFromDomain(dom)))
18853 goto cleanup;
18855 if (virDomainOpenChannelEnsureACL(dom->conn, vm->def) < 0)
18856 goto cleanup;
18858 if (virDomainObjCheckActive(vm) < 0)
18859 goto cleanup;
18861 priv = vm->privateData;
18863 if (name) {
18864 for (i = 0; !chr && i < vm->def->nchannels; i++) {
18865 if (STREQ(name, vm->def->channels[i]->info.alias))
18866 chr = vm->def->channels[i];
18868 if (vm->def->channels[i]->targetType == \
18869 VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
18870 STREQ_NULLABLE(name, vm->def->channels[i]->target.name))
18871 chr = vm->def->channels[i];
18873 } else {
18874 if (vm->def->nchannels)
18875 chr = vm->def->channels[0];
18878 if (!chr) {
18879 virReportError(VIR_ERR_INTERNAL_ERROR,
18880 _("cannot find channel %s"),
18881 NULLSTR(name));
18882 goto cleanup;
18885 if (chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
18886 virReportError(VIR_ERR_INTERNAL_ERROR,
18887 _("channel %s is not using a UNIX socket"),
18888 name ? name : NULLSTR(chr->info.alias));
18889 goto cleanup;
18892 /* handle mutually exclusive access to channel devices */
18893 ret = virChrdevOpen(priv->devs,
18894 chr->source,
18896 (flags & VIR_DOMAIN_CHANNEL_FORCE) != 0);
18898 if (ret == 1) {
18899 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
18900 _("Active channel stream exists for this domain"));
18901 ret = -1;
18904 cleanup:
18905 virDomainObjEndAPI(&vm);
18906 return ret;
18910 /* Called while holding the VM job lock, to implement a block job
18911 * abort with pivot; this updates the VM definition as appropriate, on
18912 * either success or failure. */
18913 static int
18914 qemuDomainBlockPivot(virQEMUDriverPtr driver,
18915 virDomainObjPtr vm,
18916 qemuBlockJobDataPtr job,
18917 virDomainDiskDefPtr disk)
18919 int ret = -1;
18920 qemuDomainObjPrivatePtr priv = vm->privateData;
18922 if (!disk->mirror) {
18923 virReportError(VIR_ERR_OPERATION_INVALID,
18924 _("pivot of disk '%s' requires an active copy job"),
18925 disk->dst);
18926 goto cleanup;
18929 if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY) {
18930 virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
18931 _("disk '%s' not ready for pivot yet"),
18932 disk->dst);
18933 goto cleanup;
18936 /* Attempt the pivot. Record the attempt now, to prevent duplicate
18937 * attempts; but the actual disk change will be made when emitting
18938 * the event.
18939 * XXX On libvirtd restarts, if we missed the qemu event, we need
18940 * to double check what state qemu is in.
18941 * XXX We should be using qemu's rerror flag to make sure the job
18942 * remains alive until we know its final state.
18943 * XXX If the abort command is synchronous but the qemu event says
18944 * that pivot failed, we need to reflect that failure into the
18945 * overall return value. */
18946 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT;
18947 qemuDomainObjEnterMonitor(driver, vm);
18948 ret = qemuMonitorDrivePivot(priv->mon, job->name);
18949 if (qemuDomainObjExitMonitor(driver, vm) < 0) {
18950 ret = -1;
18951 goto cleanup;
18954 if (ret < 0) {
18955 /* The pivot failed. The block job in QEMU remains in the synchronised
18956 * phase. Reset the state we changed and return the error to the user */
18957 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
18960 cleanup:
18961 return ret;
18965 /* bandwidth in MiB/s per public API. Caller must lock vm beforehand,
18966 * and not access it afterwards. */
18967 static int
18968 qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
18969 virDomainObjPtr vm,
18970 const char *path,
18971 const char *base,
18972 unsigned long bandwidth,
18973 unsigned int flags)
18975 qemuDomainObjPrivatePtr priv = vm->privateData;
18976 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
18977 char *device = NULL;
18978 virDomainDiskDefPtr disk;
18979 virStorageSourcePtr baseSource = NULL;
18980 unsigned int baseIndex = 0;
18981 char *basePath = NULL;
18982 char *backingPath = NULL;
18983 unsigned long long speed = bandwidth;
18984 qemuBlockJobDataPtr job = NULL;
18985 int ret = -1;
18987 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
18988 virReportError(VIR_ERR_INVALID_ARG, "%s",
18989 _("flag VIR_DOMAIN_BLOCK_REBASE_RELATIVE is valid only "
18990 "with non-null base"));
18991 goto cleanup;
18994 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18995 goto cleanup;
18997 if (virDomainObjCheckActive(vm) < 0)
18998 goto endjob;
19000 if (qemuDomainSupportsBlockJobs(vm) < 0)
19001 goto endjob;
19003 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19004 goto endjob;
19006 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19007 goto endjob;
19009 if (qemuDomainDiskBlockJobIsActive(disk))
19010 goto endjob;
19012 if (base &&
19013 (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
19014 !(baseSource = virStorageFileChainLookup(disk->src, disk->src,
19015 base, baseIndex, NULL))))
19016 goto endjob;
19018 if (baseSource) {
19019 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
19020 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
19021 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19022 _("this QEMU binary doesn't support relative "
19023 "block pull/rebase"));
19024 goto endjob;
19027 if (virStorageFileGetRelativeBackingPath(disk->src->backingStore,
19028 baseSource,
19029 &backingPath) < 0)
19030 goto endjob;
19032 if (!backingPath) {
19033 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19034 _("can't keep relative backing relationship"));
19035 goto endjob;
19040 /* Convert bandwidth MiB to bytes, if needed */
19041 if (!(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) {
19042 if (speed > LLONG_MAX >> 20) {
19043 virReportError(VIR_ERR_OVERFLOW,
19044 _("bandwidth must be less than %llu"),
19045 LLONG_MAX >> 20);
19046 goto endjob;
19048 speed <<= 20;
19051 if (!(job = qemuBlockJobDiskNew(disk, QEMU_BLOCKJOB_TYPE_PULL, device)))
19052 goto endjob;
19054 qemuDomainObjEnterMonitor(driver, vm);
19055 if (baseSource)
19056 basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
19057 baseSource);
19058 if (!baseSource || basePath)
19059 ret = qemuMonitorBlockStream(priv->mon, device, basePath, backingPath,
19060 speed);
19061 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19062 ret = -1;
19064 if (ret < 0)
19065 goto endjob;
19067 qemuBlockJobStarted(job);
19069 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
19070 VIR_WARN("Unable to save status on vm %s after state change",
19071 vm->def->name);
19073 endjob:
19074 qemuDomainObjEndJob(driver, vm);
19076 cleanup:
19077 qemuBlockJobStartupFinalize(job);
19078 virObjectUnref(cfg);
19079 VIR_FREE(basePath);
19080 VIR_FREE(backingPath);
19081 VIR_FREE(device);
19082 virDomainObjEndAPI(&vm);
19083 return ret;
19087 static int
19088 qemuDomainBlockJobAbort(virDomainPtr dom,
19089 const char *path,
19090 unsigned int flags)
19092 virQEMUDriverPtr driver = dom->conn->privateData;
19093 virDomainDiskDefPtr disk = NULL;
19094 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
19095 bool pivot = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT);
19096 bool async = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC);
19097 qemuBlockJobDataPtr job = NULL;
19098 virDomainObjPtr vm;
19099 int ret = -1;
19101 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
19102 VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
19104 if (!(vm = qemuDomObjFromDomain(dom)))
19105 return -1;
19107 if (virDomainBlockJobAbortEnsureACL(dom->conn, vm->def) < 0)
19108 goto cleanup;
19110 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19111 goto cleanup;
19113 if (virDomainObjCheckActive(vm) < 0)
19114 goto endjob;
19116 if (qemuDomainSupportsBlockJobs(vm) < 0)
19117 goto endjob;
19119 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19120 goto endjob;
19122 if (!(job = qemuBlockJobDiskGetJob(disk))) {
19123 virReportError(VIR_ERR_INVALID_ARG,
19124 _("disk %s does not have an active block job"), disk->dst);
19125 goto endjob;
19128 if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_NONE &&
19129 disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY) {
19130 virReportError(VIR_ERR_OPERATION_INVALID,
19131 _("another job on disk '%s' is still being ended"),
19132 disk->dst);
19133 goto endjob;
19136 if (!async)
19137 qemuBlockJobSyncBegin(job);
19139 if (pivot) {
19140 if ((ret = qemuDomainBlockPivot(driver, vm, job, disk)) < 0)
19141 goto endjob;
19142 } else {
19143 if (disk->mirror)
19144 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_ABORT;
19146 qemuDomainObjEnterMonitor(driver, vm);
19147 ret = qemuMonitorBlockJobCancel(qemuDomainGetMonitor(vm), job->name);
19148 if (qemuDomainObjExitMonitor(driver, vm) < 0) {
19149 ret = -1;
19150 goto endjob;
19153 if (ret < 0) {
19154 if (disk->mirror)
19155 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
19156 goto endjob;
19160 ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps));
19163 * With the ABORT_ASYNC flag we don't need to do anything, the event will
19164 * come from qemu and will update the XML as appropriate, but without the
19165 * ABORT_ASYNC flag, we must block to guarantee synchronous operation. We
19166 * do the waiting while still holding the VM job, to prevent newly
19167 * scheduled block jobs from confusing us. */
19168 if (!async) {
19169 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
19170 while (qemuBlockJobIsRunning(job)) {
19171 if (virDomainObjWait(vm) < 0) {
19172 ret = -1;
19173 goto endjob;
19175 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
19179 endjob:
19180 if (job && !async)
19181 qemuBlockJobSyncEnd(vm, job, QEMU_ASYNC_JOB_NONE);
19182 qemuDomainObjEndJob(driver, vm);
19184 cleanup:
19185 virObjectUnref(job);
19186 virObjectUnref(cfg);
19187 virDomainObjEndAPI(&vm);
19188 return ret;
19192 static int
19193 qemuBlockJobInfoTranslate(qemuMonitorBlockJobInfoPtr rawInfo,
19194 virDomainBlockJobInfoPtr info,
19195 virDomainDiskDefPtr disk,
19196 bool reportBytes)
19198 info->cur = rawInfo->cur;
19199 info->end = rawInfo->end;
19201 /* Fix job completeness reporting. If cur == end mgmt
19202 * applications think job is completed. Except when both cur
19203 * and end are zero, in which case qemu hasn't started the
19204 * job yet. */
19205 if (!info->cur && !info->end) {
19206 if (rawInfo->ready > 0) {
19207 info->cur = info->end = 1;
19208 } else if (!rawInfo->ready) {
19209 info->end = 1;
19213 /* If qemu reports that it's not ready yet don't make the job go to
19214 * cur == end as some apps wrote code polling this instead of waiting for
19215 * the ready event */
19216 if (rawInfo->ready == 0 &&
19217 info->cur == info->end &&
19218 info->cur > 0)
19219 info->cur -= 1;
19221 info->type = rawInfo->type;
19222 if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT &&
19223 disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT)
19224 info->type = disk->mirrorJob;
19226 if (rawInfo->bandwidth && !reportBytes)
19227 rawInfo->bandwidth = VIR_DIV_UP(rawInfo->bandwidth, 1024 * 1024);
19228 info->bandwidth = rawInfo->bandwidth;
19229 if (info->bandwidth != rawInfo->bandwidth) {
19230 virReportError(VIR_ERR_OVERFLOW,
19231 _("bandwidth %llu cannot be represented in result"),
19232 rawInfo->bandwidth);
19233 return -1;
19236 return 0;
19240 static int
19241 qemuDomainGetBlockJobInfo(virDomainPtr dom,
19242 const char *path,
19243 virDomainBlockJobInfoPtr info,
19244 unsigned int flags)
19246 virQEMUDriverPtr driver = dom->conn->privateData;
19247 virDomainObjPtr vm;
19248 virDomainDiskDefPtr disk;
19249 int ret = -1;
19250 qemuMonitorBlockJobInfo rawInfo;
19252 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
19254 if (!(vm = qemuDomObjFromDomain(dom)))
19255 return -1;
19257 if (virDomainGetBlockJobInfoEnsureACL(dom->conn, vm->def) < 0)
19258 goto cleanup;
19261 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
19262 goto cleanup;
19264 if (virDomainObjCheckActive(vm) < 0)
19265 goto endjob;
19267 if (qemuDomainSupportsBlockJobs(vm) < 0)
19268 goto endjob;
19270 if (!(disk = virDomainDiskByName(vm->def, path, true))) {
19271 virReportError(VIR_ERR_INVALID_ARG,
19272 _("disk %s not found in the domain"), path);
19273 goto endjob;
19276 qemuDomainObjEnterMonitor(driver, vm);
19277 ret = qemuMonitorGetBlockJobInfo(qemuDomainGetMonitor(vm),
19278 disk->info.alias, &rawInfo);
19279 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19280 ret = -1;
19281 if (ret <= 0)
19282 goto endjob;
19284 if (qemuBlockJobInfoTranslate(&rawInfo, info, disk,
19285 flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES) < 0) {
19286 ret = -1;
19287 goto endjob;
19290 /* Snoop block copy operations, so future cancel operations can
19291 * avoid checking if pivot is safe. Save the change to XML, but
19292 * we can ignore failure because it is only an optimization. We
19293 * hold the vm lock, so modifying the in-memory representation is
19294 * safe, even if we are a query rather than a modify job. */
19295 if (disk->mirror &&
19296 rawInfo.ready != 0 &&
19297 info->cur == info->end && !disk->mirrorState) {
19298 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
19300 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
19301 ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps));
19302 virObjectUnref(cfg);
19304 endjob:
19305 qemuDomainObjEndJob(driver, vm);
19307 cleanup:
19308 virDomainObjEndAPI(&vm);
19309 return ret;
19313 static int
19314 qemuDomainBlockJobSetSpeed(virDomainPtr dom,
19315 const char *path,
19316 unsigned long bandwidth,
19317 unsigned int flags)
19319 virQEMUDriverPtr driver = dom->conn->privateData;
19320 virDomainDiskDefPtr disk;
19321 int ret = -1;
19322 virDomainObjPtr vm;
19323 char *device = NULL;
19324 unsigned long long speed = bandwidth;
19326 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES, -1);
19328 /* Convert bandwidth MiB to bytes, if needed */
19329 if (!(flags & VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES)) {
19330 if (speed > LLONG_MAX >> 20) {
19331 virReportError(VIR_ERR_OVERFLOW,
19332 _("bandwidth must be less than %llu"),
19333 LLONG_MAX >> 20);
19334 return -1;
19336 speed <<= 20;
19339 if (!(vm = qemuDomObjFromDomain(dom)))
19340 return -1;
19342 if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0)
19343 goto cleanup;
19345 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19346 goto cleanup;
19348 if (virDomainObjCheckActive(vm) < 0)
19349 goto endjob;
19351 if (qemuDomainSupportsBlockJobs(vm) < 0)
19352 goto endjob;
19354 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19355 goto endjob;
19357 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19358 goto endjob;
19360 qemuDomainObjEnterMonitor(driver, vm);
19361 ret = qemuMonitorBlockJobSetSpeed(qemuDomainGetMonitor(vm),
19362 device,
19363 speed);
19364 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19365 ret = -1;
19367 endjob:
19368 qemuDomainObjEndJob(driver, vm);
19370 cleanup:
19371 VIR_FREE(device);
19372 virDomainObjEndAPI(&vm);
19374 return ret;
19378 static int
19379 qemuDomainBlockCopyValidateMirror(virStorageSourcePtr mirror,
19380 const char *dst,
19381 bool *reuse)
19383 int desttype = virStorageSourceGetActualType(mirror);
19384 struct stat st;
19386 if (virStorageFileAccess(mirror, F_OK) < 0) {
19387 if (errno != ENOENT) {
19388 virReportSystemError(errno, "%s",
19389 _("unable to verify existence of "
19390 "block copy target"));
19391 return -1;
19394 if (*reuse || desttype == VIR_STORAGE_TYPE_BLOCK) {
19395 virReportSystemError(errno,
19396 _("missing destination file for disk %s: %s"),
19397 dst, mirror->path);
19398 return -1;
19400 } else {
19401 if (virStorageFileStat(mirror, &st) < 0) {
19402 virReportSystemError(errno,
19403 _("unable to stat block copy target '%s'"),
19404 mirror->path);
19405 return -1;
19408 if (S_ISBLK(st.st_mode)) {
19409 /* if the target is a block device, assume that we are reusing it,
19410 * so there are no attempts to create it */
19411 *reuse = true;
19412 } else {
19413 if (st.st_size && !(*reuse)) {
19414 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19415 _("external destination file for disk %s already "
19416 "exists and is not a block device: %s"),
19417 dst, mirror->path);
19418 return -1;
19421 if (desttype == VIR_STORAGE_TYPE_BLOCK) {
19422 virReportError(VIR_ERR_INVALID_ARG,
19423 _("blockdev flag requested for disk %s, but file "
19424 "'%s' is not a block device"),
19425 dst, mirror->path);
19426 return -1;
19431 return 0;
19435 /* bandwidth in bytes/s. Caller must lock vm beforehand, and not
19436 * access mirror afterwards. */
19437 static int
19438 qemuDomainBlockCopyCommon(virDomainObjPtr vm,
19439 virConnectPtr conn,
19440 const char *path,
19441 virStorageSourcePtr mirror,
19442 unsigned long long bandwidth,
19443 unsigned int granularity,
19444 unsigned long long buf_size,
19445 unsigned int flags,
19446 bool keepParentLabel)
19448 virQEMUDriverPtr driver = conn->privateData;
19449 qemuDomainObjPrivatePtr priv;
19450 char *device = NULL;
19451 virDomainDiskDefPtr disk = NULL;
19452 int ret = -1;
19453 bool need_unlink = false;
19454 virQEMUDriverConfigPtr cfg = NULL;
19455 const char *format = NULL;
19456 virErrorPtr monitor_error = NULL;
19457 bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
19458 qemuBlockJobDataPtr job = NULL;
19460 /* Preliminaries: find the disk we are editing, sanity checks */
19461 virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
19462 VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
19463 VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
19465 priv = vm->privateData;
19466 cfg = virQEMUDriverGetConfig(driver);
19468 if (virStorageSourceIsRelative(mirror)) {
19469 virReportError(VIR_ERR_INVALID_ARG, "%s",
19470 _("absolute path must be used as block copy target"));
19471 goto cleanup;
19474 if (bandwidth > LLONG_MAX) {
19475 virReportError(VIR_ERR_INVALID_ARG,
19476 _("bandwidth must be less than "
19477 "'%llu' bytes/s (%llu MiB/s)"),
19478 LLONG_MAX, LLONG_MAX >> 20);
19479 goto cleanup;
19482 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19483 goto cleanup;
19485 if (virDomainObjCheckActive(vm) < 0)
19486 goto endjob;
19488 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19489 goto endjob;
19491 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19492 goto endjob;
19494 if (qemuDomainDiskBlockJobIsActive(disk))
19495 goto endjob;
19497 if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN &&
19498 qemuDomainDefValidateDiskLunSource(mirror) < 0)
19499 goto endjob;
19501 if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
19502 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
19503 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19504 _("block copy is not supported with this QEMU binary"));
19505 goto endjob;
19507 if (!(flags & VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB) &&
19508 vm->persistent) {
19509 /* XXX if qemu ever lets us start a new domain with mirroring
19510 * already active, we can relax this; but for now, the risk of
19511 * 'managedsave' due to libvirt-guests means we can't risk
19512 * this on persistent domains. */
19513 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19514 _("domain is not transient"));
19515 goto endjob;
19518 /* clear the _SHALLOW flag if there is only one layer */
19519 if (!virStorageSourceHasBacking(disk->src))
19520 flags &= ~VIR_DOMAIN_BLOCK_COPY_SHALLOW;
19522 /* unless the user provides a pre-created file, shallow copy into a raw
19523 * file is not possible */
19524 if ((flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW) && !reuse &&
19525 mirror->format == VIR_STORAGE_FILE_RAW) {
19526 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19527 _("shallow copy of disk '%s' into a raw file "
19528 "is not possible"),
19529 disk->dst);
19530 goto endjob;
19533 /* Prepare the destination file. */
19534 /* XXX Allow non-file mirror destinations */
19535 if (!virStorageSourceIsLocalStorage(mirror)) {
19536 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
19537 _("non-file destination not supported yet"));
19538 goto endjob;
19541 if (qemuDomainStorageFileInit(driver, vm, mirror, NULL) < 0)
19542 goto endjob;
19544 if (qemuDomainBlockCopyValidateMirror(mirror, disk->dst, &reuse) < 0)
19545 goto endjob;
19547 if (!mirror->format) {
19548 if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) {
19549 mirror->format = disk->src->format;
19550 } else {
19551 /* If the user passed the REUSE_EXT flag, then either they
19552 * can also pass the RAW flag or use XML to tell us the format.
19553 * So if we get here, we assume it is safe for us to probe the
19554 * format from the file that we will be using. */
19555 mirror->format = virStorageFileProbeFormat(mirror->path, cfg->user,
19556 cfg->group);
19560 /* When copying a shareable disk we need to make sure that the disk can
19561 * be safely shared, since block copy may change the format. */
19562 if (disk->src->shared && !disk->src->readonly &&
19563 !qemuBlockStorageSourceSupportsConcurrentAccess(mirror)) {
19564 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19565 _("can't pivot a shared disk to a storage volume not "
19566 "supporting sharing"));
19567 goto endjob;
19570 /* pre-create the image file */
19571 if (!reuse) {
19572 if (virStorageFileCreate(mirror) < 0) {
19573 virReportSystemError(errno, "%s", _("failed to create copy target"));
19574 goto endjob;
19577 need_unlink = true;
19580 if (mirror->format > 0)
19581 format = virStorageFileFormatTypeToString(mirror->format);
19583 if (virStorageSourceInitChainElement(mirror, disk->src,
19584 keepParentLabel) < 0)
19585 goto endjob;
19587 /* If reusing an external image that includes a backing file, the pivot may
19588 * result in qemu needing to open the entire backing chain, so we need to
19589 * label the full backing chain of the mirror instead of just the top image */
19590 if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT &&
19591 mirror->format >= VIR_STORAGE_FILE_BACKING &&
19592 qemuDomainDetermineDiskChain(driver, vm, disk, mirror, true) < 0)
19593 goto endjob;
19595 if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT &&
19596 virStorageSourceHasBacking(mirror)) {
19597 /* note that we don't really know whether a part of the backing chain
19598 * is shared so rolling this back is not as easy. Thus we do it only
19599 * if there's a backing chain */
19600 if (qemuDomainNamespaceSetupDisk(vm, mirror) < 0 ||
19601 qemuSetupImageChainCgroup(vm, mirror) < 0 ||
19602 qemuSecuritySetImageLabel(driver, vm, mirror, true) < 0)
19603 goto endjob;
19604 } else {
19605 if (qemuDomainDiskChainElementPrepare(driver, vm, mirror, false, true) < 0) {
19606 qemuDomainDiskChainElementRevoke(driver, vm, mirror);
19607 goto endjob;
19611 if (!(job = qemuBlockJobDiskNew(disk, QEMU_BLOCKJOB_TYPE_COPY, device)))
19612 goto endjob;
19614 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
19616 /* Actually start the mirroring */
19617 qemuDomainObjEnterMonitor(driver, vm);
19618 /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
19619 * by the user regardless of how @reuse was modified */
19620 ret = qemuMonitorDriveMirror(priv->mon, device, mirror->path, format,
19621 bandwidth, granularity, buf_size, flags);
19622 virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
19623 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19624 ret = -1;
19625 if (ret < 0) {
19626 monitor_error = virSaveLastError();
19627 qemuDomainDiskChainElementRevoke(driver, vm, mirror);
19628 goto endjob;
19631 /* Update vm in place to match changes. */
19632 qemuBlockJobStarted(job);
19633 need_unlink = false;
19634 virStorageFileDeinit(mirror);
19635 disk->mirror = mirror;
19636 mirror = NULL;
19637 disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
19639 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
19640 VIR_WARN("Unable to save status on vm %s after state change",
19641 vm->def->name);
19643 endjob:
19644 if (need_unlink && virStorageFileUnlink(mirror) < 0)
19645 VIR_WARN("%s", _("unable to remove just-created copy target"));
19646 virStorageFileDeinit(mirror);
19647 qemuDomainObjEndJob(driver, vm);
19648 if (monitor_error) {
19649 virSetError(monitor_error);
19650 virFreeError(monitor_error);
19652 qemuBlockJobStartupFinalize(job);
19654 cleanup:
19655 VIR_FREE(device);
19656 virObjectUnref(cfg);
19657 virObjectUnref(mirror);
19658 return ret;
19661 static int
19662 qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
19663 unsigned long bandwidth, unsigned int flags)
19665 virQEMUDriverPtr driver = dom->conn->privateData;
19666 virDomainObjPtr vm;
19667 int ret = -1;
19668 unsigned long long speed = bandwidth;
19669 VIR_AUTOUNREF(virStorageSourcePtr) dest = NULL;
19671 virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
19672 VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
19673 VIR_DOMAIN_BLOCK_REBASE_COPY |
19674 VIR_DOMAIN_BLOCK_REBASE_COPY_RAW |
19675 VIR_DOMAIN_BLOCK_REBASE_RELATIVE |
19676 VIR_DOMAIN_BLOCK_REBASE_COPY_DEV |
19677 VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES, -1);
19679 if (!(vm = qemuDomObjFromDomain(dom)))
19680 return -1;
19682 if (virDomainBlockRebaseEnsureACL(dom->conn, vm->def) < 0)
19683 goto cleanup;
19685 /* For normal rebase (enhanced blockpull), the common code handles
19686 * everything, including vm cleanup. */
19687 if (!(flags & VIR_DOMAIN_BLOCK_REBASE_COPY))
19688 return qemuDomainBlockPullCommon(driver, vm, path, base, bandwidth, flags);
19690 /* If we got here, we are doing a block copy rebase. */
19691 if (!(dest = virStorageSourceNew()))
19692 goto cleanup;
19693 dest->type = (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV) ?
19694 VIR_STORAGE_TYPE_BLOCK : VIR_STORAGE_TYPE_FILE;
19695 if (VIR_STRDUP(dest->path, base) < 0)
19696 goto cleanup;
19697 if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
19698 dest->format = VIR_STORAGE_FILE_RAW;
19700 /* Convert bandwidth MiB to bytes, if necessary */
19701 if (!(flags & VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES)) {
19702 if (speed > LLONG_MAX >> 20) {
19703 virReportError(VIR_ERR_OVERFLOW,
19704 _("bandwidth must be less than %llu"),
19705 LLONG_MAX >> 20);
19706 goto cleanup;
19708 speed <<= 20;
19711 /* XXX: If we are doing a shallow copy but not reusing an external
19712 * file, we should attempt to pre-create the destination with a
19713 * relative backing chain instead of qemu's default of absolute */
19714 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
19715 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
19716 _("Relative backing during copy not supported yet"));
19717 goto cleanup;
19720 /* We rely on the fact that VIR_DOMAIN_BLOCK_REBASE_SHALLOW
19721 * and VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT map to the same values
19722 * as for block copy. */
19723 flags &= (VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
19724 VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT);
19725 ret = qemuDomainBlockCopyCommon(vm, dom->conn, path, dest,
19726 speed, 0, 0, flags, true);
19727 dest = NULL;
19729 cleanup:
19730 virDomainObjEndAPI(&vm);
19731 return ret;
19735 static int
19736 qemuDomainBlockCopy(virDomainPtr dom, const char *disk, const char *destxml,
19737 virTypedParameterPtr params, int nparams,
19738 unsigned int flags)
19740 virQEMUDriverPtr driver = dom->conn->privateData;
19741 virDomainObjPtr vm;
19742 int ret = -1;
19743 unsigned long long bandwidth = 0;
19744 unsigned int granularity = 0;
19745 unsigned long long buf_size = 0;
19746 virDomainDiskDefPtr diskdef = NULL;
19747 virStorageSourcePtr dest = NULL;
19748 size_t i;
19750 virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
19751 VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
19752 VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
19753 if (virTypedParamsValidate(params, nparams,
19754 VIR_DOMAIN_BLOCK_COPY_BANDWIDTH,
19755 VIR_TYPED_PARAM_ULLONG,
19756 VIR_DOMAIN_BLOCK_COPY_GRANULARITY,
19757 VIR_TYPED_PARAM_UINT,
19758 VIR_DOMAIN_BLOCK_COPY_BUF_SIZE,
19759 VIR_TYPED_PARAM_ULLONG,
19760 NULL) < 0)
19761 return -1;
19763 if (!(vm = qemuDomObjFromDomain(dom)))
19764 return -1;
19766 if (virDomainBlockCopyEnsureACL(dom->conn, vm->def) < 0)
19767 goto cleanup;
19769 for (i = 0; i < nparams; i++) {
19770 virTypedParameterPtr param = &params[i];
19772 /* Typed params (wisely) refused to expose unsigned long, but
19773 * back-compat demands that we stick with a maximum of
19774 * unsigned long bandwidth in MiB/s, while our value is
19775 * unsigned long long in bytes/s. Hence, we have to do
19776 * overflow detection if this is a 32-bit server handling a
19777 * 64-bit client. */
19778 if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BANDWIDTH)) {
19779 if (sizeof(unsigned long)< sizeof(bandwidth) &&
19780 param->value.ul > ULONG_MAX * (1ULL << 20)) {
19781 virReportError(VIR_ERR_OVERFLOW,
19782 _("bandwidth must be less than %llu bytes"),
19783 ULONG_MAX * (1ULL << 20));
19784 goto cleanup;
19786 bandwidth = param->value.ul;
19787 } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_GRANULARITY)) {
19788 if (param->value.ui != VIR_ROUND_UP_POWER_OF_TWO(param->value.ui)) {
19789 virReportError(VIR_ERR_INVALID_ARG, "%s",
19790 _("granularity must be power of 2"));
19791 goto cleanup;
19793 granularity = param->value.ui;
19794 } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BUF_SIZE)) {
19795 buf_size = param->value.ul;
19799 if (!(diskdef = virDomainDiskDefParse(destxml, vm->def, driver->xmlopt,
19800 VIR_DOMAIN_DEF_PARSE_INACTIVE |
19801 VIR_DOMAIN_DEF_PARSE_DISK_SOURCE)))
19802 goto cleanup;
19804 VIR_STEAL_PTR(dest, diskdef->src);
19806 ret = qemuDomainBlockCopyCommon(vm, dom->conn, disk, dest, bandwidth,
19807 granularity, buf_size, flags, false);
19809 cleanup:
19810 virDomainDiskDefFree(diskdef);
19811 virDomainObjEndAPI(&vm);
19812 return ret;
19816 static int
19817 qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
19818 unsigned int flags)
19820 virDomainObjPtr vm;
19821 virCheckFlags(VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES, -1);
19823 if (!(vm = qemuDomObjFromDomain(dom)))
19824 return -1;
19826 if (virDomainBlockPullEnsureACL(dom->conn, vm->def) < 0) {
19827 virDomainObjEndAPI(&vm);
19828 return -1;
19831 return qemuDomainBlockPullCommon(dom->conn->privateData,
19832 vm, path, NULL, bandwidth, flags);
19836 static int
19837 qemuDomainBlockCommit(virDomainPtr dom,
19838 const char *path,
19839 const char *base,
19840 const char *top,
19841 unsigned long bandwidth,
19842 unsigned int flags)
19844 virQEMUDriverPtr driver = dom->conn->privateData;
19845 virQEMUDriverConfigPtr cfg = NULL;
19846 qemuDomainObjPrivatePtr priv;
19847 virDomainObjPtr vm = NULL;
19848 char *device = NULL;
19849 int ret = -1;
19850 virDomainDiskDefPtr disk = NULL;
19851 virStorageSourcePtr topSource;
19852 unsigned int topIndex = 0;
19853 virStorageSourcePtr baseSource = NULL;
19854 unsigned int baseIndex = 0;
19855 virStorageSourcePtr top_parent = NULL;
19856 bool clean_access = false;
19857 char *topPath = NULL;
19858 char *basePath = NULL;
19859 char *backingPath = NULL;
19860 unsigned long long speed = bandwidth;
19861 qemuBlockJobDataPtr job = NULL;
19862 qemuBlockJobType jobtype = QEMU_BLOCKJOB_TYPE_COMMIT;
19863 VIR_AUTOUNREF(virStorageSourcePtr) mirror = NULL;
19865 /* XXX Add support for COMMIT_DELETE */
19866 virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
19867 VIR_DOMAIN_BLOCK_COMMIT_ACTIVE |
19868 VIR_DOMAIN_BLOCK_COMMIT_RELATIVE |
19869 VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES, -1);
19871 if (!(vm = qemuDomObjFromDomain(dom)))
19872 goto cleanup;
19873 priv = vm->privateData;
19874 cfg = virQEMUDriverGetConfig(driver);
19876 if (virDomainBlockCommitEnsureACL(dom->conn, vm->def) < 0)
19877 goto cleanup;
19879 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19880 goto cleanup;
19882 if (virDomainObjCheckActive(vm) < 0)
19883 goto endjob;
19884 /* Ensure that no one backports commit to RHEL 6.2, where cancel
19885 * behaved differently */
19886 if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_COMMIT) &&
19887 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
19888 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19889 _("online commit not supported with this QEMU binary"));
19890 goto endjob;
19893 /* Convert bandwidth MiB to bytes, if necessary */
19894 if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES)) {
19895 if (speed > LLONG_MAX >> 20) {
19896 virReportError(VIR_ERR_OVERFLOW,
19897 _("bandwidth must be less than %llu"),
19898 LLONG_MAX >> 20);
19899 goto endjob;
19901 speed <<= 20;
19904 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19905 goto endjob;
19907 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19908 goto endjob;
19910 if (!disk->src->path) {
19911 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19912 _("disk %s has no source file to be committed"),
19913 disk->dst);
19914 goto endjob;
19917 if (qemuDomainDiskBlockJobIsActive(disk))
19918 goto endjob;
19920 if (!top || STREQ(top, disk->dst))
19921 topSource = disk->src;
19922 else if (virStorageFileParseChainIndex(disk->dst, top, &topIndex) < 0 ||
19923 !(topSource = virStorageFileChainLookup(disk->src, NULL,
19924 top, topIndex,
19925 &top_parent)))
19926 goto endjob;
19928 if (topSource == disk->src) {
19929 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
19930 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19931 _("active commit not supported with this QEMU binary"));
19932 goto endjob;
19934 /* XXX Should we auto-pivot when COMMIT_ACTIVE is not specified? */
19935 if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE)) {
19936 virReportError(VIR_ERR_INVALID_ARG,
19937 _("commit of '%s' active layer requires active flag"),
19938 disk->dst);
19939 goto endjob;
19942 jobtype = QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT;
19943 } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
19944 virReportError(VIR_ERR_INVALID_ARG,
19945 _("active commit requested but '%s' is not active"),
19946 topSource->path);
19947 goto endjob;
19950 if (!virStorageSourceHasBacking(topSource)) {
19951 virReportError(VIR_ERR_INVALID_ARG,
19952 _("top '%s' in chain for '%s' has no backing file"),
19953 topSource->path, path);
19954 goto endjob;
19957 if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW))
19958 baseSource = topSource->backingStore;
19959 else if (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
19960 !(baseSource = virStorageFileChainLookup(disk->src, topSource,
19961 base, baseIndex, NULL)))
19962 goto endjob;
19964 if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
19965 baseSource != topSource->backingStore) {
19966 virReportError(VIR_ERR_INVALID_ARG,
19967 _("base '%s' is not immediately below '%s' in chain "
19968 "for '%s'"),
19969 base, topSource->path, path);
19970 goto endjob;
19973 /* For an active commit, clone enough of the base to act as the mirror */
19974 if (topSource == disk->src) {
19975 if (!(mirror = virStorageSourceCopy(baseSource, false)))
19976 goto endjob;
19977 if (virStorageSourceInitChainElement(mirror,
19978 disk->src,
19979 true) < 0)
19980 goto endjob;
19983 if (flags & VIR_DOMAIN_BLOCK_COMMIT_RELATIVE &&
19984 topSource != disk->src) {
19985 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
19986 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19987 _("this qemu doesn't support relative block commit"));
19988 goto endjob;
19991 if (virStorageFileGetRelativeBackingPath(topSource, baseSource,
19992 &backingPath) < 0)
19993 goto endjob;
19995 if (!backingPath) {
19996 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19997 _("can't keep relative backing relationship"));
19998 goto endjob;
20002 /* For the commit to succeed, we must allow qemu to open both the
20003 * 'base' image and the parent of 'top' as read/write; 'top' might
20004 * not have a parent, or might already be read-write. XXX It
20005 * would also be nice to revert 'base' to read-only, as well as
20006 * revoke access to files removed from the chain, when the commit
20007 * operation succeeds, but doing that requires tracking the
20008 * operation in XML across libvirtd restarts. */
20009 clean_access = true;
20010 if (qemuDomainDiskChainElementPrepare(driver, vm, baseSource, false, false) < 0 ||
20011 (top_parent && top_parent != disk->src &&
20012 qemuDomainDiskChainElementPrepare(driver, vm, top_parent, false, false) < 0))
20013 goto endjob;
20015 if (!(job = qemuBlockJobDiskNew(disk, jobtype, device)))
20016 goto endjob;
20018 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
20020 /* Start the commit operation. Pass the user's original spelling,
20021 * if any, through to qemu, since qemu may behave differently
20022 * depending on whether the input was specified as relative or
20023 * absolute (that is, our absolute top_canon may do the wrong
20024 * thing if the user specified a relative name). */
20025 qemuDomainObjEnterMonitor(driver, vm);
20026 basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
20027 baseSource);
20028 topPath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
20029 topSource);
20030 if (basePath && topPath)
20031 ret = qemuMonitorBlockCommit(priv->mon, device,
20032 topPath, basePath, backingPath,
20033 speed);
20034 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
20035 ret = -1;
20036 goto endjob;
20039 qemuBlockJobStarted(job);
20040 if (mirror) {
20041 VIR_STEAL_PTR(disk->mirror, mirror);
20042 disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
20045 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
20046 VIR_WARN("Unable to save status on vm %s after block job",
20047 vm->def->name);
20049 endjob:
20050 if (ret < 0 && clean_access) {
20051 virErrorPtr orig_err = virSaveLastError();
20052 /* Revert access to read-only, if possible. */
20053 qemuDomainDiskChainElementPrepare(driver, vm, baseSource, true, false);
20054 if (top_parent && top_parent != disk->src)
20055 qemuDomainDiskChainElementPrepare(driver, vm, top_parent, true, false);
20057 if (orig_err) {
20058 virSetError(orig_err);
20059 virFreeError(orig_err);
20062 qemuBlockJobStartupFinalize(job);
20063 qemuDomainObjEndJob(driver, vm);
20065 cleanup:
20066 VIR_FREE(topPath);
20067 VIR_FREE(basePath);
20068 VIR_FREE(backingPath);
20069 VIR_FREE(device);
20070 virObjectUnref(cfg);
20071 virDomainObjEndAPI(&vm);
20072 return ret;
20075 static int
20076 qemuDomainOpenGraphics(virDomainPtr dom,
20077 unsigned int idx,
20078 int fd,
20079 unsigned int flags)
20081 virQEMUDriverPtr driver = dom->conn->privateData;
20082 virDomainObjPtr vm = NULL;
20083 int ret = -1;
20084 qemuDomainObjPrivatePtr priv;
20085 const char *protocol;
20087 virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
20089 if (!(vm = qemuDomObjFromDomain(dom)))
20090 return -1;
20092 if (virDomainOpenGraphicsEnsureACL(dom->conn, vm->def) < 0)
20093 goto cleanup;
20095 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20096 goto cleanup;
20098 if (virDomainObjCheckActive(vm) < 0)
20099 goto endjob;
20101 priv = vm->privateData;
20103 if (idx >= vm->def->ngraphics) {
20104 virReportError(VIR_ERR_INTERNAL_ERROR,
20105 _("No graphics backend with index %d"), idx);
20106 goto endjob;
20108 switch (vm->def->graphics[idx]->type) {
20109 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
20110 protocol = "vnc";
20111 break;
20112 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
20113 protocol = "spice";
20114 break;
20115 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
20116 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
20117 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
20118 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
20119 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20120 _("Can only open VNC or SPICE graphics backends, not %s"),
20121 virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
20122 goto endjob;
20123 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
20124 default:
20125 virReportEnumRangeError(virDomainGraphicsType,
20126 vm->def->graphics[idx]->type);
20127 goto endjob;
20130 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
20131 goto endjob;
20133 qemuDomainObjEnterMonitor(driver, vm);
20134 ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
20135 (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
20136 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20137 ret = -1;
20139 endjob:
20140 qemuDomainObjEndJob(driver, vm);
20142 cleanup:
20143 virDomainObjEndAPI(&vm);
20144 return ret;
20147 static int
20148 qemuDomainOpenGraphicsFD(virDomainPtr dom,
20149 unsigned int idx,
20150 unsigned int flags)
20152 virQEMUDriverPtr driver = dom->conn->privateData;
20153 virDomainObjPtr vm = NULL;
20154 int ret = -1;
20155 qemuDomainObjPrivatePtr priv;
20156 const char *protocol;
20157 int pair[2] = {-1, -1};
20159 virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
20161 if (!(vm = qemuDomObjFromDomain(dom)))
20162 return -1;
20164 if (virDomainOpenGraphicsFdEnsureACL(dom->conn, vm->def) < 0)
20165 goto cleanup;
20167 if (virDomainObjCheckActive(vm) < 0)
20168 goto cleanup;
20170 priv = vm->privateData;
20172 if (idx >= vm->def->ngraphics) {
20173 virReportError(VIR_ERR_INTERNAL_ERROR,
20174 _("No graphics backend with index %d"), idx);
20175 goto cleanup;
20177 switch (vm->def->graphics[idx]->type) {
20178 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
20179 protocol = "vnc";
20180 break;
20181 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
20182 protocol = "spice";
20183 break;
20184 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
20185 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
20186 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
20187 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
20188 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20189 _("Can only open VNC or SPICE graphics backends, not %s"),
20190 virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
20191 goto cleanup;
20192 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
20193 default:
20194 virReportEnumRangeError(virDomainGraphicsType,
20195 vm->def->graphics[idx]->type);
20196 goto cleanup;
20199 if (qemuSecuritySetSocketLabel(driver->securityManager, vm->def) < 0)
20200 goto cleanup;
20202 if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) < 0)
20203 goto cleanup;
20205 if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0)
20206 goto cleanup;
20208 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20209 goto cleanup;
20210 qemuDomainObjEnterMonitor(driver, vm);
20211 ret = qemuMonitorOpenGraphics(priv->mon, protocol, pair[1], "graphicsfd",
20212 (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH));
20213 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20214 ret = -1;
20215 qemuDomainObjEndJob(driver, vm);
20216 if (ret < 0)
20217 goto cleanup;
20219 ret = pair[0];
20220 pair[0] = -1;
20222 cleanup:
20223 VIR_FORCE_CLOSE(pair[0]);
20224 VIR_FORCE_CLOSE(pair[1]);
20225 virDomainObjEndAPI(&vm);
20226 return ret;
20229 typedef enum {
20230 QEMU_BLOCK_IOTUNE_SET_BYTES = 1 << 0,
20231 QEMU_BLOCK_IOTUNE_SET_IOPS = 1 << 1,
20232 QEMU_BLOCK_IOTUNE_SET_BYTES_MAX = 1 << 2,
20233 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX = 1 << 3,
20234 QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS = 1 << 4,
20235 QEMU_BLOCK_IOTUNE_SET_GROUP_NAME = 1 << 5,
20236 QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH = 1 << 6,
20237 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH = 1 << 7,
20238 } qemuBlockIoTuneSetFlags;
20241 /* If the user didn't specify bytes limits, inherit previous values;
20242 * likewise if the user didn't specify iops limits. */
20243 static int
20244 qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfoPtr newinfo,
20245 virDomainBlockIoTuneInfoPtr oldinfo,
20246 qemuBlockIoTuneSetFlags set_fields)
20248 #define SET_IOTUNE_DEFAULTS(BOOL, FIELD) \
20249 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) { \
20250 newinfo->total_##FIELD = oldinfo->total_##FIELD; \
20251 newinfo->read_##FIELD = oldinfo->read_##FIELD; \
20252 newinfo->write_##FIELD = oldinfo->write_##FIELD; \
20255 SET_IOTUNE_DEFAULTS(BYTES, bytes_sec);
20256 SET_IOTUNE_DEFAULTS(BYTES_MAX, bytes_sec_max);
20257 SET_IOTUNE_DEFAULTS(IOPS, iops_sec);
20258 SET_IOTUNE_DEFAULTS(IOPS_MAX, iops_sec_max);
20259 #undef SET_IOTUNE_DEFAULTS
20261 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))
20262 newinfo->size_iops_sec = oldinfo->size_iops_sec;
20263 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME) &&
20264 VIR_STRDUP(newinfo->group_name, oldinfo->group_name) < 0)
20265 return -1;
20267 /* The length field is handled a bit differently. If not defined/set,
20268 * QEMU will default these to 0 or 1 depending on whether something in
20269 * the same family is set or not.
20271 * Similar to other values, if nothing in the family is defined/set,
20272 * then take whatever is in the oldinfo.
20274 * To clear an existing limit, a 0 is provided; however, passing that
20275 * 0 onto QEMU if there's a family value defined/set (or defaulted)
20276 * will cause an error. So, to mimic that, if our oldinfo was set and
20277 * our newinfo is clearing, then set max_length based on whether we
20278 * have a value in the family set/defined. */
20279 #define SET_MAX_LENGTH(BOOL, FIELD) \
20280 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) \
20281 newinfo->FIELD##_max_length = oldinfo->FIELD##_max_length; \
20282 else if ((set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL) && \
20283 oldinfo->FIELD##_max_length && \
20284 !newinfo->FIELD##_max_length) \
20285 newinfo->FIELD##_max_length = (newinfo->FIELD || \
20286 newinfo->FIELD##_max) ? 1 : 0;
20288 SET_MAX_LENGTH(BYTES_MAX_LENGTH, total_bytes_sec);
20289 SET_MAX_LENGTH(BYTES_MAX_LENGTH, read_bytes_sec);
20290 SET_MAX_LENGTH(BYTES_MAX_LENGTH, write_bytes_sec);
20291 SET_MAX_LENGTH(IOPS_MAX_LENGTH, total_iops_sec);
20292 SET_MAX_LENGTH(IOPS_MAX_LENGTH, read_iops_sec);
20293 SET_MAX_LENGTH(IOPS_MAX_LENGTH, write_iops_sec);
20295 #undef SET_MAX_LENGTH
20297 return 0;
20301 static int
20302 qemuDomainSetBlockIoTune(virDomainPtr dom,
20303 const char *path,
20304 virTypedParameterPtr params,
20305 int nparams,
20306 unsigned int flags)
20308 virQEMUDriverPtr driver = dom->conn->privateData;
20309 virDomainObjPtr vm = NULL;
20310 qemuDomainObjPrivatePtr priv;
20311 virDomainDefPtr def = NULL;
20312 virDomainDefPtr persistentDef = NULL;
20313 virDomainBlockIoTuneInfo info;
20314 char *drivealias = NULL;
20315 const char *qdevid = NULL;
20316 int ret = -1;
20317 size_t i;
20318 virDomainDiskDefPtr conf_disk = NULL;
20319 virDomainDiskDefPtr disk;
20320 qemuBlockIoTuneSetFlags set_fields = 0;
20321 bool supportMaxOptions = true;
20322 bool supportGroupNameOption = true;
20323 bool supportMaxLengthOptions = true;
20324 virQEMUDriverConfigPtr cfg = NULL;
20325 virObjectEventPtr event = NULL;
20326 virTypedParameterPtr eventParams = NULL;
20327 int eventNparams = 0;
20328 int eventMaxparams = 0;
20330 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20331 VIR_DOMAIN_AFFECT_CONFIG, -1);
20332 if (virTypedParamsValidate(params, nparams,
20333 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
20334 VIR_TYPED_PARAM_ULLONG,
20335 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
20336 VIR_TYPED_PARAM_ULLONG,
20337 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
20338 VIR_TYPED_PARAM_ULLONG,
20339 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
20340 VIR_TYPED_PARAM_ULLONG,
20341 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
20342 VIR_TYPED_PARAM_ULLONG,
20343 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
20344 VIR_TYPED_PARAM_ULLONG,
20345 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
20346 VIR_TYPED_PARAM_ULLONG,
20347 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
20348 VIR_TYPED_PARAM_ULLONG,
20349 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
20350 VIR_TYPED_PARAM_ULLONG,
20351 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
20352 VIR_TYPED_PARAM_ULLONG,
20353 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
20354 VIR_TYPED_PARAM_ULLONG,
20355 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
20356 VIR_TYPED_PARAM_ULLONG,
20357 VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
20358 VIR_TYPED_PARAM_ULLONG,
20359 VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
20360 VIR_TYPED_PARAM_STRING,
20361 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
20362 VIR_TYPED_PARAM_ULLONG,
20363 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
20364 VIR_TYPED_PARAM_ULLONG,
20365 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
20366 VIR_TYPED_PARAM_ULLONG,
20367 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
20368 VIR_TYPED_PARAM_ULLONG,
20369 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
20370 VIR_TYPED_PARAM_ULLONG,
20371 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
20372 VIR_TYPED_PARAM_ULLONG,
20373 NULL) < 0)
20374 return -1;
20376 memset(&info, 0, sizeof(info));
20378 if (!(vm = qemuDomObjFromDomain(dom)))
20379 return -1;
20381 if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0)
20382 goto cleanup;
20384 cfg = virQEMUDriverGetConfig(driver);
20386 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20387 goto cleanup;
20389 priv = vm->privateData;
20391 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
20392 goto endjob;
20394 if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
20395 VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
20396 goto endjob;
20398 #define SET_IOTUNE_FIELD(FIELD, BOOL, CONST) \
20399 if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_##CONST)) { \
20400 info.FIELD = param->value.ul; \
20401 set_fields |= QEMU_BLOCK_IOTUNE_SET_##BOOL; \
20402 if (virTypedParamsAddULLong(&eventParams, &eventNparams, \
20403 &eventMaxparams, \
20404 VIR_DOMAIN_TUNABLE_BLKDEV_##CONST, \
20405 param->value.ul) < 0) \
20406 goto endjob; \
20407 continue; \
20410 for (i = 0; i < nparams; i++) {
20411 virTypedParameterPtr param = &params[i];
20413 if (param->value.ul > QEMU_BLOCK_IOTUNE_MAX) {
20414 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
20415 _("block I/O throttle limit value must"
20416 " be no more than %llu"), QEMU_BLOCK_IOTUNE_MAX);
20417 goto endjob;
20420 SET_IOTUNE_FIELD(total_bytes_sec, BYTES, TOTAL_BYTES_SEC);
20421 SET_IOTUNE_FIELD(read_bytes_sec, BYTES, READ_BYTES_SEC);
20422 SET_IOTUNE_FIELD(write_bytes_sec, BYTES, WRITE_BYTES_SEC);
20423 SET_IOTUNE_FIELD(total_iops_sec, IOPS, TOTAL_IOPS_SEC);
20424 SET_IOTUNE_FIELD(read_iops_sec, IOPS, READ_IOPS_SEC);
20425 SET_IOTUNE_FIELD(write_iops_sec, IOPS, WRITE_IOPS_SEC);
20427 SET_IOTUNE_FIELD(total_bytes_sec_max, BYTES_MAX,
20428 TOTAL_BYTES_SEC_MAX);
20429 SET_IOTUNE_FIELD(read_bytes_sec_max, BYTES_MAX,
20430 READ_BYTES_SEC_MAX);
20431 SET_IOTUNE_FIELD(write_bytes_sec_max, BYTES_MAX,
20432 WRITE_BYTES_SEC_MAX);
20433 SET_IOTUNE_FIELD(total_iops_sec_max, IOPS_MAX,
20434 TOTAL_IOPS_SEC_MAX);
20435 SET_IOTUNE_FIELD(read_iops_sec_max, IOPS_MAX,
20436 READ_IOPS_SEC_MAX);
20437 SET_IOTUNE_FIELD(write_iops_sec_max, IOPS_MAX,
20438 WRITE_IOPS_SEC_MAX);
20439 SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC);
20441 /* NB: Cannot use macro since this is a value.s not a value.ul */
20442 if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
20443 if (VIR_STRDUP(info.group_name, param->value.s) < 0)
20444 goto endjob;
20445 set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
20446 if (virTypedParamsAddString(&eventParams, &eventNparams,
20447 &eventMaxparams,
20448 VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
20449 param->value.s) < 0)
20450 goto endjob;
20451 continue;
20454 SET_IOTUNE_FIELD(total_bytes_sec_max_length, BYTES_MAX_LENGTH,
20455 TOTAL_BYTES_SEC_MAX_LENGTH);
20456 SET_IOTUNE_FIELD(read_bytes_sec_max_length, BYTES_MAX_LENGTH,
20457 READ_BYTES_SEC_MAX_LENGTH);
20458 SET_IOTUNE_FIELD(write_bytes_sec_max_length, BYTES_MAX_LENGTH,
20459 WRITE_BYTES_SEC_MAX_LENGTH);
20460 SET_IOTUNE_FIELD(total_iops_sec_max_length, IOPS_MAX_LENGTH,
20461 TOTAL_IOPS_SEC_MAX_LENGTH);
20462 SET_IOTUNE_FIELD(read_iops_sec_max_length, IOPS_MAX_LENGTH,
20463 READ_IOPS_SEC_MAX_LENGTH);
20464 SET_IOTUNE_FIELD(write_iops_sec_max_length, IOPS_MAX_LENGTH,
20465 WRITE_IOPS_SEC_MAX_LENGTH);
20468 #undef SET_IOTUNE_FIELD
20470 if ((info.total_bytes_sec && info.read_bytes_sec) ||
20471 (info.total_bytes_sec && info.write_bytes_sec)) {
20472 virReportError(VIR_ERR_INVALID_ARG, "%s",
20473 _("total and read/write of bytes_sec "
20474 "cannot be set at the same time"));
20475 goto endjob;
20478 if ((info.total_iops_sec && info.read_iops_sec) ||
20479 (info.total_iops_sec && info.write_iops_sec)) {
20480 virReportError(VIR_ERR_INVALID_ARG, "%s",
20481 _("total and read/write of iops_sec "
20482 "cannot be set at the same time"));
20483 goto endjob;
20486 if ((info.total_bytes_sec_max && info.read_bytes_sec_max) ||
20487 (info.total_bytes_sec_max && info.write_bytes_sec_max)) {
20488 virReportError(VIR_ERR_INVALID_ARG, "%s",
20489 _("total and read/write of bytes_sec_max "
20490 "cannot be set at the same time"));
20491 goto endjob;
20494 if ((info.total_iops_sec_max && info.read_iops_sec_max) ||
20495 (info.total_iops_sec_max && info.write_iops_sec_max)) {
20496 virReportError(VIR_ERR_INVALID_ARG, "%s",
20497 _("total and read/write of iops_sec_max "
20498 "cannot be set at the same time"));
20499 goto endjob;
20502 if (def) {
20503 supportMaxOptions = virQEMUCapsGet(priv->qemuCaps,
20504 QEMU_CAPS_DRIVE_IOTUNE_MAX);
20505 supportGroupNameOption = virQEMUCapsGet(priv->qemuCaps,
20506 QEMU_CAPS_DRIVE_IOTUNE_GROUP);
20507 supportMaxLengthOptions =
20508 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH);
20510 if (!supportMaxOptions &&
20511 (set_fields & (QEMU_BLOCK_IOTUNE_SET_BYTES_MAX |
20512 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX |
20513 QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))) {
20514 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20515 _("a block I/O throttling parameter is not "
20516 "supported with this QEMU binary"));
20517 goto endjob;
20520 if (!supportGroupNameOption &&
20521 (set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME)) {
20522 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20523 _("the block I/O throttling group parameter is not "
20524 "supported with this QEMU binary"));
20525 goto endjob;
20528 if (!supportMaxLengthOptions &&
20529 (set_fields & (QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH |
20530 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH))) {
20531 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20532 _("a block I/O throttling length parameter is not "
20533 "supported with this QEMU binary"));
20534 goto endjob;
20537 if (!(disk = qemuDomainDiskByName(def, path)))
20538 goto endjob;
20540 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
20541 qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
20542 } else {
20543 if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
20544 goto endjob;
20547 if (qemuDomainSetBlockIoTuneDefaults(&info, &disk->blkdeviotune,
20548 set_fields) < 0)
20549 goto endjob;
20551 #define CHECK_MAX(val, _bool) \
20552 do { \
20553 if (info.val##_max) { \
20554 if (!info.val) { \
20555 if (QEMU_BLOCK_IOTUNE_SET_##_bool) { \
20556 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20557 _("cannot reset '%s' when " \
20558 "'%s' is set"), \
20559 #val, #val "_max"); \
20560 } else { \
20561 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20562 _("value '%s' cannot be set if " \
20563 "'%s' is not set"), \
20564 #val "_max", #val); \
20566 goto endjob; \
20568 if (info.val##_max < info.val) { \
20569 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20570 _("value '%s' cannot be " \
20571 "smaller than '%s'"), \
20572 #val "_max", #val); \
20573 goto endjob; \
20576 } while (false)
20578 CHECK_MAX(total_bytes_sec, BYTES);
20579 CHECK_MAX(read_bytes_sec, BYTES);
20580 CHECK_MAX(write_bytes_sec, BYTES);
20581 CHECK_MAX(total_iops_sec, IOPS);
20582 CHECK_MAX(read_iops_sec, IOPS);
20583 CHECK_MAX(write_iops_sec, IOPS);
20585 #undef CHECK_MAX
20587 /* NB: Let's let QEMU decide how to handle issues with _length
20588 * via the JSON error code from the block_set_io_throttle call */
20590 qemuDomainObjEnterMonitor(driver, vm);
20591 ret = qemuMonitorSetBlockIoThrottle(priv->mon, drivealias, qdevid,
20592 &info, supportMaxOptions,
20593 set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME,
20594 supportMaxLengthOptions);
20595 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20596 ret = -1;
20597 if (ret < 0)
20598 goto endjob;
20599 ret = -1;
20601 if (virDomainDiskSetBlockIOTune(disk, &info) < 0)
20602 goto endjob;
20604 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
20605 vm, driver->caps) < 0)
20606 goto endjob;
20608 if (eventNparams) {
20609 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
20610 eventNparams = 0;
20611 virObjectEventStateQueue(driver->domainEventState, event);
20615 if (persistentDef) {
20616 if (!(conf_disk = virDomainDiskByName(persistentDef, path, true))) {
20617 virReportError(VIR_ERR_INVALID_ARG,
20618 _("missing persistent configuration for disk '%s'"),
20619 path);
20620 goto endjob;
20623 if (qemuDomainSetBlockIoTuneDefaults(&info, &conf_disk->blkdeviotune,
20624 set_fields) < 0)
20625 goto endjob;
20627 if (virDomainDiskSetBlockIOTune(conf_disk, &info) < 0)
20628 goto endjob;
20630 if (virDomainSaveConfig(cfg->configDir, driver->caps,
20631 persistentDef) < 0)
20632 goto endjob;
20635 ret = 0;
20636 endjob:
20637 qemuDomainObjEndJob(driver, vm);
20639 cleanup:
20640 VIR_FREE(info.group_name);
20641 VIR_FREE(drivealias);
20642 virDomainObjEndAPI(&vm);
20643 if (eventNparams)
20644 virTypedParamsFree(eventParams, eventNparams);
20645 virObjectUnref(cfg);
20646 return ret;
20649 static int
20650 qemuDomainGetBlockIoTune(virDomainPtr dom,
20651 const char *path,
20652 virTypedParameterPtr params,
20653 int *nparams,
20654 unsigned int flags)
20656 virDomainDiskDefPtr disk;
20657 virQEMUDriverPtr driver = dom->conn->privateData;
20658 virDomainObjPtr vm = NULL;
20659 qemuDomainObjPrivatePtr priv = NULL;
20660 virDomainDefPtr def = NULL;
20661 virDomainDefPtr persistentDef = NULL;
20662 virDomainBlockIoTuneInfo reply = {0};
20663 char *drivealias = NULL;
20664 const char *qdevid = NULL;
20665 int ret = -1;
20666 int maxparams;
20668 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20669 VIR_DOMAIN_AFFECT_CONFIG |
20670 VIR_TYPED_PARAM_STRING_OKAY, -1);
20672 /* We don't return strings, and thus trivially support this flag. */
20673 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
20675 if (!(vm = qemuDomObjFromDomain(dom)))
20676 return -1;
20678 priv = vm->privateData;
20680 if (virDomainGetBlockIoTuneEnsureACL(dom->conn, vm->def) < 0)
20681 goto cleanup;
20683 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20684 goto cleanup;
20686 /* the API check guarantees that only one of the definitions will be set */
20687 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
20688 goto endjob;
20690 if (def) {
20691 /* If the VM is running, we can check if the current VM can use
20692 * optional parameters or not. */
20693 maxparams = QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS;
20694 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX))
20695 maxparams += QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS;
20696 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_GROUP))
20697 maxparams += QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS;
20698 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH))
20699 maxparams += QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS;
20700 } else {
20701 maxparams = QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS;
20704 if (*nparams == 0) {
20705 *nparams = maxparams;
20706 ret = 0;
20707 goto endjob;
20708 } else if (*nparams < maxparams) {
20709 maxparams = *nparams;
20712 *nparams = 0;
20714 if (def) {
20715 if (!(disk = qemuDomainDiskByName(def, path)))
20716 goto endjob;
20718 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
20719 qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
20720 } else {
20721 if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
20722 goto endjob;
20724 qemuDomainObjEnterMonitor(driver, vm);
20725 ret = qemuMonitorGetBlockIoThrottle(priv->mon, drivealias, qdevid, &reply);
20726 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20727 goto endjob;
20728 if (ret < 0)
20729 goto endjob;
20732 if (persistentDef) {
20733 if (!(disk = virDomainDiskByName(persistentDef, path, true))) {
20734 virReportError(VIR_ERR_INVALID_ARG,
20735 _("disk '%s' was not found in the domain config"),
20736 path);
20737 goto endjob;
20739 reply = disk->blkdeviotune;
20741 /* Group name needs to be copied since qemuMonitorGetBlockIoThrottle
20742 * allocates it as well */
20743 if (VIR_STRDUP(reply.group_name, disk->blkdeviotune.group_name) < 0)
20744 goto endjob;
20747 #define BLOCK_IOTUNE_ASSIGN(name, var) \
20748 if (*nparams < maxparams && \
20749 virTypedParameterAssign(&params[(*nparams)++], \
20750 VIR_DOMAIN_BLOCK_IOTUNE_ ## name, \
20751 VIR_TYPED_PARAM_ULLONG, \
20752 reply.var) < 0) \
20753 goto endjob
20756 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC, total_bytes_sec);
20757 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC, read_bytes_sec);
20758 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC, write_bytes_sec);
20760 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC, total_iops_sec);
20761 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC, read_iops_sec);
20762 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC, write_iops_sec);
20764 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX, total_bytes_sec_max);
20765 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX, read_bytes_sec_max);
20766 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX, write_bytes_sec_max);
20768 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX, total_iops_sec_max);
20769 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX, read_iops_sec_max);
20770 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX, write_iops_sec_max);
20772 BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
20774 if (*nparams < maxparams) {
20775 if (virTypedParameterAssign(&params[(*nparams)++],
20776 VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
20777 VIR_TYPED_PARAM_STRING,
20778 reply.group_name) < 0)
20779 goto endjob;
20781 reply.group_name = NULL;
20784 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
20785 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
20786 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
20788 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
20789 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
20790 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
20791 #undef BLOCK_IOTUNE_ASSIGN
20793 ret = 0;
20795 endjob:
20796 qemuDomainObjEndJob(driver, vm);
20798 cleanup:
20799 VIR_FREE(reply.group_name);
20800 VIR_FREE(drivealias);
20801 virDomainObjEndAPI(&vm);
20802 return ret;
20805 static int
20806 qemuDomainGetDiskErrors(virDomainPtr dom,
20807 virDomainDiskErrorPtr errors,
20808 unsigned int nerrors,
20809 unsigned int flags)
20811 virQEMUDriverPtr driver = dom->conn->privateData;
20812 virDomainObjPtr vm = NULL;
20813 qemuDomainObjPrivatePtr priv;
20814 virHashTablePtr table = NULL;
20815 bool blockdev = false;
20816 int ret = -1;
20817 size_t i;
20818 int n = 0;
20820 virCheckFlags(0, -1);
20822 if (!(vm = qemuDomObjFromDomain(dom)))
20823 goto cleanup;
20825 priv = vm->privateData;
20826 blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
20828 if (virDomainGetDiskErrorsEnsureACL(dom->conn, vm->def) < 0)
20829 goto cleanup;
20831 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20832 goto cleanup;
20834 if (virDomainObjCheckActive(vm) < 0)
20835 goto endjob;
20837 if (!errors) {
20838 ret = vm->def->ndisks;
20839 goto endjob;
20842 qemuDomainObjEnterMonitor(driver, vm);
20843 table = qemuMonitorGetBlockInfo(priv->mon);
20844 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20845 goto endjob;
20846 if (!table)
20847 goto endjob;
20849 for (i = n = 0; i < vm->def->ndisks; i++) {
20850 struct qemuDomainDiskInfo *info;
20851 virDomainDiskDefPtr disk = vm->def->disks[i];
20852 qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
20853 const char *entryname = disk->info.alias;
20855 if (blockdev)
20856 entryname = diskPriv->qomName;
20858 if ((info = virHashLookup(table, entryname)) &&
20859 info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
20860 if (n == nerrors)
20861 break;
20863 if (VIR_STRDUP(errors[n].disk, disk->dst) < 0)
20864 goto endjob;
20865 errors[n].error = info->io_status;
20866 n++;
20870 ret = n;
20872 endjob:
20873 qemuDomainObjEndJob(driver, vm);
20875 cleanup:
20876 virDomainObjEndAPI(&vm);
20877 virHashFree(table);
20878 if (ret < 0) {
20879 for (i = 0; i < n; i++)
20880 VIR_FREE(errors[i].disk);
20882 return ret;
20885 static int
20886 qemuDomainSetMetadata(virDomainPtr dom,
20887 int type,
20888 const char *metadata,
20889 const char *key,
20890 const char *uri,
20891 unsigned int flags)
20893 virQEMUDriverPtr driver = dom->conn->privateData;
20894 virDomainObjPtr vm;
20895 virQEMUDriverConfigPtr cfg = NULL;
20896 virCapsPtr caps = NULL;
20897 int ret = -1;
20899 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20900 VIR_DOMAIN_AFFECT_CONFIG, -1);
20902 if (!(vm = qemuDomObjFromDomain(dom)))
20903 return -1;
20905 cfg = virQEMUDriverGetConfig(driver);
20907 if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0)
20908 goto cleanup;
20910 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
20911 goto cleanup;
20913 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20914 goto cleanup;
20916 ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps,
20917 driver->xmlopt, cfg->stateDir,
20918 cfg->configDir, flags);
20920 if (ret == 0) {
20921 virObjectEventPtr ev = NULL;
20922 ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
20923 virObjectEventStateQueue(driver->domainEventState, ev);
20926 qemuDomainObjEndJob(driver, vm);
20928 cleanup:
20929 virDomainObjEndAPI(&vm);
20930 virObjectUnref(caps);
20931 virObjectUnref(cfg);
20932 return ret;
20935 static char *
20936 qemuDomainGetMetadata(virDomainPtr dom,
20937 int type,
20938 const char *uri,
20939 unsigned int flags)
20941 virDomainObjPtr vm;
20942 char *ret = NULL;
20944 if (!(vm = qemuDomObjFromDomain(dom)))
20945 return NULL;
20947 if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0)
20948 goto cleanup;
20950 ret = virDomainObjGetMetadata(vm, type, uri, flags);
20952 cleanup:
20953 virDomainObjEndAPI(&vm);
20954 return ret;
20958 static int
20959 qemuDomainGetCPUStats(virDomainPtr domain,
20960 virTypedParameterPtr params,
20961 unsigned int nparams,
20962 int start_cpu,
20963 unsigned int ncpus,
20964 unsigned int flags)
20966 virDomainObjPtr vm = NULL;
20967 int ret = -1;
20968 qemuDomainObjPrivatePtr priv;
20969 virBitmapPtr guestvcpus = NULL;
20971 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
20973 if (!(vm = qemuDomObjFromDomain(domain)))
20974 return -1;
20976 priv = vm->privateData;
20978 if (virDomainGetCPUStatsEnsureACL(domain->conn, vm->def) < 0)
20979 goto cleanup;
20981 if (virDomainObjCheckActive(vm) < 0)
20982 goto cleanup;
20984 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
20985 virReportError(VIR_ERR_OPERATION_INVALID,
20986 "%s", _("cgroup CPUACCT controller is not mounted"));
20987 goto cleanup;
20990 if (qemuDomainHasVcpuPids(vm) &&
20991 !(guestvcpus = virDomainDefGetOnlineVcpumap(vm->def)))
20992 goto cleanup;
20994 if (start_cpu == -1)
20995 ret = virCgroupGetDomainTotalCpuStats(priv->cgroup,
20996 params, nparams);
20997 else
20998 ret = virCgroupGetPercpuStats(priv->cgroup, params, nparams,
20999 start_cpu, ncpus, guestvcpus);
21000 cleanup:
21001 virBitmapFree(guestvcpus);
21002 virDomainObjEndAPI(&vm);
21003 return ret;
21006 static int
21007 qemuDomainPMSuspendForDuration(virDomainPtr dom,
21008 unsigned int target,
21009 unsigned long long duration,
21010 unsigned int flags)
21012 virQEMUDriverPtr driver = dom->conn->privateData;
21013 virDomainObjPtr vm;
21014 qemuAgentPtr agent;
21015 int ret = -1;
21017 virCheckFlags(0, -1);
21019 if (duration) {
21020 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
21021 _("Duration not supported. Use 0 for now"));
21022 return -1;
21025 if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
21026 target == VIR_NODE_SUSPEND_TARGET_DISK ||
21027 target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
21028 virReportError(VIR_ERR_INVALID_ARG,
21029 _("Unknown suspend target: %u"),
21030 target);
21031 return -1;
21034 if (!(vm = qemuDomObjFromDomain(dom)))
21035 goto cleanup;
21037 if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0)
21038 goto cleanup;
21040 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21041 goto cleanup;
21043 if (virDomainObjCheckActive(vm) < 0)
21044 goto endjob;
21046 if (vm->def->pm.s3 || vm->def->pm.s4) {
21047 if (vm->def->pm.s3 == VIR_TRISTATE_BOOL_NO &&
21048 (target == VIR_NODE_SUSPEND_TARGET_MEM ||
21049 target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
21050 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
21051 _("S3 state is disabled for this domain"));
21052 goto endjob;
21055 if (vm->def->pm.s4 == VIR_TRISTATE_BOOL_NO &&
21056 target == VIR_NODE_SUSPEND_TARGET_DISK) {
21057 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
21058 _("S4 state is disabled for this domain"));
21059 goto endjob;
21063 if (!qemuDomainAgentAvailable(vm, true))
21064 goto endjob;
21066 agent = qemuDomainObjEnterAgent(vm);
21067 ret = qemuAgentSuspend(agent, target);
21068 qemuDomainObjExitAgent(vm, agent);
21070 endjob:
21071 qemuDomainObjEndAgentJob(vm);
21073 cleanup:
21074 virDomainObjEndAPI(&vm);
21075 return ret;
21078 static int
21079 qemuDomainPMWakeup(virDomainPtr dom,
21080 unsigned int flags)
21082 virQEMUDriverPtr driver = dom->conn->privateData;
21083 virDomainObjPtr vm;
21084 int ret = -1;
21085 qemuDomainObjPrivatePtr priv;
21087 virCheckFlags(0, -1);
21089 if (!(vm = qemuDomObjFromDomain(dom)))
21090 goto cleanup;
21092 if (virDomainPMWakeupEnsureACL(dom->conn, vm->def) < 0)
21093 goto cleanup;
21095 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
21096 goto cleanup;
21098 if (virDomainObjCheckActive(vm) < 0)
21099 goto endjob;
21101 priv = vm->privateData;
21103 qemuDomainObjEnterMonitor(driver, vm);
21104 ret = qemuMonitorSystemWakeup(priv->mon);
21105 if (qemuDomainObjExitMonitor(driver, vm) < 0)
21106 ret = -1;
21108 endjob:
21109 qemuDomainObjEndJob(driver, vm);
21111 cleanup:
21112 virDomainObjEndAPI(&vm);
21113 return ret;
21116 static int
21117 qemuConnectListAllDomains(virConnectPtr conn,
21118 virDomainPtr **domains,
21119 unsigned int flags)
21121 virQEMUDriverPtr driver = conn->privateData;
21122 int ret = -1;
21124 virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
21126 if (virConnectListAllDomainsEnsureACL(conn) < 0)
21127 goto cleanup;
21129 ret = virDomainObjListExport(driver->domains, conn, domains,
21130 virConnectListAllDomainsCheckACL, flags);
21132 cleanup:
21133 return ret;
21136 static char *
21137 qemuDomainQemuAgentCommand(virDomainPtr domain,
21138 const char *cmd,
21139 int timeout,
21140 unsigned int flags)
21142 virQEMUDriverPtr driver = domain->conn->privateData;
21143 virDomainObjPtr vm;
21144 int ret = -1;
21145 char *result = NULL;
21146 qemuAgentPtr agent;
21148 virCheckFlags(0, NULL);
21150 if (!(vm = qemuDomObjFromDomain(domain)))
21151 goto cleanup;
21153 if (virDomainQemuAgentCommandEnsureACL(domain->conn, vm->def) < 0)
21154 goto cleanup;
21156 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21157 goto cleanup;
21159 if (virDomainObjCheckActive(vm) < 0)
21160 goto endjob;
21162 if (!qemuDomainAgentAvailable(vm, true))
21163 goto endjob;
21165 qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_GA_COMMAND, NULL);
21167 agent = qemuDomainObjEnterAgent(vm);
21168 ret = qemuAgentArbitraryCommand(agent, cmd, &result, timeout);
21169 qemuDomainObjExitAgent(vm, agent);
21170 if (ret < 0)
21171 VIR_FREE(result);
21173 endjob:
21174 qemuDomainObjEndAgentJob(vm);
21176 cleanup:
21177 virDomainObjEndAPI(&vm);
21178 return result;
21182 static int
21183 qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
21184 virDomainPtr dom,
21185 const char *event,
21186 virConnectDomainQemuMonitorEventCallback callback,
21187 void *opaque,
21188 virFreeCallback freecb,
21189 unsigned int flags)
21191 virQEMUDriverPtr driver = conn->privateData;
21192 int ret = -1;
21194 if (virConnectDomainQemuMonitorEventRegisterEnsureACL(conn) < 0)
21195 goto cleanup;
21197 if (virDomainQemuMonitorEventStateRegisterID(conn,
21198 driver->domainEventState,
21199 dom, event, callback,
21200 opaque, freecb, flags,
21201 &ret) < 0)
21202 ret = -1;
21204 cleanup:
21205 return ret;
21209 static int
21210 qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
21211 int callbackID)
21213 virQEMUDriverPtr driver = conn->privateData;
21214 int ret = -1;
21216 if (virConnectDomainQemuMonitorEventDeregisterEnsureACL(conn) < 0)
21217 goto cleanup;
21219 if (virObjectEventStateDeregisterID(conn, driver->domainEventState,
21220 callbackID, true) < 0)
21221 goto cleanup;
21223 ret = 0;
21225 cleanup:
21226 return ret;
21230 static int
21231 qemuDomainFSTrim(virDomainPtr dom,
21232 const char *mountPoint,
21233 unsigned long long minimum,
21234 unsigned int flags)
21236 virQEMUDriverPtr driver = dom->conn->privateData;
21237 virDomainObjPtr vm;
21238 qemuAgentPtr agent;
21239 int ret = -1;
21241 virCheckFlags(0, -1);
21243 if (mountPoint) {
21244 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
21245 _("Specifying mount point "
21246 "is not supported for now"));
21247 return -1;
21250 if (!(vm = qemuDomObjFromDomain(dom)))
21251 goto cleanup;
21253 if (virDomainFSTrimEnsureACL(dom->conn, vm->def) < 0)
21254 goto cleanup;
21256 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21257 goto cleanup;
21259 if (!qemuDomainAgentAvailable(vm, true))
21260 goto endjob;
21262 if (virDomainObjCheckActive(vm) < 0)
21263 goto endjob;
21265 agent = qemuDomainObjEnterAgent(vm);
21266 ret = qemuAgentFSTrim(agent, minimum);
21267 qemuDomainObjExitAgent(vm, agent);
21269 endjob:
21270 qemuDomainObjEndAgentJob(vm);
21272 cleanup:
21273 virDomainObjEndAPI(&vm);
21274 return ret;
21278 static int
21279 qemuNodeGetInfo(virConnectPtr conn,
21280 virNodeInfoPtr nodeinfo)
21282 if (virNodeGetInfoEnsureACL(conn) < 0)
21283 return -1;
21285 return virCapabilitiesGetNodeInfo(nodeinfo);
21289 static int
21290 qemuNodeGetCPUStats(virConnectPtr conn,
21291 int cpuNum,
21292 virNodeCPUStatsPtr params,
21293 int *nparams,
21294 unsigned int flags)
21296 if (virNodeGetCPUStatsEnsureACL(conn) < 0)
21297 return -1;
21299 return virHostCPUGetStats(cpuNum, params, nparams, flags);
21303 static int
21304 qemuNodeGetMemoryStats(virConnectPtr conn,
21305 int cellNum,
21306 virNodeMemoryStatsPtr params,
21307 int *nparams,
21308 unsigned int flags)
21310 if (virNodeGetMemoryStatsEnsureACL(conn) < 0)
21311 return -1;
21313 return virHostMemGetStats(cellNum, params, nparams, flags);
21317 static int
21318 qemuNodeGetCellsFreeMemory(virConnectPtr conn,
21319 unsigned long long *freeMems,
21320 int startCell,
21321 int maxCells)
21323 if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
21324 return -1;
21326 return virHostMemGetCellsFree(freeMems, startCell, maxCells);
21330 static unsigned long long
21331 qemuNodeGetFreeMemory(virConnectPtr conn)
21333 unsigned long long freeMem;
21335 if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
21336 return 0;
21338 if (virHostMemGetInfo(NULL, &freeMem) < 0)
21339 return 0;
21341 return freeMem;
21345 static int
21346 qemuNodeGetMemoryParameters(virConnectPtr conn,
21347 virTypedParameterPtr params,
21348 int *nparams,
21349 unsigned int flags)
21351 if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
21352 return -1;
21354 return virHostMemGetParameters(params, nparams, flags);
21358 static int
21359 qemuNodeSetMemoryParameters(virConnectPtr conn,
21360 virTypedParameterPtr params,
21361 int nparams,
21362 unsigned int flags)
21364 if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
21365 return -1;
21367 return virHostMemSetParameters(params, nparams, flags);
21371 static int
21372 qemuNodeGetCPUMap(virConnectPtr conn,
21373 unsigned char **cpumap,
21374 unsigned int *online,
21375 unsigned int flags)
21377 if (virNodeGetCPUMapEnsureACL(conn) < 0)
21378 return -1;
21380 return virHostCPUGetMap(cpumap, online, flags);
21384 static int
21385 qemuNodeSuspendForDuration(virConnectPtr conn,
21386 unsigned int target,
21387 unsigned long long duration,
21388 unsigned int flags)
21390 if (virNodeSuspendForDurationEnsureACL(conn) < 0)
21391 return -1;
21393 return virNodeSuspend(target, duration, flags);
21396 static int
21397 qemuConnectGetCPUModelNames(virConnectPtr conn,
21398 const char *archName,
21399 char ***models,
21400 unsigned int flags)
21402 virArch arch;
21404 virCheckFlags(0, -1);
21405 if (virConnectGetCPUModelNamesEnsureACL(conn) < 0)
21406 return -1;
21408 if (!(arch = virArchFromString(archName))) {
21409 virReportError(VIR_ERR_INVALID_ARG,
21410 _("cannot find architecture %s"),
21411 archName);
21412 return -1;
21415 return virCPUGetModels(arch, models);
21419 static char *
21420 qemuDomainGetHostname(virDomainPtr dom,
21421 unsigned int flags)
21423 virQEMUDriverPtr driver = dom->conn->privateData;
21424 virDomainObjPtr vm = NULL;
21425 qemuAgentPtr agent;
21426 char *hostname = NULL;
21428 virCheckFlags(0, NULL);
21430 if (!(vm = qemuDomObjFromDomain(dom)))
21431 return NULL;
21433 if (virDomainGetHostnameEnsureACL(dom->conn, vm->def) < 0)
21434 goto cleanup;
21436 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
21437 goto cleanup;
21439 if (virDomainObjCheckActive(vm) < 0)
21440 goto endjob;
21442 if (!qemuDomainAgentAvailable(vm, true))
21443 goto endjob;
21445 agent = qemuDomainObjEnterAgent(vm);
21446 ignore_value(qemuAgentGetHostname(agent, &hostname));
21447 qemuDomainObjExitAgent(vm, agent);
21449 endjob:
21450 qemuDomainObjEndAgentJob(vm);
21452 cleanup:
21453 virDomainObjEndAPI(&vm);
21454 return hostname;
21458 static int
21459 qemuDomainGetTime(virDomainPtr dom,
21460 long long *seconds,
21461 unsigned int *nseconds,
21462 unsigned int flags)
21464 virQEMUDriverPtr driver = dom->conn->privateData;
21465 virDomainObjPtr vm = NULL;
21466 qemuAgentPtr agent;
21467 int ret = -1;
21468 int rv;
21470 virCheckFlags(0, ret);
21472 if (!(vm = qemuDomObjFromDomain(dom)))
21473 return ret;
21475 if (virDomainGetTimeEnsureACL(dom->conn, vm->def) < 0)
21476 goto cleanup;
21478 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
21479 goto cleanup;
21481 if (virDomainObjCheckActive(vm) < 0)
21482 goto endjob;
21484 if (!qemuDomainAgentAvailable(vm, true))
21485 goto endjob;
21487 agent = qemuDomainObjEnterAgent(vm);
21488 rv = qemuAgentGetTime(agent, seconds, nseconds);
21489 qemuDomainObjExitAgent(vm, agent);
21491 if (rv < 0)
21492 goto endjob;
21494 ret = 0;
21496 endjob:
21497 qemuDomainObjEndAgentJob(vm);
21499 cleanup:
21500 virDomainObjEndAPI(&vm);
21501 return ret;
21505 static int
21506 qemuDomainSetTime(virDomainPtr dom,
21507 long long seconds,
21508 unsigned int nseconds,
21509 unsigned int flags)
21511 virQEMUDriverPtr driver = dom->conn->privateData;
21512 qemuDomainObjPrivatePtr priv;
21513 virDomainObjPtr vm;
21514 qemuAgentPtr agent;
21515 bool rtcSync = flags & VIR_DOMAIN_TIME_SYNC;
21516 int ret = -1;
21517 int rv;
21519 virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret);
21521 if (!(vm = qemuDomObjFromDomain(dom)))
21522 return ret;
21524 if (virDomainSetTimeEnsureACL(dom->conn, vm->def) < 0)
21525 goto cleanup;
21527 priv = vm->privateData;
21529 if (qemuDomainObjBeginJobWithAgent(driver, vm,
21530 QEMU_JOB_MODIFY,
21531 QEMU_AGENT_JOB_MODIFY) < 0)
21532 goto cleanup;
21534 if (virDomainObjCheckActive(vm) < 0)
21535 goto endjob;
21537 /* On x86, the rtc-reset-reinjection QMP command must be called after
21538 * setting the time to avoid trouble down the line. If the command is
21539 * not available, don't set the time at all and report an error */
21540 if (ARCH_IS_X86(vm->def->os.arch) &&
21541 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION))
21543 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
21544 _("cannot set time: qemu doesn't support "
21545 "rtc-reset-reinjection command"));
21546 goto endjob;
21549 if (!qemuDomainAgentAvailable(vm, true))
21550 goto endjob;
21552 agent = qemuDomainObjEnterAgent(vm);
21553 rv = qemuAgentSetTime(agent, seconds, nseconds, rtcSync);
21554 qemuDomainObjExitAgent(vm, agent);
21556 if (rv < 0)
21557 goto endjob;
21559 if (virDomainObjCheckActive(vm) < 0)
21560 goto endjob;
21562 /* Don't try to call rtc-reset-reinjection if it's not available */
21563 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) {
21564 qemuDomainObjEnterMonitor(driver, vm);
21565 rv = qemuMonitorRTCResetReinjection(priv->mon);
21566 if (qemuDomainObjExitMonitor(driver, vm) < 0)
21567 goto endjob;
21569 if (rv < 0)
21570 goto endjob;
21573 ret = 0;
21575 endjob:
21576 qemuDomainObjEndJobWithAgent(driver, vm);
21578 cleanup:
21579 virDomainObjEndAPI(&vm);
21580 return ret;
21584 static int
21585 qemuDomainFSFreeze(virDomainPtr dom,
21586 const char **mountpoints,
21587 unsigned int nmountpoints,
21588 unsigned int flags)
21590 virQEMUDriverPtr driver = dom->conn->privateData;
21591 virDomainObjPtr vm;
21592 int ret = -1;
21594 virCheckFlags(0, -1);
21596 if (!(vm = qemuDomObjFromDomain(dom)))
21597 goto cleanup;
21599 if (virDomainFSFreezeEnsureACL(dom->conn, vm->def) < 0)
21600 goto cleanup;
21602 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21603 goto cleanup;
21605 if (virDomainObjCheckActive(vm) < 0)
21606 goto endjob;
21608 ret = qemuDomainSnapshotFSFreeze(driver, vm, mountpoints, nmountpoints);
21610 endjob:
21611 qemuDomainObjEndAgentJob(vm);
21613 cleanup:
21614 virDomainObjEndAPI(&vm);
21615 return ret;
21619 static int
21620 qemuDomainFSThaw(virDomainPtr dom,
21621 const char **mountpoints,
21622 unsigned int nmountpoints,
21623 unsigned int flags)
21625 virQEMUDriverPtr driver = dom->conn->privateData;
21626 virDomainObjPtr vm;
21627 int ret = -1;
21629 virCheckFlags(0, -1);
21631 if (mountpoints || nmountpoints) {
21632 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
21633 _("specifying mountpoints is not supported"));
21634 return ret;
21637 if (!(vm = qemuDomObjFromDomain(dom)))
21638 goto cleanup;
21640 if (virDomainFSThawEnsureACL(dom->conn, vm->def) < 0)
21641 goto cleanup;
21643 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21644 goto cleanup;
21646 if (virDomainObjCheckActive(vm) < 0)
21647 goto endjob;
21649 ret = qemuDomainSnapshotFSThaw(driver, vm, true);
21651 endjob:
21652 qemuDomainObjEndAgentJob(vm);
21654 cleanup:
21655 virDomainObjEndAPI(&vm);
21656 return ret;
21660 static int
21661 qemuNodeGetFreePages(virConnectPtr conn,
21662 unsigned int npages,
21663 unsigned int *pages,
21664 int startCell,
21665 unsigned int cellCount,
21666 unsigned long long *counts,
21667 unsigned int flags)
21669 virCheckFlags(0, -1);
21671 if (virNodeGetFreePagesEnsureACL(conn) < 0)
21672 return -1;
21674 return virHostMemGetFreePages(npages, pages, startCell, cellCount, counts);
21678 static char *
21679 qemuConnectGetDomainCapabilities(virConnectPtr conn,
21680 const char *emulatorbin,
21681 const char *arch_str,
21682 const char *machine,
21683 const char *virttype_str,
21684 unsigned int flags)
21686 char *ret = NULL;
21687 virQEMUDriverPtr driver = conn->privateData;
21688 virQEMUCapsPtr qemuCaps = NULL;
21689 virArch arch;
21690 virDomainVirtType virttype;
21691 virDomainCapsPtr domCaps = NULL;
21692 virQEMUDriverConfigPtr cfg = NULL;
21693 virCapsPtr caps = NULL;
21695 virCheckFlags(0, ret);
21697 if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
21698 return ret;
21700 cfg = virQEMUDriverGetConfig(driver);
21702 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
21703 goto cleanup;
21705 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
21706 emulatorbin,
21707 arch_str,
21708 virttype_str,
21709 machine,
21710 &arch, &virttype, &machine);
21711 if (!qemuCaps)
21712 goto cleanup;
21714 if (!(domCaps = virDomainCapsNew(virQEMUCapsGetBinary(qemuCaps), machine,
21715 arch, virttype)))
21716 goto cleanup;
21718 if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
21719 cfg->firmwares, cfg->nfirmwares) < 0)
21720 goto cleanup;
21722 ret = virDomainCapsFormat(domCaps);
21723 cleanup:
21724 virObjectUnref(cfg);
21725 virObjectUnref(caps);
21726 virObjectUnref(domCaps);
21727 virObjectUnref(qemuCaps);
21728 return ret;
21732 static int
21733 qemuDomainGetStatsState(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
21734 virDomainObjPtr dom,
21735 virDomainStatsRecordPtr record,
21736 int *maxparams,
21737 unsigned int privflags ATTRIBUTE_UNUSED)
21739 if (virTypedParamsAddInt(&record->params,
21740 &record->nparams,
21741 maxparams,
21742 "state.state",
21743 dom->state.state) < 0)
21744 return -1;
21746 if (virTypedParamsAddInt(&record->params,
21747 &record->nparams,
21748 maxparams,
21749 "state.reason",
21750 dom->state.reason) < 0)
21751 return -1;
21753 return 0;
21757 typedef enum {
21758 QEMU_DOMAIN_STATS_HAVE_JOB = 1 << 0, /* job is entered, monitor can be
21759 accessed */
21760 QEMU_DOMAIN_STATS_BACKING = 1 << 1, /* include backing chain in
21761 block stats */
21762 } qemuDomainStatsFlags;
21765 #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB)
21768 typedef struct _virQEMUResctrlMonData virQEMUResctrlMonData;
21769 typedef virQEMUResctrlMonData *virQEMUResctrlMonDataPtr;
21770 struct _virQEMUResctrlMonData {
21771 char *name;
21772 char *vcpus;
21773 virResctrlMonitorStatsPtr *stats;
21774 size_t nstats;
21778 static void
21779 qemuDomainFreeResctrlMonData(virQEMUResctrlMonDataPtr resdata)
21781 VIR_FREE(resdata->name);
21782 VIR_FREE(resdata->vcpus);
21783 virResctrlMonitorFreeStats(resdata->stats, resdata->nstats);
21784 VIR_FREE(resdata);
21789 * qemuDomainGetResctrlMonData:
21790 * @dom: Pointer for the domain that the resctrl monitors reside in
21791 * @resdata: Pointer of virQEMUResctrlMonDataPtr pointer for receiving the
21792 * virQEMUResctrlMonDataPtr array. Caller is responsible for
21793 * freeing the array.
21794 * @nresdata: Pointer of size_t to report the size virQEMUResctrlMonDataPtr
21795 * array to caller. If *@nresdata is not 0, even if function
21796 * returns an error, the caller is also required to call
21797 * qemuDomainFreeResctrlMonData to free each element in the
21798 * *@resdata array and then the array itself.
21799 * @tag: Could be VIR_RESCTRL_MONITOR_TYPE_CACHE for getting cache statistics
21800 * from @dom cache monitors. VIR_RESCTRL_MONITOR_TYPE_MEMBW for
21801 * getting memory bandwidth statistics from memory bandwidth monitors.
21803 * Get cache or memory bandwidth statistics from @dom monitors.
21805 * Returns -1 on failure, or 0 on success.
21807 static int
21808 qemuDomainGetResctrlMonData(virDomainObjPtr dom,
21809 virQEMUResctrlMonDataPtr **resdata,
21810 size_t *nresdata,
21811 virResctrlMonitorType tag)
21813 virDomainResctrlDefPtr resctrl = NULL;
21814 virQEMUResctrlMonDataPtr res = NULL;
21815 size_t i = 0;
21816 size_t j = 0;
21818 for (i = 0; i < dom->def->nresctrls; i++) {
21819 resctrl = dom->def->resctrls[i];
21821 for (j = 0; j < resctrl->nmonitors; j++) {
21822 virDomainResctrlMonDefPtr domresmon = NULL;
21823 virResctrlMonitorPtr monitor = NULL;
21825 domresmon = resctrl->monitors[j];
21826 monitor = domresmon->instance;
21828 if (domresmon->tag != tag)
21829 continue;
21831 if (VIR_ALLOC(res) < 0)
21832 return -1;
21834 /* If virBitmapFormat successfully returns an vcpu string, then
21835 * res.vcpus is assigned with an memory space holding it,
21836 * let this newly allocated memory buffer to be freed along with
21837 * the free of 'res' */
21838 if (!(res->vcpus = virBitmapFormat(domresmon->vcpus)))
21839 goto error;
21841 if (VIR_STRDUP(res->name, virResctrlMonitorGetID(monitor)) < 0)
21842 goto error;
21844 if (virResctrlMonitorGetCacheOccupancy(monitor,
21845 &res->stats,
21846 &res->nstats) < 0)
21847 goto error;
21849 if (VIR_APPEND_ELEMENT(*resdata, *nresdata, res) < 0)
21850 goto error;
21854 return 0;
21856 error:
21857 qemuDomainFreeResctrlMonData(res);
21858 return -1;
21862 static int
21863 qemuDomainGetStatsCpuCache(virDomainObjPtr dom,
21864 virDomainStatsRecordPtr record,
21865 int *maxparams)
21867 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
21868 virQEMUResctrlMonDataPtr *resdata = NULL;
21869 size_t nresdata = 0;
21870 size_t i = 0;
21871 size_t j = 0;
21872 int ret = -1;
21874 if (!virDomainObjIsActive(dom))
21875 return 0;
21877 if (qemuDomainGetResctrlMonData(dom, &resdata, &nresdata,
21878 VIR_RESCTRL_MONITOR_TYPE_CACHE) < 0)
21879 goto cleanup;
21881 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21882 "cpu.cache.monitor.count");
21883 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21884 maxparams, param_name, nresdata) < 0)
21885 goto cleanup;
21887 for (i = 0; i < nresdata; i++) {
21888 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21889 "cpu.cache.monitor.%zu.name", i);
21890 if (virTypedParamsAddString(&record->params,
21891 &record->nparams,
21892 maxparams,
21893 param_name,
21894 resdata[i]->name) < 0)
21895 goto cleanup;
21897 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21898 "cpu.cache.monitor.%zu.vcpus", i);
21899 if (virTypedParamsAddString(&record->params, &record->nparams,
21900 maxparams, param_name,
21901 resdata[i]->vcpus) < 0)
21902 goto cleanup;
21904 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21905 "cpu.cache.monitor.%zu.bank.count", i);
21906 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21907 maxparams, param_name,
21908 resdata[i]->nstats) < 0)
21909 goto cleanup;
21911 for (j = 0; j < resdata[i]->nstats; j++) {
21912 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21913 "cpu.cache.monitor.%zu.bank.%zu.id", i, j);
21914 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21915 maxparams, param_name,
21916 resdata[i]->stats[j]->id) < 0)
21917 goto cleanup;
21919 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21920 "cpu.cache.monitor.%zu.bank.%zu.bytes", i, j);
21921 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21922 maxparams, param_name,
21923 resdata[i]->stats[j]->val) < 0)
21924 goto cleanup;
21928 ret = 0;
21929 cleanup:
21930 for (i = 0; i < nresdata; i++)
21931 qemuDomainFreeResctrlMonData(resdata[i]);
21932 VIR_FREE(resdata);
21933 return ret;
21937 static int
21938 qemuDomainGetStatsCpuCgroup(virDomainObjPtr dom,
21939 virDomainStatsRecordPtr record,
21940 int *maxparams)
21942 qemuDomainObjPrivatePtr priv = dom->privateData;
21943 unsigned long long cpu_time = 0;
21944 unsigned long long user_time = 0;
21945 unsigned long long sys_time = 0;
21946 int err = 0;
21948 if (!priv->cgroup)
21949 return 0;
21951 err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
21952 if (!err && virTypedParamsAddULLong(&record->params,
21953 &record->nparams,
21954 maxparams,
21955 "cpu.time",
21956 cpu_time) < 0)
21957 return -1;
21959 err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time);
21960 if (!err && virTypedParamsAddULLong(&record->params,
21961 &record->nparams,
21962 maxparams,
21963 "cpu.user",
21964 user_time) < 0)
21965 return -1;
21966 if (!err && virTypedParamsAddULLong(&record->params,
21967 &record->nparams,
21968 maxparams,
21969 "cpu.system",
21970 sys_time) < 0)
21971 return -1;
21973 return 0;
21977 static int
21978 qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
21979 virDomainObjPtr dom,
21980 virDomainStatsRecordPtr record,
21981 int *maxparams,
21982 unsigned int privflags ATTRIBUTE_UNUSED)
21984 if (qemuDomainGetStatsCpuCgroup(dom, record, maxparams) < 0)
21985 return -1;
21987 if (qemuDomainGetStatsCpuCache(dom, record, maxparams) < 0)
21988 return -1;
21990 return 0;
21994 static int
21995 qemuDomainGetStatsBalloon(virQEMUDriverPtr driver,
21996 virDomainObjPtr dom,
21997 virDomainStatsRecordPtr record,
21998 int *maxparams,
21999 unsigned int privflags)
22001 virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR];
22002 int nr_stats;
22003 unsigned long long cur_balloon = 0;
22004 size_t i;
22006 if (!virDomainDefHasMemballoon(dom->def)) {
22007 cur_balloon = virDomainDefGetMemoryTotal(dom->def);
22008 } else {
22009 cur_balloon = dom->def->mem.cur_balloon;
22012 if (virTypedParamsAddULLong(&record->params,
22013 &record->nparams,
22014 maxparams,
22015 "balloon.current",
22016 cur_balloon) < 0)
22017 return -1;
22019 if (virTypedParamsAddULLong(&record->params,
22020 &record->nparams,
22021 maxparams,
22022 "balloon.maximum",
22023 virDomainDefGetMemoryTotal(dom->def)) < 0)
22024 return -1;
22026 if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
22027 return 0;
22029 nr_stats = qemuDomainMemoryStatsInternal(driver, dom, stats,
22030 VIR_DOMAIN_MEMORY_STAT_NR);
22031 if (nr_stats < 0)
22032 return 0;
22034 #define STORE_MEM_RECORD(TAG, NAME) \
22035 if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ ##TAG) \
22036 if (virTypedParamsAddULLong(&record->params, \
22037 &record->nparams, \
22038 maxparams, \
22039 "balloon." NAME, \
22040 stats[i].val) < 0) \
22041 return -1;
22043 for (i = 0; i < nr_stats; i++) {
22044 STORE_MEM_RECORD(SWAP_IN, "swap_in")
22045 STORE_MEM_RECORD(SWAP_OUT, "swap_out")
22046 STORE_MEM_RECORD(MAJOR_FAULT, "major_fault")
22047 STORE_MEM_RECORD(MINOR_FAULT, "minor_fault")
22048 STORE_MEM_RECORD(UNUSED, "unused")
22049 STORE_MEM_RECORD(AVAILABLE, "available")
22050 STORE_MEM_RECORD(RSS, "rss")
22051 STORE_MEM_RECORD(LAST_UPDATE, "last-update")
22052 STORE_MEM_RECORD(USABLE, "usable")
22053 STORE_MEM_RECORD(DISK_CACHES, "disk_caches")
22056 #undef STORE_MEM_RECORD
22058 return 0;
22062 static int
22063 qemuDomainGetStatsVcpu(virQEMUDriverPtr driver,
22064 virDomainObjPtr dom,
22065 virDomainStatsRecordPtr record,
22066 int *maxparams,
22067 unsigned int privflags)
22069 virDomainVcpuDefPtr vcpu;
22070 qemuDomainVcpuPrivatePtr vcpupriv;
22071 size_t i;
22072 int ret = -1;
22073 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
22074 virVcpuInfoPtr cpuinfo = NULL;
22075 unsigned long long *cpuwait = NULL;
22077 if (virTypedParamsAddUInt(&record->params,
22078 &record->nparams,
22079 maxparams,
22080 "vcpu.current",
22081 virDomainDefGetVcpus(dom->def)) < 0)
22082 return -1;
22084 if (virTypedParamsAddUInt(&record->params,
22085 &record->nparams,
22086 maxparams,
22087 "vcpu.maximum",
22088 virDomainDefGetVcpusMax(dom->def)) < 0)
22089 return -1;
22091 if (VIR_ALLOC_N(cpuinfo, virDomainDefGetVcpus(dom->def)) < 0 ||
22092 VIR_ALLOC_N(cpuwait, virDomainDefGetVcpus(dom->def)) < 0)
22093 goto cleanup;
22095 if (HAVE_JOB(privflags) && virDomainObjIsActive(dom) &&
22096 qemuDomainRefreshVcpuHalted(driver, dom, QEMU_ASYNC_JOB_NONE) < 0) {
22097 /* it's ok to be silent and go ahead, because halted vcpu info
22098 * wasn't here from the beginning */
22099 virResetLastError();
22102 if (qemuDomainHelperGetVcpus(dom, cpuinfo, cpuwait,
22103 virDomainDefGetVcpus(dom->def),
22104 NULL, 0) < 0) {
22105 virResetLastError();
22106 ret = 0; /* it's ok to be silent and go ahead */
22107 goto cleanup;
22110 for (i = 0; i < virDomainDefGetVcpus(dom->def); i++) {
22111 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
22112 "vcpu.%u.state", cpuinfo[i].number);
22113 if (virTypedParamsAddInt(&record->params,
22114 &record->nparams,
22115 maxparams,
22116 param_name,
22117 cpuinfo[i].state) < 0)
22118 goto cleanup;
22120 /* stats below are available only if the VM is alive */
22121 if (!virDomainObjIsActive(dom))
22122 continue;
22124 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
22125 "vcpu.%u.time", cpuinfo[i].number);
22126 if (virTypedParamsAddULLong(&record->params,
22127 &record->nparams,
22128 maxparams,
22129 param_name,
22130 cpuinfo[i].cpuTime) < 0)
22131 goto cleanup;
22132 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
22133 "vcpu.%u.wait", cpuinfo[i].number);
22134 if (virTypedParamsAddULLong(&record->params,
22135 &record->nparams,
22136 maxparams,
22137 param_name,
22138 cpuwait[i]) < 0)
22139 goto cleanup;
22141 /* state below is extracted from the individual vcpu structs */
22142 if (!(vcpu = virDomainDefGetVcpu(dom->def, cpuinfo[i].number)))
22143 continue;
22145 vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
22147 if (vcpupriv->halted != VIR_TRISTATE_BOOL_ABSENT) {
22148 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
22149 "vcpu.%u.halted", cpuinfo[i].number);
22150 if (virTypedParamsAddBoolean(&record->params,
22151 &record->nparams,
22152 maxparams,
22153 param_name,
22154 vcpupriv->halted == VIR_TRISTATE_BOOL_YES) < 0)
22155 goto cleanup;
22159 ret = 0;
22161 cleanup:
22162 VIR_FREE(cpuinfo);
22163 VIR_FREE(cpuwait);
22164 return ret;
22167 #define QEMU_ADD_COUNT_PARAM(record, maxparams, type, count) \
22168 do { \
22169 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22170 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \
22171 if (virTypedParamsAddUInt(&(record)->params, \
22172 &(record)->nparams, \
22173 maxparams, \
22174 param_name, \
22175 count) < 0) \
22176 goto cleanup; \
22177 } while (0)
22179 #define QEMU_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \
22180 do { \
22181 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22182 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22183 "%s.%zu.%s", type, num, subtype); \
22184 if (virTypedParamsAddString(&(record)->params, \
22185 &(record)->nparams, \
22186 maxparams, \
22187 param_name, \
22188 name) < 0) \
22189 goto cleanup; \
22190 } while (0)
22192 #define QEMU_ADD_NET_PARAM(record, maxparams, num, name, value) \
22193 do { \
22194 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22195 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22196 "net.%zu.%s", num, name); \
22197 if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
22198 &(record)->nparams, \
22199 maxparams, \
22200 param_name, \
22201 value) < 0) \
22202 return -1; \
22203 } while (0)
22205 static int
22206 qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
22207 virDomainObjPtr dom,
22208 virDomainStatsRecordPtr record,
22209 int *maxparams,
22210 unsigned int privflags ATTRIBUTE_UNUSED)
22212 size_t i;
22213 struct _virDomainInterfaceStats tmp;
22214 int ret = -1;
22216 if (!virDomainObjIsActive(dom))
22217 return 0;
22219 QEMU_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets);
22221 /* Check the path is one of the domain's network interfaces. */
22222 for (i = 0; i < dom->def->nnets; i++) {
22223 virDomainNetDefPtr net = dom->def->nets[i];
22224 virDomainNetType actualType;
22226 if (!net->ifname)
22227 continue;
22229 memset(&tmp, 0, sizeof(tmp));
22231 actualType = virDomainNetGetActualType(net);
22233 QEMU_ADD_NAME_PARAM(record, maxparams,
22234 "net", "name", i, net->ifname);
22236 if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
22237 if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) {
22238 virResetLastError();
22239 continue;
22241 } else {
22242 if (virNetDevTapInterfaceStats(net->ifname, &tmp,
22243 !virDomainNetTypeSharesHostView(net)) < 0) {
22244 virResetLastError();
22245 continue;
22249 QEMU_ADD_NET_PARAM(record, maxparams, i,
22250 "rx.bytes", tmp.rx_bytes);
22251 QEMU_ADD_NET_PARAM(record, maxparams, i,
22252 "rx.pkts", tmp.rx_packets);
22253 QEMU_ADD_NET_PARAM(record, maxparams, i,
22254 "rx.errs", tmp.rx_errs);
22255 QEMU_ADD_NET_PARAM(record, maxparams, i,
22256 "rx.drop", tmp.rx_drop);
22257 QEMU_ADD_NET_PARAM(record, maxparams, i,
22258 "tx.bytes", tmp.tx_bytes);
22259 QEMU_ADD_NET_PARAM(record, maxparams, i,
22260 "tx.pkts", tmp.tx_packets);
22261 QEMU_ADD_NET_PARAM(record, maxparams, i,
22262 "tx.errs", tmp.tx_errs);
22263 QEMU_ADD_NET_PARAM(record, maxparams, i,
22264 "tx.drop", tmp.tx_drop);
22267 ret = 0;
22268 cleanup:
22269 return ret;
22272 #undef QEMU_ADD_NET_PARAM
22274 #define QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, num, name, value) \
22275 do { \
22276 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22277 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22278 "block.%zu.%s", num, name); \
22279 if (virTypedParamsAddUInt(&(record)->params, \
22280 &(record)->nparams, \
22281 maxparams, \
22282 param_name, \
22283 value) < 0) \
22284 goto cleanup; \
22285 } while (0)
22287 /* expects a LL, but typed parameter must be ULL */
22288 #define QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, num, name, value) \
22289 do { \
22290 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22291 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22292 "block.%zu.%s", num, name); \
22293 if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
22294 &(record)->nparams, \
22295 maxparams, \
22296 param_name, \
22297 value) < 0) \
22298 goto cleanup; \
22299 } while (0)
22301 #define QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, num, name, value) \
22302 do { \
22303 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22304 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22305 "block.%zu.%s", num, name); \
22306 if (virTypedParamsAddULLong(&(record)->params, \
22307 &(record)->nparams, \
22308 maxparams, \
22309 param_name, \
22310 value) < 0) \
22311 goto cleanup; \
22312 } while (0)
22314 /* refresh information by opening images on the disk */
22315 static int
22316 qemuDomainGetStatsOneBlockFallback(virQEMUDriverPtr driver,
22317 virQEMUDriverConfigPtr cfg,
22318 virDomainObjPtr dom,
22319 virDomainStatsRecordPtr record,
22320 int *maxparams,
22321 virStorageSourcePtr src,
22322 size_t block_idx)
22324 int ret = -1;
22326 if (virStorageSourceIsEmpty(src))
22327 return 0;
22329 if (qemuStorageLimitsRefresh(driver, cfg, dom, src) < 0) {
22330 virResetLastError();
22331 return 0;
22334 if (src->allocation)
22335 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22336 "allocation", src->allocation);
22337 if (src->capacity)
22338 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22339 "capacity", src->capacity);
22340 if (src->physical)
22341 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22342 "physical", src->physical);
22343 ret = 0;
22344 cleanup:
22345 return ret;
22350 * qemuDomainGetStatsOneBlockRefreshNamed:
22351 * @src: disk source structure
22352 * @alias: disk alias
22353 * @stats: hash table containing stats for all disks
22354 * @nodedata: reply containing 'query-named-block-nodes' data
22356 * Refresh disk block stats data (qemuBlockStatsPtr) which are present only
22357 * in the reply of 'query-named-block-nodes' in cases when the data was gathered
22358 * by using query-block originally.
22360 static void
22361 qemuDomainGetStatsOneBlockRefreshNamed(virStorageSourcePtr src,
22362 const char *alias,
22363 virHashTablePtr stats,
22364 virHashTablePtr nodedata)
22366 qemuBlockStatsPtr entry;
22368 virJSONValuePtr data;
22369 unsigned long long tmp;
22371 if (!nodedata || !src->nodestorage)
22372 return;
22374 if (!(entry = virHashLookup(stats, alias)))
22375 return;
22377 if (!(data = virHashLookup(nodedata, src->nodestorage)))
22378 return;
22380 if (virJSONValueObjectGetNumberUlong(data, "write_threshold", &tmp) == 0)
22381 entry->write_threshold = tmp;
22385 static int
22386 qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
22387 virQEMUDriverConfigPtr cfg,
22388 virDomainObjPtr dom,
22389 virDomainStatsRecordPtr record,
22390 int *maxparams,
22391 const char *entryname,
22392 virStorageSourcePtr src,
22393 size_t block_idx,
22394 virHashTablePtr stats)
22396 qemuBlockStats *entry;
22397 int ret = -1;
22399 /* the VM is offline so we have to go and load the stast from the disk by
22400 * ourselves */
22401 if (!virDomainObjIsActive(dom)) {
22402 ret = qemuDomainGetStatsOneBlockFallback(driver, cfg, dom, record,
22403 maxparams, src, block_idx);
22404 goto cleanup;
22407 /* In case where qemu didn't provide the stats we stop here rather than
22408 * trying to refresh the stats from the disk. Inability to provide stats is
22409 * usually caused by blocked storage so this would make libvirtd hang */
22410 if (!stats || !entryname || !(entry = virHashLookup(stats, entryname))) {
22411 ret = 0;
22412 goto cleanup;
22415 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22416 "allocation", entry->wr_highest_offset);
22418 if (entry->capacity)
22419 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22420 "capacity", entry->capacity);
22421 if (entry->physical) {
22422 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22423 "physical", entry->physical);
22424 } else {
22425 if (qemuDomainStorageUpdatePhysical(driver, cfg, dom, src) == 0) {
22426 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22427 "physical", src->physical);
22428 } else {
22429 virResetLastError();
22433 ret = 0;
22434 cleanup:
22435 return ret;
22439 static int
22440 qemuDomainGetStatsBlockExportBackendStorage(const char *entryname,
22441 virHashTablePtr stats,
22442 size_t recordnr,
22443 virDomainStatsRecordPtr records,
22444 int *nrecords)
22446 qemuBlockStats *entry;
22447 int ret = -1;
22449 if (!stats || !entryname || !(entry = virHashLookup(stats, entryname))) {
22450 ret = 0;
22451 goto cleanup;
22454 if (entry->write_threshold)
22455 QEMU_ADD_BLOCK_PARAM_ULL(records, nrecords, recordnr, "threshold",
22456 entry->write_threshold);
22458 ret = 0;
22459 cleanup:
22460 return ret;
22464 static int
22465 qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
22466 virHashTablePtr stats,
22467 size_t recordnr,
22468 virDomainStatsRecordPtr records,
22469 int *nrecords)
22471 qemuBlockStats *entry;
22472 int ret = -1;
22474 /* In case where qemu didn't provide the stats we stop here rather than
22475 * trying to refresh the stats from the disk. Inability to provide stats is
22476 * usually caused by blocked storage so this would make libvirtd hang */
22477 if (!stats || !frontendname || !(entry = virHashLookup(stats, frontendname))) {
22478 ret = 0;
22479 goto cleanup;
22482 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.reqs", entry->rd_req);
22483 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.bytes", entry->rd_bytes);
22484 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.times", entry->rd_total_times);
22485 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.reqs", entry->wr_req);
22486 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.bytes", entry->wr_bytes);
22487 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.times", entry->wr_total_times);
22488 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "fl.reqs", entry->flush_req);
22489 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "fl.times", entry->flush_total_times);
22491 ret = 0;
22492 cleanup:
22493 return ret;
22497 static int
22498 qemuDomainGetStatsBlockExportHeader(virDomainDiskDefPtr disk,
22499 virStorageSourcePtr src,
22500 size_t recordnr,
22501 virDomainStatsRecordPtr records,
22502 int *nrecords)
22504 int ret = -1;
22506 QEMU_ADD_NAME_PARAM(records, nrecords, "block", "name", recordnr, disk->dst);
22508 if (virStorageSourceIsLocalStorage(src) && src->path)
22509 QEMU_ADD_NAME_PARAM(records, nrecords, "block", "path", recordnr, src->path);
22510 if (src->id)
22511 QEMU_ADD_BLOCK_PARAM_UI(records, nrecords, recordnr, "backingIndex",
22512 src->id);
22514 ret = 0;
22515 cleanup:
22516 return ret;
22520 static int
22521 qemuDomainGetStatsBlockExportDisk(virDomainDiskDefPtr disk,
22522 virHashTablePtr stats,
22523 virHashTablePtr nodestats,
22524 virDomainStatsRecordPtr records,
22525 int *nrecords,
22526 size_t *recordnr,
22527 bool visitBacking,
22528 virQEMUDriverPtr driver,
22529 virQEMUDriverConfigPtr cfg,
22530 virDomainObjPtr dom,
22531 bool blockdev)
22534 char *alias = NULL;
22535 virStorageSourcePtr n;
22536 const char *frontendalias;
22537 const char *backendalias;
22538 const char *backendstoragealias;
22539 int ret = -1;
22542 * This helps to keep logs clean from error messages on getting stats
22543 * for optional disk with nonexistent source file. We won't get any
22544 * stats for such a disk anyway in below code.
22546 if (!virDomainObjIsActive(dom) &&
22547 qemuDomainDiskIsMissingLocalOptional(disk)) {
22548 VIR_INFO("optional disk '%s' source file is missing, "
22549 "skip getting stats", disk->dst);
22551 return qemuDomainGetStatsBlockExportHeader(disk, disk->src, *recordnr,
22552 records, nrecords);
22555 for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
22556 if (blockdev) {
22557 frontendalias = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
22558 backendalias = n->nodeformat;
22559 backendstoragealias = n->nodestorage;
22560 } else {
22561 /* alias may be NULL if the VM is not running */
22562 if (disk->info.alias &&
22563 !(alias = qemuDomainStorageAlias(disk->info.alias, n->id)))
22564 goto cleanup;
22566 qemuDomainGetStatsOneBlockRefreshNamed(n, alias, stats, nodestats);
22568 frontendalias = alias;
22569 backendalias = alias;
22570 backendstoragealias = alias;
22573 if (qemuDomainGetStatsBlockExportHeader(disk, n, *recordnr,
22574 records, nrecords) < 0)
22575 goto cleanup;
22577 /* The following stats make sense only for the frontend device */
22578 if (n == disk->src) {
22579 if (qemuDomainGetStatsBlockExportFrontend(frontendalias, stats, *recordnr,
22580 records, nrecords) < 0)
22581 goto cleanup;
22584 if (qemuDomainGetStatsOneBlock(driver, cfg, dom, records, nrecords,
22585 backendalias, n, *recordnr,
22586 stats) < 0)
22587 goto cleanup;
22589 if (qemuDomainGetStatsBlockExportBackendStorage(backendstoragealias,
22590 stats, *recordnr,
22591 records, nrecords) < 0)
22592 goto cleanup;
22594 VIR_FREE(alias);
22595 (*recordnr)++;
22597 if (!visitBacking)
22598 break;
22601 ret = 0;
22603 cleanup:
22604 VIR_FREE(alias);
22605 return ret;
22609 static int
22610 qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
22611 virDomainObjPtr dom,
22612 virDomainStatsRecordPtr record,
22613 int *maxparams,
22614 unsigned int privflags)
22616 size_t i;
22617 int ret = -1;
22618 int rc;
22619 virHashTablePtr stats = NULL;
22620 virHashTablePtr nodestats = NULL;
22621 virJSONValuePtr nodedata = NULL;
22622 qemuDomainObjPrivatePtr priv = dom->privateData;
22623 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
22624 bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
22625 bool fetchnodedata = virQEMUCapsGet(priv->qemuCaps,
22626 QEMU_CAPS_QUERY_NAMED_BLOCK_NODES) && !blockdev;
22627 int count_index = -1;
22628 size_t visited = 0;
22629 bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING);
22631 if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) {
22632 qemuDomainObjEnterMonitor(driver, dom);
22634 rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, visitBacking);
22636 if (rc >= 0) {
22637 if (blockdev)
22638 rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, stats);
22639 else
22640 ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats,
22641 visitBacking));
22644 if (fetchnodedata)
22645 nodedata = qemuMonitorQueryNamedBlockNodes(priv->mon);
22647 if (qemuDomainObjExitMonitor(driver, dom) < 0)
22648 goto cleanup;
22650 /* failure to retrieve stats is fine at this point */
22651 if (rc < 0 || (fetchnodedata && !nodedata))
22652 virResetLastError();
22655 if (nodedata &&
22656 !(nodestats = qemuBlockGetNodeData(nodedata)))
22657 goto cleanup;
22659 /* When listing backing chains, it's easier to fix up the count
22660 * after the iteration than it is to iterate twice; but we still
22661 * want count listed first. */
22662 count_index = record->nparams;
22663 QEMU_ADD_COUNT_PARAM(record, maxparams, "block", 0);
22665 for (i = 0; i < dom->def->ndisks; i++) {
22666 if (qemuDomainGetStatsBlockExportDisk(dom->def->disks[i], stats, nodestats,
22667 record, maxparams, &visited,
22668 visitBacking, driver, cfg, dom,
22669 blockdev) < 0)
22670 goto cleanup;
22673 record->params[count_index].value.ui = visited;
22674 ret = 0;
22676 cleanup:
22677 virHashFree(stats);
22678 virHashFree(nodestats);
22679 virJSONValueFree(nodedata);
22680 virObjectUnref(cfg);
22681 return ret;
22684 #undef QEMU_ADD_BLOCK_PARAM_LL
22686 #undef QEMU_ADD_BLOCK_PARAM_ULL
22688 #undef QEMU_ADD_NAME_PARAM
22690 #define QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams, id, name, value) \
22691 do { \
22692 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22693 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22694 "iothread.%u.%s", id, name); \
22695 if (virTypedParamsAddUInt(&(record)->params, \
22696 &(record)->nparams, \
22697 maxparams, \
22698 param_name, \
22699 value) < 0) \
22700 goto cleanup; \
22701 } while (0)
22703 #define QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams, id, name, value) \
22704 do { \
22705 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22706 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22707 "iothread.%u.%s", id, name); \
22708 if (virTypedParamsAddULLong(&(record)->params, \
22709 &(record)->nparams, \
22710 maxparams, \
22711 param_name, \
22712 value) < 0) \
22713 goto cleanup; \
22714 } while (0)
22716 static int
22717 qemuDomainGetStatsIOThread(virQEMUDriverPtr driver,
22718 virDomainObjPtr dom,
22719 virDomainStatsRecordPtr record,
22720 int *maxparams,
22721 unsigned int privflags ATTRIBUTE_UNUSED)
22723 qemuDomainObjPrivatePtr priv = dom->privateData;
22724 size_t i;
22725 qemuMonitorIOThreadInfoPtr *iothreads = NULL;
22726 int niothreads;
22727 int ret = -1;
22729 if (!virDomainObjIsActive(dom))
22730 return 0;
22732 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD))
22733 return 0;
22735 if ((niothreads = qemuDomainGetIOThreadsMon(driver, dom, &iothreads)) < 0)
22736 return -1;
22738 if (niothreads == 0)
22739 return 0;
22741 QEMU_ADD_COUNT_PARAM(record, maxparams, "iothread", niothreads);
22743 for (i = 0; i < niothreads; i++) {
22744 if (iothreads[i]->poll_valid) {
22745 QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams,
22746 iothreads[i]->iothread_id,
22747 "poll-max-ns",
22748 iothreads[i]->poll_max_ns);
22749 QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
22750 iothreads[i]->iothread_id,
22751 "poll-grow",
22752 iothreads[i]->poll_grow);
22753 QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
22754 iothreads[i]->iothread_id,
22755 "poll-shrink",
22756 iothreads[i]->poll_shrink);
22760 ret = 0;
22762 cleanup:
22763 for (i = 0; i < niothreads; i++)
22764 VIR_FREE(iothreads[i]);
22765 VIR_FREE(iothreads);
22767 return ret;
22770 #undef QEMU_ADD_IOTHREAD_PARAM_UI
22772 #undef QEMU_ADD_IOTHREAD_PARAM_ULL
22774 #undef QEMU_ADD_COUNT_PARAM
22776 static int
22777 qemuDomainGetStatsPerfOneEvent(virPerfPtr perf,
22778 virPerfEventType type,
22779 virDomainStatsRecordPtr record,
22780 int *maxparams)
22782 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
22783 uint64_t value = 0;
22785 if (virPerfReadEvent(perf, type, &value) < 0)
22786 return -1;
22788 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "perf.%s",
22789 virPerfEventTypeToString(type));
22791 if (virTypedParamsAddULLong(&record->params,
22792 &record->nparams,
22793 maxparams,
22794 param_name,
22795 value) < 0)
22796 return -1;
22798 return 0;
22801 static int
22802 qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
22803 virDomainObjPtr dom,
22804 virDomainStatsRecordPtr record,
22805 int *maxparams,
22806 unsigned int privflags ATTRIBUTE_UNUSED)
22808 size_t i;
22809 qemuDomainObjPrivatePtr priv = dom->privateData;
22810 int ret = -1;
22812 for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
22813 if (!virPerfEventIsEnabled(priv->perf, i))
22814 continue;
22816 if (qemuDomainGetStatsPerfOneEvent(priv->perf, i,
22817 record, maxparams) < 0)
22818 goto cleanup;
22821 ret = 0;
22823 cleanup:
22824 return ret;
22827 typedef int
22828 (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
22829 virDomainObjPtr dom,
22830 virDomainStatsRecordPtr record,
22831 int *maxparams,
22832 unsigned int flags);
22834 struct qemuDomainGetStatsWorker {
22835 qemuDomainGetStatsFunc func;
22836 unsigned int stats;
22837 bool monitor;
22840 static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
22841 { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false },
22842 { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false },
22843 { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true },
22844 { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true },
22845 { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
22846 { qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
22847 { qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false },
22848 { qemuDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD, true },
22849 { NULL, 0, false }
22853 static int
22854 qemuDomainGetStatsCheckSupport(unsigned int *stats,
22855 bool enforce)
22857 unsigned int supportedstats = 0;
22858 size_t i;
22860 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++)
22861 supportedstats |= qemuDomainGetStatsWorkers[i].stats;
22863 if (*stats == 0) {
22864 *stats = supportedstats;
22865 return 0;
22868 if (enforce &&
22869 *stats & ~supportedstats) {
22870 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
22871 _("Stats types bits 0x%x are not supported by this daemon"),
22872 *stats & ~supportedstats);
22873 return -1;
22876 *stats &= supportedstats;
22877 return 0;
22881 static bool
22882 qemuDomainGetStatsNeedMonitor(unsigned int stats)
22884 size_t i;
22886 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++)
22887 if (stats & qemuDomainGetStatsWorkers[i].stats &&
22888 qemuDomainGetStatsWorkers[i].monitor)
22889 return true;
22891 return false;
22895 static int
22896 qemuDomainGetStats(virConnectPtr conn,
22897 virDomainObjPtr dom,
22898 unsigned int stats,
22899 virDomainStatsRecordPtr *record,
22900 unsigned int flags)
22902 int maxparams = 0;
22903 virDomainStatsRecordPtr tmp;
22904 size_t i;
22905 int ret = -1;
22907 if (VIR_ALLOC(tmp) < 0)
22908 goto cleanup;
22910 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++) {
22911 if (stats & qemuDomainGetStatsWorkers[i].stats) {
22912 if (qemuDomainGetStatsWorkers[i].func(conn->privateData, dom, tmp,
22913 &maxparams, flags) < 0)
22914 goto cleanup;
22918 if (!(tmp->dom = virGetDomain(conn, dom->def->name,
22919 dom->def->uuid, dom->def->id)))
22920 goto cleanup;
22922 *record = tmp;
22923 tmp = NULL;
22924 ret = 0;
22926 cleanup:
22927 if (tmp) {
22928 virTypedParamsFree(tmp->params, tmp->nparams);
22929 VIR_FREE(tmp);
22932 return ret;
22936 static int
22937 qemuConnectGetAllDomainStats(virConnectPtr conn,
22938 virDomainPtr *doms,
22939 unsigned int ndoms,
22940 unsigned int stats,
22941 virDomainStatsRecordPtr **retStats,
22942 unsigned int flags)
22944 virQEMUDriverPtr driver = conn->privateData;
22945 virErrorPtr orig_err = NULL;
22946 virDomainObjPtr *vms = NULL;
22947 virDomainObjPtr vm;
22948 size_t nvms;
22949 virDomainStatsRecordPtr *tmpstats = NULL;
22950 bool enforce = !!(flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS);
22951 int nstats = 0;
22952 size_t i;
22953 int ret = -1;
22954 unsigned int privflags = 0;
22955 unsigned int domflags = 0;
22956 unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
22957 VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
22958 VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
22960 virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
22961 VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
22962 VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE |
22963 VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT |
22964 VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING |
22965 VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1);
22967 if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
22968 return -1;
22970 if (qemuDomainGetStatsCheckSupport(&stats, enforce) < 0)
22971 return -1;
22973 if (ndoms) {
22974 if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
22975 &nvms, virConnectGetAllDomainStatsCheckACL,
22976 lflags, true) < 0)
22977 return -1;
22978 } else {
22979 if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
22980 virConnectGetAllDomainStatsCheckACL,
22981 lflags) < 0)
22982 return -1;
22985 if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0)
22986 goto cleanup;
22988 if (qemuDomainGetStatsNeedMonitor(stats))
22989 privflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
22991 for (i = 0; i < nvms; i++) {
22992 virDomainStatsRecordPtr tmp = NULL;
22993 domflags = 0;
22994 vm = vms[i];
22996 virObjectLock(vm);
22998 if (HAVE_JOB(privflags)) {
22999 int rv;
23001 if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT)
23002 rv = qemuDomainObjBeginJobNowait(driver, vm, QEMU_JOB_QUERY);
23003 else
23004 rv = qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY);
23006 if (rv == 0)
23007 domflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
23009 /* else: without a job it's still possible to gather some data */
23011 if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING)
23012 domflags |= QEMU_DOMAIN_STATS_BACKING;
23013 if (qemuDomainGetStats(conn, vm, stats, &tmp, domflags) < 0) {
23014 if (HAVE_JOB(domflags) && vm)
23015 qemuDomainObjEndJob(driver, vm);
23017 virObjectUnlock(vm);
23018 goto cleanup;
23021 if (tmp)
23022 tmpstats[nstats++] = tmp;
23024 if (HAVE_JOB(domflags))
23025 qemuDomainObjEndJob(driver, vm);
23027 virObjectUnlock(vm);
23030 *retStats = tmpstats;
23031 tmpstats = NULL;
23033 ret = nstats;
23035 cleanup:
23036 virErrorPreserveLast(&orig_err);
23037 virDomainStatsRecordListFree(tmpstats);
23038 virObjectListFreeCount(vms, nvms);
23039 virErrorRestore(&orig_err);
23041 return ret;
23045 static int
23046 qemuNodeAllocPages(virConnectPtr conn,
23047 unsigned int npages,
23048 unsigned int *pageSizes,
23049 unsigned long long *pageCounts,
23050 int startCell,
23051 unsigned int cellCount,
23052 unsigned int flags)
23054 bool add = !(flags & VIR_NODE_ALLOC_PAGES_SET);
23056 virCheckFlags(VIR_NODE_ALLOC_PAGES_SET, -1);
23058 if (virNodeAllocPagesEnsureACL(conn) < 0)
23059 return -1;
23061 return virHostMemAllocPages(npages, pageSizes, pageCounts,
23062 startCell, cellCount, add);
23066 static int
23067 qemuDomainGetFSInfo(virDomainPtr dom,
23068 virDomainFSInfoPtr **info,
23069 unsigned int flags)
23071 virQEMUDriverPtr driver = dom->conn->privateData;
23072 virDomainObjPtr vm;
23073 qemuAgentPtr agent;
23074 virCapsPtr caps = NULL;
23075 virDomainDefPtr def = NULL;
23076 int ret = -1;
23078 virCheckFlags(0, ret);
23080 if (!(vm = qemuDomObjFromDomain(dom)))
23081 return ret;
23083 if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0)
23084 goto cleanup;
23086 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
23087 goto cleanup;
23089 if (virDomainObjCheckActive(vm) < 0)
23090 goto endjob;
23092 if (!qemuDomainAgentAvailable(vm, true))
23093 goto endjob;
23095 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
23096 goto endjob;
23098 if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, false)))
23099 goto endjob;
23101 agent = qemuDomainObjEnterAgent(vm);
23102 ret = qemuAgentGetFSInfo(agent, info, def);
23103 qemuDomainObjExitAgent(vm, agent);
23105 endjob:
23106 qemuDomainObjEndAgentJob(vm);
23108 cleanup:
23109 virDomainObjEndAPI(&vm);
23110 virDomainDefFree(def);
23111 virObjectUnref(caps);
23112 return ret;
23115 static int
23116 qemuDomainInterfaceAddresses(virDomainPtr dom,
23117 virDomainInterfacePtr **ifaces,
23118 unsigned int source,
23119 unsigned int flags)
23121 virQEMUDriverPtr driver = dom->conn->privateData;
23122 virDomainObjPtr vm = NULL;
23123 qemuAgentPtr agent;
23124 int ret = -1;
23126 virCheckFlags(0, -1);
23128 if (!(vm = qemuDomObjFromDomain(dom)))
23129 goto cleanup;
23131 if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0)
23132 goto cleanup;
23134 if (virDomainObjCheckActive(vm) < 0)
23135 goto cleanup;
23137 switch (source) {
23138 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE:
23139 ret = qemuGetDHCPInterfaces(dom, vm, ifaces);
23140 break;
23142 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT:
23143 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
23144 goto cleanup;
23146 if (!qemuDomainAgentAvailable(vm, true))
23147 goto endjob;
23149 agent = qemuDomainObjEnterAgent(vm);
23150 ret = qemuAgentGetInterfaces(agent, ifaces);
23151 qemuDomainObjExitAgent(vm, agent);
23153 endjob:
23154 qemuDomainObjEndAgentJob(vm);
23156 break;
23158 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP:
23159 ret = qemuARPGetInterfaces(vm, ifaces);
23160 break;
23162 default:
23163 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
23164 _("Unknown IP address data source %d"),
23165 source);
23166 break;
23169 cleanup:
23170 virDomainObjEndAPI(&vm);
23171 return ret;
23174 static int
23175 qemuGetDHCPInterfaces(virDomainPtr dom,
23176 virDomainObjPtr vm,
23177 virDomainInterfacePtr **ifaces)
23179 int rv = -1;
23180 int n_leases = 0;
23181 size_t i, j;
23182 size_t ifaces_count = 0;
23183 virNetworkPtr network = NULL;
23184 char macaddr[VIR_MAC_STRING_BUFLEN];
23185 virDomainInterfacePtr iface = NULL;
23186 virNetworkDHCPLeasePtr *leases = NULL;
23187 virDomainInterfacePtr *ifaces_ret = NULL;
23189 if (!dom->conn->networkDriver ||
23190 !dom->conn->networkDriver->networkGetDHCPLeases) {
23191 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
23192 _("Network driver does not support DHCP lease query"));
23193 return -1;
23196 for (i = 0; i < vm->def->nnets; i++) {
23197 if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK)
23198 continue;
23200 virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
23201 virObjectUnref(network);
23202 network = virNetworkLookupByName(dom->conn,
23203 vm->def->nets[i]->data.network.name);
23205 if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
23206 &leases, 0)) < 0)
23207 goto error;
23209 if (n_leases) {
23210 if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0)
23211 goto error;
23213 if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0)
23214 goto error;
23216 iface = ifaces_ret[ifaces_count - 1];
23217 /* Assuming each lease corresponds to a separate IP */
23218 iface->naddrs = n_leases;
23220 if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0)
23221 goto error;
23223 if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0)
23224 goto error;
23226 if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
23227 goto error;
23230 for (j = 0; j < n_leases; j++) {
23231 virNetworkDHCPLeasePtr lease = leases[j];
23232 virDomainIPAddressPtr ip_addr = &iface->addrs[j];
23234 if (VIR_STRDUP(ip_addr->addr, lease->ipaddr) < 0)
23235 goto error;
23237 ip_addr->type = lease->type;
23238 ip_addr->prefix = lease->prefix;
23241 for (j = 0; j < n_leases; j++)
23242 virNetworkDHCPLeaseFree(leases[j]);
23244 VIR_FREE(leases);
23247 VIR_STEAL_PTR(*ifaces, ifaces_ret);
23248 rv = ifaces_count;
23250 cleanup:
23251 virObjectUnref(network);
23252 if (leases) {
23253 for (i = 0; i < n_leases; i++)
23254 virNetworkDHCPLeaseFree(leases[i]);
23256 VIR_FREE(leases);
23258 return rv;
23260 error:
23261 if (ifaces_ret) {
23262 for (i = 0; i < ifaces_count; i++)
23263 virDomainInterfaceFree(ifaces_ret[i]);
23265 VIR_FREE(ifaces_ret);
23267 goto cleanup;
23271 static int
23272 qemuARPGetInterfaces(virDomainObjPtr vm,
23273 virDomainInterfacePtr **ifaces)
23275 size_t i, j;
23276 size_t ifaces_count = 0;
23277 int ret = -1;
23278 char macaddr[VIR_MAC_STRING_BUFLEN];
23279 virDomainInterfacePtr *ifaces_ret = NULL;
23280 virDomainInterfacePtr iface = NULL;
23281 virArpTablePtr table;
23283 table = virArpTableGet();
23284 if (!table)
23285 goto cleanup;
23287 for (i = 0; i < vm->def->nnets; i++) {
23288 virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
23289 for (j = 0; j < table->n; j++) {
23290 virArpTableEntry entry = table->t[j];
23292 if (STREQ(entry.mac, macaddr)) {
23293 if (VIR_ALLOC(iface) < 0)
23294 goto cleanup;
23296 if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0)
23297 goto cleanup;
23299 if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
23300 goto cleanup;
23302 if (VIR_ALLOC(iface->addrs) < 0)
23303 goto cleanup;
23304 iface->naddrs = 1;
23306 if (VIR_STRDUP(iface->addrs->addr, entry.ipaddr) < 0)
23307 goto cleanup;
23309 if (VIR_APPEND_ELEMENT(ifaces_ret, ifaces_count, iface) < 0)
23310 goto cleanup;
23315 VIR_STEAL_PTR(*ifaces, ifaces_ret);
23316 ret = ifaces_count;
23318 cleanup:
23319 virArpTableFree(table);
23320 virDomainInterfaceFree(iface);
23322 if (ifaces_ret) {
23323 for (i = 0; i < ifaces_count; i++)
23324 virDomainInterfaceFree(ifaces_ret[i]);
23326 VIR_FREE(ifaces_ret);
23328 return ret;
23332 static int
23333 qemuDomainSetUserPassword(virDomainPtr dom,
23334 const char *user,
23335 const char *password,
23336 unsigned int flags)
23338 virQEMUDriverPtr driver = dom->conn->privateData;
23339 virDomainObjPtr vm;
23340 qemuAgentPtr agent;
23341 int ret = -1;
23342 int rv;
23344 virCheckFlags(VIR_DOMAIN_PASSWORD_ENCRYPTED, -1);
23346 if (!(vm = qemuDomObjFromDomain(dom)))
23347 return ret;
23349 if (virDomainSetUserPasswordEnsureACL(dom->conn, vm->def) < 0)
23350 goto cleanup;
23352 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
23353 goto cleanup;
23355 if (virDomainObjCheckActive(vm) < 0)
23356 goto endjob;
23358 if (!qemuDomainAgentAvailable(vm, true))
23359 goto endjob;
23361 agent = qemuDomainObjEnterAgent(vm);
23362 rv = qemuAgentSetUserPassword(agent, user, password,
23363 flags & VIR_DOMAIN_PASSWORD_ENCRYPTED);
23364 qemuDomainObjExitAgent(vm, agent);
23366 if (rv < 0)
23367 goto endjob;
23369 ret = 0;
23371 endjob:
23372 qemuDomainObjEndAgentJob(vm);
23374 cleanup:
23375 virDomainObjEndAPI(&vm);
23376 return ret;
23380 static int
23381 qemuDomainRenameCallback(virDomainObjPtr vm,
23382 const char *new_name,
23383 unsigned int flags,
23384 void *opaque)
23386 virQEMUDriverPtr driver = opaque;
23387 virQEMUDriverConfigPtr cfg = NULL;
23388 virObjectEventPtr event_new = NULL;
23389 virObjectEventPtr event_old = NULL;
23390 int ret = -1;
23391 char *new_dom_name = NULL;
23392 char *old_dom_name = NULL;
23393 char *new_dom_cfg_file = NULL;
23394 char *old_dom_cfg_file = NULL;
23395 char *new_dom_autostart_link = NULL;
23396 char *old_dom_autostart_link = NULL;
23398 virCheckFlags(0, ret);
23400 if (strchr(new_name, '/')) {
23401 virReportError(VIR_ERR_XML_ERROR,
23402 _("name %s cannot contain '/'"), new_name);
23403 return -1;
23406 cfg = virQEMUDriverGetConfig(driver);
23408 if (VIR_STRDUP(new_dom_name, new_name) < 0)
23409 goto cleanup;
23411 if (!(new_dom_cfg_file = virDomainConfigFile(cfg->configDir,
23412 new_dom_name)) ||
23413 !(old_dom_cfg_file = virDomainConfigFile(cfg->configDir,
23414 vm->def->name)))
23415 goto cleanup;
23417 if (vm->autostart) {
23418 if (!(new_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
23419 new_dom_name)) ||
23420 !(old_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
23421 vm->def->name)))
23422 goto cleanup;
23424 if (symlink(new_dom_cfg_file, new_dom_autostart_link) < 0) {
23425 virReportSystemError(errno,
23426 _("Failed to create symlink '%s to '%s'"),
23427 new_dom_autostart_link, new_dom_cfg_file);
23428 goto cleanup;
23432 event_old = virDomainEventLifecycleNewFromObj(vm,
23433 VIR_DOMAIN_EVENT_UNDEFINED,
23434 VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);
23436 /* Switch name in domain definition. */
23437 old_dom_name = vm->def->name;
23438 vm->def->name = new_dom_name;
23439 new_dom_name = NULL;
23441 if (virDomainSaveConfig(cfg->configDir, driver->caps, vm->def) < 0)
23442 goto rollback;
23444 if (virFileExists(old_dom_cfg_file) &&
23445 unlink(old_dom_cfg_file) < 0) {
23446 virReportSystemError(errno,
23447 _("cannot remove old domain config file %s"),
23448 old_dom_cfg_file);
23449 goto rollback;
23452 if (vm->autostart) {
23453 if (virFileIsLink(old_dom_autostart_link) &&
23454 unlink(old_dom_autostart_link) < 0) {
23455 virReportSystemError(errno,
23456 _("Failed to delete symlink '%s'"),
23457 old_dom_autostart_link);
23458 goto rollback;
23462 event_new = virDomainEventLifecycleNewFromObj(vm,
23463 VIR_DOMAIN_EVENT_DEFINED,
23464 VIR_DOMAIN_EVENT_DEFINED_RENAMED);
23465 ret = 0;
23467 cleanup:
23468 VIR_FREE(old_dom_autostart_link);
23469 VIR_FREE(new_dom_autostart_link);
23470 VIR_FREE(old_dom_cfg_file);
23471 VIR_FREE(new_dom_cfg_file);
23472 VIR_FREE(old_dom_name);
23473 VIR_FREE(new_dom_name);
23474 virObjectEventStateQueue(driver->domainEventState, event_old);
23475 virObjectEventStateQueue(driver->domainEventState, event_new);
23476 virObjectUnref(cfg);
23477 return ret;
23479 rollback:
23480 if (old_dom_name) {
23481 new_dom_name = vm->def->name;
23482 vm->def->name = old_dom_name;
23483 old_dom_name = NULL;
23486 if (virFileExists(new_dom_cfg_file))
23487 unlink(new_dom_cfg_file);
23489 if (vm->autostart &&
23490 virFileExists(new_dom_autostart_link))
23491 unlink(new_dom_autostart_link);
23493 goto cleanup;
23496 static int qemuDomainRename(virDomainPtr dom,
23497 const char *new_name,
23498 unsigned int flags)
23500 virQEMUDriverPtr driver = dom->conn->privateData;
23501 virDomainObjPtr vm = NULL;
23502 int ret = -1;
23504 virCheckFlags(0, ret);
23506 if (!(vm = qemuDomObjFromDomain(dom)))
23507 goto cleanup;
23509 if (virDomainRenameEnsureACL(dom->conn, vm->def) < 0)
23510 goto cleanup;
23512 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23513 goto cleanup;
23515 if (virDomainObjIsActive(vm)) {
23516 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23517 _("cannot rename active domain"));
23518 goto endjob;
23521 if (!vm->persistent) {
23522 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23523 _("cannot rename a transient domain"));
23524 goto endjob;
23527 if (vm->hasManagedSave) {
23528 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23529 _("domain with a managed saved state can't be renamed"));
23530 goto endjob;
23533 if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
23534 virReportError(VIR_ERR_OPERATION_INVALID,
23535 "%s", _("domain has to be shutoff before renaming"));
23536 goto endjob;
23539 if (virDomainSnapshotObjListNum(vm->snapshots, NULL, 0) > 0) {
23540 virReportError(VIR_ERR_OPERATION_INVALID,
23541 "%s", _("cannot rename domain with snapshots"));
23542 goto endjob;
23545 if (virDomainListAllCheckpoints(vm->checkpoints, NULL, dom, NULL, flags) > 0) {
23546 virReportError(VIR_ERR_OPERATION_INVALID,
23547 "%s", _("cannot rename domain with checkpoints"));
23548 goto endjob;
23551 if (virDomainObjListRename(driver->domains, vm, new_name, flags,
23552 qemuDomainRenameCallback, driver) < 0)
23553 goto endjob;
23555 /* Success, domain has been renamed. */
23556 ret = 0;
23558 endjob:
23559 qemuDomainObjEndJob(driver, vm);
23561 cleanup:
23562 virDomainObjEndAPI(&vm);
23563 return ret;
23567 static int
23568 qemuDomainGetGuestVcpusParams(virTypedParameterPtr *params,
23569 unsigned int *nparams,
23570 qemuAgentCPUInfoPtr info,
23571 int ninfo)
23573 virTypedParameterPtr par = NULL;
23574 int npar = 0;
23575 int maxpar = 0;
23576 virBitmapPtr vcpus = NULL;
23577 virBitmapPtr online = NULL;
23578 virBitmapPtr offlinable = NULL;
23579 char *tmp = NULL;
23580 size_t i;
23581 int ret = -1;
23583 if (!(vcpus = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)) ||
23584 !(online = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)) ||
23585 !(offlinable = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)))
23586 goto cleanup;
23588 for (i = 0; i < ninfo; i++) {
23589 if (virBitmapSetBit(vcpus, info[i].id) < 0) {
23590 virReportError(VIR_ERR_INTERNAL_ERROR,
23591 _("vcpu id '%u' reported by guest agent is out of "
23592 "range"), info[i].id);
23593 goto cleanup;
23596 if (info[i].online)
23597 ignore_value(virBitmapSetBit(online, info[i].id));
23599 if (info[i].offlinable)
23600 ignore_value(virBitmapSetBit(offlinable, info[i].id));
23603 #define ADD_BITMAP(name) \
23604 if (!(tmp = virBitmapFormat(name))) \
23605 goto cleanup; \
23606 if (virTypedParamsAddString(&par, &npar, &maxpar, #name, tmp) < 0) \
23607 goto cleanup; \
23608 VIR_FREE(tmp)
23610 ADD_BITMAP(vcpus);
23611 ADD_BITMAP(online);
23612 ADD_BITMAP(offlinable);
23614 #undef ADD_BITMAP
23616 *params = par;
23617 *nparams = npar;
23618 par = NULL;
23619 ret = 0;
23621 cleanup:
23622 VIR_FREE(tmp);
23623 virBitmapFree(vcpus);
23624 virBitmapFree(online);
23625 virBitmapFree(offlinable);
23626 virTypedParamsFree(par, npar);
23627 return ret;
23631 static int
23632 qemuDomainGetGuestVcpus(virDomainPtr dom,
23633 virTypedParameterPtr *params,
23634 unsigned int *nparams,
23635 unsigned int flags)
23637 virQEMUDriverPtr driver = dom->conn->privateData;
23638 virDomainObjPtr vm = NULL;
23639 qemuAgentPtr agent;
23640 qemuAgentCPUInfoPtr info = NULL;
23641 int ninfo = 0;
23642 int ret = -1;
23644 virCheckFlags(0, ret);
23646 if (!(vm = qemuDomObjFromDomain(dom)))
23647 goto cleanup;
23649 if (virDomainGetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
23650 goto cleanup;
23652 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
23653 goto cleanup;
23655 if (!qemuDomainAgentAvailable(vm, true))
23656 goto endjob;
23658 agent = qemuDomainObjEnterAgent(vm);
23659 ninfo = qemuAgentGetVCPUs(agent, &info);
23660 qemuDomainObjExitAgent(vm, agent);
23662 if (ninfo < 0)
23663 goto endjob;
23665 if (qemuDomainGetGuestVcpusParams(params, nparams, info, ninfo) < 0)
23666 goto endjob;
23668 ret = 0;
23670 endjob:
23671 qemuDomainObjEndAgentJob(vm);
23673 cleanup:
23674 VIR_FREE(info);
23675 virDomainObjEndAPI(&vm);
23676 return ret;
23680 static int
23681 qemuDomainSetGuestVcpus(virDomainPtr dom,
23682 const char *cpumap,
23683 int state,
23684 unsigned int flags)
23686 virQEMUDriverPtr driver = dom->conn->privateData;
23687 virDomainObjPtr vm = NULL;
23688 virBitmapPtr map = NULL;
23689 qemuAgentCPUInfoPtr info = NULL;
23690 qemuAgentPtr agent;
23691 int ninfo = 0;
23692 size_t i;
23693 int ret = -1;
23695 virCheckFlags(0, -1);
23697 if (state != 0 && state != 1) {
23698 virReportInvalidArg(state, "%s", _("unsupported state value"));
23699 return -1;
23702 if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
23703 goto cleanup;
23705 if (!(vm = qemuDomObjFromDomain(dom)))
23706 goto cleanup;
23708 if (virDomainSetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
23709 goto cleanup;
23711 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
23712 goto cleanup;
23714 if (!qemuDomainAgentAvailable(vm, true))
23715 goto endjob;
23717 agent = qemuDomainObjEnterAgent(vm);
23718 ninfo = qemuAgentGetVCPUs(agent, &info);
23719 qemuDomainObjExitAgent(vm, agent);
23720 agent = NULL;
23722 if (ninfo < 0)
23723 goto endjob;
23725 for (i = 0; i < ninfo; i++) {
23726 if (!virBitmapIsBitSet(map, info[i].id))
23727 continue;
23729 if (!state && !info[i].offlinable) {
23730 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
23731 _("vCPU '%u' is not offlinable"), info[i].id);
23732 goto endjob;
23735 info[i].online = !!state;
23736 info[i].modified = true;
23738 ignore_value(virBitmapClearBit(map, info[i].id));
23741 if (!virBitmapIsAllClear(map)) {
23742 char *tmp = virBitmapFormat(map);
23743 virReportError(VIR_ERR_INVALID_ARG,
23744 _("guest is missing vCPUs '%s'"), NULLSTR(tmp));
23745 VIR_FREE(tmp);
23746 goto endjob;
23749 if (!qemuDomainAgentAvailable(vm, true))
23750 goto endjob;
23752 agent = qemuDomainObjEnterAgent(vm);
23753 ret = qemuAgentSetVCPUs(agent, info, ninfo);
23754 qemuDomainObjExitAgent(vm, agent);
23756 endjob:
23757 qemuDomainObjEndAgentJob(vm);
23759 cleanup:
23760 VIR_FREE(info);
23761 virBitmapFree(map);
23762 virDomainObjEndAPI(&vm);
23763 return ret;
23767 static int
23768 qemuDomainSetVcpu(virDomainPtr dom,
23769 const char *cpumap,
23770 int state,
23771 unsigned int flags)
23773 virQEMUDriverPtr driver = dom->conn->privateData;
23774 virDomainObjPtr vm = NULL;
23775 virDomainDefPtr def = NULL;
23776 virDomainDefPtr persistentDef = NULL;
23777 virBitmapPtr map = NULL;
23778 ssize_t lastvcpu;
23779 int ret = -1;
23781 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
23782 VIR_DOMAIN_AFFECT_CONFIG, -1);
23784 if (state != 0 && state != 1) {
23785 virReportInvalidArg(state, "%s", _("unsupported state value"));
23786 return -1;
23789 if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
23790 goto cleanup;
23792 if ((lastvcpu = virBitmapLastSetBit(map)) < 0) {
23793 virReportError(VIR_ERR_INVALID_ARG, "%s",
23794 _("no vcpus selected for modification"));
23795 goto cleanup;
23798 if (!(vm = qemuDomObjFromDomain(dom)))
23799 goto cleanup;
23801 if (virDomainSetVcpuEnsureACL(dom->conn, vm->def, flags) < 0)
23802 goto cleanup;
23804 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23805 goto cleanup;
23807 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
23808 goto endjob;
23810 if (persistentDef) {
23811 if (lastvcpu >= virDomainDefGetVcpusMax(persistentDef)) {
23812 virReportError(VIR_ERR_INVALID_ARG,
23813 _("vcpu %zd is not present in persistent config"),
23814 lastvcpu);
23815 goto endjob;
23819 if (def) {
23820 if (lastvcpu >= virDomainDefGetVcpusMax(def)) {
23821 virReportError(VIR_ERR_INVALID_ARG,
23822 _("vcpu %zd is not present in live config"),
23823 lastvcpu);
23824 goto endjob;
23828 ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map, !!state);
23830 endjob:
23831 qemuDomainObjEndJob(driver, vm);
23833 cleanup:
23834 virBitmapFree(map);
23835 virDomainObjEndAPI(&vm);
23836 return ret;
23840 static int
23841 qemuDomainSetBlockThreshold(virDomainPtr dom,
23842 const char *dev,
23843 unsigned long long threshold,
23844 unsigned int flags)
23846 virQEMUDriverPtr driver = dom->conn->privateData;
23847 qemuDomainObjPrivatePtr priv;
23848 virDomainObjPtr vm = NULL;
23849 virStorageSourcePtr src;
23850 char *nodename = NULL;
23851 int rc;
23852 int ret = -1;
23854 virCheckFlags(0, -1);
23856 if (!(vm = qemuDomObjFromDomain(dom)))
23857 goto cleanup;
23859 priv = vm->privateData;
23861 if (virDomainSetBlockThresholdEnsureACL(dom->conn, vm->def) < 0)
23862 goto cleanup;
23864 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23865 goto cleanup;
23867 if (virDomainObjCheckActive(vm) < 0)
23868 goto endjob;
23870 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_WRITE_THRESHOLD)) {
23871 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
23872 _("this qemu does not support setting device threshold"));
23873 goto endjob;
23876 if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def)))
23877 goto endjob;
23879 if (!src->nodestorage &&
23880 qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
23881 goto endjob;
23883 if (!src->nodestorage) {
23884 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
23885 _("threshold currently can't be set for block device '%s'"),
23886 dev);
23887 goto endjob;
23890 if (VIR_STRDUP(nodename, src->nodestorage) < 0)
23891 goto endjob;
23893 qemuDomainObjEnterMonitor(driver, vm);
23894 rc = qemuMonitorSetBlockThreshold(priv->mon, nodename, threshold);
23895 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
23896 goto endjob;
23898 ret = 0;
23900 endjob:
23901 qemuDomainObjEndJob(driver, vm);
23903 cleanup:
23904 VIR_FREE(nodename);
23905 virDomainObjEndAPI(&vm);
23906 return ret;
23910 static void
23911 qemuDomainModifyLifecycleAction(virDomainDefPtr def,
23912 virDomainLifecycle type,
23913 virDomainLifecycleAction action)
23915 switch (type) {
23916 case VIR_DOMAIN_LIFECYCLE_POWEROFF:
23917 def->onPoweroff = action;
23918 break;
23919 case VIR_DOMAIN_LIFECYCLE_REBOOT:
23920 def->onReboot = action;
23921 break;
23922 case VIR_DOMAIN_LIFECYCLE_CRASH:
23923 def->onCrash = action;
23924 break;
23925 case VIR_DOMAIN_LIFECYCLE_LAST:
23926 break;
23932 static int
23933 qemuDomainSetLifecycleAction(virDomainPtr dom,
23934 unsigned int type,
23935 unsigned int action,
23936 unsigned int flags)
23938 virQEMUDriverPtr driver = dom->conn->privateData;
23939 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
23940 qemuDomainObjPrivatePtr priv;
23941 virDomainObjPtr vm = NULL;
23942 virDomainDefPtr def = NULL;
23943 virDomainDefPtr persistentDef = NULL;
23944 int ret = -1;
23946 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
23947 VIR_DOMAIN_AFFECT_CONFIG, -1);
23949 if (!virDomainDefLifecycleActionAllowed(type, action))
23950 goto cleanup;
23952 if (!(vm = qemuDomObjFromDomain(dom)))
23953 goto cleanup;
23955 priv = vm->privateData;
23957 if (virDomainSetLifecycleActionEnsureACL(dom->conn, vm->def) < 0)
23958 goto cleanup;
23960 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23961 goto cleanup;
23963 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
23964 goto endjob;
23966 if (def) {
23967 if (priv->allowReboot == VIR_TRISTATE_BOOL_NO) {
23968 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
23969 _("cannot update lifecycle action because QEMU "
23970 "was started with -no-reboot option"));
23971 goto endjob;
23974 qemuDomainModifyLifecycleAction(def, type, action);
23976 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
23977 vm, driver->caps) < 0)
23978 goto endjob;
23981 if (persistentDef) {
23982 qemuDomainModifyLifecycleAction(persistentDef, type, action);
23984 if (virDomainSaveConfig(cfg->configDir, driver->caps,
23985 persistentDef) < 0)
23986 goto endjob;
23989 ret = 0;
23991 endjob:
23992 qemuDomainObjEndJob(driver, vm);
23994 cleanup:
23995 virDomainObjEndAPI(&vm);
23996 virObjectUnref(cfg);
23997 return ret;
24001 static int
24002 qemuGetSEVInfoToParams(virQEMUCapsPtr qemuCaps,
24003 virTypedParameterPtr *params,
24004 int *nparams,
24005 unsigned int flags)
24007 int maxpar = 0;
24008 int n = 0;
24009 virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
24010 virTypedParameterPtr sevParams = NULL;
24012 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
24014 if (virTypedParamsAddString(&sevParams, &n, &maxpar,
24015 VIR_NODE_SEV_PDH, sev->pdh) < 0)
24016 return -1;
24018 if (virTypedParamsAddString(&sevParams, &n, &maxpar,
24019 VIR_NODE_SEV_CERT_CHAIN, sev->cert_chain) < 0)
24020 goto cleanup;
24022 if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
24023 VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
24024 goto cleanup;
24026 if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
24027 VIR_NODE_SEV_REDUCED_PHYS_BITS,
24028 sev->reduced_phys_bits) < 0)
24029 goto cleanup;
24031 VIR_STEAL_PTR(*params, sevParams);
24032 *nparams = n;
24033 return 0;
24035 cleanup:
24036 virTypedParamsFree(sevParams, n);
24037 return -1;
24041 static int
24042 qemuNodeGetSEVInfo(virConnectPtr conn,
24043 virTypedParameterPtr *params,
24044 int *nparams,
24045 unsigned int flags)
24047 virQEMUDriverPtr driver = conn->privateData;
24048 virQEMUCapsPtr qemucaps = NULL;
24049 int ret = -1;
24051 if (virNodeGetSevInfoEnsureACL(conn) < 0)
24052 return ret;
24054 qemucaps = virQEMUCapsCacheLookupByArch(driver->qemuCapsCache,
24055 virArchFromHost());
24056 if (!qemucaps)
24057 goto cleanup;
24059 if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
24060 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
24061 _("QEMU does not support SEV guest"));
24062 goto cleanup;
24065 if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
24066 goto cleanup;
24068 ret = 0;
24070 cleanup:
24071 virObjectUnref(qemucaps);
24073 return ret;
24077 static int
24078 qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
24079 virDomainObjPtr vm,
24080 virTypedParameterPtr *params,
24081 int *nparams,
24082 unsigned int flags)
24084 int ret = -1;
24085 char *tmp = NULL;
24086 int maxpar = 0;
24088 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
24090 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
24091 return -1;
24093 qemuDomainObjEnterMonitor(driver, vm);
24094 tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
24096 if (qemuDomainObjExitMonitor(driver, vm) < 0)
24097 goto endjob;
24099 if (!tmp)
24100 goto endjob;
24102 if (virTypedParamsAddString(params, nparams, &maxpar,
24103 VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
24104 tmp) < 0)
24105 goto endjob;
24107 ret = 0;
24109 endjob:
24110 VIR_FREE(tmp);
24111 qemuDomainObjEndJob(driver, vm);
24112 return ret;
24116 static int
24117 qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
24118 virTypedParameterPtr *params,
24119 int *nparams,
24120 unsigned int flags)
24122 virQEMUDriverPtr driver = domain->conn->privateData;
24123 virDomainObjPtr vm;
24124 int ret = -1;
24126 if (!(vm = qemuDomObjFromDomain(domain)))
24127 goto cleanup;
24129 if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
24130 goto cleanup;
24132 if (vm->def->sev) {
24133 if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0)
24134 goto cleanup;
24137 ret = 0;
24139 cleanup:
24140 virDomainObjEndAPI(&vm);
24141 return ret;
24144 static virHypervisorDriver qemuHypervisorDriver = {
24145 .name = QEMU_DRIVER_NAME,
24146 .connectURIProbe = qemuConnectURIProbe,
24147 .connectOpen = qemuConnectOpen, /* 0.2.0 */
24148 .connectClose = qemuConnectClose, /* 0.2.0 */
24149 .connectSupportsFeature = qemuConnectSupportsFeature, /* 0.5.0 */
24150 .connectGetType = qemuConnectGetType, /* 0.2.0 */
24151 .connectGetVersion = qemuConnectGetVersion, /* 0.2.0 */
24152 .connectGetHostname = qemuConnectGetHostname, /* 0.3.3 */
24153 .connectGetSysinfo = qemuConnectGetSysinfo, /* 0.8.8 */
24154 .connectGetMaxVcpus = qemuConnectGetMaxVcpus, /* 0.2.1 */
24155 .nodeGetInfo = qemuNodeGetInfo, /* 0.2.0 */
24156 .connectGetCapabilities = qemuConnectGetCapabilities, /* 0.2.1 */
24157 .connectListDomains = qemuConnectListDomains, /* 0.2.0 */
24158 .connectNumOfDomains = qemuConnectNumOfDomains, /* 0.2.0 */
24159 .connectListAllDomains = qemuConnectListAllDomains, /* 0.9.13 */
24160 .domainCreateXML = qemuDomainCreateXML, /* 0.2.0 */
24161 .domainLookupByID = qemuDomainLookupByID, /* 0.2.0 */
24162 .domainLookupByUUID = qemuDomainLookupByUUID, /* 0.2.0 */
24163 .domainLookupByName = qemuDomainLookupByName, /* 0.2.0 */
24164 .domainSuspend = qemuDomainSuspend, /* 0.2.0 */
24165 .domainResume = qemuDomainResume, /* 0.2.0 */
24166 .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
24167 .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */
24168 .domainReboot = qemuDomainReboot, /* 0.9.3 */
24169 .domainReset = qemuDomainReset, /* 0.9.7 */
24170 .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
24171 .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
24172 .domainGetOSType = qemuDomainGetOSType, /* 0.2.2 */
24173 .domainGetMaxMemory = qemuDomainGetMaxMemory, /* 0.4.2 */
24174 .domainSetMaxMemory = qemuDomainSetMaxMemory, /* 0.4.2 */
24175 .domainSetMemory = qemuDomainSetMemory, /* 0.4.2 */
24176 .domainSetMemoryFlags = qemuDomainSetMemoryFlags, /* 0.9.0 */
24177 .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
24178 .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
24179 .domainSetMemoryStatsPeriod = qemuDomainSetMemoryStatsPeriod, /* 1.1.1 */
24180 .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
24181 .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
24182 .domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
24183 .domainGetState = qemuDomainGetState, /* 0.9.2 */
24184 .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
24185 .domainSave = qemuDomainSave, /* 0.2.0 */
24186 .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
24187 .domainRestore = qemuDomainRestore, /* 0.2.0 */
24188 .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
24189 .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
24190 .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
24191 .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */
24192 .domainCoreDumpWithFormat = qemuDomainCoreDumpWithFormat, /* 1.2.3 */
24193 .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
24194 .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
24195 .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
24196 .domainGetVcpusFlags = qemuDomainGetVcpusFlags, /* 0.8.5 */
24197 .domainPinVcpu = qemuDomainPinVcpu, /* 0.4.4 */
24198 .domainPinVcpuFlags = qemuDomainPinVcpuFlags, /* 0.9.3 */
24199 .domainGetVcpuPinInfo = qemuDomainGetVcpuPinInfo, /* 0.9.3 */
24200 .domainPinEmulator = qemuDomainPinEmulator, /* 0.10.0 */
24201 .domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
24202 .domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
24203 .domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
24204 .domainGetIOThreadInfo = qemuDomainGetIOThreadInfo, /* 1.2.14 */
24205 .domainPinIOThread = qemuDomainPinIOThread, /* 1.2.14 */
24206 .domainAddIOThread = qemuDomainAddIOThread, /* 1.2.15 */
24207 .domainDelIOThread = qemuDomainDelIOThread, /* 1.2.15 */
24208 .domainSetIOThreadParams = qemuDomainSetIOThreadParams, /* 4.10.0 */
24209 .domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
24210 .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
24211 .nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
24212 .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
24213 .connectDomainXMLFromNative = qemuConnectDomainXMLFromNative, /* 0.6.4 */
24214 .connectDomainXMLToNative = qemuConnectDomainXMLToNative, /* 0.6.4 */
24215 .connectListDefinedDomains = qemuConnectListDefinedDomains, /* 0.2.0 */
24216 .connectNumOfDefinedDomains = qemuConnectNumOfDefinedDomains, /* 0.2.0 */
24217 .domainCreate = qemuDomainCreate, /* 0.2.0 */
24218 .domainCreateWithFlags = qemuDomainCreateWithFlags, /* 0.8.2 */
24219 .domainDefineXML = qemuDomainDefineXML, /* 0.2.0 */
24220 .domainDefineXMLFlags = qemuDomainDefineXMLFlags, /* 1.2.12 */
24221 .domainUndefine = qemuDomainUndefine, /* 0.2.0 */
24222 .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
24223 .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */
24224 .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */
24225 .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */
24226 .domainDetachDeviceFlags = qemuDomainDetachDeviceFlags, /* 0.7.7 */
24227 .domainUpdateDeviceFlags = qemuDomainUpdateDeviceFlags, /* 0.8.0 */
24228 .domainDetachDeviceAlias = qemuDomainDetachDeviceAlias, /* 4.4.0 */
24229 .domainGetAutostart = qemuDomainGetAutostart, /* 0.2.1 */
24230 .domainSetAutostart = qemuDomainSetAutostart, /* 0.2.1 */
24231 .domainGetSchedulerType = qemuDomainGetSchedulerType, /* 0.7.0 */
24232 .domainGetSchedulerParameters = qemuDomainGetSchedulerParameters, /* 0.7.0 */
24233 .domainGetSchedulerParametersFlags = qemuDomainGetSchedulerParametersFlags, /* 0.9.2 */
24234 .domainSetSchedulerParameters = qemuDomainSetSchedulerParameters, /* 0.7.0 */
24235 .domainSetSchedulerParametersFlags = qemuDomainSetSchedulerParametersFlags, /* 0.9.2 */
24236 .domainMigratePerform = qemuDomainMigratePerform, /* 0.5.0 */
24237 .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
24238 .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
24239 .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
24240 .domainInterfaceStats = qemuDomainInterfaceStats, /* 0.4.1 */
24241 .domainMemoryStats = qemuDomainMemoryStats, /* 0.7.5 */
24242 .domainBlockPeek = qemuDomainBlockPeek, /* 0.4.4 */
24243 .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */
24244 .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
24245 .nodeGetCPUStats = qemuNodeGetCPUStats, /* 0.9.3 */
24246 .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */
24247 .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */
24248 .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */
24249 .connectDomainEventRegister = qemuConnectDomainEventRegister, /* 0.5.0 */
24250 .connectDomainEventDeregister = qemuConnectDomainEventDeregister, /* 0.5.0 */
24251 .domainMigratePrepare2 = qemuDomainMigratePrepare2, /* 0.5.0 */
24252 .domainMigrateFinish2 = qemuDomainMigrateFinish2, /* 0.5.0 */
24253 .nodeDeviceDettach = qemuNodeDeviceDettach, /* 0.6.1 */
24254 .nodeDeviceDetachFlags = qemuNodeDeviceDetachFlags, /* 1.0.5 */
24255 .nodeDeviceReAttach = qemuNodeDeviceReAttach, /* 0.6.1 */
24256 .nodeDeviceReset = qemuNodeDeviceReset, /* 0.6.1 */
24257 .domainMigratePrepareTunnel = qemuDomainMigratePrepareTunnel, /* 0.7.2 */
24258 .connectIsEncrypted = qemuConnectIsEncrypted, /* 0.7.3 */
24259 .connectIsSecure = qemuConnectIsSecure, /* 0.7.3 */
24260 .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
24261 .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
24262 .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
24263 .connectCompareCPU = qemuConnectCompareCPU, /* 0.7.5 */
24264 .connectBaselineCPU = qemuConnectBaselineCPU, /* 0.7.7 */
24265 .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
24266 .domainGetJobStats = qemuDomainGetJobStats, /* 1.0.3 */
24267 .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
24268 .domainMigrateGetMaxDowntime = qemuDomainMigrateGetMaxDowntime, /* 3.7.0 */
24269 .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
24270 .domainMigrateGetCompressionCache = qemuDomainMigrateGetCompressionCache, /* 1.0.3 */
24271 .domainMigrateSetCompressionCache = qemuDomainMigrateSetCompressionCache, /* 1.0.3 */
24272 .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
24273 .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
24274 .connectDomainEventRegisterAny = qemuConnectDomainEventRegisterAny, /* 0.8.0 */
24275 .connectDomainEventDeregisterAny = qemuConnectDomainEventDeregisterAny, /* 0.8.0 */
24276 .domainManagedSave = qemuDomainManagedSave, /* 0.8.0 */
24277 .domainHasManagedSaveImage = qemuDomainHasManagedSaveImage, /* 0.8.0 */
24278 .domainManagedSaveRemove = qemuDomainManagedSaveRemove, /* 0.8.0 */
24279 .domainManagedSaveGetXMLDesc = qemuDomainManagedSaveGetXMLDesc, /* 3.7.0 */
24280 .domainManagedSaveDefineXML = qemuDomainManagedSaveDefineXML, /* 3.7.0 */
24281 .domainSnapshotCreateXML = qemuDomainSnapshotCreateXML, /* 0.8.0 */
24282 .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
24283 .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
24284 .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
24285 .domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
24286 .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
24287 .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
24288 .domainSnapshotListAllChildren = qemuDomainSnapshotListAllChildren, /* 0.9.13 */
24289 .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
24290 .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
24291 .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
24292 .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
24293 .domainSnapshotIsCurrent = qemuDomainSnapshotIsCurrent, /* 0.9.13 */
24294 .domainSnapshotHasMetadata = qemuDomainSnapshotHasMetadata, /* 0.9.13 */
24295 .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
24296 .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
24297 .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
24298 .domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
24299 .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
24300 .connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
24301 .connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
24302 .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
24303 .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
24304 .domainOpenGraphicsFD = qemuDomainOpenGraphicsFD, /* 1.2.8 */
24305 .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
24306 .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
24307 .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
24308 .domainMigratePrepareTunnel3 = qemuDomainMigratePrepareTunnel3, /* 0.9.2 */
24309 .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
24310 .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
24311 .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
24312 .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
24313 .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.3 */
24314 .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.3 */
24315 .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
24316 .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
24317 .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
24318 .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
24319 .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
24320 .domainBlockCopy = qemuDomainBlockCopy, /* 1.2.9 */
24321 .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
24322 .connectIsAlive = qemuConnectIsAlive, /* 0.9.8 */
24323 .nodeSuspendForDuration = qemuNodeSuspendForDuration, /* 0.9.8 */
24324 .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
24325 .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
24326 .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
24327 .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
24328 .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
24329 .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
24330 .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
24331 .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
24332 .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
24333 .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
24334 .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
24335 .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
24336 .nodeGetMemoryParameters = qemuNodeGetMemoryParameters, /* 0.10.2 */
24337 .nodeSetMemoryParameters = qemuNodeSetMemoryParameters, /* 0.10.2 */
24338 .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */
24339 .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
24340 .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
24341 .domainMigrateBegin3Params = qemuDomainMigrateBegin3Params, /* 1.1.0 */
24342 .domainMigratePrepare3Params = qemuDomainMigratePrepare3Params, /* 1.1.0 */
24343 .domainMigratePrepareTunnel3Params = qemuDomainMigratePrepareTunnel3Params, /* 1.1.0 */
24344 .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.1.0 */
24345 .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.1.0 */
24346 .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.1.0 */
24347 .connectGetCPUModelNames = qemuConnectGetCPUModelNames, /* 1.1.3 */
24348 .domainFSFreeze = qemuDomainFSFreeze, /* 1.2.5 */
24349 .domainFSThaw = qemuDomainFSThaw, /* 1.2.5 */
24350 .domainGetHostname = qemuDomainGetHostname, /* 4.8.0 */
24351 .domainGetTime = qemuDomainGetTime, /* 1.2.5 */
24352 .domainSetTime = qemuDomainSetTime, /* 1.2.5 */
24353 .nodeGetFreePages = qemuNodeGetFreePages, /* 1.2.6 */
24354 .connectGetDomainCapabilities = qemuConnectGetDomainCapabilities, /* 1.2.7 */
24355 .connectGetAllDomainStats = qemuConnectGetAllDomainStats, /* 1.2.8 */
24356 .nodeAllocPages = qemuNodeAllocPages, /* 1.2.9 */
24357 .domainGetFSInfo = qemuDomainGetFSInfo, /* 1.2.11 */
24358 .domainInterfaceAddresses = qemuDomainInterfaceAddresses, /* 1.2.14 */
24359 .domainSetUserPassword = qemuDomainSetUserPassword, /* 1.2.16 */
24360 .domainRename = qemuDomainRename, /* 1.2.19 */
24361 .domainMigrateStartPostCopy = qemuDomainMigrateStartPostCopy, /* 1.3.3 */
24362 .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */
24363 .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */
24364 .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
24365 .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
24366 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
24367 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
24368 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
24369 .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
24370 .domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
24371 .domainCheckpointCreateXML = qemuDomainCheckpointCreateXML, /* 5.2.0 */
24372 .domainCheckpointGetXMLDesc = qemuDomainCheckpointGetXMLDesc, /* 5.2.0 */
24374 .domainListCheckpoints = qemuDomainListCheckpoints, /* 5.2.0 */
24375 .domainCheckpointListChildren = qemuDomainCheckpointListChildren, /* 5.2.0 */
24376 .domainCheckpointLookupByName = qemuDomainCheckpointLookupByName, /* 5.2.0 */
24377 .domainHasCurrentCheckpoint = qemuDomainHasCurrentCheckpoint, /* 5.2.0 */
24378 .domainCheckpointGetParent = qemuDomainCheckpointGetParent, /* 5.2.0 */
24379 .domainCheckpointCurrent = qemuDomainCheckpointCurrent, /* 5.2.0 */
24380 .domainCheckpointIsCurrent = qemuDomainCheckpointIsCurrent, /* 5.2.0 */
24381 .domainCheckpointHasMetadata = qemuDomainCheckpointHasMetadata, /* 5.2.0 */
24382 .domainCheckpointDelete = qemuDomainCheckpointDelete, /* 5.2.0 */
24383 .domainBackupBegin = qemuDomainBackupBegin, /* 5.2.0 */
24384 .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 5.2.0 */
24385 .domainBackupEnd = qemuDomainBackupEnd, /* 5.2.0 */
24389 static virConnectDriver qemuConnectDriver = {
24390 .localOnly = true,
24391 .uriSchemes = (const char *[]){ "qemu", NULL },
24392 .hypervisorDriver = &qemuHypervisorDriver,
24395 static virStateDriver qemuStateDriver = {
24396 .name = QEMU_DRIVER_NAME,
24397 .stateInitialize = qemuStateInitialize,
24398 .stateCleanup = qemuStateCleanup,
24399 .stateReload = qemuStateReload,
24400 .stateStop = qemuStateStop,
24403 int qemuRegister(void)
24405 if (virRegisterConnectDriver(&qemuConnectDriver,
24406 true) < 0)
24407 return -1;
24408 if (virRegisterStateDriver(&qemuStateDriver) < 0)
24409 return -1;
24410 return 0;