fixup! to ? - more compiler fixes
[libvirt/ericb.git] / src / qemu / qemu_driver.c
blob667479b505da4883779b742da124f153a45489f3
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"
105 #include "virdomainsnapshotobjlist.h"
106 #include "virdomaincheckpointobjlist.h"
107 #include "backup_conf.h"
109 #define VIR_FROM_THIS VIR_FROM_QEMU
111 VIR_LOG_INIT("qemu.qemu_driver");
113 #define QEMU_NB_MEM_PARAM 3
115 #define QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS 6
116 #define QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS 7
117 #define QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS 6
118 #define QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS 1
119 #define QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS (QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS + \
120 QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS + \
121 QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS + \
122 QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS)
124 #define QEMU_NB_NUMA_PARAM 2
126 #define QEMU_SCHED_MIN_PERIOD 1000LL
127 #define QEMU_SCHED_MAX_PERIOD 1000000LL
128 #define QEMU_SCHED_MIN_QUOTA 1000LL
129 #define QEMU_SCHED_MAX_QUOTA 18446744073709551LL
131 #define QEMU_GUEST_VCPU_MAX_ID 4096
133 #define QEMU_NB_BLKIO_PARAM 6
135 #define QEMU_NB_BANDWIDTH_PARAM 7
137 static void qemuProcessEventHandler(void *data, void *opaque);
139 static int qemuStateCleanup(void);
141 static int qemuDomainObjStart(virConnectPtr conn,
142 virQEMUDriverPtr driver,
143 virDomainObjPtr vm,
144 unsigned int flags,
145 qemuDomainAsyncJob asyncJob);
147 static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
148 void *opaque);
150 static int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
151 bool dynamicOwnership,
152 const char *path, int oflags,
153 bool *needUnlink);
155 static int qemuGetDHCPInterfaces(virDomainPtr dom,
156 virDomainObjPtr vm,
157 virDomainInterfacePtr **ifaces);
159 static int qemuARPGetInterfaces(virDomainObjPtr vm,
160 virDomainInterfacePtr **ifaces);
162 static virQEMUDriverPtr qemu_driver;
165 * qemuDomObjFromDomain:
166 * @domain: Domain pointer that has to be looked up
168 * This function looks up @domain and returns the appropriate virDomainObjPtr
169 * that has to be released by calling virDomainObjEndAPI().
171 * Returns the domain object with incremented reference counter which is locked
172 * on success, NULL otherwise.
174 static virDomainObjPtr
175 qemuDomObjFromDomain(virDomainPtr domain)
177 virDomainObjPtr vm;
178 virQEMUDriverPtr driver = domain->conn->privateData;
179 char uuidstr[VIR_UUID_STRING_BUFLEN];
181 vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
182 if (!vm) {
183 virUUIDFormat(domain->uuid, uuidstr);
184 virReportError(VIR_ERR_NO_DOMAIN,
185 _("no domain with matching uuid '%s' (%s)"),
186 uuidstr, domain->name);
187 return NULL;
190 return vm;
193 /* Looks up the domain object from snapshot and unlocks the
194 * driver. The returned domain object is locked and ref'd and the
195 * caller must call virDomainObjEndAPI() on it. */
196 static virDomainObjPtr
197 qemuDomObjFromSnapshot(virDomainSnapshotPtr snapshot)
199 return qemuDomObjFromDomain(snapshot->domain);
203 /* Looks up snapshot object from VM and name */
204 static virDomainMomentObjPtr
205 qemuSnapObjFromName(virDomainObjPtr vm,
206 const char *name)
208 virDomainMomentObjPtr snap = NULL;
209 snap = virDomainSnapshotFindByName(vm->snapshots, name);
210 if (!snap)
211 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
212 _("no domain snapshot with matching name '%s'"),
213 name);
215 return snap;
219 /* Looks up snapshot object from VM and snapshotPtr */
220 static virDomainMomentObjPtr
221 qemuSnapObjFromSnapshot(virDomainObjPtr vm,
222 virDomainSnapshotPtr snapshot)
224 return qemuSnapObjFromName(vm, snapshot->name);
227 /* Looks up the domain object from checkpoint and unlocks the
228 * driver. The returned domain object is locked and ref'd and the
229 * caller must call virDomainObjEndAPI() on it. */
230 static virDomainObjPtr
231 qemuDomObjFromCheckpoint(virDomainCheckpointPtr checkpoint)
233 return qemuDomObjFromDomain(checkpoint->domain);
237 /* Looks up checkpoint object from VM and name */
238 static virDomainMomentObjPtr
239 qemuCheckObjFromName(virDomainObjPtr vm,
240 const char *name)
242 virDomainMomentObjPtr chk = NULL;
243 chk = virDomainCheckpointFindByName(vm->checkpoints, name);
244 if (!chk)
245 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
246 _("no domain checkpoint with matching name '%s'"),
247 name);
249 return chk;
253 /* Looks up checkpoint object from VM and checkpointPtr */
254 static virDomainMomentObjPtr
255 qemuCheckObjFromCheckpoint(virDomainObjPtr vm,
256 virDomainCheckpointPtr checkpoint)
258 return qemuCheckObjFromName(vm, checkpoint->name);
261 static int
262 qemuAutostartDomain(virDomainObjPtr vm,
263 void *opaque)
265 virQEMUDriverPtr driver = opaque;
266 int flags = 0;
267 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
268 int ret = -1;
270 if (cfg->autoStartBypassCache)
271 flags |= VIR_DOMAIN_START_BYPASS_CACHE;
273 virObjectLock(vm);
274 virObjectRef(vm);
275 virResetLastError();
276 if (vm->autostart &&
277 !virDomainObjIsActive(vm)) {
278 if (qemuProcessBeginJob(driver, vm,
279 VIR_DOMAIN_JOB_OPERATION_START, flags) < 0) {
280 virReportError(VIR_ERR_INTERNAL_ERROR,
281 _("Failed to start job on VM '%s': %s"),
282 vm->def->name, virGetLastErrorMessage());
283 goto cleanup;
286 if (qemuDomainObjStart(NULL, driver, vm, flags,
287 QEMU_ASYNC_JOB_START) < 0) {
288 virReportError(VIR_ERR_INTERNAL_ERROR,
289 _("Failed to autostart VM '%s': %s"),
290 vm->def->name, virGetLastErrorMessage());
293 qemuProcessEndJob(driver, vm);
296 ret = 0;
297 cleanup:
298 virDomainObjEndAPI(&vm);
299 virObjectUnref(cfg);
300 return ret;
304 static void
305 qemuAutostartDomains(virQEMUDriverPtr driver)
307 virDomainObjListForEach(driver->domains, qemuAutostartDomain, driver);
311 static int
312 qemuSecurityChownCallback(const virStorageSource *src,
313 uid_t uid,
314 gid_t gid)
316 struct stat sb;
317 int save_errno = 0;
318 int ret = -1;
319 int rv;
320 VIR_AUTOUNREF(virStorageSourcePtr) cpy = NULL;
322 rv = virStorageFileSupportsSecurityDriver(src);
323 if (rv <= 0)
324 return rv;
326 if (virStorageSourceIsLocalStorage(src)) {
327 /* use direct chown for local files so that the file doesn't
328 * need to be initialized */
329 if (!src->path)
330 return 0;
332 if (stat(src->path, &sb) >= 0) {
333 if (sb.st_uid == uid &&
334 sb.st_gid == gid) {
335 /* It's alright, there's nothing to change anyway. */
336 return 0;
340 if (chown(src->path, uid, gid) < 0)
341 goto cleanup;
342 } else {
343 if (!(cpy = virStorageSourceCopy(src, false)))
344 goto cleanup;
346 /* src file init reports errors, return -2 on failure */
347 if (virStorageFileInit(cpy) < 0) {
348 ret = -2;
349 goto cleanup;
352 if (virStorageFileChown(cpy, uid, gid) < 0)
353 goto cleanup;
356 ret = 0;
358 cleanup:
359 save_errno = errno;
360 virStorageFileDeinit(cpy);
361 errno = save_errno;
363 return ret;
367 static int
368 qemuSecurityInit(virQEMUDriverPtr driver)
370 char **names;
371 virSecurityManagerPtr mgr = NULL;
372 virSecurityManagerPtr stack = NULL;
373 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
374 unsigned int flags = 0;
376 if (cfg->securityDefaultConfined)
377 flags |= VIR_SECURITY_MANAGER_DEFAULT_CONFINED;
378 if (cfg->securityRequireConfined)
379 flags |= VIR_SECURITY_MANAGER_REQUIRE_CONFINED;
380 if (virQEMUDriverIsPrivileged(driver))
381 flags |= VIR_SECURITY_MANAGER_PRIVILEGED;
383 if (cfg->securityDriverNames &&
384 cfg->securityDriverNames[0]) {
385 names = cfg->securityDriverNames;
386 while (names && *names) {
387 if (!(mgr = qemuSecurityNew(*names,
388 QEMU_DRIVER_NAME,
389 flags)))
390 goto error;
391 if (!stack) {
392 if (!(stack = qemuSecurityNewStack(mgr)))
393 goto error;
394 } else {
395 if (qemuSecurityStackAddNested(stack, mgr) < 0)
396 goto error;
398 mgr = NULL;
399 names++;
401 } else {
402 if (!(mgr = qemuSecurityNew(NULL,
403 QEMU_DRIVER_NAME,
404 flags)))
405 goto error;
406 if (!(stack = qemuSecurityNewStack(mgr)))
407 goto error;
408 mgr = NULL;
411 if (virQEMUDriverIsPrivileged(driver)) {
412 if (cfg->dynamicOwnership)
413 flags |= VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP;
414 if (virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT))
415 flags |= VIR_SECURITY_MANAGER_MOUNT_NAMESPACE;
416 if (!(mgr = qemuSecurityNewDAC(QEMU_DRIVER_NAME,
417 cfg->user,
418 cfg->group,
419 flags,
420 qemuSecurityChownCallback)))
421 goto error;
422 if (!stack) {
423 if (!(stack = qemuSecurityNewStack(mgr)))
424 goto error;
425 } else {
426 if (qemuSecurityStackAddNested(stack, mgr) < 0)
427 goto error;
429 mgr = NULL;
432 driver->securityManager = stack;
433 virObjectUnref(cfg);
434 return 0;
436 error:
437 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
438 _("Failed to initialize security drivers"));
439 virObjectUnref(stack);
440 virObjectUnref(mgr);
441 virObjectUnref(cfg);
442 return -1;
446 static int
447 qemuDomainSnapshotLoad(virDomainObjPtr vm,
448 void *data)
450 char *baseDir = (char *)data;
451 char *snapDir = NULL;
452 DIR *dir = NULL;
453 struct dirent *entry;
454 char *xmlStr;
455 char *fullpath;
456 virDomainSnapshotDefPtr def = NULL;
457 virDomainMomentObjPtr snap = NULL;
458 virDomainMomentObjPtr current = NULL;
459 bool cur;
460 unsigned int flags = (VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE |
461 VIR_DOMAIN_SNAPSHOT_PARSE_DISKS |
462 VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL);
463 int ret = -1;
464 virCapsPtr caps = NULL;
465 int direrr;
467 virObjectLock(vm);
468 if (virAsprintf(&snapDir, "%s/%s", baseDir, vm->def->name) < 0) {
469 virReportError(VIR_ERR_INTERNAL_ERROR,
470 _("Failed to allocate memory for "
471 "snapshot directory for domain %s"),
472 vm->def->name);
473 goto cleanup;
476 if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
477 goto cleanup;
479 VIR_INFO("Scanning for snapshots for domain %s in %s", vm->def->name,
480 snapDir);
482 if (virDirOpenIfExists(&dir, snapDir) <= 0)
483 goto cleanup;
485 while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
486 /* NB: ignoring errors, so one malformed config doesn't
487 kill the whole process */
488 VIR_INFO("Loading snapshot file '%s'", entry->d_name);
490 if (virAsprintf(&fullpath, "%s/%s", snapDir, entry->d_name) < 0) {
491 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
492 _("Failed to allocate memory for path"));
493 continue;
496 if (virFileReadAll(fullpath, 1024*1024*1, &xmlStr) < 0) {
497 /* Nothing we can do here, skip this one */
498 virReportSystemError(errno,
499 _("Failed to read snapshot file %s"),
500 fullpath);
501 VIR_FREE(fullpath);
502 continue;
505 def = virDomainSnapshotDefParseString(xmlStr, caps,
506 qemu_driver->xmlopt, &cur,
507 flags);
508 if (def == NULL) {
509 /* Nothing we can do here, skip this one */
510 virReportError(VIR_ERR_INTERNAL_ERROR,
511 _("Failed to parse snapshot XML from file '%s'"),
512 fullpath);
513 VIR_FREE(fullpath);
514 VIR_FREE(xmlStr);
515 continue;
518 snap = virDomainSnapshotAssignDef(vm->snapshots, def);
519 if (snap == NULL) {
520 virDomainSnapshotDefFree(def);
521 } else if (cur) {
522 if (current)
523 virReportError(VIR_ERR_INTERNAL_ERROR,
524 _("Too many snapshots claiming to be current for domain %s"),
525 vm->def->name);
526 current = snap;
529 VIR_FREE(fullpath);
530 VIR_FREE(xmlStr);
532 if (direrr < 0)
533 virReportError(VIR_ERR_INTERNAL_ERROR,
534 _("Failed to fully read directory %s"),
535 snapDir);
537 virDomainSnapshotSetCurrent(vm->snapshots, current);
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 virDomainMomentObjPtr chk = NULL;
576 virDomainMomentObjPtr current = NULL;
577 bool cur;
578 unsigned int flags = (VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE |
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, &cur,
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 (cur) {
639 if (current)
640 virReportError(VIR_ERR_INTERNAL_ERROR,
641 _("Too many snapshots claiming to be current for domain %s"),
642 vm->def->name);
643 current = chk;
646 VIR_FREE(fullpath);
647 VIR_FREE(xmlStr);
649 if (direrr < 0)
650 virReportError(VIR_ERR_INTERNAL_ERROR,
651 _("Failed to fully read directory %s"),
652 chkDir);
654 virDomainCheckpointSetCurrent(vm->checkpoints, current);
656 if (virDomainCheckpointUpdateRelations(vm->checkpoints) < 0)
657 virReportError(VIR_ERR_INTERNAL_ERROR,
658 _("Checkpoints have inconsistent relations for domain %s"),
659 vm->def->name);
661 /* FIXME: qemu keeps internal track of bitmaps, which form the
662 * basis for checkpoints; it would be nice if we could update our
663 * internal state to reflect that information automatically. But
664 * qemu 3.0 did not have access to this via qemu-img for offline
665 * images (you have to use QMP commands on a running guest), and
666 * it also does not track <parent> relations which we find
667 * important in our metadata.
670 virResetLastError();
672 ret = 0;
673 cleanup:
674 VIR_DIR_CLOSE(dir);
675 VIR_FREE(chkDir);
676 virObjectUnref(caps);
677 virObjectUnlock(vm);
678 return ret;
682 static int
683 qemuDomainNetsRestart(virDomainObjPtr vm,
684 void *data ATTRIBUTE_UNUSED)
686 size_t i;
687 virDomainDefPtr def = vm->def;
689 virObjectLock(vm);
691 for (i = 0; i < def->nnets; i++) {
692 virDomainNetDefPtr net = def->nets[i];
693 if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT &&
694 virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_VEPA) {
695 VIR_DEBUG("VEPA mode device %s active in domain %s. Reassociating.",
696 net->ifname, def->name);
697 ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname,
698 &net->mac,
699 virDomainNetGetActualDirectDev(net),
700 def->uuid,
701 virDomainNetGetActualVirtPortProfile(net),
702 VIR_NETDEV_VPORT_PROFILE_OP_CREATE));
706 virObjectUnlock(vm);
707 return 0;
711 static int
712 qemuDomainFindMaxID(virDomainObjPtr vm,
713 void *data)
715 int *driver_maxid = data;
717 if (vm->def->id > *driver_maxid)
718 *driver_maxid = vm->def->id;
720 return 0;
725 * qemuStateInitialize:
727 * Initialization function for the QEMU daemon
729 static int
730 qemuStateInitialize(bool privileged,
731 virStateInhibitCallback callback,
732 void *opaque)
734 char *driverConf = NULL;
735 virQEMUDriverConfigPtr cfg;
736 uid_t run_uid = -1;
737 gid_t run_gid = -1;
738 char *hugepagePath = NULL;
739 char *memoryBackingPath = NULL;
740 size_t i;
741 virCPUDefPtr hostCPU = NULL;
742 unsigned int microcodeVersion = 0;
744 if (VIR_ALLOC(qemu_driver) < 0)
745 return -1;
747 if (virMutexInit(&qemu_driver->lock) < 0) {
748 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
749 _("cannot initialize mutex"));
750 VIR_FREE(qemu_driver);
751 return -1;
754 qemu_driver->inhibitCallback = callback;
755 qemu_driver->inhibitOpaque = opaque;
757 qemu_driver->privileged = privileged;
759 if (!(qemu_driver->domains = virDomainObjListNew()))
760 goto error;
762 /* Init domain events */
763 qemu_driver->domainEventState = virObjectEventStateNew();
764 if (!qemu_driver->domainEventState)
765 goto error;
767 /* read the host sysinfo */
768 if (privileged)
769 qemu_driver->hostsysinfo = virSysinfoRead();
771 if (!(qemu_driver->config = cfg = virQEMUDriverConfigNew(privileged)))
772 goto error;
774 if (virAsprintf(&driverConf, "%s/qemu.conf", cfg->configBaseDir) < 0)
775 goto error;
777 if (virQEMUDriverConfigLoadFile(cfg, driverConf, privileged) < 0)
778 goto error;
779 VIR_FREE(driverConf);
781 if (virQEMUDriverConfigValidate(cfg) < 0)
782 goto error;
784 if (virQEMUDriverConfigSetDefaults(cfg) < 0)
785 goto error;
787 if (virFileMakePath(cfg->stateDir) < 0) {
788 virReportSystemError(errno, _("Failed to create state dir %s"),
789 cfg->stateDir);
790 goto error;
792 if (virFileMakePath(cfg->libDir) < 0) {
793 virReportSystemError(errno, _("Failed to create lib dir %s"),
794 cfg->libDir);
795 goto error;
797 if (virFileMakePath(cfg->cacheDir) < 0) {
798 virReportSystemError(errno, _("Failed to create cache dir %s"),
799 cfg->cacheDir);
800 goto error;
802 if (virFileMakePath(cfg->saveDir) < 0) {
803 virReportSystemError(errno, _("Failed to create save dir %s"),
804 cfg->saveDir);
805 goto error;
807 if (virFileMakePath(cfg->snapshotDir) < 0) {
808 virReportSystemError(errno, _("Failed to create snapshot dir %s"),
809 cfg->snapshotDir);
810 goto error;
812 if (virFileMakePath(cfg->checkpointDir) < 0) {
813 virReportSystemError(errno, _("Failed to create checkpoint dir %s"),
814 cfg->checkpointDir);
815 goto error;
817 if (virFileMakePath(cfg->autoDumpPath) < 0) {
818 virReportSystemError(errno, _("Failed to create dump dir %s"),
819 cfg->autoDumpPath);
820 goto error;
822 if (virFileMakePath(cfg->channelTargetDir) < 0) {
823 virReportSystemError(errno, _("Failed to create channel target dir %s"),
824 cfg->channelTargetDir);
825 goto error;
827 if (virFileMakePath(cfg->nvramDir) < 0) {
828 virReportSystemError(errno, _("Failed to create nvram dir %s"),
829 cfg->nvramDir);
830 goto error;
832 if (virFileMakePath(cfg->memoryBackingDir) < 0) {
833 virReportSystemError(errno, _("Failed to create memory backing dir %s"),
834 cfg->memoryBackingDir);
835 goto error;
838 qemu_driver->qemuImgBinary = virFindFileInPath("qemu-img");
840 if (!(qemu_driver->lockManager =
841 virLockManagerPluginNew(cfg->lockManagerName ?
842 cfg->lockManagerName : "nop",
843 "qemu",
844 cfg->configBaseDir,
845 0)))
846 goto error;
848 if (cfg->macFilter) {
849 if (!(qemu_driver->ebtables = ebtablesContextNew("qemu"))) {
850 virReportSystemError(errno,
851 _("failed to enable mac filter in '%s'"),
852 __FILE__);
853 goto error;
856 if (ebtablesAddForwardPolicyReject(qemu_driver->ebtables) < 0)
857 goto error;
860 /* Allocate bitmap for remote display port reservations. We cannot
861 * do this before the config is loaded properly, since the port
862 * numbers are configurable now */
863 if ((qemu_driver->remotePorts =
864 virPortAllocatorRangeNew(_("display"),
865 cfg->remotePortMin,
866 cfg->remotePortMax)) == NULL)
867 goto error;
869 if ((qemu_driver->webSocketPorts =
870 virPortAllocatorRangeNew(_("webSocket"),
871 cfg->webSocketPortMin,
872 cfg->webSocketPortMax)) == NULL)
873 goto error;
875 if ((qemu_driver->migrationPorts =
876 virPortAllocatorRangeNew(_("migration"),
877 cfg->migrationPortMin,
878 cfg->migrationPortMax)) == NULL)
879 goto error;
881 if (qemuSecurityInit(qemu_driver) < 0)
882 goto error;
884 if (!(qemu_driver->hostdevMgr = virHostdevManagerGetDefault()))
885 goto error;
887 if (!(qemu_driver->sharedDevices = virHashCreate(30, qemuSharedDeviceEntryFree)))
888 goto error;
890 if (qemuMigrationDstErrorInit(qemu_driver) < 0)
891 goto error;
893 if (privileged) {
894 char *channeldir;
896 if (chown(cfg->libDir, cfg->user, cfg->group) < 0) {
897 virReportSystemError(errno,
898 _("unable to set ownership of '%s' to user %d:%d"),
899 cfg->libDir, (int)cfg->user,
900 (int)cfg->group);
901 goto error;
903 if (chown(cfg->cacheDir, cfg->user, cfg->group) < 0) {
904 virReportSystemError(errno,
905 _("unable to set ownership of '%s' to %d:%d"),
906 cfg->cacheDir, (int)cfg->user,
907 (int)cfg->group);
908 goto error;
910 if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) {
911 virReportSystemError(errno,
912 _("unable to set ownership of '%s' to %d:%d"),
913 cfg->saveDir, (int)cfg->user,
914 (int)cfg->group);
915 goto error;
917 if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) {
918 virReportSystemError(errno,
919 _("unable to set ownership of '%s' to %d:%d"),
920 cfg->snapshotDir, (int)cfg->user,
921 (int)cfg->group);
922 goto error;
924 if (chown(cfg->checkpointDir, cfg->user, cfg->group) < 0) {
925 virReportSystemError(errno,
926 _("unable to set ownership of '%s' to %d:%d"),
927 cfg->checkpointDir, (int)cfg->user,
928 (int)cfg->group);
929 goto error;
931 if (chown(cfg->autoDumpPath, cfg->user, cfg->group) < 0) {
932 virReportSystemError(errno,
933 _("unable to set ownership of '%s' to %d:%d"),
934 cfg->autoDumpPath, (int)cfg->user,
935 (int)cfg->group);
936 goto error;
938 if (!(channeldir = mdir_name(cfg->channelTargetDir))) {
939 virReportOOMError();
940 goto error;
942 if (chown(channeldir, cfg->user, cfg->group) < 0) {
943 virReportSystemError(errno,
944 _("unable to set ownership of '%s' to %d:%d"),
945 channeldir, (int)cfg->user,
946 (int)cfg->group);
947 VIR_FREE(channeldir);
948 goto error;
950 VIR_FREE(channeldir);
951 if (chown(cfg->channelTargetDir, cfg->user, cfg->group) < 0) {
952 virReportSystemError(errno,
953 _("unable to set ownership of '%s' to %d:%d"),
954 cfg->channelTargetDir, (int)cfg->user,
955 (int)cfg->group);
956 goto error;
958 if (chown(cfg->nvramDir, cfg->user, cfg->group) < 0) {
959 virReportSystemError(errno,
960 _("unable to set ownership of '%s' to %d:%d"),
961 cfg->nvramDir, (int)cfg->user,
962 (int)cfg->group);
963 goto error;
965 if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) {
966 virReportSystemError(errno,
967 _("unable to set ownership of '%s' to %d:%d"),
968 cfg->memoryBackingDir, (int)cfg->user,
969 (int)cfg->group);
970 goto error;
973 run_uid = cfg->user;
974 run_gid = cfg->group;
977 if ((hostCPU = virCPUProbeHost(virArchFromHost())))
978 microcodeVersion = hostCPU->microcodeVersion;
979 virCPUDefFree(hostCPU);
981 qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
982 cfg->cacheDir,
983 run_uid,
984 run_gid,
985 microcodeVersion);
986 if (!qemu_driver->qemuCapsCache)
987 goto error;
989 if ((qemu_driver->caps = virQEMUDriverCreateCapabilities(qemu_driver)) == NULL)
990 goto error;
992 if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver)))
993 goto error;
995 /* If hugetlbfs is present, then we need to create a sub-directory within
996 * it, since we can't assume the root mount point has permissions that
997 * will let our spawned QEMU instances use it. */
998 for (i = 0; i < cfg->nhugetlbfs; i++) {
999 hugepagePath = qemuGetBaseHugepagePath(&cfg->hugetlbfs[i]);
1001 if (!hugepagePath)
1002 goto error;
1004 if (virFileMakePath(hugepagePath) < 0) {
1005 virReportSystemError(errno,
1006 _("unable to create hugepage path %s"),
1007 hugepagePath);
1008 goto error;
1010 if (privileged &&
1011 virFileUpdatePerm(cfg->hugetlbfs[i].mnt_dir,
1012 0, S_IXGRP | S_IXOTH) < 0)
1013 goto error;
1014 VIR_FREE(hugepagePath);
1017 if (qemuGetMemoryBackingBasePath(cfg, &memoryBackingPath) < 0)
1018 goto error;
1020 if (virFileMakePath(memoryBackingPath) < 0) {
1021 virReportSystemError(errno,
1022 _("unable to create memory backing path %s"),
1023 memoryBackingPath);
1024 goto error;
1027 if (privileged &&
1028 virFileUpdatePerm(memoryBackingPath,
1029 0, S_IXGRP | S_IXOTH) < 0)
1030 goto error;
1031 VIR_FREE(memoryBackingPath);
1033 if (!(qemu_driver->closeCallbacks = virCloseCallbacksNew()))
1034 goto error;
1036 /* Get all the running persistent or transient configs first */
1037 if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
1038 cfg->stateDir,
1039 NULL, true,
1040 qemu_driver->caps,
1041 qemu_driver->xmlopt,
1042 NULL, NULL) < 0)
1043 goto error;
1045 /* find the maximum ID from active and transient configs to initialize
1046 * the driver with. This is to avoid race between autostart and reconnect
1047 * threads */
1048 virDomainObjListForEach(qemu_driver->domains,
1049 qemuDomainFindMaxID,
1050 &qemu_driver->lastvmid);
1052 virDomainObjListForEach(qemu_driver->domains,
1053 qemuDomainNetsRestart,
1054 NULL);
1056 /* Then inactive persistent configs */
1057 if (virDomainObjListLoadAllConfigs(qemu_driver->domains,
1058 cfg->configDir,
1059 cfg->autostartDir, false,
1060 qemu_driver->caps,
1061 qemu_driver->xmlopt,
1062 NULL, NULL) < 0)
1063 goto error;
1065 virDomainObjListForEach(qemu_driver->domains,
1066 qemuDomainSnapshotLoad,
1067 cfg->snapshotDir);
1069 virDomainObjListForEach(qemu_driver->domains,
1070 qemuDomainCheckpointLoad,
1071 cfg->checkpointDir);
1073 virDomainObjListForEach(qemu_driver->domains,
1074 qemuDomainManagedSaveLoad,
1075 qemu_driver);
1077 /* must be initialized before trying to reconnect to all the
1078 * running domains since there might occur some QEMU monitor
1079 * events that will be dispatched to the worker pool */
1080 qemu_driver->workerPool = virThreadPoolNew(0, 1, 0, qemuProcessEventHandler, qemu_driver);
1081 if (!qemu_driver->workerPool)
1082 goto error;
1084 qemuProcessReconnectAll(qemu_driver);
1086 qemuAutostartDomains(qemu_driver);
1088 return 0;
1090 error:
1091 VIR_FREE(driverConf);
1092 VIR_FREE(hugepagePath);
1093 VIR_FREE(memoryBackingPath);
1094 qemuStateCleanup();
1095 return -1;
1098 static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
1100 virQEMUDriverPtr driver = opaque;
1102 if (newVM) {
1103 virObjectEventPtr event =
1104 virDomainEventLifecycleNewFromObj(vm,
1105 VIR_DOMAIN_EVENT_DEFINED,
1106 VIR_DOMAIN_EVENT_DEFINED_ADDED);
1107 virObjectEventStateQueue(driver->domainEventState, event);
1112 * qemuStateReload:
1114 * Function to restart the QEMU daemon, it will recheck the configuration
1115 * files and update its state and the networking
1117 static int
1118 qemuStateReload(void)
1120 virQEMUDriverConfigPtr cfg = NULL;
1121 virCapsPtr caps = NULL;
1123 if (!qemu_driver)
1124 return 0;
1126 if (!(caps = virQEMUDriverGetCapabilities(qemu_driver, false)))
1127 goto cleanup;
1129 cfg = virQEMUDriverGetConfig(qemu_driver);
1130 virDomainObjListLoadAllConfigs(qemu_driver->domains,
1131 cfg->configDir,
1132 cfg->autostartDir, false,
1133 caps, qemu_driver->xmlopt,
1134 qemuNotifyLoadDomain, qemu_driver);
1135 cleanup:
1136 virObjectUnref(cfg);
1137 virObjectUnref(caps);
1138 return 0;
1143 * qemuStateStop:
1145 * Save any VMs in preparation for shutdown
1148 static int
1149 qemuStateStop(void)
1151 int ret = -1;
1152 virConnectPtr conn;
1153 int numDomains = 0;
1154 size_t i;
1155 int state;
1156 virDomainPtr *domains = NULL;
1157 unsigned int *flags = NULL;
1158 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(qemu_driver);
1160 if (!(conn = virConnectOpen(cfg->uri)))
1161 goto cleanup;
1163 if ((numDomains = virConnectListAllDomains(conn,
1164 &domains,
1165 VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
1166 goto cleanup;
1168 if (VIR_ALLOC_N(flags, numDomains) < 0)
1169 goto cleanup;
1171 /* First we pause all VMs to make them stop dirtying
1172 pages, etc. We remember if any VMs were paused so
1173 we can restore that on resume. */
1174 for (i = 0; i < numDomains; i++) {
1175 flags[i] = VIR_DOMAIN_SAVE_RUNNING;
1176 if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
1177 if (state == VIR_DOMAIN_PAUSED)
1178 flags[i] = VIR_DOMAIN_SAVE_PAUSED;
1180 virDomainSuspend(domains[i]);
1183 ret = 0;
1184 /* Then we save the VMs to disk */
1185 for (i = 0; i < numDomains; i++)
1186 if (virDomainManagedSave(domains[i], flags[i]) < 0)
1187 ret = -1;
1189 cleanup:
1190 if (domains) {
1191 for (i = 0; i < numDomains; i++)
1192 virObjectUnref(domains[i]);
1193 VIR_FREE(domains);
1195 VIR_FREE(flags);
1196 virObjectUnref(conn);
1197 virObjectUnref(cfg);
1199 return ret;
1203 * qemuStateCleanup:
1205 * Shutdown the QEMU daemon, it will stop all active domains and networks
1207 static int
1208 qemuStateCleanup(void)
1210 if (!qemu_driver)
1211 return -1;
1213 virThreadPoolFree(qemu_driver->workerPool);
1214 virObjectUnref(qemu_driver->config);
1215 virObjectUnref(qemu_driver->hostdevMgr);
1216 virHashFree(qemu_driver->sharedDevices);
1217 virObjectUnref(qemu_driver->caps);
1218 virObjectUnref(qemu_driver->qemuCapsCache);
1220 virObjectUnref(qemu_driver->domains);
1221 virPortAllocatorRangeFree(qemu_driver->remotePorts);
1222 virPortAllocatorRangeFree(qemu_driver->webSocketPorts);
1223 virPortAllocatorRangeFree(qemu_driver->migrationPorts);
1224 virObjectUnref(qemu_driver->migrationErrors);
1226 virObjectUnref(qemu_driver->xmlopt);
1228 virSysinfoDefFree(qemu_driver->hostsysinfo);
1230 virObjectUnref(qemu_driver->closeCallbacks);
1232 VIR_FREE(qemu_driver->qemuImgBinary);
1234 virObjectUnref(qemu_driver->securityManager);
1236 ebtablesContextFree(qemu_driver->ebtables);
1238 /* Free domain callback list */
1239 virObjectUnref(qemu_driver->domainEventState);
1241 virLockManagerPluginUnref(qemu_driver->lockManager);
1243 virMutexDestroy(&qemu_driver->lock);
1244 VIR_FREE(qemu_driver);
1246 return 0;
1250 static int
1251 qemuConnectURIProbe(char **uri)
1253 virQEMUDriverConfigPtr cfg = NULL;
1254 int ret = -1;
1256 if (qemu_driver == NULL)
1257 return 0;
1259 cfg = virQEMUDriverGetConfig(qemu_driver);
1260 if (VIR_STRDUP(*uri, cfg->uri) < 0)
1261 goto cleanup;
1263 ret = 0;
1264 cleanup:
1265 virObjectUnref(cfg);
1266 return ret;
1269 static virDrvOpenStatus qemuConnectOpen(virConnectPtr conn,
1270 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1271 virConfPtr conf ATTRIBUTE_UNUSED,
1272 unsigned int flags)
1274 virQEMUDriverConfigPtr cfg = NULL;
1275 virDrvOpenStatus ret = VIR_DRV_OPEN_ERROR;
1276 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
1278 if (qemu_driver == NULL) {
1279 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1280 _("qemu state driver is not active"));
1281 goto cleanup;
1284 cfg = virQEMUDriverGetConfig(qemu_driver);
1286 if (virQEMUDriverIsPrivileged(qemu_driver)) {
1287 if (STRNEQ(conn->uri->path, "/system") &&
1288 STRNEQ(conn->uri->path, "/session")) {
1289 virReportError(VIR_ERR_INTERNAL_ERROR,
1290 _("unexpected QEMU URI path '%s', try qemu:///system"),
1291 conn->uri->path);
1292 goto cleanup;
1294 } else {
1295 if (STRNEQ(conn->uri->path, "/session")) {
1296 virReportError(VIR_ERR_INTERNAL_ERROR,
1297 _("unexpected QEMU URI path '%s', try qemu:///session"),
1298 conn->uri->path);
1299 goto cleanup;
1303 if (virConnectOpenEnsureACL(conn) < 0)
1304 goto cleanup;
1306 conn->privateData = qemu_driver;
1308 ret = VIR_DRV_OPEN_SUCCESS;
1309 cleanup:
1310 virObjectUnref(cfg);
1311 return ret;
1314 static int qemuConnectClose(virConnectPtr conn)
1316 virQEMUDriverPtr driver = conn->privateData;
1318 /* Get rid of callbacks registered for this conn */
1319 virCloseCallbacksRun(driver->closeCallbacks, conn, driver->domains, driver);
1321 conn->privateData = NULL;
1323 return 0;
1326 /* Which features are supported by this driver? */
1327 static int
1328 qemuConnectSupportsFeature(virConnectPtr conn, int feature)
1330 if (virConnectSupportsFeatureEnsureACL(conn) < 0)
1331 return -1;
1333 switch ((virDrvFeature) feature) {
1334 case VIR_DRV_FEATURE_MIGRATION_V2:
1335 case VIR_DRV_FEATURE_MIGRATION_V3:
1336 case VIR_DRV_FEATURE_MIGRATION_P2P:
1337 case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
1338 case VIR_DRV_FEATURE_FD_PASSING:
1339 case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
1340 case VIR_DRV_FEATURE_XML_MIGRATABLE:
1341 case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
1342 case VIR_DRV_FEATURE_MIGRATION_PARAMS:
1343 return 1;
1344 case VIR_DRV_FEATURE_MIGRATION_DIRECT:
1345 case VIR_DRV_FEATURE_MIGRATION_V1:
1346 case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
1347 case VIR_DRV_FEATURE_REMOTE:
1348 case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
1349 case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
1350 default:
1351 return 0;
1355 static const char *qemuConnectGetType(virConnectPtr conn) {
1356 if (virConnectGetTypeEnsureACL(conn) < 0)
1357 return NULL;
1359 return "QEMU";
1363 static int qemuConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1365 /* Trivially secure, since always inside the daemon */
1366 return 1;
1369 static int qemuConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1371 /* Not encrypted, but remote driver takes care of that */
1372 return 0;
1375 static int qemuConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1377 return 1;
1381 static char *
1382 qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
1384 virQEMUDriverPtr driver = conn->privateData;
1385 virBuffer buf = VIR_BUFFER_INITIALIZER;
1387 virCheckFlags(0, NULL);
1389 if (virConnectGetSysinfoEnsureACL(conn) < 0)
1390 return NULL;
1392 if (!driver->hostsysinfo) {
1393 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1394 _("Host SMBIOS information is not available"));
1395 return NULL;
1398 if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
1399 return NULL;
1400 if (virBufferCheckError(&buf) < 0)
1401 return NULL;
1402 return virBufferContentAndReset(&buf);
1405 static int
1406 qemuConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type)
1408 if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
1409 return -1;
1411 if (!type)
1412 return 16;
1414 if (STRCASEEQ(type, "qemu"))
1415 return 16;
1417 if (STRCASEEQ(type, "kvm"))
1418 return virHostCPUGetKVMMaxVCPUs();
1420 virReportError(VIR_ERR_INVALID_ARG,
1421 _("unknown type '%s'"), type);
1422 return -1;
1426 static char *qemuConnectGetCapabilities(virConnectPtr conn) {
1427 virQEMUDriverPtr driver = conn->privateData;
1428 virCapsPtr caps = NULL;
1429 char *xml = NULL;
1431 if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
1432 return NULL;
1434 if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
1435 goto cleanup;
1437 xml = virCapabilitiesFormatXML(caps);
1438 virObjectUnref(caps);
1440 cleanup:
1442 return xml;
1446 static int
1447 qemuGetSchedInfo(unsigned long long *cpuWait,
1448 pid_t pid, pid_t tid)
1450 char *proc = NULL;
1451 char *data = NULL;
1452 char **lines = NULL;
1453 size_t i;
1454 int ret = -1;
1455 double val;
1457 *cpuWait = 0;
1459 /* In general, we cannot assume pid_t fits in int; but /proc parsing
1460 * is specific to Linux where int works fine. */
1461 if (tid)
1462 ret = virAsprintf(&proc, "/proc/%d/task/%d/sched", (int)pid, (int)tid);
1463 else
1464 ret = virAsprintf(&proc, "/proc/%d/sched", (int)pid);
1465 if (ret < 0)
1466 goto cleanup;
1467 ret = -1;
1469 /* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
1470 if (access(proc, R_OK) < 0) {
1471 ret = 0;
1472 goto cleanup;
1475 if (virFileReadAll(proc, (1<<16), &data) < 0)
1476 goto cleanup;
1478 lines = virStringSplit(data, "\n", 0);
1479 if (!lines)
1480 goto cleanup;
1482 for (i = 0; lines[i] != NULL; i++) {
1483 const char *line = lines[i];
1485 /* Needs CONFIG_SCHEDSTATS. The second check
1486 * is the old name the kernel used in past */
1487 if (STRPREFIX(line, "se.statistics.wait_sum") ||
1488 STRPREFIX(line, "se.wait_sum")) {
1489 line = strchr(line, ':');
1490 if (!line) {
1491 virReportError(VIR_ERR_INTERNAL_ERROR,
1492 _("Missing separator in sched info '%s'"),
1493 lines[i]);
1494 goto cleanup;
1496 line++;
1497 while (*line == ' ')
1498 line++;
1500 if (virStrToDouble(line, NULL, &val) < 0) {
1501 virReportError(VIR_ERR_INTERNAL_ERROR,
1502 _("Unable to parse sched info value '%s'"),
1503 line);
1504 goto cleanup;
1507 *cpuWait = (unsigned long long)(val * 1000000);
1508 break;
1512 ret = 0;
1514 cleanup:
1515 VIR_FREE(data);
1516 VIR_FREE(proc);
1517 virStringListFree(lines);
1518 return ret;
1522 static int
1523 qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
1524 pid_t pid, int tid)
1526 char *proc;
1527 FILE *pidinfo;
1528 unsigned long long usertime = 0, systime = 0;
1529 long rss = 0;
1530 int cpu = 0;
1531 int ret;
1533 /* In general, we cannot assume pid_t fits in int; but /proc parsing
1534 * is specific to Linux where int works fine. */
1535 if (tid)
1536 ret = virAsprintf(&proc, "/proc/%d/task/%d/stat", (int)pid, tid);
1537 else
1538 ret = virAsprintf(&proc, "/proc/%d/stat", (int)pid);
1539 if (ret < 0)
1540 return -1;
1542 pidinfo = fopen(proc, "r");
1543 VIR_FREE(proc);
1545 /* See 'man proc' for information about what all these fields are. We're
1546 * only interested in a very few of them */
1547 if (!pidinfo ||
1548 fscanf(pidinfo,
1549 /* pid -> stime */
1550 "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu"
1551 /* cutime -> endcode */
1552 "%*d %*d %*d %*d %*d %*d %*u %*u %ld %*u %*u %*u"
1553 /* startstack -> processor */
1554 "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
1555 &usertime, &systime, &rss, &cpu) != 4) {
1556 VIR_WARN("cannot parse process status data");
1559 /* We got jiffies
1560 * We want nanoseconds
1561 * _SC_CLK_TCK is jiffies per second
1562 * So calculate thus....
1564 if (cpuTime)
1565 *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
1566 / (unsigned long long)sysconf(_SC_CLK_TCK);
1567 if (lastCpu)
1568 *lastCpu = cpu;
1570 if (vm_rss)
1571 *vm_rss = rss * virGetSystemPageSizeKB();
1574 VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
1575 (int)pid, tid, usertime, systime, cpu, rss);
1577 VIR_FORCE_FCLOSE(pidinfo);
1579 return 0;
1583 static int
1584 qemuDomainHelperGetVcpus(virDomainObjPtr vm,
1585 virVcpuInfoPtr info,
1586 unsigned long long *cpuwait,
1587 int maxinfo,
1588 unsigned char *cpumaps,
1589 int maplen)
1591 size_t ncpuinfo = 0;
1592 size_t i;
1594 if (maxinfo == 0)
1595 return 0;
1597 if (!qemuDomainHasVcpuPids(vm)) {
1598 virReportError(VIR_ERR_OPERATION_INVALID,
1599 "%s", _("cpu affinity is not supported"));
1600 return -1;
1603 if (info)
1604 memset(info, 0, sizeof(*info) * maxinfo);
1606 if (cpumaps)
1607 memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
1609 for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; i++) {
1610 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
1611 pid_t vcpupid = qemuDomainGetVcpuPid(vm, i);
1612 virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
1614 if (!vcpu->online)
1615 continue;
1617 if (info) {
1618 vcpuinfo->number = i;
1619 vcpuinfo->state = VIR_VCPU_RUNNING;
1621 if (qemuGetProcessInfo(&vcpuinfo->cpuTime,
1622 &vcpuinfo->cpu, NULL,
1623 vm->pid, vcpupid) < 0) {
1624 virReportSystemError(errno, "%s",
1625 _("cannot get vCPU placement & pCPU time"));
1626 return -1;
1630 if (cpumaps) {
1631 unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
1632 virBitmapPtr map = NULL;
1634 if (!(map = virProcessGetAffinity(vcpupid)))
1635 return -1;
1637 virBitmapToDataBuf(map, cpumap, maplen);
1638 virBitmapFree(map);
1641 if (cpuwait) {
1642 if (qemuGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) < 0)
1643 return -1;
1646 ncpuinfo++;
1649 return ncpuinfo;
1653 static virDomainPtr qemuDomainLookupByID(virConnectPtr conn,
1654 int id)
1656 virQEMUDriverPtr driver = conn->privateData;
1657 virDomainObjPtr vm;
1658 virDomainPtr dom = NULL;
1660 vm = virDomainObjListFindByID(driver->domains, id);
1662 if (!vm) {
1663 virReportError(VIR_ERR_NO_DOMAIN,
1664 _("no domain with matching id %d"), id);
1665 goto cleanup;
1668 if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
1669 goto cleanup;
1671 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1673 cleanup:
1674 virDomainObjEndAPI(&vm);
1675 return dom;
1678 static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn,
1679 const unsigned char *uuid)
1681 virQEMUDriverPtr driver = conn->privateData;
1682 virDomainObjPtr vm;
1683 virDomainPtr dom = NULL;
1685 vm = virDomainObjListFindByUUID(driver->domains, uuid);
1687 if (!vm) {
1688 char uuidstr[VIR_UUID_STRING_BUFLEN];
1689 virUUIDFormat(uuid, uuidstr);
1690 virReportError(VIR_ERR_NO_DOMAIN,
1691 _("no domain with matching uuid '%s'"), uuidstr);
1692 goto cleanup;
1695 if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
1696 goto cleanup;
1698 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1700 cleanup:
1701 virDomainObjEndAPI(&vm);
1702 return dom;
1705 static virDomainPtr qemuDomainLookupByName(virConnectPtr conn,
1706 const char *name)
1708 virQEMUDriverPtr driver = conn->privateData;
1709 virDomainObjPtr vm;
1710 virDomainPtr dom = NULL;
1712 vm = virDomainObjListFindByName(driver->domains, name);
1714 if (!vm) {
1715 virReportError(VIR_ERR_NO_DOMAIN,
1716 _("no domain with matching name '%s'"), name);
1717 goto cleanup;
1720 if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
1721 goto cleanup;
1723 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1725 cleanup:
1726 virDomainObjEndAPI(&vm);
1727 return dom;
1731 static int qemuDomainIsActive(virDomainPtr dom)
1733 virDomainObjPtr obj;
1734 int ret = -1;
1736 if (!(obj = qemuDomObjFromDomain(dom)))
1737 goto cleanup;
1739 if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
1740 goto cleanup;
1742 ret = virDomainObjIsActive(obj);
1744 cleanup:
1745 virDomainObjEndAPI(&obj);
1746 return ret;
1749 static int qemuDomainIsPersistent(virDomainPtr dom)
1751 virDomainObjPtr obj;
1752 int ret = -1;
1754 if (!(obj = qemuDomObjFromDomain(dom)))
1755 goto cleanup;
1757 if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
1758 goto cleanup;
1760 ret = obj->persistent;
1762 cleanup:
1763 virDomainObjEndAPI(&obj);
1764 return ret;
1767 static int qemuDomainIsUpdated(virDomainPtr dom)
1769 virDomainObjPtr obj;
1770 int ret = -1;
1772 if (!(obj = qemuDomObjFromDomain(dom)))
1773 goto cleanup;
1775 if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0)
1776 goto cleanup;
1778 ret = obj->updated;
1780 cleanup:
1781 virDomainObjEndAPI(&obj);
1782 return ret;
1785 static int qemuConnectGetVersion(virConnectPtr conn, unsigned long *version)
1787 virQEMUDriverPtr driver = conn->privateData;
1788 int ret = -1;
1789 unsigned int qemuVersion = 0;
1790 virCapsPtr caps = NULL;
1792 if (virConnectGetVersionEnsureACL(conn) < 0)
1793 return -1;
1795 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
1796 goto cleanup;
1798 if (virQEMUCapsGetDefaultVersion(caps,
1799 driver->qemuCapsCache,
1800 &qemuVersion) < 0)
1801 goto cleanup;
1803 *version = qemuVersion;
1804 ret = 0;
1806 cleanup:
1807 virObjectUnref(caps);
1808 return ret;
1812 static char *qemuConnectGetHostname(virConnectPtr conn)
1814 if (virConnectGetHostnameEnsureACL(conn) < 0)
1815 return NULL;
1817 return virGetHostname();
1821 static int qemuConnectListDomains(virConnectPtr conn, int *ids, int nids)
1823 virQEMUDriverPtr driver = conn->privateData;
1824 int n;
1826 if (virConnectListDomainsEnsureACL(conn) < 0)
1827 return -1;
1829 n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
1830 virConnectListDomainsCheckACL, conn);
1832 return n;
1835 static int qemuConnectNumOfDomains(virConnectPtr conn)
1837 virQEMUDriverPtr driver = conn->privateData;
1838 int n;
1840 if (virConnectNumOfDomainsEnsureACL(conn) < 0)
1841 return -1;
1843 n = virDomainObjListNumOfDomains(driver->domains, true,
1844 virConnectNumOfDomainsCheckACL, conn);
1846 return n;
1850 static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
1851 const char *xml,
1852 unsigned int flags)
1854 virQEMUDriverPtr driver = conn->privateData;
1855 virDomainDefPtr def = NULL;
1856 virDomainObjPtr vm = NULL;
1857 virDomainPtr dom = NULL;
1858 virObjectEventPtr event = NULL;
1859 virObjectEventPtr event2 = NULL;
1860 unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
1861 virCapsPtr caps = NULL;
1862 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
1863 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
1865 virCheckFlags(VIR_DOMAIN_START_PAUSED |
1866 VIR_DOMAIN_START_AUTODESTROY |
1867 VIR_DOMAIN_START_VALIDATE, NULL);
1869 if (flags & VIR_DOMAIN_START_VALIDATE)
1870 parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
1871 if (flags & VIR_DOMAIN_START_PAUSED)
1872 start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
1873 if (flags & VIR_DOMAIN_START_AUTODESTROY)
1874 start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
1876 virNWFilterReadLockFilterUpdates();
1878 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
1879 goto cleanup;
1881 if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
1882 NULL, parse_flags)))
1883 goto cleanup;
1885 if (virDomainCreateXMLEnsureACL(conn, def) < 0)
1886 goto cleanup;
1888 if (!(vm = virDomainObjListAdd(driver->domains, def,
1889 driver->xmlopt,
1890 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1891 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
1892 NULL)))
1893 goto cleanup;
1894 def = NULL;
1896 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
1897 flags) < 0) {
1898 qemuDomainRemoveInactiveJob(driver, vm);
1899 goto cleanup;
1902 if (qemuProcessStart(conn, driver, vm, NULL, QEMU_ASYNC_JOB_START,
1903 NULL, -1, NULL, NULL,
1904 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
1905 start_flags) < 0) {
1906 virDomainAuditStart(vm, "booted", false);
1907 qemuDomainRemoveInactive(driver, vm);
1908 qemuProcessEndJob(driver, vm);
1909 goto cleanup;
1912 event = virDomainEventLifecycleNewFromObj(vm,
1913 VIR_DOMAIN_EVENT_STARTED,
1914 VIR_DOMAIN_EVENT_STARTED_BOOTED);
1915 if (event && (flags & VIR_DOMAIN_START_PAUSED)) {
1916 /* There are two classes of event-watching clients - those
1917 * that only care about on/off (and must see a started event
1918 * no matter what, but don't care about suspend events), and
1919 * those that also care about running/paused. To satisfy both
1920 * client types, we have to send two events. */
1921 event2 = virDomainEventLifecycleNewFromObj(vm,
1922 VIR_DOMAIN_EVENT_SUSPENDED,
1923 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
1925 virDomainAuditStart(vm, "booted", true);
1927 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
1929 qemuProcessEndJob(driver, vm);
1931 cleanup:
1932 virDomainDefFree(def);
1933 virDomainObjEndAPI(&vm);
1934 virObjectEventStateQueue(driver->domainEventState, event);
1935 virObjectEventStateQueue(driver->domainEventState, event2);
1936 virObjectUnref(caps);
1937 virNWFilterUnlockFilterUpdates();
1938 return dom;
1942 static int qemuDomainSuspend(virDomainPtr dom)
1944 virQEMUDriverPtr driver = dom->conn->privateData;
1945 virDomainObjPtr vm;
1946 int ret = -1;
1947 virObjectEventPtr event = NULL;
1948 qemuDomainObjPrivatePtr priv;
1949 virDomainPausedReason reason;
1950 int eventDetail;
1951 int state;
1952 virQEMUDriverConfigPtr cfg = NULL;
1954 if (!(vm = qemuDomObjFromDomain(dom)))
1955 return -1;
1957 if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
1958 goto cleanup;
1960 cfg = virQEMUDriverGetConfig(driver);
1961 priv = vm->privateData;
1963 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND) < 0)
1964 goto cleanup;
1966 if (virDomainObjCheckActive(vm) < 0)
1967 goto endjob;
1969 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
1970 reason = VIR_DOMAIN_PAUSED_MIGRATION;
1971 eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED;
1972 } else if (priv->job.asyncJob == QEMU_ASYNC_JOB_SNAPSHOT) {
1973 reason = VIR_DOMAIN_PAUSED_SNAPSHOT;
1974 eventDetail = -1; /* don't create lifecycle events when doing snapshot */
1975 } else {
1976 reason = VIR_DOMAIN_PAUSED_USER;
1977 eventDetail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
1980 state = virDomainObjGetState(vm, NULL);
1981 if (state == VIR_DOMAIN_PMSUSPENDED) {
1982 virReportError(VIR_ERR_OPERATION_INVALID,
1983 "%s", _("domain is pmsuspended"));
1984 goto endjob;
1985 } else if (state != VIR_DOMAIN_PAUSED) {
1986 if (qemuProcessStopCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0)
1987 goto endjob;
1989 if (eventDetail >= 0) {
1990 event = virDomainEventLifecycleNewFromObj(vm,
1991 VIR_DOMAIN_EVENT_SUSPENDED,
1992 eventDetail);
1995 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
1996 goto endjob;
1997 ret = 0;
1999 endjob:
2000 qemuDomainObjEndJob(driver, vm);
2002 cleanup:
2003 virDomainObjEndAPI(&vm);
2005 virObjectEventStateQueue(driver->domainEventState, event);
2006 virObjectUnref(cfg);
2007 return ret;
2011 static int qemuDomainResume(virDomainPtr dom)
2013 virQEMUDriverPtr driver = dom->conn->privateData;
2014 virDomainObjPtr vm;
2015 int ret = -1;
2016 int state;
2017 int reason;
2018 virQEMUDriverConfigPtr cfg = NULL;
2020 if (!(vm = qemuDomObjFromDomain(dom)))
2021 return -1;
2023 cfg = virQEMUDriverGetConfig(driver);
2025 if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
2026 goto cleanup;
2028 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2029 goto cleanup;
2031 if (virDomainObjCheckActive(vm) < 0)
2032 goto endjob;
2034 state = virDomainObjGetState(vm, &reason);
2035 if (state == VIR_DOMAIN_PMSUSPENDED) {
2036 virReportError(VIR_ERR_OPERATION_INVALID,
2037 "%s", _("domain is pmsuspended"));
2038 goto endjob;
2039 } else if (state == VIR_DOMAIN_RUNNING) {
2040 virReportError(VIR_ERR_OPERATION_INVALID,
2041 "%s", _("domain is already running"));
2042 goto endjob;
2043 } else if ((state == VIR_DOMAIN_CRASHED &&
2044 reason == VIR_DOMAIN_CRASHED_PANICKED) ||
2045 state == VIR_DOMAIN_PAUSED) {
2046 if (qemuProcessStartCPUs(driver, vm,
2047 VIR_DOMAIN_RUNNING_UNPAUSED,
2048 QEMU_ASYNC_JOB_NONE) < 0) {
2049 if (virGetLastErrorCode() == VIR_ERR_OK)
2050 virReportError(VIR_ERR_OPERATION_FAILED,
2051 "%s", _("resume operation failed"));
2052 goto endjob;
2055 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
2056 goto endjob;
2057 ret = 0;
2059 endjob:
2060 qemuDomainObjEndJob(driver, vm);
2062 cleanup:
2063 virDomainObjEndAPI(&vm);
2064 virObjectUnref(cfg);
2065 return ret;
2068 static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
2070 virQEMUDriverPtr driver = dom->conn->privateData;
2071 virDomainObjPtr vm;
2072 int ret = -1;
2073 qemuDomainObjPrivatePtr priv;
2074 bool useAgent = false, agentRequested, acpiRequested;
2075 bool isReboot = false;
2076 bool agentForced;
2077 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
2078 int agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
2080 virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
2081 VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
2083 if (!(vm = qemuDomObjFromDomain(dom)))
2084 goto cleanup;
2086 if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
2087 vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME) {
2088 isReboot = true;
2089 agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
2090 VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
2093 priv = vm->privateData;
2094 agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
2095 acpiRequested = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
2097 /* Prefer agent unless we were requested to not to. */
2098 if (agentRequested || (!flags && priv->agent))
2099 useAgent = true;
2101 if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2102 goto cleanup;
2104 if (useAgent)
2105 agentJob = QEMU_AGENT_JOB_MODIFY;
2107 if (qemuDomainObjBeginJobWithAgent(driver, vm,
2108 QEMU_JOB_MODIFY,
2109 agentJob) < 0)
2110 goto cleanup;
2112 if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
2113 virReportError(VIR_ERR_OPERATION_INVALID,
2114 "%s", _("domain is not running"));
2115 goto endjob;
2118 agentForced = agentRequested && !acpiRequested;
2119 if (!qemuDomainAgentAvailable(vm, agentForced)) {
2120 if (agentForced)
2121 goto endjob;
2122 useAgent = false;
2126 if (useAgent) {
2127 qemuAgentPtr agent;
2128 qemuDomainSetFakeReboot(driver, vm, false);
2129 agent = qemuDomainObjEnterAgent(vm);
2130 ret = qemuAgentShutdown(agent, agentFlag);
2131 qemuDomainObjExitAgent(vm, agent);
2134 /* If we are not enforced to use just an agent, try ACPI
2135 * shutdown as well in case agent did not succeed.
2137 if (!useAgent ||
2138 (ret < 0 && (acpiRequested || !flags))) {
2140 /* Even if agent failed, we have to check if guest went away
2141 * by itself while our locks were down. */
2142 if (useAgent && !virDomainObjIsActive(vm)) {
2143 ret = 0;
2144 goto endjob;
2147 qemuDomainSetFakeReboot(driver, vm, isReboot);
2148 qemuDomainObjEnterMonitor(driver, vm);
2149 ret = qemuMonitorSystemPowerdown(priv->mon);
2150 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2151 ret = -1;
2154 endjob:
2155 if (agentJob)
2156 qemuDomainObjEndJobWithAgent(driver, vm);
2157 else
2158 qemuDomainObjEndJob(driver, vm);
2160 cleanup:
2161 virDomainObjEndAPI(&vm);
2162 return ret;
2165 static int qemuDomainShutdown(virDomainPtr dom)
2167 return qemuDomainShutdownFlags(dom, 0);
2171 static int
2172 qemuDomainReboot(virDomainPtr dom, unsigned int flags)
2174 virQEMUDriverPtr driver = dom->conn->privateData;
2175 virDomainObjPtr vm;
2176 int ret = -1;
2177 qemuDomainObjPrivatePtr priv;
2178 bool useAgent = false, agentRequested, acpiRequested;
2179 bool isReboot = true;
2180 bool agentForced;
2181 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
2182 int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
2184 virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
2185 VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
2187 if (!(vm = qemuDomObjFromDomain(dom)))
2188 goto cleanup;
2190 if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
2191 vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE) {
2192 agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
2193 isReboot = false;
2194 VIR_INFO("Domain on_reboot setting overridden, shutting down");
2197 priv = vm->privateData;
2198 agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
2199 acpiRequested = flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
2201 /* Prefer agent unless we were requested to not to. */
2202 if (agentRequested || (!flags && priv->agent))
2203 useAgent = true;
2205 if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
2206 goto cleanup;
2208 if (useAgent)
2209 agentJob = QEMU_AGENT_JOB_MODIFY;
2211 if (qemuDomainObjBeginJobWithAgent(driver, vm,
2212 QEMU_JOB_MODIFY,
2213 agentJob) < 0)
2214 goto cleanup;
2216 agentForced = agentRequested && !acpiRequested;
2217 if (!qemuDomainAgentAvailable(vm, agentForced)) {
2218 if (agentForced)
2219 goto endjob;
2220 useAgent = false;
2223 if (virDomainObjCheckActive(vm) < 0)
2224 goto endjob;
2226 if (useAgent) {
2227 qemuAgentPtr agent;
2229 qemuDomainSetFakeReboot(driver, vm, false);
2230 agent = qemuDomainObjEnterAgent(vm);
2231 ret = qemuAgentShutdown(agent, agentFlag);
2232 qemuDomainObjExitAgent(vm, agent);
2235 /* If we are not enforced to use just an agent, try ACPI
2236 * shutdown as well in case agent did not succeed.
2238 if ((!useAgent) ||
2239 (ret < 0 && (acpiRequested || !flags))) {
2240 #if !WITH_YAJL
2241 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2242 _("ACPI reboot is not supported without the JSON monitor"));
2243 goto endjob;
2244 #endif
2245 qemuDomainSetFakeReboot(driver, vm, isReboot);
2246 qemuDomainObjEnterMonitor(driver, vm);
2247 ret = qemuMonitorSystemPowerdown(priv->mon);
2248 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2249 ret = -1;
2252 endjob:
2253 if (agentJob)
2254 qemuDomainObjEndJobWithAgent(driver, vm);
2255 else
2256 qemuDomainObjEndJob(driver, vm);
2258 cleanup:
2259 virDomainObjEndAPI(&vm);
2260 return ret;
2264 static int
2265 qemuDomainReset(virDomainPtr dom, unsigned int flags)
2267 virQEMUDriverPtr driver = dom->conn->privateData;
2268 virDomainObjPtr vm;
2269 int ret = -1;
2270 qemuDomainObjPrivatePtr priv;
2271 virDomainState state;
2273 virCheckFlags(0, -1);
2275 if (!(vm = qemuDomObjFromDomain(dom)))
2276 goto cleanup;
2278 if (virDomainResetEnsureACL(dom->conn, vm->def) < 0)
2279 goto cleanup;
2281 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2282 goto cleanup;
2284 if (virDomainObjCheckActive(vm) < 0)
2285 goto endjob;
2287 priv = vm->privateData;
2288 qemuDomainObjEnterMonitor(driver, vm);
2289 ret = qemuMonitorSystemReset(priv->mon);
2290 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2291 ret = -1;
2293 priv->fakeReboot = false;
2295 state = virDomainObjGetState(vm, NULL);
2296 if (state == VIR_DOMAIN_CRASHED)
2297 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED);
2299 endjob:
2300 qemuDomainObjEndJob(driver, vm);
2302 cleanup:
2303 virDomainObjEndAPI(&vm);
2304 return ret;
2308 /* Count how many snapshots in a set are external snapshots. */
2309 static int
2310 qemuDomainSnapshotCountExternal(void *payload,
2311 const void *name ATTRIBUTE_UNUSED,
2312 void *data)
2314 virDomainMomentObjPtr snap = payload;
2315 int *count = data;
2317 if (virDomainSnapshotIsExternal(snap))
2318 (*count)++;
2319 return 0;
2322 static int
2323 qemuDomainDestroyFlags(virDomainPtr dom,
2324 unsigned int flags)
2326 virQEMUDriverPtr driver = dom->conn->privateData;
2327 virDomainObjPtr vm;
2328 int ret = -1;
2329 virObjectEventPtr event = NULL;
2330 qemuDomainObjPrivatePtr priv;
2331 unsigned int stopFlags = 0;
2332 int state;
2333 int reason;
2334 bool starting;
2336 virCheckFlags(VIR_DOMAIN_DESTROY_GRACEFUL, -1);
2338 if (!(vm = qemuDomObjFromDomain(dom)))
2339 return -1;
2341 priv = vm->privateData;
2343 if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
2344 goto cleanup;
2346 if (virDomainObjCheckActive(vm) < 0)
2347 goto cleanup;
2349 state = virDomainObjGetState(vm, &reason);
2350 starting = (state == VIR_DOMAIN_PAUSED &&
2351 reason == VIR_DOMAIN_PAUSED_STARTING_UP &&
2352 !priv->beingDestroyed);
2354 if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY,
2355 !(flags & VIR_DOMAIN_DESTROY_GRACEFUL)) < 0)
2356 goto cleanup;
2358 if (!virDomainObjIsActive(vm)) {
2359 if (starting) {
2360 VIR_DEBUG("Domain %s is not running anymore", vm->def->name);
2361 ret = 0;
2362 } else {
2363 virReportError(VIR_ERR_OPERATION_INVALID,
2364 "%s", _("domain is not running"));
2366 goto endjob;
2369 qemuDomainSetFakeReboot(driver, vm, false);
2371 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN)
2372 stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
2374 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED,
2375 QEMU_ASYNC_JOB_NONE, stopFlags);
2376 event = virDomainEventLifecycleNewFromObj(vm,
2377 VIR_DOMAIN_EVENT_STOPPED,
2378 VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
2379 virDomainAuditStop(vm, "destroyed");
2381 ret = 0;
2382 endjob:
2383 if (ret == 0)
2384 qemuDomainRemoveInactive(driver, vm);
2385 qemuDomainObjEndJob(driver, vm);
2387 cleanup:
2388 virDomainObjEndAPI(&vm);
2389 virObjectEventStateQueue(driver->domainEventState, event);
2390 return ret;
2393 static int
2394 qemuDomainDestroy(virDomainPtr dom)
2396 return qemuDomainDestroyFlags(dom, 0);
2399 static char *qemuDomainGetOSType(virDomainPtr dom) {
2400 virDomainObjPtr vm;
2401 char *type = NULL;
2403 if (!(vm = qemuDomObjFromDomain(dom)))
2404 goto cleanup;
2406 if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
2407 goto cleanup;
2409 ignore_value(VIR_STRDUP(type, virDomainOSTypeToString(vm->def->os.type)));
2411 cleanup:
2412 virDomainObjEndAPI(&vm);
2413 return type;
2416 /* Returns max memory in kb, 0 if error */
2417 static unsigned long long
2418 qemuDomainGetMaxMemory(virDomainPtr dom)
2420 virDomainObjPtr vm;
2421 unsigned long long ret = 0;
2423 if (!(vm = qemuDomObjFromDomain(dom)))
2424 goto cleanup;
2426 if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
2427 goto cleanup;
2429 ret = virDomainDefGetMemoryTotal(vm->def);
2431 cleanup:
2432 virDomainObjEndAPI(&vm);
2433 return ret;
2436 static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
2437 unsigned int flags)
2439 virQEMUDriverPtr driver = dom->conn->privateData;
2440 qemuDomainObjPrivatePtr priv;
2441 virDomainObjPtr vm;
2442 virDomainDefPtr def;
2443 virDomainDefPtr persistentDef;
2444 int ret = -1, r;
2445 virQEMUDriverConfigPtr cfg = NULL;
2447 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2448 VIR_DOMAIN_AFFECT_CONFIG |
2449 VIR_DOMAIN_MEM_MAXIMUM, -1);
2451 if (!(vm = qemuDomObjFromDomain(dom)))
2452 goto cleanup;
2454 cfg = virQEMUDriverGetConfig(driver);
2456 if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2457 goto cleanup;
2459 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2460 goto cleanup;
2462 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2463 goto endjob;
2466 if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
2467 /* resize the maximum memory */
2469 if (def) {
2470 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2471 _("cannot resize the maximum memory on an "
2472 "active domain"));
2473 goto endjob;
2476 if (persistentDef) {
2477 /* resizing memory with NUMA nodes specified doesn't work as there
2478 * is no way to change the individual node sizes with this API */
2479 if (virDomainNumaGetNodeCount(persistentDef->numa) > 0) {
2480 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2481 _("initial memory size of a domain with NUMA "
2482 "nodes cannot be modified with this API"));
2483 goto endjob;
2486 if (persistentDef->mem.max_memory &&
2487 persistentDef->mem.max_memory < newmem) {
2488 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2489 _("cannot set initial memory size greater than "
2490 "the maximum memory size"));
2491 goto endjob;
2494 virDomainDefSetMemoryTotal(persistentDef, newmem);
2496 if (persistentDef->mem.cur_balloon > newmem)
2497 persistentDef->mem.cur_balloon = newmem;
2498 ret = virDomainSaveConfig(cfg->configDir, driver->caps,
2499 persistentDef);
2500 goto endjob;
2503 } else {
2504 /* resize the current memory */
2505 unsigned long oldmax = 0;
2507 if (def)
2508 oldmax = virDomainDefGetMemoryTotal(def);
2509 if (persistentDef) {
2510 if (!oldmax || oldmax > virDomainDefGetMemoryTotal(persistentDef))
2511 oldmax = virDomainDefGetMemoryTotal(persistentDef);
2514 if (newmem > oldmax) {
2515 virReportError(VIR_ERR_INVALID_ARG, "%s",
2516 _("cannot set memory higher than max memory"));
2517 goto endjob;
2520 if (def) {
2521 priv = vm->privateData;
2522 qemuDomainObjEnterMonitor(driver, vm);
2523 r = qemuMonitorSetBalloon(priv->mon, newmem);
2524 if (qemuDomainObjExitMonitor(driver, vm) < 0 || r < 0)
2525 goto endjob;
2527 /* Lack of balloon support is a fatal error */
2528 if (r == 0) {
2529 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2530 _("Unable to change memory of active domain without "
2531 "the balloon device and guest OS balloon driver"));
2532 goto endjob;
2536 if (persistentDef) {
2537 persistentDef->mem.cur_balloon = newmem;
2538 ret = virDomainSaveConfig(cfg->configDir, driver->caps,
2539 persistentDef);
2540 goto endjob;
2544 ret = 0;
2545 endjob:
2546 qemuDomainObjEndJob(driver, vm);
2548 cleanup:
2549 virDomainObjEndAPI(&vm);
2550 virObjectUnref(cfg);
2551 return ret;
2554 static int qemuDomainSetMemory(virDomainPtr dom, unsigned long newmem)
2556 return qemuDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_AFFECT_LIVE);
2559 static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
2561 return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
2564 static int qemuDomainSetMemoryStatsPeriod(virDomainPtr dom, int period,
2565 unsigned int flags)
2567 virQEMUDriverPtr driver = dom->conn->privateData;
2568 qemuDomainObjPrivatePtr priv;
2569 virDomainObjPtr vm;
2570 virDomainDefPtr def;
2571 virDomainDefPtr persistentDef;
2572 int ret = -1, r;
2573 virQEMUDriverConfigPtr cfg = NULL;
2575 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
2576 VIR_DOMAIN_AFFECT_CONFIG, -1);
2578 if (!(vm = qemuDomObjFromDomain(dom)))
2579 goto cleanup;
2581 cfg = virQEMUDriverGetConfig(driver);
2583 if (virDomainSetMemoryStatsPeriodEnsureACL(dom->conn, vm->def, flags) < 0)
2584 goto cleanup;
2586 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2587 goto cleanup;
2589 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
2590 goto endjob;
2592 /* Set the balloon driver collection interval */
2593 priv = vm->privateData;
2595 if (def) {
2596 if (!virDomainDefHasMemballoon(def)) {
2597 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2598 _("No memory balloon device configured, "
2599 "can not set the collection period"));
2600 goto endjob;
2603 qemuDomainObjEnterMonitor(driver, vm);
2604 r = qemuMonitorSetMemoryStatsPeriod(priv->mon, def->memballoon, period);
2605 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2606 goto endjob;
2607 if (r < 0) {
2608 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2609 _("unable to set balloon driver collection period"));
2610 goto endjob;
2613 def->memballoon->period = period;
2614 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
2615 goto endjob;
2618 if (persistentDef) {
2619 if (!virDomainDefHasMemballoon(persistentDef)) {
2620 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2621 _("No memory balloon device configured, "
2622 "can not set the collection period"));
2623 goto endjob;
2625 persistentDef->memballoon->period = period;
2626 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
2627 goto endjob;
2630 ret = 0;
2631 endjob:
2632 qemuDomainObjEndJob(driver, vm);
2634 cleanup:
2635 virDomainObjEndAPI(&vm);
2636 virObjectUnref(cfg);
2637 return ret;
2640 static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
2642 virQEMUDriverPtr driver = domain->conn->privateData;
2643 virDomainObjPtr vm = NULL;
2644 int ret = -1;
2645 qemuDomainObjPrivatePtr priv;
2647 virCheckFlags(0, -1);
2649 if (!(vm = qemuDomObjFromDomain(domain)))
2650 return -1;
2652 if (virDomainInjectNMIEnsureACL(domain->conn, vm->def) < 0)
2653 goto cleanup;
2655 priv = vm->privateData;
2657 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2658 goto cleanup;
2660 if (virDomainObjCheckActive(vm) < 0)
2661 goto endjob;
2663 qemuDomainObjEnterMonitor(driver, vm);
2664 ret = qemuMonitorInjectNMI(priv->mon);
2665 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2666 ret = -1;
2668 endjob:
2669 qemuDomainObjEndJob(driver, vm);
2671 cleanup:
2672 virDomainObjEndAPI(&vm);
2673 return ret;
2676 static int qemuDomainSendKey(virDomainPtr domain,
2677 unsigned int codeset,
2678 unsigned int holdtime,
2679 unsigned int *keycodes,
2680 int nkeycodes,
2681 unsigned int flags)
2683 virQEMUDriverPtr driver = domain->conn->privateData;
2684 virDomainObjPtr vm = NULL;
2685 int ret = -1;
2686 qemuDomainObjPrivatePtr priv;
2688 virCheckFlags(0, -1);
2690 /* translate the keycode to QNUM for qemu driver */
2691 if (codeset != VIR_KEYCODE_SET_QNUM) {
2692 size_t i;
2693 int keycode;
2695 for (i = 0; i < nkeycodes; i++) {
2696 keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_QNUM,
2697 keycodes[i]);
2698 if (keycode < 0) {
2699 virReportError(VIR_ERR_INTERNAL_ERROR,
2700 _("cannot translate keycode %u of %s codeset to qnum keycode"),
2701 keycodes[i],
2702 virKeycodeSetTypeToString(codeset));
2703 return -1;
2705 keycodes[i] = keycode;
2709 if (!(vm = qemuDomObjFromDomain(domain)))
2710 goto cleanup;
2712 priv = vm->privateData;
2714 if (virDomainSendKeyEnsureACL(domain->conn, vm->def) < 0)
2715 goto cleanup;
2717 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
2718 goto cleanup;
2720 if (virDomainObjCheckActive(vm) < 0)
2721 goto endjob;
2723 qemuDomainObjEnterMonitor(driver, vm);
2724 ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
2725 if (qemuDomainObjExitMonitor(driver, vm) < 0)
2726 ret = -1;
2728 endjob:
2729 qemuDomainObjEndJob(driver, vm);
2731 cleanup:
2732 virDomainObjEndAPI(&vm);
2733 return ret;
2737 static int
2738 qemuDomainGetInfo(virDomainPtr dom,
2739 virDomainInfoPtr info)
2741 unsigned long long maxmem;
2742 virDomainObjPtr vm;
2743 int ret = -1;
2745 if (!(vm = qemuDomObjFromDomain(dom)))
2746 goto cleanup;
2748 if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
2749 goto cleanup;
2751 qemuDomainUpdateCurrentMemorySize(vm);
2753 memset(info, 0, sizeof(*info));
2755 info->state = virDomainObjGetState(vm, NULL);
2757 maxmem = virDomainDefGetMemoryTotal(vm->def);
2758 if (VIR_ASSIGN_IS_OVERFLOW(info->maxMem, maxmem)) {
2759 virReportError(VIR_ERR_OVERFLOW, "%s",
2760 _("Initial memory size too large"));
2761 goto cleanup;
2764 if (VIR_ASSIGN_IS_OVERFLOW(info->memory, vm->def->mem.cur_balloon)) {
2765 virReportError(VIR_ERR_OVERFLOW, "%s",
2766 _("Current memory size too large"));
2767 goto cleanup;
2770 if (virDomainObjIsActive(vm)) {
2771 if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) < 0) {
2772 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2773 _("cannot read cputime for domain"));
2774 goto cleanup;
2778 if (VIR_ASSIGN_IS_OVERFLOW(info->nrVirtCpu, virDomainDefGetVcpus(vm->def))) {
2779 virReportError(VIR_ERR_OVERFLOW, "%s", _("cpu count too large"));
2780 goto cleanup;
2783 ret = 0;
2785 cleanup:
2786 virDomainObjEndAPI(&vm);
2787 return ret;
2790 static int
2791 qemuDomainGetState(virDomainPtr dom,
2792 int *state,
2793 int *reason,
2794 unsigned int flags)
2796 virDomainObjPtr vm;
2797 int ret = -1;
2799 virCheckFlags(0, -1);
2801 if (!(vm = qemuDomObjFromDomain(dom)))
2802 goto cleanup;
2804 if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
2805 goto cleanup;
2807 *state = virDomainObjGetState(vm, reason);
2808 ret = 0;
2810 cleanup:
2811 virDomainObjEndAPI(&vm);
2812 return ret;
2815 static int
2816 qemuDomainGetControlInfo(virDomainPtr dom,
2817 virDomainControlInfoPtr info,
2818 unsigned int flags)
2820 virDomainObjPtr vm;
2821 qemuDomainObjPrivatePtr priv;
2822 int ret = -1;
2824 virCheckFlags(0, -1);
2826 if (!(vm = qemuDomObjFromDomain(dom)))
2827 goto cleanup;
2829 if (virDomainGetControlInfoEnsureACL(dom->conn, vm->def) < 0)
2830 goto cleanup;
2832 if (virDomainObjCheckActive(vm) < 0)
2833 goto cleanup;
2835 priv = vm->privateData;
2837 memset(info, 0, sizeof(*info));
2839 if (priv->monError) {
2840 info->state = VIR_DOMAIN_CONTROL_ERROR;
2841 info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_MONITOR;
2842 } else if (priv->job.active) {
2843 if (virTimeMillisNow(&info->stateTime) < 0)
2844 goto cleanup;
2845 if (priv->job.current) {
2846 info->state = VIR_DOMAIN_CONTROL_JOB;
2847 info->stateTime -= priv->job.current->started;
2848 } else {
2849 if (priv->monStart > 0) {
2850 info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
2851 info->stateTime -= priv->monStart;
2852 } else {
2853 /* At this point the domain has an active job, but monitor was
2854 * not entered and the domain object lock is not held thus we
2855 * are stuck in the job forever due to a programming error.
2857 info->state = VIR_DOMAIN_CONTROL_ERROR;
2858 info->details = VIR_DOMAIN_CONTROL_ERROR_REASON_INTERNAL;
2859 info->stateTime = 0;
2862 } else {
2863 info->state = VIR_DOMAIN_CONTROL_OK;
2866 ret = 0;
2868 cleanup:
2869 virDomainObjEndAPI(&vm);
2870 return ret;
2874 /* It would be nice to replace 'Qemud' with 'Qemu' but
2875 * this magic string is ABI, so it can't be changed
2877 #define QEMU_SAVE_MAGIC "LibvirtQemudSave"
2878 #define QEMU_SAVE_PARTIAL "LibvirtQemudPart"
2879 #define QEMU_SAVE_VERSION 2
2881 verify(sizeof(QEMU_SAVE_MAGIC) == sizeof(QEMU_SAVE_PARTIAL));
2883 typedef enum {
2884 QEMU_SAVE_FORMAT_RAW = 0,
2885 QEMU_SAVE_FORMAT_GZIP = 1,
2886 QEMU_SAVE_FORMAT_BZIP2 = 2,
2888 * Deprecated by xz and never used as part of a release
2889 * QEMU_SAVE_FORMAT_LZMA
2891 QEMU_SAVE_FORMAT_XZ = 3,
2892 QEMU_SAVE_FORMAT_LZOP = 4,
2893 /* Note: add new members only at the end.
2894 These values are used in the on-disk format.
2895 Do not change or re-use numbers. */
2897 QEMU_SAVE_FORMAT_LAST
2898 } virQEMUSaveFormat;
2900 VIR_ENUM_DECL(qemuSaveCompression);
2901 VIR_ENUM_IMPL(qemuSaveCompression, QEMU_SAVE_FORMAT_LAST,
2902 "raw",
2903 "gzip",
2904 "bzip2",
2905 "xz",
2906 "lzop",
2909 VIR_ENUM_DECL(qemuDumpFormat);
2910 VIR_ENUM_IMPL(qemuDumpFormat, VIR_DOMAIN_CORE_DUMP_FORMAT_LAST,
2911 "elf",
2912 "kdump-zlib",
2913 "kdump-lzo",
2914 "kdump-snappy",
2917 typedef struct _virQEMUSaveHeader virQEMUSaveHeader;
2918 typedef virQEMUSaveHeader *virQEMUSaveHeaderPtr;
2919 struct _virQEMUSaveHeader {
2920 char magic[sizeof(QEMU_SAVE_MAGIC)-1];
2921 uint32_t version;
2922 uint32_t data_len;
2923 uint32_t was_running;
2924 uint32_t compressed;
2925 uint32_t cookieOffset;
2926 uint32_t unused[14];
2929 typedef struct _virQEMUSaveData virQEMUSaveData;
2930 typedef virQEMUSaveData *virQEMUSaveDataPtr;
2931 struct _virQEMUSaveData {
2932 virQEMUSaveHeader header;
2933 char *xml;
2934 char *cookie;
2938 static inline void
2939 bswap_header(virQEMUSaveHeaderPtr hdr)
2941 hdr->version = bswap_32(hdr->version);
2942 hdr->data_len = bswap_32(hdr->data_len);
2943 hdr->was_running = bswap_32(hdr->was_running);
2944 hdr->compressed = bswap_32(hdr->compressed);
2945 hdr->cookieOffset = bswap_32(hdr->cookieOffset);
2949 static void
2950 virQEMUSaveDataFree(virQEMUSaveDataPtr data)
2952 if (!data)
2953 return;
2955 VIR_FREE(data->xml);
2956 VIR_FREE(data->cookie);
2957 VIR_FREE(data);
2962 * This function steals @domXML on success.
2964 static virQEMUSaveDataPtr
2965 virQEMUSaveDataNew(char *domXML,
2966 qemuDomainSaveCookiePtr cookieObj,
2967 bool running,
2968 int compressed,
2969 virDomainXMLOptionPtr xmlopt)
2971 virQEMUSaveDataPtr data = NULL;
2972 virQEMUSaveHeaderPtr header;
2974 if (VIR_ALLOC(data) < 0)
2975 return NULL;
2977 VIR_STEAL_PTR(data->xml, domXML);
2979 if (cookieObj &&
2980 !(data->cookie = virSaveCookieFormat((virObjectPtr) cookieObj,
2981 virDomainXMLOptionGetSaveCookie(xmlopt))))
2982 goto error;
2984 header = &data->header;
2985 memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic));
2986 header->version = QEMU_SAVE_VERSION;
2987 header->was_running = running ? 1 : 0;
2988 header->compressed = compressed;
2990 return data;
2992 error:
2993 virQEMUSaveDataFree(data);
2994 return NULL;
2998 /* virQEMUSaveDataWrite:
3000 * Writes libvirt's header (including domain XML) into a saved image of a
3001 * running domain. If @header has data_len filled in (because it was previously
3002 * read from the file), the function will make sure the new data will fit
3003 * within data_len.
3005 * Returns -1 on failure, or 0 on success.
3007 static int
3008 virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
3009 int fd,
3010 const char *path)
3012 virQEMUSaveHeaderPtr header = &data->header;
3013 size_t len;
3014 size_t xml_len;
3015 size_t cookie_len = 0;
3016 int ret = -1;
3017 size_t zerosLen = 0;
3018 char *zeros = NULL;
3020 xml_len = strlen(data->xml) + 1;
3021 if (data->cookie)
3022 cookie_len = strlen(data->cookie) + 1;
3024 len = xml_len + cookie_len;
3026 if (header->data_len > 0) {
3027 if (len > header->data_len) {
3028 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3029 _("new xml too large to fit in file"));
3030 goto cleanup;
3033 zerosLen = header->data_len - len;
3034 if (VIR_ALLOC_N(zeros, zerosLen) < 0)
3035 goto cleanup;
3036 } else {
3037 header->data_len = len;
3040 if (data->cookie)
3041 header->cookieOffset = xml_len;
3043 if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
3044 virReportSystemError(errno,
3045 _("failed to write header to domain save file '%s'"),
3046 path);
3047 goto cleanup;
3050 if (safewrite(fd, data->xml, xml_len) != xml_len) {
3051 virReportSystemError(errno,
3052 _("failed to write domain xml to '%s'"),
3053 path);
3054 goto cleanup;
3057 if (data->cookie &&
3058 safewrite(fd, data->cookie, cookie_len) != cookie_len) {
3059 virReportSystemError(errno,
3060 _("failed to write cookie to '%s'"),
3061 path);
3062 goto cleanup;
3065 if (safewrite(fd, zeros, zerosLen) != zerosLen) {
3066 virReportSystemError(errno,
3067 _("failed to write padding to '%s'"),
3068 path);
3069 goto cleanup;
3072 ret = 0;
3074 cleanup:
3075 VIR_FREE(zeros);
3076 return ret;
3080 static int
3081 virQEMUSaveDataFinish(virQEMUSaveDataPtr data,
3082 int *fd,
3083 const char *path)
3085 virQEMUSaveHeaderPtr header = &data->header;
3087 memcpy(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic));
3089 if (safewrite(*fd, header, sizeof(*header)) != sizeof(*header) ||
3090 VIR_CLOSE(*fd) < 0) {
3091 virReportSystemError(errno,
3092 _("failed to write header to domain save file '%s'"),
3093 path);
3094 return -1;
3097 return 0;
3101 static virCommandPtr
3102 qemuCompressGetCommand(virQEMUSaveFormat compression)
3104 virCommandPtr ret = NULL;
3105 const char *prog = qemuSaveCompressionTypeToString(compression);
3107 if (!prog) {
3108 virReportError(VIR_ERR_OPERATION_FAILED,
3109 _("Invalid compressed save format %d"),
3110 compression);
3111 return NULL;
3114 ret = virCommandNew(prog);
3115 virCommandAddArg(ret, "-dc");
3117 if (compression == QEMU_SAVE_FORMAT_LZOP)
3118 virCommandAddArg(ret, "--ignore-warn");
3120 return ret;
3124 * qemuOpenFile:
3125 * @driver: driver object
3126 * @vm: domain object
3127 * @path: path to file to open
3128 * @oflags: flags for opening/creation of the file
3129 * @needUnlink: set to true if file was created by this function
3131 * Internal function to properly create or open existing files, with
3132 * ownership affected by qemu driver setup and domain DAC label.
3134 * Returns the file descriptor on success and negative errno on failure.
3136 * This function should not be used on storage sources. Use
3137 * qemuDomainStorageFileInit and storage driver APIs if possible.
3139 static int
3140 qemuOpenFile(virQEMUDriverPtr driver,
3141 virDomainObjPtr vm,
3142 const char *path,
3143 int oflags,
3144 bool *needUnlink)
3146 int ret = -1;
3147 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3148 uid_t user = cfg->user;
3149 gid_t group = cfg->group;
3150 bool dynamicOwnership = cfg->dynamicOwnership;
3151 virSecurityLabelDefPtr seclabel;
3153 virObjectUnref(cfg);
3155 /* TODO: Take imagelabel into account? */
3156 if (vm &&
3157 (seclabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) != NULL &&
3158 seclabel->label != NULL &&
3159 (virParseOwnershipIds(seclabel->label, &user, &group) < 0))
3160 goto cleanup;
3162 ret = qemuOpenFileAs(user, group, dynamicOwnership,
3163 path, oflags, needUnlink);
3165 cleanup:
3166 return ret;
3169 static int
3170 qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
3171 bool dynamicOwnership,
3172 const char *path, int oflags,
3173 bool *needUnlink)
3175 struct stat sb;
3176 bool is_reg = true;
3177 bool need_unlink = false;
3178 unsigned int vfoflags = 0;
3179 int fd = -1;
3180 int path_shared = virFileIsSharedFS(path);
3181 uid_t uid = geteuid();
3182 gid_t gid = getegid();
3184 /* path might be a pre-existing block dev, in which case
3185 * we need to skip the create step, and also avoid unlink
3186 * in the failure case */
3187 if (oflags & O_CREAT) {
3188 need_unlink = true;
3190 /* Don't force chown on network-shared FS
3191 * as it is likely to fail. */
3192 if (path_shared <= 0 || dynamicOwnership)
3193 vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
3195 if (stat(path, &sb) == 0) {
3196 /* It already exists, we don't want to delete it on error */
3197 need_unlink = false;
3199 is_reg = !!S_ISREG(sb.st_mode);
3200 /* If the path is regular file which exists
3201 * already and dynamic_ownership is off, we don't
3202 * want to change its ownership, just open it as-is */
3203 if (is_reg && !dynamicOwnership) {
3204 uid = sb.st_uid;
3205 gid = sb.st_gid;
3210 /* First try creating the file as root */
3211 if (!is_reg) {
3212 if ((fd = open(path, oflags & ~O_CREAT)) < 0) {
3213 fd = -errno;
3214 goto error;
3216 } else {
3217 if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
3218 vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
3219 /* If we failed as root, and the error was permission-denied
3220 (EACCES or EPERM), assume it's on a network-connected share
3221 where root access is restricted (eg, root-squashed NFS). If the
3222 qemu user is non-root, just set a flag to
3223 bypass security driver shenanigans, and retry the operation
3224 after doing setuid to qemu user */
3225 if ((fd != -EACCES && fd != -EPERM) || fallback_uid == geteuid())
3226 goto error;
3228 /* On Linux we can also verify the FS-type of the directory. */
3229 switch (path_shared) {
3230 case 1:
3231 /* it was on a network share, so we'll continue
3232 * as outlined above
3234 break;
3236 case -1:
3237 virReportSystemError(-fd, oflags & O_CREAT
3238 ? _("Failed to create file "
3239 "'%s': couldn't determine fs type")
3240 : _("Failed to open file "
3241 "'%s': couldn't determine fs type"),
3242 path);
3243 goto cleanup;
3245 case 0:
3246 default:
3247 /* local file - log the error returned by virFileOpenAs */
3248 goto error;
3251 /* If we created the file above, then we need to remove it;
3252 * otherwise, the next attempt to create will fail. If the
3253 * file had already existed before we got here, then we also
3254 * don't want to delete it and allow the following to succeed
3255 * or fail based on existing protections
3257 if (need_unlink)
3258 unlink(path);
3260 /* Retry creating the file as qemu user */
3262 /* Since we're passing different modes... */
3263 vfoflags |= VIR_FILE_OPEN_FORCE_MODE;
3265 if ((fd = virFileOpenAs(path, oflags,
3266 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
3267 fallback_uid, fallback_gid,
3268 vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
3269 virReportSystemError(-fd, oflags & O_CREAT
3270 ? _("Error from child process creating '%s'")
3271 : _("Error from child process opening '%s'"),
3272 path);
3273 goto cleanup;
3277 cleanup:
3278 if (needUnlink)
3279 *needUnlink = need_unlink;
3280 return fd;
3282 error:
3283 virReportSystemError(-fd, oflags & O_CREAT
3284 ? _("Failed to create file '%s'")
3285 : _("Failed to open file '%s'"),
3286 path);
3287 goto cleanup;
3291 static int
3292 qemuFileWrapperFDClose(virDomainObjPtr vm,
3293 virFileWrapperFdPtr fd)
3295 int ret;
3297 /* virFileWrapperFd uses iohelper to write data onto disk.
3298 * However, iohelper calls fdatasync() which may take ages to
3299 * finish. Therefore, we shouldn't be waiting with the domain
3300 * object locked. */
3302 /* XXX Currently, this function is intended for *Save() only
3303 * as restore needs some reworking before it's ready for
3304 * this. */
3306 virObjectUnlock(vm);
3307 ret = virFileWrapperFdClose(fd);
3308 virObjectLock(vm);
3309 if (!virDomainObjIsActive(vm)) {
3310 if (virGetLastErrorCode() == VIR_ERR_OK)
3311 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3312 _("domain is no longer running"));
3313 ret = -1;
3315 return ret;
3319 /* Helper function to execute a migration to file with a correct save header
3320 * the caller needs to make sure that the processors are stopped and do all other
3321 * actions besides saving memory */
3322 static int
3323 qemuDomainSaveMemory(virQEMUDriverPtr driver,
3324 virDomainObjPtr vm,
3325 const char *path,
3326 virQEMUSaveDataPtr data,
3327 const char *compressedpath,
3328 unsigned int flags,
3329 qemuDomainAsyncJob asyncJob)
3331 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3332 bool needUnlink = false;
3333 int ret = -1;
3334 int fd = -1;
3335 int directFlag = 0;
3336 virFileWrapperFdPtr wrapperFd = NULL;
3337 unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
3339 /* Obtain the file handle. */
3340 if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
3341 wrapperFlags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3342 directFlag = virFileDirectFdFlag();
3343 if (directFlag < 0) {
3344 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3345 _("bypass cache unsupported by this system"));
3346 goto cleanup;
3350 fd = qemuOpenFileAs(cfg->user, cfg->group, false, path,
3351 O_WRONLY | O_TRUNC | O_CREAT | directFlag,
3352 &needUnlink);
3353 if (fd < 0)
3354 goto cleanup;
3356 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
3357 goto cleanup;
3359 if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
3360 goto cleanup;
3362 if (virQEMUSaveDataWrite(data, fd, path) < 0)
3363 goto cleanup;
3365 /* Perform the migration */
3366 if (qemuMigrationSrcToFile(driver, vm, fd, compressedpath, asyncJob) < 0)
3367 goto cleanup;
3369 /* Touch up file header to mark image complete. */
3371 /* Reopen the file to touch up the header, since we aren't set
3372 * up to seek backwards on wrapperFd. The reopened fd will
3373 * trigger a single page of file system cache pollution, but
3374 * that's acceptable. */
3375 if (VIR_CLOSE(fd) < 0) {
3376 virReportSystemError(errno, _("unable to close %s"), path);
3377 goto cleanup;
3380 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3381 goto cleanup;
3383 if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL)) < 0 ||
3384 virQEMUSaveDataFinish(data, &fd, path) < 0)
3385 goto cleanup;
3387 ret = 0;
3389 cleanup:
3390 VIR_FORCE_CLOSE(fd);
3391 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3392 ret = -1;
3393 virFileWrapperFdFree(wrapperFd);
3394 virObjectUnref(cfg);
3396 if (ret < 0 && needUnlink)
3397 unlink(path);
3399 return ret;
3402 /* The vm must be active + locked. Vm will be unlocked and
3403 * potentially free'd after this returns (eg transient VMs are freed
3404 * shutdown). So 'vm' must not be referenced by the caller after
3405 * this returns (whether returning success or failure).
3407 static int
3408 qemuDomainSaveInternal(virQEMUDriverPtr driver,
3409 virDomainObjPtr vm, const char *path,
3410 int compressed, const char *compressedpath,
3411 const char *xmlin, unsigned int flags)
3413 char *xml = NULL;
3414 bool was_running = false;
3415 int ret = -1;
3416 virObjectEventPtr event = NULL;
3417 qemuDomainObjPrivatePtr priv = vm->privateData;
3418 virCapsPtr caps;
3419 virQEMUSaveDataPtr data = NULL;
3420 qemuDomainSaveCookiePtr cookie = NULL;
3422 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
3423 goto cleanup;
3425 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
3426 goto cleanup;
3428 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SAVE,
3429 VIR_DOMAIN_JOB_OPERATION_SAVE, flags) < 0)
3430 goto cleanup;
3432 if (!virDomainObjIsActive(vm)) {
3433 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3434 _("guest unexpectedly quit"));
3435 goto endjob;
3438 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
3440 /* Pause */
3441 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
3442 was_running = true;
3443 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
3444 QEMU_ASYNC_JOB_SAVE) < 0)
3445 goto endjob;
3447 if (!virDomainObjIsActive(vm)) {
3448 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3449 _("guest unexpectedly quit"));
3450 goto endjob;
3454 /* libvirt-domain.c already guaranteed these two flags are exclusive. */
3455 if (flags & VIR_DOMAIN_SAVE_RUNNING)
3456 was_running = true;
3457 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
3458 was_running = false;
3460 /* Get XML for the domain. Restore needs only the inactive xml,
3461 * including secure. We should get the same result whether xmlin
3462 * is NULL or whether it was the live xml of the domain moments
3463 * before. */
3464 if (xmlin) {
3465 virDomainDefPtr def = NULL;
3467 if (!(def = virDomainDefParseString(xmlin, caps, driver->xmlopt, NULL,
3468 VIR_DOMAIN_DEF_PARSE_INACTIVE |
3469 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) {
3470 goto endjob;
3472 if (!qemuDomainCheckABIStability(driver, vm, def)) {
3473 virDomainDefFree(def);
3474 goto endjob;
3476 xml = qemuDomainDefFormatLive(driver, def, NULL, true, true);
3477 } else {
3478 xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU, true, true);
3480 if (!xml) {
3481 virReportError(VIR_ERR_OPERATION_FAILED,
3482 "%s", _("failed to get domain xml"));
3483 goto endjob;
3486 if (!(cookie = qemuDomainSaveCookieNew(vm)))
3487 goto endjob;
3489 if (!(data = virQEMUSaveDataNew(xml, cookie, was_running, compressed,
3490 driver->xmlopt)))
3491 goto endjob;
3492 xml = NULL;
3494 ret = qemuDomainSaveMemory(driver, vm, path, data, compressedpath,
3495 flags, QEMU_ASYNC_JOB_SAVE);
3496 if (ret < 0)
3497 goto endjob;
3499 /* Shut it down */
3500 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED,
3501 QEMU_ASYNC_JOB_SAVE, 0);
3502 virDomainAuditStop(vm, "saved");
3503 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
3504 VIR_DOMAIN_EVENT_STOPPED_SAVED);
3505 endjob:
3506 if (ret < 0) {
3507 if (was_running && virDomainObjIsActive(vm)) {
3508 virErrorPtr save_err = virSaveLastError();
3509 if (qemuProcessStartCPUs(driver, vm,
3510 VIR_DOMAIN_RUNNING_SAVE_CANCELED,
3511 QEMU_ASYNC_JOB_SAVE) < 0) {
3512 VIR_WARN("Unable to resume guest CPUs after save failure");
3513 virObjectEventStateQueue(driver->domainEventState,
3514 virDomainEventLifecycleNewFromObj(vm,
3515 VIR_DOMAIN_EVENT_SUSPENDED,
3516 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR));
3518 virSetError(save_err);
3519 virFreeError(save_err);
3522 qemuDomainObjEndAsyncJob(driver, vm);
3523 if (ret == 0)
3524 qemuDomainRemoveInactiveJob(driver, vm);
3526 cleanup:
3527 virObjectUnref(cookie);
3528 VIR_FREE(xml);
3529 virQEMUSaveDataFree(data);
3530 virObjectEventStateQueue(driver->domainEventState, event);
3531 virObjectUnref(caps);
3532 return ret;
3536 /* qemuGetCompressionProgram:
3537 * @imageFormat: String representation from qemu.conf for the compression
3538 * image format being used (dump, save, or snapshot).
3539 * @compresspath: Pointer to a character string to store the fully qualified
3540 * path from virFindFileInPath.
3541 * @styleFormat: String representing the style of format (dump, save, snapshot)
3542 * @use_raw_on_fail: Boolean indicating how to handle the error path. For
3543 * callers that are OK with invalid data or inability to
3544 * find the compression program, just return a raw format
3545 * and let the path remain as NULL.
3547 * Returns:
3548 * virQEMUSaveFormat - Integer representation of the compression
3549 * program to be used for particular style
3550 * (e.g. dump, save, or snapshot).
3551 * QEMU_SAVE_FORMAT_RAW - If there is no qemu.conf imageFormat value or
3552 * no there was an error, then just return RAW
3553 * indicating none.
3555 static int ATTRIBUTE_NONNULL(2)
3556 qemuGetCompressionProgram(const char *imageFormat,
3557 char **compresspath,
3558 const char *styleFormat,
3559 bool use_raw_on_fail)
3561 int ret;
3563 *compresspath = NULL;
3565 if (!imageFormat)
3566 return QEMU_SAVE_FORMAT_RAW;
3568 if ((ret = qemuSaveCompressionTypeFromString(imageFormat)) < 0)
3569 goto error;
3571 if (ret == QEMU_SAVE_FORMAT_RAW)
3572 return QEMU_SAVE_FORMAT_RAW;
3574 if (!(*compresspath = virFindFileInPath(imageFormat)))
3575 goto error;
3577 return ret;
3579 error:
3580 if (ret < 0) {
3581 if (use_raw_on_fail)
3582 VIR_WARN("Invalid %s image format specified in "
3583 "configuration file, using raw",
3584 styleFormat);
3585 else
3586 virReportError(VIR_ERR_OPERATION_FAILED,
3587 _("Invalid %s image format specified "
3588 "in configuration file"),
3589 styleFormat);
3590 } else {
3591 if (use_raw_on_fail)
3592 VIR_WARN("Compression program for %s image format in "
3593 "configuration file isn't available, using raw",
3594 styleFormat);
3595 else
3596 virReportError(VIR_ERR_OPERATION_FAILED,
3597 _("Compression program for %s image format "
3598 "in configuration file isn't available"),
3599 styleFormat);
3602 /* Use "raw" as the format if the specified format is not valid,
3603 * or the compress program is not available. */
3604 if (use_raw_on_fail)
3605 return QEMU_SAVE_FORMAT_RAW;
3607 return -1;
3611 static int
3612 qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
3613 unsigned int flags)
3615 virQEMUDriverPtr driver = dom->conn->privateData;
3616 int compressed;
3617 char *compressedpath = NULL;
3618 int ret = -1;
3619 virDomainObjPtr vm = NULL;
3620 virQEMUDriverConfigPtr cfg = NULL;
3622 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
3623 VIR_DOMAIN_SAVE_RUNNING |
3624 VIR_DOMAIN_SAVE_PAUSED, -1);
3626 cfg = virQEMUDriverGetConfig(driver);
3627 if ((compressed = qemuGetCompressionProgram(cfg->saveImageFormat,
3628 &compressedpath,
3629 "save", false)) < 0)
3630 goto cleanup;
3632 if (!(vm = qemuDomObjFromDomain(dom)))
3633 goto cleanup;
3635 if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
3636 goto cleanup;
3638 if (virDomainObjCheckActive(vm) < 0)
3639 goto cleanup;
3641 ret = qemuDomainSaveInternal(driver, vm, path, compressed,
3642 compressedpath, dxml, flags);
3644 cleanup:
3645 virDomainObjEndAPI(&vm);
3646 VIR_FREE(compressedpath);
3647 virObjectUnref(cfg);
3648 return ret;
3651 static int
3652 qemuDomainSave(virDomainPtr dom, const char *path)
3654 return qemuDomainSaveFlags(dom, path, NULL, 0);
3657 static char *
3658 qemuDomainManagedSavePath(virQEMUDriverPtr driver, virDomainObjPtr vm)
3660 char *ret;
3661 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3663 if (virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name) < 0) {
3664 virObjectUnref(cfg);
3665 return NULL;
3668 virObjectUnref(cfg);
3669 return ret;
3672 static int
3673 qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
3675 virQEMUDriverPtr driver = dom->conn->privateData;
3676 virQEMUDriverConfigPtr cfg = NULL;
3677 int compressed;
3678 char *compressedpath = NULL;
3679 virDomainObjPtr vm;
3680 char *name = NULL;
3681 int ret = -1;
3683 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
3684 VIR_DOMAIN_SAVE_RUNNING |
3685 VIR_DOMAIN_SAVE_PAUSED, -1);
3687 if (!(vm = qemuDomObjFromDomain(dom)))
3688 return -1;
3690 if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
3691 goto cleanup;
3693 if (virDomainObjCheckActive(vm) < 0)
3694 goto cleanup;
3696 if (!vm->persistent) {
3697 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
3698 _("cannot do managed save for transient domain"));
3699 goto cleanup;
3702 cfg = virQEMUDriverGetConfig(driver);
3703 if ((compressed = qemuGetCompressionProgram(cfg->saveImageFormat,
3704 &compressedpath,
3705 "save", false)) < 0)
3706 goto cleanup;
3708 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3709 goto cleanup;
3711 VIR_INFO("Saving state of domain '%s' to '%s'", vm->def->name, name);
3713 ret = qemuDomainSaveInternal(driver, vm, name, compressed,
3714 compressedpath, NULL, flags);
3715 if (ret == 0)
3716 vm->hasManagedSave = true;
3718 cleanup:
3719 virDomainObjEndAPI(&vm);
3720 VIR_FREE(name);
3721 VIR_FREE(compressedpath);
3722 virObjectUnref(cfg);
3724 return ret;
3727 static int
3728 qemuDomainManagedSaveLoad(virDomainObjPtr vm,
3729 void *opaque)
3731 virQEMUDriverPtr driver = opaque;
3732 char *name;
3733 int ret = -1;
3735 virObjectLock(vm);
3737 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3738 goto cleanup;
3740 vm->hasManagedSave = virFileExists(name);
3742 ret = 0;
3743 cleanup:
3744 virObjectUnlock(vm);
3745 VIR_FREE(name);
3746 return ret;
3750 static int
3751 qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
3753 virDomainObjPtr vm = NULL;
3754 int ret = -1;
3756 virCheckFlags(0, -1);
3758 if (!(vm = qemuDomObjFromDomain(dom)))
3759 return -1;
3761 if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
3762 goto cleanup;
3764 ret = vm->hasManagedSave;
3766 cleanup:
3767 virDomainObjEndAPI(&vm);
3768 return ret;
3771 static int
3772 qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
3774 virQEMUDriverPtr driver = dom->conn->privateData;
3775 virDomainObjPtr vm;
3776 int ret = -1;
3777 char *name = NULL;
3779 virCheckFlags(0, -1);
3781 if (!(vm = qemuDomObjFromDomain(dom)))
3782 return -1;
3784 if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
3785 goto cleanup;
3787 if (!(name = qemuDomainManagedSavePath(driver, vm)))
3788 goto cleanup;
3790 if (unlink(name) < 0) {
3791 virReportSystemError(errno,
3792 _("Failed to remove managed save file '%s'"),
3793 name);
3794 goto cleanup;
3797 vm->hasManagedSave = false;
3798 ret = 0;
3800 cleanup:
3801 VIR_FREE(name);
3802 virDomainObjEndAPI(&vm);
3803 return ret;
3808 * qemuDumpWaitForCompletion:
3809 * @vm: domain object
3811 * If the query dump capability exists, then it's possible to start a
3812 * guest memory dump operation using a thread via a 'detach' qualifier
3813 * to the dump guest memory command. This allows the async check if the
3814 * dump is done.
3816 * Returns 0 on success, -1 on failure
3818 static int
3819 qemuDumpWaitForCompletion(virDomainObjPtr vm)
3821 qemuDomainObjPrivatePtr priv = vm->privateData;
3822 int ret = -1;
3824 VIR_DEBUG("Waiting for dump completion");
3825 while (!priv->job.dumpCompleted && !priv->job.abortJob) {
3826 if (virDomainObjWait(vm) < 0)
3827 return -1;
3830 if (priv->job.current->stats.dump.status == QEMU_MONITOR_DUMP_STATUS_FAILED) {
3831 if (priv->job.error)
3832 virReportError(VIR_ERR_OPERATION_FAILED,
3833 _("memory-only dump failed: %s"),
3834 priv->job.error);
3835 else
3836 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3837 _("memory-only dump failed for unknown reason"));
3839 goto cleanup;
3841 qemuDomainJobInfoUpdateTime(priv->job.current);
3843 ret = 0;
3845 cleanup:
3846 return ret;
3850 static int
3851 qemuDumpToFd(virQEMUDriverPtr driver,
3852 virDomainObjPtr vm,
3853 int fd,
3854 qemuDomainAsyncJob asyncJob,
3855 const char *dumpformat)
3857 qemuDomainObjPrivatePtr priv = vm->privateData;
3858 bool detach = false;
3859 int ret = -1;
3861 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
3862 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3863 _("dump-guest-memory is not supported"));
3864 return -1;
3867 detach = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_COMPLETED);
3869 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
3870 return -1;
3872 if (detach)
3873 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP;
3874 else
3875 VIR_FREE(priv->job.current);
3877 if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
3878 return -1;
3880 if (dumpformat) {
3881 ret = qemuMonitorGetDumpGuestMemoryCapability(priv->mon, dumpformat);
3883 if (ret <= 0) {
3884 virReportError(VIR_ERR_INVALID_ARG,
3885 _("unsupported dumpformat '%s' "
3886 "for this QEMU binary"),
3887 dumpformat);
3888 ret = -1;
3889 ignore_value(qemuDomainObjExitMonitor(driver, vm));
3890 goto cleanup;
3894 ret = qemuMonitorDumpToFd(priv->mon, fd, dumpformat, detach);
3896 if ((qemuDomainObjExitMonitor(driver, vm) < 0) || ret < 0)
3897 goto cleanup;
3899 if (detach)
3900 ret = qemuDumpWaitForCompletion(vm);
3902 cleanup:
3903 return ret;
3907 static int
3908 doCoreDump(virQEMUDriverPtr driver,
3909 virDomainObjPtr vm,
3910 const char *path,
3911 unsigned int dump_flags,
3912 unsigned int dumpformat)
3914 int fd = -1;
3915 int ret = -1;
3916 virFileWrapperFdPtr wrapperFd = NULL;
3917 int directFlag = 0;
3918 unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
3919 const char *memory_dump_format = NULL;
3920 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3921 char *compressedpath = NULL;
3923 /* We reuse "save" flag for "dump" here. Then, we can support the same
3924 * format in "save" and "dump". This path doesn't need the compression
3925 * program to exist and can ignore the return value - it only cares to
3926 * get the compressedpath */
3927 ignore_value(qemuGetCompressionProgram(cfg->dumpImageFormat,
3928 &compressedpath,
3929 "dump", true));
3931 /* Create an empty file with appropriate ownership. */
3932 if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
3933 flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
3934 directFlag = virFileDirectFdFlag();
3935 if (directFlag < 0) {
3936 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3937 _("bypass cache unsupported by this system"));
3938 goto cleanup;
3941 /* Core dumps usually imply last-ditch analysis efforts are
3942 * desired, so we intentionally do not unlink even if a file was
3943 * created. */
3944 if ((fd = qemuOpenFileAs(cfg->user, cfg->group, false, path,
3945 O_CREAT | O_TRUNC | O_WRONLY | directFlag,
3946 NULL)) < 0)
3947 goto cleanup;
3949 if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
3950 goto cleanup;
3952 if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
3953 if (!(memory_dump_format = qemuDumpFormatTypeToString(dumpformat))) {
3954 virReportError(VIR_ERR_INVALID_ARG,
3955 _("unknown dumpformat '%d'"), dumpformat);
3956 goto cleanup;
3959 /* qemu dumps in "elf" without dumpformat set */
3960 if (STREQ(memory_dump_format, "elf"))
3961 memory_dump_format = NULL;
3963 ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP,
3964 memory_dump_format);
3965 } else {
3966 if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) {
3967 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
3968 _("kdump-compressed format is only supported with "
3969 "memory-only dump"));
3970 goto cleanup;
3973 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
3974 goto cleanup;
3976 ret = qemuMigrationSrcToFile(driver, vm, fd, compressedpath,
3977 QEMU_ASYNC_JOB_DUMP);
3980 if (ret < 0)
3981 goto cleanup;
3983 if (VIR_CLOSE(fd) < 0) {
3984 virReportSystemError(errno,
3985 _("unable to close file %s"),
3986 path);
3987 goto cleanup;
3989 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3990 goto cleanup;
3992 ret = 0;
3994 cleanup:
3995 VIR_FORCE_CLOSE(fd);
3996 if (qemuFileWrapperFDClose(vm, wrapperFd) < 0)
3997 ret = -1;
3998 virFileWrapperFdFree(wrapperFd);
3999 if (ret != 0)
4000 unlink(path);
4001 VIR_FREE(compressedpath);
4002 virObjectUnref(cfg);
4003 return ret;
4007 static int
4008 qemuDomainCoreDumpWithFormat(virDomainPtr dom,
4009 const char *path,
4010 unsigned int dumpformat,
4011 unsigned int flags)
4013 virQEMUDriverPtr driver = dom->conn->privateData;
4014 virDomainObjPtr vm;
4015 qemuDomainObjPrivatePtr priv = NULL;
4016 bool resume = false, paused = false;
4017 int ret = -1;
4018 virObjectEventPtr event = NULL;
4020 virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
4021 VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
4022 VIR_DUMP_MEMORY_ONLY, -1);
4024 if (!(vm = qemuDomObjFromDomain(dom)))
4025 return -1;
4027 if (virDomainCoreDumpWithFormatEnsureACL(dom->conn, vm->def) < 0)
4028 goto cleanup;
4030 if (qemuDomainObjBeginAsyncJob(driver, vm,
4031 QEMU_ASYNC_JOB_DUMP,
4032 VIR_DOMAIN_JOB_OPERATION_DUMP,
4033 flags) < 0)
4034 goto cleanup;
4036 if (virDomainObjCheckActive(vm) < 0)
4037 goto endjob;
4039 priv = vm->privateData;
4040 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
4042 /* Migrate will always stop the VM, so the resume condition is
4043 independent of whether the stop command is issued. */
4044 resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
4046 /* Pause domain for non-live dump */
4047 if (!(flags & VIR_DUMP_LIVE) &&
4048 virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
4049 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP,
4050 QEMU_ASYNC_JOB_DUMP) < 0)
4051 goto endjob;
4052 paused = true;
4054 if (!virDomainObjIsActive(vm)) {
4055 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4056 _("guest unexpectedly quit"));
4057 goto endjob;
4061 if ((ret = doCoreDump(driver, vm, path, flags, dumpformat)) < 0)
4062 goto endjob;
4064 paused = true;
4066 endjob:
4067 if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
4068 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
4069 QEMU_ASYNC_JOB_DUMP, 0);
4070 virDomainAuditStop(vm, "crashed");
4071 event = virDomainEventLifecycleNewFromObj(vm,
4072 VIR_DOMAIN_EVENT_STOPPED,
4073 VIR_DOMAIN_EVENT_STOPPED_CRASHED);
4074 } else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
4075 virDomainObjIsActive(vm)) {
4076 if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
4077 qemuDomainObjEnterMonitor(driver, vm);
4078 ret = qemuMonitorSystemReset(priv->mon);
4079 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4080 ret = -1;
4083 if (resume && virDomainObjIsActive(vm)) {
4084 if (qemuProcessStartCPUs(driver, vm,
4085 VIR_DOMAIN_RUNNING_UNPAUSED,
4086 QEMU_ASYNC_JOB_DUMP) < 0) {
4087 event = virDomainEventLifecycleNewFromObj(vm,
4088 VIR_DOMAIN_EVENT_SUSPENDED,
4089 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
4090 if (virGetLastErrorCode() == VIR_ERR_OK)
4091 virReportError(VIR_ERR_OPERATION_FAILED,
4092 "%s", _("resuming after dump failed"));
4097 qemuDomainObjEndAsyncJob(driver, vm);
4098 if (ret == 0 && flags & VIR_DUMP_CRASH)
4099 qemuDomainRemoveInactiveJob(driver, vm);
4101 cleanup:
4102 virDomainObjEndAPI(&vm);
4103 virObjectEventStateQueue(driver->domainEventState, event);
4104 return ret;
4108 static int
4109 qemuDomainCoreDump(virDomainPtr dom,
4110 const char *path,
4111 unsigned int flags)
4113 return qemuDomainCoreDumpWithFormat(dom, path,
4114 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW,
4115 flags);
4119 static char *
4120 qemuDomainScreenshot(virDomainPtr dom,
4121 virStreamPtr st,
4122 unsigned int screen,
4123 unsigned int flags)
4125 virQEMUDriverPtr driver = dom->conn->privateData;
4126 virDomainObjPtr vm;
4127 qemuDomainObjPrivatePtr priv;
4128 char *tmp = NULL;
4129 int tmp_fd = -1;
4130 size_t i;
4131 const char *videoAlias = NULL;
4132 char *ret = NULL;
4133 bool unlink_tmp = false;
4134 virQEMUDriverConfigPtr cfg = NULL;
4136 virCheckFlags(0, NULL);
4138 if (!(vm = qemuDomObjFromDomain(dom)))
4139 goto cleanup;
4141 priv = vm->privateData;
4142 cfg = virQEMUDriverGetConfig(driver);
4144 if (virDomainScreenshotEnsureACL(dom->conn, vm->def) < 0)
4145 goto cleanup;
4147 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
4148 goto cleanup;
4150 if (virDomainObjCheckActive(vm) < 0)
4151 goto endjob;
4153 if (!vm->def->nvideos) {
4154 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4155 _("no screens to take screenshot from"));
4156 goto endjob;
4159 if (screen) {
4160 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SCREENDUMP_DEVICE)) {
4161 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
4162 _("qemu does not allow specifying screen ID"));
4163 goto endjob;
4166 for (i = 0; i < vm->def->nvideos; i++) {
4167 const virDomainVideoDef *video = vm->def->videos[i];
4169 if (screen < video->heads) {
4170 videoAlias = video->info.alias;
4171 break;
4174 screen -= video->heads;
4177 if (i == vm->def->nvideos) {
4178 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4179 _("no such screen ID"));
4180 goto endjob;
4184 if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", cfg->cacheDir) < 0)
4185 goto endjob;
4187 if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
4188 virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
4189 goto endjob;
4191 unlink_tmp = true;
4193 qemuSecuritySetSavedStateLabel(driver, vm, tmp);
4195 qemuDomainObjEnterMonitor(driver, vm);
4196 if (qemuMonitorScreendump(priv->mon, videoAlias, screen, tmp) < 0) {
4197 ignore_value(qemuDomainObjExitMonitor(driver, vm));
4198 goto endjob;
4200 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4201 goto endjob;
4203 if (VIR_CLOSE(tmp_fd) < 0) {
4204 virReportSystemError(errno, _("unable to close %s"), tmp);
4205 goto endjob;
4208 if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
4209 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
4210 _("unable to open stream"));
4211 goto endjob;
4214 ignore_value(VIR_STRDUP(ret, "image/x-portable-pixmap"));
4216 endjob:
4217 VIR_FORCE_CLOSE(tmp_fd);
4218 if (unlink_tmp)
4219 unlink(tmp);
4220 VIR_FREE(tmp);
4222 qemuDomainObjEndJob(driver, vm);
4224 cleanup:
4225 virDomainObjEndAPI(&vm);
4226 virObjectUnref(cfg);
4227 return ret;
4230 static char *
4231 getAutoDumpPath(virQEMUDriverPtr driver,
4232 virDomainObjPtr vm)
4234 char *dumpfile = NULL;
4235 char *domname = virDomainDefGetShortName(vm->def);
4236 char timestr[100];
4237 struct tm time_info;
4238 time_t curtime = time(NULL);
4239 virQEMUDriverConfigPtr cfg = NULL;
4241 if (!domname)
4242 return NULL;
4244 cfg = virQEMUDriverGetConfig(driver);
4246 localtime_r(&curtime, &time_info);
4247 strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info);
4249 ignore_value(virAsprintf(&dumpfile, "%s/%s-%s",
4250 cfg->autoDumpPath,
4251 domname,
4252 timestr));
4254 virObjectUnref(cfg);
4255 VIR_FREE(domname);
4256 return dumpfile;
4259 static void
4260 processWatchdogEvent(virQEMUDriverPtr driver,
4261 virDomainObjPtr vm,
4262 int action)
4264 int ret;
4265 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4266 char *dumpfile = getAutoDumpPath(driver, vm);
4267 unsigned int flags = VIR_DUMP_MEMORY_ONLY;
4269 if (!dumpfile)
4270 goto cleanup;
4272 switch (action) {
4273 case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
4274 if (qemuDomainObjBeginAsyncJob(driver, vm,
4275 QEMU_ASYNC_JOB_DUMP,
4276 VIR_DOMAIN_JOB_OPERATION_DUMP,
4277 flags) < 0) {
4278 goto cleanup;
4281 if (virDomainObjCheckActive(vm) < 0)
4282 goto endjob;
4284 flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
4285 if ((ret = doCoreDump(driver, vm, dumpfile, flags,
4286 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
4287 virReportError(VIR_ERR_OPERATION_FAILED,
4288 "%s", _("Dump failed"));
4290 ret = qemuProcessStartCPUs(driver, vm,
4291 VIR_DOMAIN_RUNNING_UNPAUSED,
4292 QEMU_ASYNC_JOB_DUMP);
4294 if (ret < 0)
4295 virReportError(VIR_ERR_OPERATION_FAILED,
4296 "%s", _("Resuming after dump failed"));
4297 break;
4298 default:
4299 goto cleanup;
4302 endjob:
4303 qemuDomainObjEndAsyncJob(driver, vm);
4305 cleanup:
4306 virObjectUnref(cfg);
4307 VIR_FREE(dumpfile);
4310 static int
4311 doCoreDumpToAutoDumpPath(virQEMUDriverPtr driver,
4312 virDomainObjPtr vm,
4313 unsigned int flags)
4315 int ret = -1;
4316 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4317 char *dumpfile = getAutoDumpPath(driver, vm);
4319 if (!dumpfile)
4320 goto cleanup;
4322 flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
4323 if ((ret = doCoreDump(driver, vm, dumpfile, flags,
4324 VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0)
4325 virReportError(VIR_ERR_OPERATION_FAILED,
4326 "%s", _("Dump failed"));
4327 cleanup:
4328 VIR_FREE(dumpfile);
4329 virObjectUnref(cfg);
4330 return ret;
4334 static void
4335 qemuProcessGuestPanicEventInfo(virQEMUDriverPtr driver,
4336 virDomainObjPtr vm,
4337 qemuMonitorEventPanicInfoPtr info)
4339 char *msg = qemuMonitorGuestPanicEventInfoFormatMsg(info);
4340 char *timestamp = virTimeStringNow();
4342 if (msg && timestamp)
4343 qemuDomainLogAppendMessage(driver, vm, "%s: panic %s\n", timestamp, msg);
4345 VIR_FREE(timestamp);
4346 VIR_FREE(msg);
4350 static void
4351 processGuestPanicEvent(virQEMUDriverPtr driver,
4352 virDomainObjPtr vm,
4353 int action,
4354 qemuMonitorEventPanicInfoPtr info)
4356 qemuDomainObjPrivatePtr priv = vm->privateData;
4357 virObjectEventPtr event = NULL;
4358 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4359 bool removeInactive = false;
4360 unsigned long flags = VIR_DUMP_MEMORY_ONLY;
4362 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_DUMP,
4363 VIR_DOMAIN_JOB_OPERATION_DUMP, flags) < 0)
4364 goto cleanup;
4366 if (!virDomainObjIsActive(vm)) {
4367 VIR_DEBUG("Ignoring GUEST_PANICKED event from inactive domain %s",
4368 vm->def->name);
4369 goto endjob;
4372 if (info)
4373 qemuProcessGuestPanicEventInfo(driver, vm, info);
4375 virDomainObjSetState(vm, VIR_DOMAIN_CRASHED, VIR_DOMAIN_CRASHED_PANICKED);
4377 event = virDomainEventLifecycleNewFromObj(vm,
4378 VIR_DOMAIN_EVENT_CRASHED,
4379 VIR_DOMAIN_EVENT_CRASHED_PANICKED);
4381 virObjectEventStateQueue(driver->domainEventState, event);
4383 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
4384 VIR_WARN("Unable to save status on vm %s after state change",
4385 vm->def->name);
4388 if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
4389 VIR_WARN("Unable to release lease on %s", vm->def->name);
4390 VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
4392 switch (action) {
4393 case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
4394 if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
4395 goto endjob;
4396 ATTRIBUTE_FALLTHROUGH;
4398 case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
4399 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED,
4400 QEMU_ASYNC_JOB_DUMP, 0);
4401 event = virDomainEventLifecycleNewFromObj(vm,
4402 VIR_DOMAIN_EVENT_STOPPED,
4403 VIR_DOMAIN_EVENT_STOPPED_CRASHED);
4405 virObjectEventStateQueue(driver->domainEventState, event);
4406 virDomainAuditStop(vm, "destroyed");
4407 removeInactive = true;
4408 break;
4410 case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
4411 if (doCoreDumpToAutoDumpPath(driver, vm, flags) < 0)
4412 goto endjob;
4413 ATTRIBUTE_FALLTHROUGH;
4415 case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
4416 qemuDomainSetFakeReboot(driver, vm, true);
4417 qemuProcessShutdownOrReboot(driver, vm);
4418 break;
4420 case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
4421 break;
4423 default:
4424 break;
4427 endjob:
4428 qemuDomainObjEndAsyncJob(driver, vm);
4429 if (removeInactive)
4430 qemuDomainRemoveInactiveJob(driver, vm);
4432 cleanup:
4433 virObjectUnref(cfg);
4437 static void
4438 processDeviceDeletedEvent(virQEMUDriverPtr driver,
4439 virDomainObjPtr vm,
4440 const char *devAlias)
4442 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4443 virDomainDeviceDef dev;
4445 VIR_DEBUG("Removing device %s from domain %p %s",
4446 devAlias, vm, vm->def->name);
4448 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4449 goto cleanup;
4451 if (!virDomainObjIsActive(vm)) {
4452 VIR_DEBUG("Domain is not running");
4453 goto endjob;
4456 if (STRPREFIX(devAlias, "vcpu")) {
4457 qemuDomainRemoveVcpuAlias(driver, vm, devAlias);
4458 } else {
4459 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
4460 goto endjob;
4462 if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
4463 goto endjob;
4466 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
4467 VIR_WARN("unable to save domain status after removing device %s",
4468 devAlias);
4470 endjob:
4471 qemuDomainObjEndJob(driver, vm);
4473 cleanup:
4474 virObjectUnref(cfg);
4478 static void
4479 syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter,
4480 virNetDevRxFilterPtr hostFilter)
4482 char newMacStr[VIR_MAC_STRING_BUFLEN];
4484 if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
4485 virMacAddrFormat(&guestFilter->mac, newMacStr);
4487 /* set new MAC address from guest to associated macvtap device */
4488 if (virNetDevSetMAC(ifname, &guestFilter->mac) < 0) {
4489 VIR_WARN("Couldn't set new MAC address %s to device %s "
4490 "while responding to NIC_RX_FILTER_CHANGED",
4491 newMacStr, ifname);
4492 } else {
4493 VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
4499 static void
4500 syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
4501 virNetDevRxFilterPtr hostFilter)
4503 size_t i, j;
4504 bool found;
4505 char macstr[VIR_MAC_STRING_BUFLEN];
4507 for (i = 0; i < guestFilter->multicast.nTable; i++) {
4508 found = false;
4510 for (j = 0; j < hostFilter->multicast.nTable; j++) {
4511 if (virMacAddrCmp(&guestFilter->multicast.table[i],
4512 &hostFilter->multicast.table[j]) == 0) {
4513 found = true;
4514 break;
4518 if (!found) {
4519 virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
4521 if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i]) < 0) {
4522 VIR_WARN("Couldn't add new multicast MAC address %s to "
4523 "device %s while responding to NIC_RX_FILTER_CHANGED",
4524 macstr, ifname);
4525 } else {
4526 VIR_DEBUG("Added multicast MAC %s to %s interface",
4527 macstr, ifname);
4534 static void
4535 syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
4536 virNetDevRxFilterPtr hostFilter)
4538 size_t i, j;
4539 bool found;
4540 char macstr[VIR_MAC_STRING_BUFLEN];
4542 for (i = 0; i < hostFilter->multicast.nTable; i++) {
4543 found = false;
4545 for (j = 0; j < guestFilter->multicast.nTable; j++) {
4546 if (virMacAddrCmp(&hostFilter->multicast.table[i],
4547 &guestFilter->multicast.table[j]) == 0) {
4548 found = true;
4549 break;
4553 if (!found) {
4554 virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
4556 if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i]) < 0) {
4557 VIR_WARN("Couldn't delete multicast MAC address %s from "
4558 "device %s while responding to NIC_RX_FILTER_CHANGED",
4559 macstr, ifname);
4560 } else {
4561 VIR_DEBUG("Deleted multicast MAC %s from %s interface",
4562 macstr, ifname);
4569 static void
4570 syncNicRxFilterPromiscMode(char *ifname,
4571 virNetDevRxFilterPtr guestFilter,
4572 virNetDevRxFilterPtr hostFilter)
4574 bool promisc;
4575 bool setpromisc = false;
4577 /* Set macvtap promisc mode to true if the guest has vlans defined */
4578 /* or synchronize the macvtap promisc mode if different from guest */
4579 if (guestFilter->vlan.nTable > 0) {
4580 if (!hostFilter->promiscuous) {
4581 setpromisc = true;
4582 promisc = true;
4584 } else if (hostFilter->promiscuous != guestFilter->promiscuous) {
4585 setpromisc = true;
4586 promisc = guestFilter->promiscuous;
4589 if (setpromisc) {
4590 if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
4591 VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
4592 "while responding to NIC_RX_FILTER_CHANGED",
4593 promisc ? "true" : "false", ifname);
4599 static void
4600 syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
4601 virNetDevRxFilterPtr hostFilter)
4603 if (hostFilter->multicast.mode != guestFilter->multicast.mode ||
4604 (guestFilter->multicast.overflow &&
4605 guestFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_NORMAL)) {
4606 switch (guestFilter->multicast.mode) {
4607 case VIR_NETDEV_RX_FILTER_MODE_ALL:
4608 if (virNetDevSetRcvAllMulti(ifname, true) < 0) {
4609 VIR_WARN("Couldn't set allmulticast flag to 'on' for "
4610 "device %s while responding to "
4611 "NIC_RX_FILTER_CHANGED", ifname);
4613 break;
4615 case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
4616 if (guestFilter->multicast.overflow &&
4617 (hostFilter->multicast.mode == VIR_NETDEV_RX_FILTER_MODE_ALL)) {
4618 break;
4621 if (virNetDevSetRcvMulti(ifname, true) < 0) {
4622 VIR_WARN("Couldn't set multicast flag to 'on' for "
4623 "device %s while responding to "
4624 "NIC_RX_FILTER_CHANGED", ifname);
4627 if (virNetDevSetRcvAllMulti(ifname,
4628 guestFilter->multicast.overflow) < 0) {
4629 VIR_WARN("Couldn't set allmulticast flag to '%s' for "
4630 "device %s while responding to "
4631 "NIC_RX_FILTER_CHANGED",
4632 virTristateSwitchTypeToString(virTristateSwitchFromBool(guestFilter->multicast.overflow)),
4633 ifname);
4635 break;
4637 case VIR_NETDEV_RX_FILTER_MODE_NONE:
4638 if (virNetDevSetRcvAllMulti(ifname, false) < 0) {
4639 VIR_WARN("Couldn't set allmulticast flag to 'off' for "
4640 "device %s while responding to "
4641 "NIC_RX_FILTER_CHANGED", ifname);
4644 if (virNetDevSetRcvMulti(ifname, false) < 0) {
4645 VIR_WARN("Couldn't set multicast flag to 'off' for "
4646 "device %s while responding to "
4647 "NIC_RX_FILTER_CHANGED",
4648 ifname);
4650 break;
4656 static void
4657 syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
4658 virNetDevRxFilterPtr hostFilter)
4660 syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
4661 syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
4665 static void
4666 syncNicRxFilterMulticast(char *ifname,
4667 virNetDevRxFilterPtr guestFilter,
4668 virNetDevRxFilterPtr hostFilter)
4670 syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
4671 syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
4674 static void
4675 processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
4676 virDomainObjPtr vm,
4677 const char *devAlias)
4679 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4680 qemuDomainObjPrivatePtr priv = vm->privateData;
4681 virDomainDeviceDef dev;
4682 virDomainNetDefPtr def;
4683 virNetDevRxFilterPtr guestFilter = NULL;
4684 virNetDevRxFilterPtr hostFilter = NULL;
4685 int ret;
4687 VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
4688 "from domain %p %s",
4689 devAlias, vm, vm->def->name);
4691 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4692 goto cleanup;
4694 if (!virDomainObjIsActive(vm)) {
4695 VIR_DEBUG("Domain is not running");
4696 goto endjob;
4699 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
4700 VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
4701 "non-existent device %s in domain %s",
4702 devAlias, vm->def->name);
4703 goto endjob;
4705 if (dev.type != VIR_DOMAIN_DEVICE_NET) {
4706 VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
4707 "non-network device %s in domain %s",
4708 devAlias, vm->def->name);
4709 goto endjob;
4711 def = dev.data.net;
4713 if (!virDomainNetGetActualTrustGuestRxFilters(def)) {
4714 VIR_DEBUG("ignore NIC_RX_FILTER_CHANGED event for network "
4715 "device %s in domain %s",
4716 def->info.alias, vm->def->name);
4717 /* not sending "query-rx-filter" will also suppress any
4718 * further NIC_RX_FILTER_CHANGED events for this device
4720 goto endjob;
4723 /* handle the event - send query-rx-filter and respond to it. */
4725 VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
4726 "device %s in domain %s", def->info.alias, vm->def->name);
4728 qemuDomainObjEnterMonitor(driver, vm);
4729 ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
4730 if (qemuDomainObjExitMonitor(driver, vm) < 0)
4731 ret = -1;
4732 if (ret < 0)
4733 goto endjob;
4735 if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_DIRECT) {
4737 if (virNetDevGetRxFilter(def->ifname, &hostFilter)) {
4738 VIR_WARN("Couldn't get current RX filter for device %s "
4739 "while responding to NIC_RX_FILTER_CHANGED",
4740 def->ifname);
4741 goto endjob;
4744 /* For macvtap connections, set the following macvtap network device
4745 * attributes to match those of the guest network device:
4746 * - MAC address
4747 * - Multicast MAC address table
4748 * - Device options:
4749 * - PROMISC
4750 * - MULTICAST
4751 * - ALLMULTI
4753 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
4754 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
4755 syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
4758 if (virDomainNetGetActualType(def) == VIR_DOMAIN_NET_TYPE_NETWORK) {
4759 const char *brname = virDomainNetGetActualBridgeName(def);
4761 /* For libivrt network connections, set the following TUN/TAP network
4762 * device attributes to match those of the guest network device:
4763 * - QoS filters (which are based on MAC address)
4765 if (virDomainNetGetActualBandwidth(def) &&
4766 def->data.network.actual &&
4767 virNetDevBandwidthUpdateFilter(brname, &guestFilter->mac,
4768 def->data.network.actual->class_id) < 0)
4769 goto endjob;
4772 endjob:
4773 qemuDomainObjEndJob(driver, vm);
4775 cleanup:
4776 virNetDevRxFilterFree(hostFilter);
4777 virNetDevRxFilterFree(guestFilter);
4778 virObjectUnref(cfg);
4782 static void
4783 processSerialChangedEvent(virQEMUDriverPtr driver,
4784 virDomainObjPtr vm,
4785 const char *devAlias,
4786 bool connected)
4788 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4789 virDomainChrDeviceState newstate;
4790 virObjectEventPtr event = NULL;
4791 virDomainDeviceDef dev;
4792 qemuDomainObjPrivatePtr priv = vm->privateData;
4794 if (connected)
4795 newstate = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
4796 else
4797 newstate = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
4799 VIR_DEBUG("Changing serial port state %s in domain %p %s",
4800 devAlias, vm, vm->def->name);
4802 if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED &&
4803 virDomainObjIsActive(vm) && priv->agent) {
4804 /* peek into the domain definition to find the channel */
4805 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) == 0 &&
4806 dev.type == VIR_DOMAIN_DEVICE_CHR &&
4807 dev.data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
4808 dev.data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
4809 STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0"))
4810 /* Close agent monitor early, so that other threads
4811 * waiting for the agent to reply can finish and our
4812 * job we acquire below can succeed. */
4813 qemuAgentNotifyClose(priv->agent);
4815 /* now discard the data, since it may possibly change once we unlock
4816 * while entering the job */
4817 memset(&dev, 0, sizeof(dev));
4820 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4821 goto cleanup;
4823 if (!virDomainObjIsActive(vm)) {
4824 VIR_DEBUG("Domain is not running");
4825 goto endjob;
4828 if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
4829 goto endjob;
4831 /* we care only about certain devices */
4832 if (dev.type != VIR_DOMAIN_DEVICE_CHR ||
4833 dev.data.chr->deviceType != VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL ||
4834 dev.data.chr->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
4835 goto endjob;
4837 dev.data.chr->state = newstate;
4839 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
4840 VIR_WARN("unable to save status of domain %s after updating state of "
4841 "channel %s", vm->def->name, devAlias);
4843 if (STREQ_NULLABLE(dev.data.chr->target.name, "org.qemu.guest_agent.0")) {
4844 if (newstate == VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED) {
4845 if (qemuConnectAgent(driver, vm) < 0)
4846 goto endjob;
4847 } else {
4848 if (priv->agent) {
4849 qemuAgentClose(priv->agent);
4850 priv->agent = NULL;
4852 priv->agentError = false;
4855 event = virDomainEventAgentLifecycleNewFromObj(vm, newstate,
4856 VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL);
4857 virObjectEventStateQueue(driver->domainEventState, event);
4860 endjob:
4861 qemuDomainObjEndJob(driver, vm);
4863 cleanup:
4864 virObjectUnref(cfg);
4868 static void
4869 processBlockJobEvent(virQEMUDriverPtr driver,
4870 virDomainObjPtr vm,
4871 const char *diskAlias,
4872 int type,
4873 int status)
4875 virDomainDiskDefPtr disk;
4876 qemuBlockJobDataPtr job = NULL;
4878 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
4879 return;
4881 if (!virDomainObjIsActive(vm)) {
4882 VIR_DEBUG("Domain is not running");
4883 goto endjob;
4886 if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL))) {
4887 VIR_DEBUG("disk %s not found", diskAlias);
4888 goto endjob;
4891 if (!(job = qemuBlockJobDiskGetJob(disk))) {
4892 if (!(job = qemuBlockJobDiskNew(disk, type, diskAlias)))
4893 goto endjob;
4894 qemuBlockJobStarted(job);
4897 job->newstate = status;
4899 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
4901 endjob:
4902 qemuBlockJobStartupFinalize(job);
4903 qemuDomainObjEndJob(driver, vm);
4907 static void
4908 processMonitorEOFEvent(virQEMUDriverPtr driver,
4909 virDomainObjPtr vm)
4911 qemuDomainObjPrivatePtr priv = vm->privateData;
4912 int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
4913 int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
4914 const char *auditReason = "shutdown";
4915 unsigned int stopFlags = 0;
4916 virObjectEventPtr event = NULL;
4918 if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY, true) < 0)
4919 return;
4921 if (!virDomainObjIsActive(vm)) {
4922 VIR_DEBUG("Domain %p '%s' is not active, ignoring EOF",
4923 vm, vm->def->name);
4924 goto endjob;
4927 if (priv->monJSON &&
4928 virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTDOWN) {
4929 VIR_DEBUG("Monitor connection to '%s' closed without SHUTDOWN event; "
4930 "assuming the domain crashed", vm->def->name);
4931 eventReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
4932 stopReason = VIR_DOMAIN_SHUTOFF_CRASHED;
4933 auditReason = "failed";
4936 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
4937 stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
4938 qemuMigrationDstErrorSave(driver, vm->def->name,
4939 qemuMonitorLastError(priv->mon));
4942 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
4943 eventReason);
4944 qemuProcessStop(driver, vm, stopReason, QEMU_ASYNC_JOB_NONE, stopFlags);
4945 virDomainAuditStop(vm, auditReason);
4946 virObjectEventStateQueue(driver->domainEventState, event);
4948 endjob:
4949 qemuDomainRemoveInactive(driver, vm);
4950 qemuDomainObjEndJob(driver, vm);
4954 static void
4955 processPRDisconnectEvent(virDomainObjPtr vm)
4957 qemuDomainObjPrivatePtr priv = vm->privateData;
4959 if (!virDomainObjIsActive(vm))
4960 return;
4962 if (!priv->prDaemonRunning &&
4963 virDomainDefHasManagedPR(vm->def))
4964 qemuProcessStartManagedPRDaemon(vm);
4968 static void
4969 processRdmaGidStatusChangedEvent(virDomainObjPtr vm,
4970 qemuMonitorRdmaGidStatusPtr info)
4972 unsigned int prefix_len;
4973 virSocketAddr addr;
4974 VIR_AUTOFREE(char *) addrStr = NULL;
4975 int rc;
4977 if (!virDomainObjIsActive(vm))
4978 return;
4980 VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%llx, interface_id=0x%llx",
4981 info->netdev, info->gid_status, info->subnet_prefix,
4982 info->interface_id);
4984 if (info->subnet_prefix) {
4985 uint32_t ipv6[4] = {0};
4987 prefix_len = 64;
4988 memcpy(&ipv6[0], &info->subnet_prefix, sizeof(info->subnet_prefix));
4989 memcpy(&ipv6[2], &info->interface_id, sizeof(info->interface_id));
4990 virSocketAddrSetIPv6AddrNetOrder(&addr, ipv6);
4991 } else {
4992 prefix_len = 24;
4993 virSocketAddrSetIPv4AddrNetOrder(&addr, info->interface_id >> 32);
4996 if (!(addrStr = virSocketAddrFormat(&addr)))
4997 return;
4999 if (info->gid_status) {
5000 VIR_DEBUG("Adding %s to %s", addrStr, info->netdev);
5001 rc = virNetDevIPAddrAdd(info->netdev, &addr, NULL, prefix_len);
5002 } else {
5003 VIR_DEBUG("Removing %s from %s", addrStr, info->netdev);
5004 rc = virNetDevIPAddrDel(info->netdev, &addr, prefix_len);
5007 if (rc < 0)
5008 VIR_WARN("Fail to update address %s to %s", addrStr, info->netdev);
5012 static void qemuProcessEventHandler(void *data, void *opaque)
5014 struct qemuProcessEvent *processEvent = data;
5015 virDomainObjPtr vm = processEvent->vm;
5016 virQEMUDriverPtr driver = opaque;
5018 VIR_DEBUG("vm=%p, event=%d", vm, processEvent->eventType);
5020 virObjectLock(vm);
5022 switch (processEvent->eventType) {
5023 case QEMU_PROCESS_EVENT_WATCHDOG:
5024 processWatchdogEvent(driver, vm, processEvent->action);
5025 break;
5026 case QEMU_PROCESS_EVENT_GUESTPANIC:
5027 processGuestPanicEvent(driver, vm, processEvent->action,
5028 processEvent->data);
5029 break;
5030 case QEMU_PROCESS_EVENT_DEVICE_DELETED:
5031 processDeviceDeletedEvent(driver, vm, processEvent->data);
5032 break;
5033 case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
5034 processNicRxFilterChangedEvent(driver, vm, processEvent->data);
5035 break;
5036 case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
5037 processSerialChangedEvent(driver, vm, processEvent->data,
5038 processEvent->action);
5039 break;
5040 case QEMU_PROCESS_EVENT_BLOCK_JOB:
5041 processBlockJobEvent(driver, vm,
5042 processEvent->data,
5043 processEvent->action,
5044 processEvent->status);
5045 break;
5046 case QEMU_PROCESS_EVENT_MONITOR_EOF:
5047 processMonitorEOFEvent(driver, vm);
5048 break;
5049 case QEMU_PROCESS_EVENT_PR_DISCONNECT:
5050 processPRDisconnectEvent(vm);
5051 break;
5052 case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
5053 processRdmaGidStatusChangedEvent(vm, processEvent->data);
5054 break;
5055 case QEMU_PROCESS_EVENT_LAST:
5056 break;
5059 virDomainObjEndAPI(&vm);
5060 qemuProcessEventFree(processEvent);
5064 static int
5065 qemuDomainSetVcpusAgent(virDomainObjPtr vm,
5066 unsigned int nvcpus)
5068 qemuAgentCPUInfoPtr cpuinfo = NULL;
5069 qemuAgentPtr agent;
5070 int ncpuinfo;
5071 int ret = -1;
5073 if (!qemuDomainAgentAvailable(vm, true))
5074 goto cleanup;
5076 if (nvcpus > virDomainDefGetVcpus(vm->def)) {
5077 virReportError(VIR_ERR_INVALID_ARG,
5078 _("requested vcpu count is greater than the count "
5079 "of enabled vcpus in the domain: %d > %d"),
5080 nvcpus, virDomainDefGetVcpus(vm->def));
5081 goto cleanup;
5084 agent = qemuDomainObjEnterAgent(vm);
5085 ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
5086 qemuDomainObjExitAgent(vm, agent);
5087 agent = NULL;
5089 if (ncpuinfo < 0)
5090 goto cleanup;
5092 if (qemuAgentUpdateCPUInfo(nvcpus, cpuinfo, ncpuinfo) < 0)
5093 goto cleanup;
5095 if (!qemuDomainAgentAvailable(vm, true))
5096 goto cleanup;
5098 agent = qemuDomainObjEnterAgent(vm);
5099 ret = qemuAgentSetVCPUs(agent, cpuinfo, ncpuinfo);
5100 qemuDomainObjExitAgent(vm, agent);
5102 cleanup:
5103 VIR_FREE(cpuinfo);
5105 return ret;
5109 static int
5110 qemuDomainSetVcpusMax(virQEMUDriverPtr driver,
5111 virDomainDefPtr def,
5112 virDomainDefPtr persistentDef,
5113 unsigned int nvcpus)
5115 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
5116 unsigned int topologycpus;
5117 int ret = -1;
5119 if (def) {
5120 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
5121 _("maximum vcpu count of a live domain can't be modified"));
5122 goto cleanup;
5125 if (virDomainNumaGetCPUCountTotal(persistentDef->numa) > nvcpus) {
5126 virReportError(VIR_ERR_INVALID_ARG, "%s",
5127 _("Number of CPUs in <numa> exceeds the desired "
5128 "maximum vcpu count"));
5129 goto cleanup;
5132 if (virDomainDefGetVcpusTopology(persistentDef, &topologycpus) == 0 &&
5133 nvcpus != topologycpus) {
5134 /* allow setting a valid vcpu count for the topology so an invalid
5135 * setting may be corrected via this API */
5136 virReportError(VIR_ERR_INVALID_ARG, "%s",
5137 _("CPU topology doesn't match the desired vcpu count"));
5138 goto cleanup;
5141 /* ordering information may become invalid, thus clear it */
5142 virDomainDefVcpuOrderClear(persistentDef);
5144 if (virDomainDefSetVcpusMax(persistentDef, nvcpus, driver->xmlopt) < 0)
5145 goto cleanup;
5147 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
5148 goto cleanup;
5150 ret = 0;
5152 cleanup:
5153 virObjectUnref(cfg);
5154 return ret;
5158 static int
5159 qemuDomainSetVcpusFlags(virDomainPtr dom,
5160 unsigned int nvcpus,
5161 unsigned int flags)
5163 virQEMUDriverPtr driver = dom->conn->privateData;
5164 virDomainObjPtr vm = NULL;
5165 virDomainDefPtr def;
5166 virDomainDefPtr persistentDef;
5167 bool hotpluggable = !!(flags & VIR_DOMAIN_VCPU_HOTPLUGGABLE);
5168 bool useAgent = !!(flags & VIR_DOMAIN_VCPU_GUEST);
5169 qemuDomainJob job = QEMU_JOB_NONE;
5170 qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
5171 int ret = -1;
5173 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5174 VIR_DOMAIN_AFFECT_CONFIG |
5175 VIR_DOMAIN_VCPU_MAXIMUM |
5176 VIR_DOMAIN_VCPU_GUEST |
5177 VIR_DOMAIN_VCPU_HOTPLUGGABLE, -1);
5179 if (!(vm = qemuDomObjFromDomain(dom)))
5180 goto cleanup;
5182 if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5183 goto cleanup;
5185 if (useAgent)
5186 agentJob = QEMU_AGENT_JOB_MODIFY;
5187 else
5188 job = QEMU_JOB_MODIFY;
5190 if (qemuDomainObjBeginJobWithAgent(driver, vm, job, agentJob) < 0)
5191 goto cleanup;
5193 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5194 goto endjob;
5196 if (useAgent)
5197 ret = qemuDomainSetVcpusAgent(vm, nvcpus);
5198 else if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
5199 ret = qemuDomainSetVcpusMax(driver, def, persistentDef, nvcpus);
5200 else
5201 ret = qemuDomainSetVcpusInternal(driver, vm, def, persistentDef,
5202 nvcpus, hotpluggable);
5204 endjob:
5205 if (agentJob)
5206 qemuDomainObjEndAgentJob(vm);
5207 else
5208 qemuDomainObjEndJob(driver, vm);
5210 cleanup:
5211 virDomainObjEndAPI(&vm);
5212 return ret;
5216 static int
5217 qemuDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
5219 return qemuDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
5223 static int
5224 qemuDomainPinVcpuLive(virDomainObjPtr vm,
5225 virDomainDefPtr def,
5226 int vcpu,
5227 virQEMUDriverPtr driver,
5228 virQEMUDriverConfigPtr cfg,
5229 virBitmapPtr cpumap)
5231 virBitmapPtr tmpmap = NULL;
5232 virDomainVcpuDefPtr vcpuinfo;
5233 qemuDomainObjPrivatePtr priv = vm->privateData;
5234 virCgroupPtr cgroup_vcpu = NULL;
5235 char *str = NULL;
5236 virObjectEventPtr event = NULL;
5237 char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
5238 virTypedParameterPtr eventParams = NULL;
5239 int eventNparams = 0;
5240 int eventMaxparams = 0;
5241 int ret = -1;
5243 if (!qemuDomainHasVcpuPids(vm)) {
5244 virReportError(VIR_ERR_OPERATION_INVALID,
5245 "%s", _("cpu affinity is not supported"));
5246 goto cleanup;
5249 if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
5250 virReportError(VIR_ERR_INVALID_ARG,
5251 _("vcpu %d is out of range of live cpu count %d"),
5252 vcpu, virDomainDefGetVcpusMax(def));
5253 goto cleanup;
5256 if (!(tmpmap = virBitmapNewCopy(cpumap)))
5257 goto cleanup;
5259 if (!(str = virBitmapFormat(cpumap)))
5260 goto cleanup;
5262 if (vcpuinfo->online) {
5263 /* Configure the corresponding cpuset cgroup before set affinity. */
5264 if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
5265 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
5266 false, &cgroup_vcpu) < 0)
5267 goto cleanup;
5268 if (qemuSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
5269 goto cleanup;
5272 if (virProcessSetAffinity(qemuDomainGetVcpuPid(vm, vcpu), cpumap) < 0)
5273 goto cleanup;
5276 virBitmapFree(vcpuinfo->cpumask);
5277 vcpuinfo->cpumask = tmpmap;
5278 tmpmap = NULL;
5280 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5281 goto cleanup;
5283 if (snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
5284 VIR_DOMAIN_TUNABLE_CPU_VCPUPIN, vcpu) < 0) {
5285 goto cleanup;
5288 if (virTypedParamsAddString(&eventParams, &eventNparams,
5289 &eventMaxparams, paramField, str) < 0)
5290 goto cleanup;
5292 event = virDomainEventTunableNewFromObj(vm, eventParams, eventNparams);
5294 ret = 0;
5296 cleanup:
5297 virBitmapFree(tmpmap);
5298 virCgroupFree(&cgroup_vcpu);
5299 VIR_FREE(str);
5300 virObjectEventStateQueue(driver->domainEventState, event);
5301 return ret;
5305 static int
5306 qemuDomainPinVcpuFlags(virDomainPtr dom,
5307 unsigned int vcpu,
5308 unsigned char *cpumap,
5309 int maplen,
5310 unsigned int flags)
5312 virQEMUDriverPtr driver = dom->conn->privateData;
5313 virDomainObjPtr vm;
5314 virDomainDefPtr def;
5315 virDomainDefPtr persistentDef;
5316 int ret = -1;
5317 virBitmapPtr pcpumap = NULL;
5318 virDomainVcpuDefPtr vcpuinfo = NULL;
5319 virQEMUDriverConfigPtr cfg = NULL;
5321 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5322 VIR_DOMAIN_AFFECT_CONFIG, -1);
5324 cfg = virQEMUDriverGetConfig(driver);
5326 if (!(vm = qemuDomObjFromDomain(dom)))
5327 goto cleanup;
5329 if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5330 goto cleanup;
5332 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5333 goto cleanup;
5335 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5336 goto endjob;
5338 if (persistentDef &&
5339 !(vcpuinfo = virDomainDefGetVcpu(persistentDef, vcpu))) {
5340 virReportError(VIR_ERR_INVALID_ARG,
5341 _("vcpu %d is out of range of persistent cpu count %d"),
5342 vcpu, virDomainDefGetVcpus(persistentDef));
5343 goto endjob;
5346 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5347 goto endjob;
5349 if (virBitmapIsAllClear(pcpumap)) {
5350 virReportError(VIR_ERR_INVALID_ARG, "%s",
5351 _("Empty cpu list for pinning"));
5352 goto endjob;
5355 if (def &&
5356 qemuDomainPinVcpuLive(vm, def, vcpu, driver, cfg, pcpumap) < 0)
5357 goto endjob;
5359 if (persistentDef) {
5360 virBitmapFree(vcpuinfo->cpumask);
5361 vcpuinfo->cpumask = pcpumap;
5362 pcpumap = NULL;
5364 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
5365 goto endjob;
5368 ret = 0;
5370 endjob:
5371 qemuDomainObjEndJob(driver, vm);
5373 cleanup:
5374 virDomainObjEndAPI(&vm);
5375 virBitmapFree(pcpumap);
5376 virObjectUnref(cfg);
5377 return ret;
5380 static int
5381 qemuDomainPinVcpu(virDomainPtr dom,
5382 unsigned int vcpu,
5383 unsigned char *cpumap,
5384 int maplen)
5386 return qemuDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
5387 VIR_DOMAIN_AFFECT_LIVE);
5390 static int
5391 qemuDomainGetVcpuPinInfo(virDomainPtr dom,
5392 int ncpumaps,
5393 unsigned char *cpumaps,
5394 int maplen,
5395 unsigned int flags)
5397 virDomainObjPtr vm = NULL;
5398 virDomainDefPtr def;
5399 bool live;
5400 int ret = -1;
5401 virBitmapPtr autoCpuset = NULL;
5403 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5404 VIR_DOMAIN_AFFECT_CONFIG, -1);
5406 if (!(vm = qemuDomObjFromDomain(dom)))
5407 goto cleanup;
5409 if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
5410 goto cleanup;
5412 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
5413 goto cleanup;
5415 if (live)
5416 autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
5418 ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
5419 virHostCPUGetCount(), autoCpuset);
5420 cleanup:
5421 virDomainObjEndAPI(&vm);
5422 return ret;
5425 static int
5426 qemuDomainPinEmulator(virDomainPtr dom,
5427 unsigned char *cpumap,
5428 int maplen,
5429 unsigned int flags)
5431 virQEMUDriverPtr driver = dom->conn->privateData;
5432 virDomainObjPtr vm;
5433 virCgroupPtr cgroup_emulator = NULL;
5434 virDomainDefPtr def;
5435 virDomainDefPtr persistentDef;
5436 int ret = -1;
5437 qemuDomainObjPrivatePtr priv;
5438 virBitmapPtr pcpumap = NULL;
5439 virQEMUDriverConfigPtr cfg = NULL;
5440 virObjectEventPtr event = NULL;
5441 char *str = NULL;
5442 virTypedParameterPtr eventParams = NULL;
5443 int eventNparams = 0;
5444 int eventMaxparams = 0;
5446 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5447 VIR_DOMAIN_AFFECT_CONFIG, -1);
5449 cfg = virQEMUDriverGetConfig(driver);
5451 if (!(vm = qemuDomObjFromDomain(dom)))
5452 goto cleanup;
5454 if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
5455 goto cleanup;
5457 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5458 goto cleanup;
5460 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5461 goto endjob;
5463 priv = vm->privateData;
5465 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5466 goto endjob;
5468 if (virBitmapIsAllClear(pcpumap)) {
5469 virReportError(VIR_ERR_INVALID_ARG, "%s",
5470 _("Empty cpu list for pinning"));
5471 goto endjob;
5474 if (def) {
5475 if (virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
5476 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
5477 0, false, &cgroup_emulator) < 0)
5478 goto endjob;
5480 if (qemuSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
5481 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5482 _("failed to set cpuset.cpus in cgroup"
5483 " for emulator threads"));
5484 goto endjob;
5488 if (virProcessSetAffinity(vm->pid, pcpumap) < 0)
5489 goto endjob;
5491 virBitmapFree(def->cputune.emulatorpin);
5492 def->cputune.emulatorpin = NULL;
5494 if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
5495 goto endjob;
5497 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5498 goto endjob;
5500 str = virBitmapFormat(pcpumap);
5501 if (virTypedParamsAddString(&eventParams, &eventNparams,
5502 &eventMaxparams,
5503 VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
5504 str) < 0)
5505 goto endjob;
5507 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
5510 if (persistentDef) {
5511 virBitmapFree(persistentDef->cputune.emulatorpin);
5512 persistentDef->cputune.emulatorpin = NULL;
5514 if (!(persistentDef->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
5515 goto endjob;
5517 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
5518 goto endjob;
5521 ret = 0;
5523 endjob:
5524 qemuDomainObjEndJob(driver, vm);
5526 cleanup:
5527 if (cgroup_emulator)
5528 virCgroupFree(&cgroup_emulator);
5529 virObjectEventStateQueue(driver->domainEventState, event);
5530 VIR_FREE(str);
5531 virBitmapFree(pcpumap);
5532 virDomainObjEndAPI(&vm);
5533 virObjectUnref(cfg);
5534 return ret;
5537 static int
5538 qemuDomainGetEmulatorPinInfo(virDomainPtr dom,
5539 unsigned char *cpumaps,
5540 int maplen,
5541 unsigned int flags)
5543 virDomainObjPtr vm = NULL;
5544 virDomainDefPtr def;
5545 bool live;
5546 int ret = -1;
5547 int hostcpus;
5548 virBitmapPtr cpumask = NULL;
5549 virBitmapPtr bitmap = NULL;
5550 virBitmapPtr autoCpuset = NULL;
5552 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5553 VIR_DOMAIN_AFFECT_CONFIG, -1);
5555 if (!(vm = qemuDomObjFromDomain(dom)))
5556 goto cleanup;
5558 if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
5559 goto cleanup;
5561 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
5562 goto cleanup;
5564 if ((hostcpus = virHostCPUGetCount()) < 0)
5565 goto cleanup;
5567 if (live)
5568 autoCpuset = QEMU_DOMAIN_PRIVATE(vm)->autoCpuset;
5570 if (def->cputune.emulatorpin) {
5571 cpumask = def->cputune.emulatorpin;
5572 } else if (def->cpumask) {
5573 cpumask = def->cpumask;
5574 } else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
5575 autoCpuset) {
5576 cpumask = autoCpuset;
5577 } else {
5578 if (!(bitmap = virBitmapNew(hostcpus)))
5579 goto cleanup;
5580 virBitmapSetAll(bitmap);
5581 cpumask = bitmap;
5584 virBitmapToDataBuf(cpumask, cpumaps, maplen);
5586 ret = 1;
5588 cleanup:
5589 virDomainObjEndAPI(&vm);
5590 virBitmapFree(bitmap);
5591 return ret;
5594 static int
5595 qemuDomainGetVcpus(virDomainPtr dom,
5596 virVcpuInfoPtr info,
5597 int maxinfo,
5598 unsigned char *cpumaps,
5599 int maplen)
5601 virDomainObjPtr vm;
5602 int ret = -1;
5604 if (!(vm = qemuDomObjFromDomain(dom)))
5605 goto cleanup;
5607 if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
5608 goto cleanup;
5610 if (!virDomainObjIsActive(vm)) {
5611 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5612 _("cannot retrieve vcpu information for inactive domain"));
5613 goto cleanup;
5616 ret = qemuDomainHelperGetVcpus(vm, info, NULL, maxinfo, cpumaps, maplen);
5618 cleanup:
5619 virDomainObjEndAPI(&vm);
5620 return ret;
5624 static int
5625 qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
5627 virQEMUDriverPtr driver = dom->conn->privateData;
5628 virDomainObjPtr vm;
5629 virDomainDefPtr def;
5630 int ret = -1;
5631 qemuAgentCPUInfoPtr cpuinfo = NULL;
5632 qemuAgentPtr agent;
5633 int ncpuinfo = -1;
5634 size_t i;
5636 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5637 VIR_DOMAIN_AFFECT_CONFIG |
5638 VIR_DOMAIN_VCPU_MAXIMUM |
5639 VIR_DOMAIN_VCPU_GUEST, -1);
5641 if (!(vm = qemuDomObjFromDomain(dom)))
5642 return -1;
5644 if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
5645 goto cleanup;
5647 if (!(def = virDomainObjGetOneDef(vm, flags)))
5648 goto cleanup;
5650 if (flags & VIR_DOMAIN_VCPU_GUEST) {
5651 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
5652 goto cleanup;
5654 if (!virDomainObjIsActive(vm)) {
5655 virReportError(VIR_ERR_INVALID_ARG, "%s",
5656 _("vCPU count provided by the guest agent can only be "
5657 "requested for live domains"));
5658 goto endjob;
5661 if (!qemuDomainAgentAvailable(vm, true))
5662 goto endjob;
5664 agent = qemuDomainObjEnterAgent(vm);
5665 ncpuinfo = qemuAgentGetVCPUs(agent, &cpuinfo);
5666 qemuDomainObjExitAgent(vm, agent);
5668 endjob:
5669 qemuDomainObjEndAgentJob(vm);
5671 if (ncpuinfo < 0)
5672 goto cleanup;
5674 if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
5675 ret = ncpuinfo;
5676 goto cleanup;
5679 /* count the online vcpus */
5680 ret = 0;
5681 for (i = 0; i < ncpuinfo; i++) {
5682 if (cpuinfo[i].online)
5683 ret++;
5685 } else {
5686 if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
5687 ret = virDomainDefGetVcpusMax(def);
5688 else
5689 ret = virDomainDefGetVcpus(def);
5693 cleanup:
5694 virDomainObjEndAPI(&vm);
5695 VIR_FREE(cpuinfo);
5696 return ret;
5699 static int
5700 qemuDomainGetMaxVcpus(virDomainPtr dom)
5702 return qemuDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
5703 VIR_DOMAIN_VCPU_MAXIMUM));
5707 static int
5708 qemuDomainGetIOThreadsMon(virQEMUDriverPtr driver,
5709 virDomainObjPtr vm,
5710 qemuMonitorIOThreadInfoPtr **iothreads)
5712 qemuDomainObjPrivatePtr priv = vm->privateData;
5713 int niothreads = 0;
5715 qemuDomainObjEnterMonitor(driver, vm);
5716 niothreads = qemuMonitorGetIOThreads(priv->mon, iothreads);
5717 if (qemuDomainObjExitMonitor(driver, vm) < 0 || niothreads < 0)
5718 return -1;
5720 return niothreads;
5724 static int
5725 qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
5726 virDomainObjPtr vm,
5727 virDomainIOThreadInfoPtr **info)
5729 qemuDomainObjPrivatePtr priv;
5730 qemuMonitorIOThreadInfoPtr *iothreads = NULL;
5731 virDomainIOThreadInfoPtr *info_ret = NULL;
5732 int niothreads = 0;
5733 size_t i;
5734 int ret = -1;
5736 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
5737 goto cleanup;
5739 if (!virDomainObjIsActive(vm)) {
5740 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5741 _("cannot list IOThreads for an inactive domain"));
5742 goto endjob;
5745 priv = vm->privateData;
5746 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
5747 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5748 _("IOThreads not supported with this binary"));
5749 goto endjob;
5752 if ((niothreads = qemuDomainGetIOThreadsMon(driver, vm, &iothreads)) < 0)
5753 goto endjob;
5755 /* Nothing to do */
5756 if (niothreads == 0) {
5757 ret = 0;
5758 goto endjob;
5761 if (VIR_ALLOC_N(info_ret, niothreads) < 0)
5762 goto endjob;
5764 for (i = 0; i < niothreads; i++) {
5765 virBitmapPtr map = NULL;
5767 if (VIR_ALLOC(info_ret[i]) < 0)
5768 goto endjob;
5769 info_ret[i]->iothread_id = iothreads[i]->iothread_id;
5771 if (!(map = virProcessGetAffinity(iothreads[i]->thread_id)))
5772 goto endjob;
5774 if (virBitmapToData(map, &info_ret[i]->cpumap,
5775 &info_ret[i]->cpumaplen) < 0) {
5776 virBitmapFree(map);
5777 goto endjob;
5779 virBitmapFree(map);
5782 VIR_STEAL_PTR(*info, info_ret);
5783 ret = niothreads;
5785 endjob:
5786 qemuDomainObjEndJob(driver, vm);
5788 cleanup:
5789 if (info_ret) {
5790 for (i = 0; i < niothreads; i++)
5791 virDomainIOThreadInfoFree(info_ret[i]);
5792 VIR_FREE(info_ret);
5794 if (iothreads) {
5795 for (i = 0; i < niothreads; i++)
5796 VIR_FREE(iothreads[i]);
5797 VIR_FREE(iothreads);
5800 return ret;
5803 static int
5804 qemuDomainGetIOThreadsConfig(virDomainDefPtr targetDef,
5805 virDomainIOThreadInfoPtr **info)
5807 virDomainIOThreadInfoPtr *info_ret = NULL;
5808 virBitmapPtr bitmap = NULL;
5809 virBitmapPtr cpumask = NULL;
5810 int hostcpus;
5811 size_t i;
5812 int ret = -1;
5814 if (targetDef->niothreadids == 0)
5815 return 0;
5817 if ((hostcpus = virHostCPUGetCount()) < 0)
5818 goto cleanup;
5820 if (VIR_ALLOC_N(info_ret, targetDef->niothreadids) < 0)
5821 goto cleanup;
5823 for (i = 0; i < targetDef->niothreadids; i++) {
5824 if (VIR_ALLOC(info_ret[i]) < 0)
5825 goto cleanup;
5827 /* IOThread ID's are taken from the iothreadids list */
5828 info_ret[i]->iothread_id = targetDef->iothreadids[i]->iothread_id;
5830 cpumask = targetDef->iothreadids[i]->cpumask;
5831 if (!cpumask) {
5832 if (targetDef->cpumask) {
5833 cpumask = targetDef->cpumask;
5834 } else {
5835 if (!(bitmap = virBitmapNew(hostcpus)))
5836 goto cleanup;
5837 virBitmapSetAll(bitmap);
5838 cpumask = bitmap;
5841 if (virBitmapToData(cpumask, &info_ret[i]->cpumap,
5842 &info_ret[i]->cpumaplen) < 0)
5843 goto cleanup;
5844 virBitmapFree(bitmap);
5845 bitmap = NULL;
5848 *info = info_ret;
5849 info_ret = NULL;
5850 ret = targetDef->niothreadids;
5852 cleanup:
5853 if (info_ret) {
5854 for (i = 0; i < targetDef->niothreadids; i++)
5855 virDomainIOThreadInfoFree(info_ret[i]);
5856 VIR_FREE(info_ret);
5858 virBitmapFree(bitmap);
5860 return ret;
5863 static int
5864 qemuDomainGetIOThreadInfo(virDomainPtr dom,
5865 virDomainIOThreadInfoPtr **info,
5866 unsigned int flags)
5868 virQEMUDriverPtr driver = dom->conn->privateData;
5869 virDomainObjPtr vm;
5870 virDomainDefPtr targetDef = NULL;
5871 int ret = -1;
5873 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5874 VIR_DOMAIN_AFFECT_CONFIG, -1);
5876 if (!(vm = qemuDomObjFromDomain(dom)))
5877 goto cleanup;
5879 if (virDomainGetIOThreadInfoEnsureACL(dom->conn, vm->def) < 0)
5880 goto cleanup;
5882 if (virDomainObjGetDefs(vm, flags, NULL, &targetDef) < 0)
5883 goto cleanup;
5885 if (!targetDef)
5886 ret = qemuDomainGetIOThreadsLive(driver, vm, info);
5887 else
5888 ret = qemuDomainGetIOThreadsConfig(targetDef, info);
5890 cleanup:
5891 virDomainObjEndAPI(&vm);
5892 return ret;
5895 static int
5896 qemuDomainPinIOThread(virDomainPtr dom,
5897 unsigned int iothread_id,
5898 unsigned char *cpumap,
5899 int maplen,
5900 unsigned int flags)
5902 int ret = -1;
5903 virQEMUDriverPtr driver = dom->conn->privateData;
5904 virQEMUDriverConfigPtr cfg = NULL;
5905 virDomainObjPtr vm;
5906 virDomainDefPtr def;
5907 virDomainDefPtr persistentDef;
5908 virBitmapPtr pcpumap = NULL;
5909 qemuDomainObjPrivatePtr priv;
5910 virCgroupPtr cgroup_iothread = NULL;
5911 virObjectEventPtr event = NULL;
5912 char paramField[VIR_TYPED_PARAM_FIELD_LENGTH] = "";
5913 char *str = NULL;
5914 virTypedParameterPtr eventParams = NULL;
5915 int eventNparams = 0;
5916 int eventMaxparams = 0;
5918 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
5919 VIR_DOMAIN_AFFECT_CONFIG, -1);
5921 cfg = virQEMUDriverGetConfig(driver);
5923 if (!(vm = qemuDomObjFromDomain(dom)))
5924 goto cleanup;
5925 priv = vm->privateData;
5927 if (virDomainPinIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
5928 goto cleanup;
5930 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
5931 goto cleanup;
5933 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
5934 goto endjob;
5936 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
5937 goto endjob;
5939 if (virBitmapIsAllClear(pcpumap)) {
5940 virReportError(VIR_ERR_INVALID_ARG, "%s",
5941 _("Empty iothread cpumap list for pinning"));
5942 goto endjob;
5945 if (def) {
5946 virDomainIOThreadIDDefPtr iothrid;
5947 virBitmapPtr cpumask;
5949 if (!(iothrid = virDomainIOThreadIDFind(def, iothread_id))) {
5950 virReportError(VIR_ERR_INVALID_ARG,
5951 _("iothread %d not found"), iothread_id);
5952 goto endjob;
5955 if (!(cpumask = virBitmapNewData(cpumap, maplen)))
5956 goto endjob;
5958 virBitmapFree(iothrid->cpumask);
5959 iothrid->cpumask = cpumask;
5960 iothrid->autofill = false;
5962 /* Configure the corresponding cpuset cgroup before set affinity. */
5963 if (virCgroupHasController(priv->cgroup,
5964 VIR_CGROUP_CONTROLLER_CPUSET)) {
5965 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
5966 iothread_id, false, &cgroup_iothread) < 0)
5967 goto endjob;
5968 if (qemuSetupCgroupCpusetCpus(cgroup_iothread, pcpumap) < 0) {
5969 virReportError(VIR_ERR_OPERATION_INVALID,
5970 _("failed to set cpuset.cpus in cgroup"
5971 " for iothread %d"), iothread_id);
5972 goto endjob;
5976 if (virProcessSetAffinity(iothrid->thread_id, pcpumap) < 0)
5977 goto endjob;
5979 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
5980 goto endjob;
5982 if (snprintf(paramField, VIR_TYPED_PARAM_FIELD_LENGTH,
5983 VIR_DOMAIN_TUNABLE_CPU_IOTHREADSPIN, iothread_id) < 0) {
5984 goto endjob;
5987 str = virBitmapFormat(pcpumap);
5988 if (virTypedParamsAddString(&eventParams, &eventNparams,
5989 &eventMaxparams, paramField, str) < 0)
5990 goto endjob;
5992 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
5995 if (persistentDef) {
5996 virDomainIOThreadIDDefPtr iothrid;
5997 virBitmapPtr cpumask;
5999 if (!(iothrid = virDomainIOThreadIDFind(persistentDef, iothread_id))) {
6000 virReportError(VIR_ERR_INVALID_ARG,
6001 _("iothreadid %d not found"), iothread_id);
6002 goto endjob;
6005 if (!(cpumask = virBitmapNewData(cpumap, maplen)))
6006 goto endjob;
6008 virBitmapFree(iothrid->cpumask);
6009 iothrid->cpumask = cpumask;
6010 iothrid->autofill = false;
6012 ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
6013 goto endjob;
6016 ret = 0;
6018 endjob:
6019 qemuDomainObjEndJob(driver, vm);
6021 cleanup:
6022 if (cgroup_iothread)
6023 virCgroupFree(&cgroup_iothread);
6024 virObjectEventStateQueue(driver->domainEventState, event);
6025 VIR_FREE(str);
6026 virBitmapFree(pcpumap);
6027 virDomainObjEndAPI(&vm);
6028 virObjectUnref(cfg);
6029 return ret;
6032 static int
6033 qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
6034 virDomainObjPtr vm,
6035 unsigned int iothread_id)
6037 qemuDomainObjPrivatePtr priv = vm->privateData;
6038 char *alias = NULL;
6039 size_t idx;
6040 int ret = -1;
6041 unsigned int orig_niothreads = vm->def->niothreadids;
6042 unsigned int exp_niothreads = vm->def->niothreadids;
6043 int new_niothreads = 0;
6044 qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
6045 virDomainIOThreadIDDefPtr iothrid;
6046 virJSONValuePtr props = NULL;
6048 if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
6049 return -1;
6051 if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0)
6052 goto cleanup;
6054 qemuDomainObjEnterMonitor(driver, vm);
6056 if (qemuMonitorAddObject(priv->mon, &props, NULL) < 0)
6057 goto exit_monitor;
6059 exp_niothreads++;
6061 /* After hotplugging the IOThreads we need to re-detect the
6062 * IOThreads thread_id's, adjust the cgroups, thread affinity,
6063 * and add the thread_id to the vm->def->iothreadids list.
6065 if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
6066 &new_iothreads)) < 0)
6067 goto exit_monitor;
6069 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6070 goto cleanup;
6072 if (new_niothreads != exp_niothreads) {
6073 virReportError(VIR_ERR_INTERNAL_ERROR,
6074 _("got wrong number of IOThread ids from QEMU monitor. "
6075 "got %d, wanted %d"),
6076 new_niothreads, exp_niothreads);
6077 goto cleanup;
6081 * If we've successfully added an IOThread, find out where we added it
6082 * in the QEMU IOThread list, so we can add it to our iothreadids list
6084 for (idx = 0; idx < new_niothreads; idx++) {
6085 if (new_iothreads[idx]->iothread_id == iothread_id)
6086 break;
6089 if (idx == new_niothreads) {
6090 virReportError(VIR_ERR_INTERNAL_ERROR,
6091 _("cannot find new IOThread '%u' in QEMU monitor."),
6092 iothread_id);
6093 goto cleanup;
6096 if (!(iothrid = virDomainIOThreadIDAdd(vm->def, iothread_id)))
6097 goto cleanup;
6099 iothrid->thread_id = new_iothreads[idx]->thread_id;
6101 if (qemuProcessSetupIOThread(vm, iothrid) < 0)
6102 goto cleanup;
6104 ret = 0;
6106 cleanup:
6107 if (new_iothreads) {
6108 for (idx = 0; idx < new_niothreads; idx++)
6109 VIR_FREE(new_iothreads[idx]);
6110 VIR_FREE(new_iothreads);
6112 virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
6113 "update", ret == 0);
6114 VIR_FREE(alias);
6115 virJSONValueFree(props);
6116 return ret;
6118 exit_monitor:
6119 ignore_value(qemuDomainObjExitMonitor(driver, vm));
6120 goto cleanup;
6124 static int
6125 qemuDomainHotplugModIOThread(virQEMUDriverPtr driver,
6126 virDomainObjPtr vm,
6127 qemuMonitorIOThreadInfo iothread)
6129 qemuDomainObjPrivatePtr priv = vm->privateData;
6130 int rc;
6132 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) {
6133 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6134 _("IOThreads polling is not supported for this QEMU"));
6135 return -1;
6138 qemuDomainObjEnterMonitor(driver, vm);
6140 rc = qemuMonitorSetIOThread(priv->mon, &iothread);
6142 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6143 return -1;
6145 if (rc < 0)
6146 return -1;
6148 return 0;
6152 static int
6153 qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
6154 virDomainObjPtr vm,
6155 unsigned int iothread_id)
6157 qemuDomainObjPrivatePtr priv = vm->privateData;
6158 size_t idx;
6159 char *alias = NULL;
6160 int rc = -1;
6161 int ret = -1;
6162 unsigned int orig_niothreads = vm->def->niothreadids;
6163 unsigned int exp_niothreads = vm->def->niothreadids;
6164 int new_niothreads = 0;
6165 qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
6167 if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
6168 return -1;
6170 qemuDomainObjEnterMonitor(driver, vm);
6172 rc = qemuMonitorDelObject(priv->mon, alias);
6173 exp_niothreads--;
6174 if (rc < 0)
6175 goto exit_monitor;
6177 if ((new_niothreads = qemuMonitorGetIOThreads(priv->mon,
6178 &new_iothreads)) < 0)
6179 goto exit_monitor;
6181 if (qemuDomainObjExitMonitor(driver, vm) < 0)
6182 goto cleanup;
6184 if (new_niothreads != exp_niothreads) {
6185 virReportError(VIR_ERR_INTERNAL_ERROR,
6186 _("got wrong number of IOThread ids from QEMU monitor. "
6187 "got %d, wanted %d"),
6188 new_niothreads, exp_niothreads);
6189 goto cleanup;
6192 virDomainIOThreadIDDel(vm->def, iothread_id);
6194 if (virCgroupDelThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
6195 iothread_id) < 0)
6196 goto cleanup;
6198 ret = 0;
6200 cleanup:
6201 if (new_iothreads) {
6202 for (idx = 0; idx < new_niothreads; idx++)
6203 VIR_FREE(new_iothreads[idx]);
6204 VIR_FREE(new_iothreads);
6206 virDomainAuditIOThread(vm, orig_niothreads, new_niothreads,
6207 "update", rc == 0);
6208 VIR_FREE(alias);
6209 return ret;
6211 exit_monitor:
6212 ignore_value(qemuDomainObjExitMonitor(driver, vm));
6213 goto cleanup;
6217 static int
6218 qemuDomainAddIOThreadCheck(virDomainDefPtr def,
6219 unsigned int iothread_id)
6221 if (virDomainIOThreadIDFind(def, iothread_id)) {
6222 virReportError(VIR_ERR_INVALID_ARG,
6223 _("an IOThread is already using iothread_id '%u'"),
6224 iothread_id);
6225 return -1;
6228 return 0;
6232 static int
6233 qemuDomainDelIOThreadCheck(virDomainDefPtr def,
6234 unsigned int iothread_id)
6236 size_t i;
6238 if (!virDomainIOThreadIDFind(def, iothread_id)) {
6239 virReportError(VIR_ERR_INVALID_ARG,
6240 _("cannot find IOThread '%u' in iothreadids list"),
6241 iothread_id);
6242 return -1;
6245 for (i = 0; i < def->ndisks; i++) {
6246 if (def->disks[i]->iothread == iothread_id) {
6247 virReportError(VIR_ERR_INVALID_ARG,
6248 _("cannot remove IOThread %u since it "
6249 "is being used by disk '%s'"),
6250 iothread_id, def->disks[i]->dst);
6251 return -1;
6255 for (i = 0; i < def->ncontrollers; i++) {
6256 if (def->controllers[i]->iothread == iothread_id) {
6257 virReportError(VIR_ERR_INVALID_ARG,
6258 _("cannot remove IOThread '%u' since it "
6259 "is being used by controller"),
6260 iothread_id);
6261 return -1;
6265 return 0;
6270 * @params: Pointer to params list
6271 * @nparams: Number of params to be parsed
6272 * @iothread: Buffer to store the values
6274 * The following is a description of each value parsed:
6276 * - "poll-max-ns" for each IOThread is the maximum time in nanoseconds
6277 * to allow each polling interval to occur. A polling interval is a
6278 * period of time allowed for a thread to process data before it returns
6279 * the CPU quantum back to the host. A value set too small will not allow
6280 * the IOThread to run long enough on a CPU to process data. A value set
6281 * too high will consume too much CPU time per IOThread failing to allow
6282 * other threads running on the CPU to get time. A value of 0 (zero) will
6283 * disable the polling.
6285 * - "poll-grow" - factor to grow the current polling time when deemed
6286 * necessary. If a 0 (zero) value is provided, QEMU currently doubles
6287 * its polling interval unless the current value is greater than the
6288 * poll-max-ns.
6290 * - "poll-shrink" - divisor to reduced the current polling time when deemed
6291 * necessary. If a 0 (zero) value is provided, QEMU resets the polling
6292 * interval to 0 (zero) allowing the poll-grow to manipulate the time.
6294 * QEMU keeps track of the polling time elapsed and may grow or shrink the
6295 * its polling interval based upon its heuristic algorithm. It is possible
6296 * that calculations determine that it has found a "sweet spot" and no
6297 * adjustments are made. The polling time value is not available.
6299 * Returns 0 on success, -1 on failure with error set.
6301 static int
6302 qemuDomainIOThreadParseParams(virTypedParameterPtr params,
6303 int nparams,
6304 qemuMonitorIOThreadInfoPtr iothread)
6306 int rc;
6308 if (virTypedParamsValidate(params, nparams,
6309 VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
6310 VIR_TYPED_PARAM_ULLONG,
6311 VIR_DOMAIN_IOTHREAD_POLL_GROW,
6312 VIR_TYPED_PARAM_UINT,
6313 VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
6314 VIR_TYPED_PARAM_UINT,
6315 NULL) < 0)
6316 return -1;
6318 if ((rc = virTypedParamsGetULLong(params, nparams,
6319 VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
6320 &iothread->poll_max_ns)) < 0)
6321 return -1;
6322 if (rc == 1)
6323 iothread->set_poll_max_ns = true;
6325 if ((rc = virTypedParamsGetUInt(params, nparams,
6326 VIR_DOMAIN_IOTHREAD_POLL_GROW,
6327 &iothread->poll_grow)) < 0)
6328 return -1;
6329 if (rc == 1)
6330 iothread->set_poll_grow = true;
6332 if ((rc = virTypedParamsGetUInt(params, nparams,
6333 VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
6334 &iothread->poll_shrink)) < 0)
6335 return -1;
6336 if (rc == 1)
6337 iothread->set_poll_shrink = true;
6339 if (iothread->set_poll_max_ns && iothread->poll_max_ns > INT_MAX) {
6340 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6341 _("poll-max-ns (%llu) must be less than or equal to %d"),
6342 iothread->poll_max_ns, INT_MAX);
6343 return -1;
6346 if (iothread->set_poll_grow && iothread->poll_grow > INT_MAX) {
6347 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6348 _("poll-grow (%u) must be less than or equal to %d"),
6349 iothread->poll_grow, INT_MAX);
6350 return -1;
6353 if (iothread->set_poll_shrink && iothread->poll_shrink > INT_MAX) {
6354 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6355 _("poll-shrink (%u) must be less than or equal to %d"),
6356 iothread->poll_shrink, INT_MAX);
6357 return -1;
6360 return 0;
6364 typedef enum {
6365 VIR_DOMAIN_IOTHREAD_ACTION_ADD,
6366 VIR_DOMAIN_IOTHREAD_ACTION_DEL,
6367 VIR_DOMAIN_IOTHREAD_ACTION_MOD,
6368 } virDomainIOThreadAction;
6370 static int
6371 qemuDomainChgIOThread(virQEMUDriverPtr driver,
6372 virDomainObjPtr vm,
6373 qemuMonitorIOThreadInfo iothread,
6374 virDomainIOThreadAction action,
6375 unsigned int flags)
6377 virQEMUDriverConfigPtr cfg = NULL;
6378 qemuDomainObjPrivatePtr priv;
6379 virDomainDefPtr def;
6380 virDomainDefPtr persistentDef;
6381 int ret = -1;
6383 cfg = virQEMUDriverGetConfig(driver);
6385 priv = vm->privateData;
6387 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
6388 goto cleanup;
6390 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
6391 goto endjob;
6393 if (def) {
6394 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
6395 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6396 _("IOThreads not supported with this binary"));
6397 goto endjob;
6400 switch (action) {
6401 case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
6402 if (qemuDomainAddIOThreadCheck(def, iothread.iothread_id) < 0)
6403 goto endjob;
6405 if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
6406 goto endjob;
6408 break;
6410 case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
6411 if (qemuDomainDelIOThreadCheck(def, iothread.iothread_id) < 0)
6412 goto endjob;
6414 if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
6415 goto endjob;
6417 break;
6419 case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
6420 if (!(virDomainIOThreadIDFind(def, iothread.iothread_id))) {
6421 virReportError(VIR_ERR_INVALID_ARG,
6422 _("cannot find IOThread '%u' in iothreadids"),
6423 iothread.iothread_id);
6424 goto endjob;
6427 if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
6428 goto endjob;
6430 break;
6434 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
6435 goto endjob;
6438 if (persistentDef) {
6439 switch (action) {
6440 case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
6441 if (qemuDomainAddIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
6442 goto endjob;
6444 if (!virDomainIOThreadIDAdd(persistentDef, iothread.iothread_id))
6445 goto endjob;
6447 break;
6449 case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
6450 if (qemuDomainDelIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
6451 goto endjob;
6453 virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);
6455 break;
6457 case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
6458 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
6459 _("configuring persistent polling values is "
6460 "not supported"));
6461 goto endjob;
6463 break;
6466 if (virDomainSaveConfig(cfg->configDir, driver->caps,
6467 persistentDef) < 0)
6468 goto endjob;
6471 ret = 0;
6473 endjob:
6474 qemuDomainObjEndJob(driver, vm);
6476 cleanup:
6477 virObjectUnref(cfg);
6478 return ret;
6481 static int
6482 qemuDomainAddIOThread(virDomainPtr dom,
6483 unsigned int iothread_id,
6484 unsigned int flags)
6486 virQEMUDriverPtr driver = dom->conn->privateData;
6487 virDomainObjPtr vm = NULL;
6488 qemuMonitorIOThreadInfo iothread = {0};
6489 int ret = -1;
6491 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6492 VIR_DOMAIN_AFFECT_CONFIG, -1);
6494 if (iothread_id == 0) {
6495 virReportError(VIR_ERR_INVALID_ARG, "%s",
6496 _("invalid value of 0 for iothread_id"));
6497 return -1;
6500 if (!(vm = qemuDomObjFromDomain(dom)))
6501 goto cleanup;
6503 if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
6504 goto cleanup;
6506 iothread.iothread_id = iothread_id;
6507 ret = qemuDomainChgIOThread(driver, vm, iothread,
6508 VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);
6510 cleanup:
6511 virDomainObjEndAPI(&vm);
6512 return ret;
6516 static int
6517 qemuDomainDelIOThread(virDomainPtr dom,
6518 unsigned int iothread_id,
6519 unsigned int flags)
6521 virQEMUDriverPtr driver = dom->conn->privateData;
6522 virDomainObjPtr vm = NULL;
6523 qemuMonitorIOThreadInfo iothread = {0};
6524 int ret = -1;
6526 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
6527 VIR_DOMAIN_AFFECT_CONFIG, -1);
6529 if (iothread_id == 0) {
6530 virReportError(VIR_ERR_INVALID_ARG, "%s",
6531 _("invalid value of 0 for iothread_id"));
6532 return -1;
6535 if (!(vm = qemuDomObjFromDomain(dom)))
6536 goto cleanup;
6538 if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
6539 goto cleanup;
6541 iothread.iothread_id = iothread_id;
6542 ret = qemuDomainChgIOThread(driver, vm, iothread,
6543 VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);
6545 cleanup:
6546 virDomainObjEndAPI(&vm);
6547 return ret;
6552 * @dom: Domain to set IOThread params
6553 * @iothread_id: IOThread 'id' that will be modified
6554 * @params: List of parameters to change
6555 * @nparams: Number of parameters in the list
6556 * @flags: Flags for the set (only supports live alteration)
6558 * Alter the specified @iothread_id with the values provided.
6560 * Returs 0 on success, -1 on failure
6562 static int
6563 qemuDomainSetIOThreadParams(virDomainPtr dom,
6564 unsigned int iothread_id,
6565 virTypedParameterPtr params,
6566 int nparams,
6567 unsigned int flags)
6569 virQEMUDriverPtr driver = dom->conn->privateData;
6570 virDomainObjPtr vm = NULL;
6571 qemuMonitorIOThreadInfo iothread = {0};
6572 int ret = -1;
6574 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE, -1);
6576 if (iothread_id == 0) {
6577 virReportError(VIR_ERR_INVALID_ARG, "%s",
6578 _("invalid value of 0 for iothread_id"));
6579 goto cleanup;
6582 iothread.iothread_id = iothread_id;
6584 if (!(vm = qemuDomObjFromDomain(dom)))
6585 goto cleanup;
6587 if (virDomainSetIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
6588 goto cleanup;
6590 if (qemuDomainIOThreadParseParams(params, nparams, &iothread) < 0)
6591 goto cleanup;
6593 ret = qemuDomainChgIOThread(driver, vm, iothread,
6594 VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags);
6596 cleanup:
6597 virDomainObjEndAPI(&vm);
6598 return ret;
6602 static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
6604 virQEMUDriverPtr driver = dom->conn->privateData;
6605 virDomainObjPtr vm;
6606 int ret = -1;
6608 memset(seclabel, 0, sizeof(*seclabel));
6610 if (!(vm = qemuDomObjFromDomain(dom)))
6611 return -1;
6613 if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0)
6614 goto cleanup;
6617 * Theoretically, the pid can be replaced during this operation and
6618 * return the label of a different process. If atomicity is needed,
6619 * further validation will be required.
6621 * Comment from Dan Berrange:
6623 * Well the PID as stored in the virDomainObjPtr can't be changed
6624 * because you've got a locked object. The OS level PID could have
6625 * exited, though and in extreme circumstances have cycled through all
6626 * PIDs back to ours. We could sanity check that our PID still exists
6627 * after reading the label, by checking that our FD connecting to the
6628 * QEMU monitor hasn't seen SIGHUP/ERR on poll().
6630 if (virDomainObjIsActive(vm)) {
6631 if (qemuSecurityGetProcessLabel(driver->securityManager,
6632 vm->def, vm->pid, seclabel) < 0)
6633 goto cleanup;
6636 ret = 0;
6638 cleanup:
6639 virDomainObjEndAPI(&vm);
6640 return ret;
6643 static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
6644 virSecurityLabelPtr* seclabels)
6646 virQEMUDriverPtr driver = dom->conn->privateData;
6647 virDomainObjPtr vm;
6648 size_t i;
6649 int ret = -1;
6651 if (!(vm = qemuDomObjFromDomain(dom)))
6652 return -1;
6654 if (virDomainGetSecurityLabelListEnsureACL(dom->conn, vm->def) < 0)
6655 goto cleanup;
6658 * Check the comment in qemuDomainGetSecurityLabel function.
6660 if (!virDomainObjIsActive(vm)) {
6661 /* No seclabels */
6662 *seclabels = NULL;
6663 ret = 0;
6664 } else {
6665 int len = 0;
6666 virSecurityManagerPtr* mgrs = qemuSecurityGetNested(driver->securityManager);
6667 if (!mgrs)
6668 goto cleanup;
6670 /* Allocate seclabels array */
6671 for (i = 0; mgrs[i]; i++)
6672 len++;
6674 if (VIR_ALLOC_N((*seclabels), len) < 0) {
6675 VIR_FREE(mgrs);
6676 goto cleanup;
6678 memset(*seclabels, 0, sizeof(**seclabels) * len);
6680 /* Fill the array */
6681 for (i = 0; i < len; i++) {
6682 if (qemuSecurityGetProcessLabel(mgrs[i], vm->def, vm->pid,
6683 &(*seclabels)[i]) < 0) {
6684 VIR_FREE(mgrs);
6685 VIR_FREE(*seclabels);
6686 goto cleanup;
6689 ret = len;
6690 VIR_FREE(mgrs);
6693 cleanup:
6694 virDomainObjEndAPI(&vm);
6695 return ret;
6699 static int qemuNodeGetSecurityModel(virConnectPtr conn,
6700 virSecurityModelPtr secmodel)
6702 virQEMUDriverPtr driver = conn->privateData;
6703 char *p;
6704 int ret = 0;
6705 virCapsPtr caps = NULL;
6707 memset(secmodel, 0, sizeof(*secmodel));
6709 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6710 goto cleanup;
6712 if (virNodeGetSecurityModelEnsureACL(conn) < 0)
6713 goto cleanup;
6715 /* We treat no driver as success, but simply return no data in *secmodel */
6716 if (caps->host.nsecModels == 0 ||
6717 caps->host.secModels[0].model == NULL)
6718 goto cleanup;
6720 p = caps->host.secModels[0].model;
6721 if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
6722 virReportError(VIR_ERR_INTERNAL_ERROR,
6723 _("security model string exceeds max %d bytes"),
6724 VIR_SECURITY_MODEL_BUFLEN-1);
6725 ret = -1;
6726 goto cleanup;
6728 strcpy(secmodel->model, p);
6730 p = caps->host.secModels[0].doi;
6731 if (strlen(p) >= VIR_SECURITY_DOI_BUFLEN-1) {
6732 virReportError(VIR_ERR_INTERNAL_ERROR,
6733 _("security DOI string exceeds max %d bytes"),
6734 VIR_SECURITY_DOI_BUFLEN-1);
6735 ret = -1;
6736 goto cleanup;
6738 strcpy(secmodel->doi, p);
6740 cleanup:
6741 virObjectUnref(caps);
6742 return ret;
6747 * qemuDomainSaveImageUpdateDef:
6748 * @driver: qemu driver data
6749 * @def: def of the domain from the save image
6750 * @newxml: user provided replacement XML
6752 * Returns the new domain definition in case @newxml is ABI compatible with the
6753 * guest.
6755 static virDomainDefPtr
6756 qemuDomainSaveImageUpdateDef(virQEMUDriverPtr driver,
6757 virDomainDefPtr def,
6758 const char *newxml)
6760 virDomainDefPtr ret = NULL;
6761 virDomainDefPtr newdef_migr = NULL;
6762 virDomainDefPtr newdef = NULL;
6763 virCapsPtr caps = NULL;
6765 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6766 goto cleanup;
6768 if (!(newdef = virDomainDefParseString(newxml, caps, driver->xmlopt, NULL,
6769 VIR_DOMAIN_DEF_PARSE_INACTIVE)))
6770 goto cleanup;
6772 if (!(newdef_migr = qemuDomainDefCopy(driver,
6773 newdef,
6774 QEMU_DOMAIN_FORMAT_LIVE_FLAGS |
6775 VIR_DOMAIN_XML_MIGRATABLE)))
6776 goto cleanup;
6778 if (!virDomainDefCheckABIStability(def, newdef_migr, driver->xmlopt)) {
6779 virErrorPtr err = virSaveLastError();
6781 /* Due to a bug in older version of external snapshot creation
6782 * code, the XML saved in the save image was not a migratable
6783 * XML. To ensure backwards compatibility with the change of the
6784 * saved XML type, we need to check the ABI compatibility against
6785 * the user provided XML if the check against the migratable XML
6786 * fails. Snapshots created prior to v1.1.3 have this issue. */
6787 if (!virDomainDefCheckABIStability(def, newdef, driver->xmlopt)) {
6788 virSetError(err);
6789 virFreeError(err);
6790 goto cleanup;
6792 virFreeError(err);
6794 /* use the user provided XML */
6795 VIR_STEAL_PTR(ret, newdef);
6796 } else {
6797 VIR_STEAL_PTR(ret, newdef_migr);
6800 cleanup:
6801 virObjectUnref(caps);
6802 virDomainDefFree(newdef);
6803 virDomainDefFree(newdef_migr);
6805 return ret;
6810 * qemuDomainSaveImageOpen:
6811 * @driver: qemu driver data
6812 * @path: path of the save image
6813 * @ret_def: returns domain definition created from the XML stored in the image
6814 * @ret_data: returns structure filled with data from the image header
6815 * @bypass_cache: bypass cache when opening the file
6816 * @wrapperFd: returns the file wrapper structure
6817 * @open_write: open the file for writing (for updates)
6818 * @unlink_corrupt: remove the image file if it is corrupted
6820 * Returns the opened fd of the save image file and fills the appropriate fields
6821 * on success. On error returns -1 on most failures, -3 if corrupt image was
6822 * unlinked (no error raised).
6824 static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
6825 qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
6826 const char *path,
6827 virDomainDefPtr *ret_def,
6828 virQEMUSaveDataPtr *ret_data,
6829 bool bypass_cache,
6830 virFileWrapperFdPtr *wrapperFd,
6831 bool open_write,
6832 bool unlink_corrupt)
6834 int fd = -1;
6835 virQEMUSaveDataPtr data = NULL;
6836 virQEMUSaveHeaderPtr header;
6837 virDomainDefPtr def = NULL;
6838 int oflags = open_write ? O_RDWR : O_RDONLY;
6839 virCapsPtr caps = NULL;
6840 size_t xml_len;
6841 size_t cookie_len;
6843 if (bypass_cache) {
6844 int directFlag = virFileDirectFdFlag();
6845 if (directFlag < 0) {
6846 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
6847 _("bypass cache unsupported by this system"));
6848 goto error;
6850 oflags |= directFlag;
6853 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6854 goto error;
6856 if ((fd = qemuOpenFile(driver, NULL, path, oflags, NULL)) < 0)
6857 goto error;
6858 if (bypass_cache &&
6859 !(*wrapperFd = virFileWrapperFdNew(&fd, path,
6860 VIR_FILE_WRAPPER_BYPASS_CACHE)))
6861 goto error;
6863 if (VIR_ALLOC(data) < 0)
6864 goto error;
6866 header = &data->header;
6867 if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) {
6868 if (unlink_corrupt) {
6869 if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
6870 virReportSystemError(errno,
6871 _("cannot remove corrupt file: %s"),
6872 path);
6873 } else {
6874 fd = -3;
6876 } else {
6877 virReportError(VIR_ERR_OPERATION_FAILED,
6878 "%s", _("failed to read qemu header"));
6880 goto error;
6883 if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) {
6884 const char *msg = _("image magic is incorrect");
6886 if (memcmp(header->magic, QEMU_SAVE_PARTIAL,
6887 sizeof(header->magic)) == 0) {
6888 msg = _("save image is incomplete");
6889 if (unlink_corrupt) {
6890 if (VIR_CLOSE(fd) < 0 || unlink(path) < 0) {
6891 virReportSystemError(errno,
6892 _("cannot remove corrupt file: %s"),
6893 path);
6894 } else {
6895 fd = -3;
6897 goto error;
6900 virReportError(VIR_ERR_OPERATION_FAILED, "%s", msg);
6901 goto error;
6904 if (header->version > QEMU_SAVE_VERSION) {
6905 /* convert endianess and try again */
6906 bswap_header(header);
6909 if (header->version > QEMU_SAVE_VERSION) {
6910 virReportError(VIR_ERR_OPERATION_FAILED,
6911 _("image version is not supported (%d > %d)"),
6912 header->version, QEMU_SAVE_VERSION);
6913 goto error;
6916 if (header->data_len <= 0) {
6917 virReportError(VIR_ERR_OPERATION_FAILED,
6918 _("invalid header data length: %d"), header->data_len);
6919 goto error;
6922 if (header->cookieOffset)
6923 xml_len = header->cookieOffset;
6924 else
6925 xml_len = header->data_len;
6927 cookie_len = header->data_len - xml_len;
6929 if (VIR_ALLOC_N(data->xml, xml_len) < 0)
6930 goto error;
6932 if (saferead(fd, data->xml, xml_len) != xml_len) {
6933 virReportError(VIR_ERR_OPERATION_FAILED,
6934 "%s", _("failed to read domain XML"));
6935 goto error;
6938 if (cookie_len > 0) {
6939 if (VIR_ALLOC_N(data->cookie, cookie_len) < 0)
6940 goto error;
6942 if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
6943 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
6944 _("failed to read cookie"));
6945 goto error;
6949 /* Create a domain from this XML */
6950 if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL,
6951 VIR_DOMAIN_DEF_PARSE_INACTIVE |
6952 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
6953 goto error;
6955 *ret_def = def;
6956 *ret_data = data;
6958 cleanup:
6959 virObjectUnref(caps);
6960 return fd;
6962 error:
6963 virDomainDefFree(def);
6964 virQEMUSaveDataFree(data);
6965 VIR_FORCE_CLOSE(fd);
6966 goto cleanup;
6969 static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6)
6970 qemuDomainSaveImageStartVM(virConnectPtr conn,
6971 virQEMUDriverPtr driver,
6972 virDomainObjPtr vm,
6973 int *fd,
6974 virQEMUSaveDataPtr data,
6975 const char *path,
6976 bool start_paused,
6977 qemuDomainAsyncJob asyncJob)
6979 int ret = -1;
6980 bool restored = false;
6981 virObjectEventPtr event;
6982 int intermediatefd = -1;
6983 virCommandPtr cmd = NULL;
6984 char *errbuf = NULL;
6985 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
6986 virQEMUSaveHeaderPtr header = &data->header;
6987 qemuDomainSaveCookiePtr cookie = NULL;
6989 if (virSaveCookieParseString(data->cookie, (virObjectPtr *)&cookie,
6990 virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0)
6991 goto cleanup;
6993 if ((header->version == 2) &&
6994 (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
6995 if (!(cmd = qemuCompressGetCommand(header->compressed)))
6996 goto cleanup;
6998 intermediatefd = *fd;
6999 *fd = -1;
7001 virCommandSetInputFD(cmd, intermediatefd);
7002 virCommandSetOutputFD(cmd, fd);
7003 virCommandSetErrorBuffer(cmd, &errbuf);
7004 virCommandDoAsyncIO(cmd);
7006 if (virCommandRunAsync(cmd, NULL) < 0) {
7007 *fd = intermediatefd;
7008 goto cleanup;
7012 /* No cookie means libvirt which saved the domain was too old to mess up
7013 * the CPU definitions.
7015 if (cookie &&
7016 qemuDomainFixupCPUs(vm, &cookie->cpu) < 0)
7017 goto cleanup;
7019 if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
7020 asyncJob, "stdio", *fd, path, NULL,
7021 VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
7022 VIR_QEMU_PROCESS_START_PAUSED |
7023 VIR_QEMU_PROCESS_START_GEN_VMID) == 0)
7024 restored = true;
7026 if (intermediatefd != -1) {
7027 virErrorPtr orig_err = NULL;
7029 if (!restored) {
7030 /* if there was an error setting up qemu, the intermediate
7031 * process will wait forever to write to stdout, so we
7032 * must manually kill it and ignore any error related to
7033 * the process
7035 orig_err = virSaveLastError();
7036 VIR_FORCE_CLOSE(intermediatefd);
7037 VIR_FORCE_CLOSE(*fd);
7040 if (virCommandWait(cmd, NULL) < 0) {
7041 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, asyncJob, 0);
7042 restored = false;
7044 VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
7046 if (orig_err) {
7047 virSetError(orig_err);
7048 virFreeError(orig_err);
7051 VIR_FORCE_CLOSE(intermediatefd);
7053 if (VIR_CLOSE(*fd) < 0) {
7054 virReportSystemError(errno, _("cannot close file: %s"), path);
7055 restored = false;
7058 virDomainAuditStart(vm, "restored", restored);
7059 if (!restored)
7060 goto cleanup;
7062 /* qemuProcessStart doesn't unset the qemu error reporting infrastructure
7063 * in case of migration (which is used in this case) so we need to reset it
7064 * so that the handle to virtlogd is not held open unnecessarily */
7065 qemuMonitorSetDomainLog(qemuDomainGetMonitor(vm), NULL, NULL, NULL);
7067 event = virDomainEventLifecycleNewFromObj(vm,
7068 VIR_DOMAIN_EVENT_STARTED,
7069 VIR_DOMAIN_EVENT_STARTED_RESTORED);
7070 virObjectEventStateQueue(driver->domainEventState, event);
7073 /* If it was running before, resume it now unless caller requested pause. */
7074 if (header->was_running && !start_paused) {
7075 if (qemuProcessStartCPUs(driver, vm,
7076 VIR_DOMAIN_RUNNING_RESTORED,
7077 asyncJob) < 0) {
7078 if (virGetLastErrorCode() == VIR_ERR_OK)
7079 virReportError(VIR_ERR_OPERATION_FAILED,
7080 "%s", _("failed to resume domain"));
7081 goto cleanup;
7083 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
7084 VIR_WARN("Failed to save status on vm %s", vm->def->name);
7085 goto cleanup;
7087 } else {
7088 int detail = (start_paused ? VIR_DOMAIN_EVENT_SUSPENDED_PAUSED :
7089 VIR_DOMAIN_EVENT_SUSPENDED_RESTORED);
7090 event = virDomainEventLifecycleNewFromObj(vm,
7091 VIR_DOMAIN_EVENT_SUSPENDED,
7092 detail);
7093 virObjectEventStateQueue(driver->domainEventState, event);
7096 ret = 0;
7098 cleanup:
7099 virObjectUnref(cookie);
7100 virCommandFree(cmd);
7101 VIR_FREE(errbuf);
7102 if (qemuSecurityRestoreSavedStateLabel(driver, vm, path) < 0)
7103 VIR_WARN("failed to restore save state label on %s", path);
7104 virObjectUnref(cfg);
7105 return ret;
7108 static int
7109 qemuDomainRestoreFlags(virConnectPtr conn,
7110 const char *path,
7111 const char *dxml,
7112 unsigned int flags)
7114 virQEMUDriverPtr driver = conn->privateData;
7115 qemuDomainObjPrivatePtr priv = NULL;
7116 virDomainDefPtr def = NULL;
7117 virDomainObjPtr vm = NULL;
7118 char *xmlout = NULL;
7119 const char *newxml = dxml;
7120 int fd = -1;
7121 int ret = -1;
7122 virQEMUSaveDataPtr data = NULL;
7123 virFileWrapperFdPtr wrapperFd = NULL;
7124 bool hook_taint = false;
7126 virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
7127 VIR_DOMAIN_SAVE_RUNNING |
7128 VIR_DOMAIN_SAVE_PAUSED, -1);
7131 virNWFilterReadLockFilterUpdates();
7133 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7134 (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
7135 &wrapperFd, false, false);
7136 if (fd < 0)
7137 goto cleanup;
7139 if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
7140 goto cleanup;
7142 if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
7143 int hookret;
7145 if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
7146 VIR_HOOK_QEMU_OP_RESTORE,
7147 VIR_HOOK_SUBOP_BEGIN,
7148 NULL,
7149 dxml ? dxml : data->xml,
7150 &xmlout)) < 0)
7151 goto cleanup;
7153 if (hookret == 0 && !virStringIsEmpty(xmlout)) {
7154 VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
7155 hook_taint = true;
7156 newxml = xmlout;
7160 if (newxml) {
7161 virDomainDefPtr tmp;
7162 if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, newxml)))
7163 goto cleanup;
7165 virDomainDefFree(def);
7166 def = tmp;
7169 if (!(vm = virDomainObjListAdd(driver->domains, def,
7170 driver->xmlopt,
7171 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
7172 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
7173 NULL)))
7174 goto cleanup;
7175 def = NULL;
7177 if (flags & VIR_DOMAIN_SAVE_RUNNING)
7178 data->header.was_running = 1;
7179 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
7180 data->header.was_running = 0;
7182 if (hook_taint) {
7183 priv = vm->privateData;
7184 priv->hookRun = true;
7187 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_RESTORE,
7188 flags) < 0)
7189 goto cleanup;
7191 ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path,
7192 false, QEMU_ASYNC_JOB_START);
7194 qemuProcessEndJob(driver, vm);
7196 cleanup:
7197 virDomainDefFree(def);
7198 VIR_FORCE_CLOSE(fd);
7199 if (virFileWrapperFdClose(wrapperFd) < 0)
7200 ret = -1;
7201 virFileWrapperFdFree(wrapperFd);
7202 virQEMUSaveDataFree(data);
7203 VIR_FREE(xmlout);
7204 if (vm && ret < 0)
7205 qemuDomainRemoveInactiveJob(driver, vm);
7206 virDomainObjEndAPI(&vm);
7207 virNWFilterUnlockFilterUpdates();
7208 return ret;
7211 static int
7212 qemuDomainRestore(virConnectPtr conn,
7213 const char *path)
7215 return qemuDomainRestoreFlags(conn, path, NULL, 0);
7218 static char *
7219 qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
7220 unsigned int flags)
7222 virQEMUDriverPtr driver = conn->privateData;
7223 char *ret = NULL;
7224 virDomainDefPtr def = NULL;
7225 int fd = -1;
7226 virQEMUSaveDataPtr data = NULL;
7228 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
7230 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7231 false, NULL, false, false);
7233 if (fd < 0)
7234 goto cleanup;
7236 if (virDomainSaveImageGetXMLDescEnsureACL(conn, def, flags) < 0)
7237 goto cleanup;
7239 ret = qemuDomainDefFormatXML(driver, def, flags);
7241 cleanup:
7242 virQEMUSaveDataFree(data);
7243 virDomainDefFree(def);
7244 VIR_FORCE_CLOSE(fd);
7245 return ret;
7248 static int
7249 qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
7250 const char *dxml, unsigned int flags)
7252 virQEMUDriverPtr driver = conn->privateData;
7253 int ret = -1;
7254 virDomainDefPtr def = NULL;
7255 virDomainDefPtr newdef = NULL;
7256 int fd = -1;
7257 virQEMUSaveDataPtr data = NULL;
7258 int state = -1;
7260 virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
7261 VIR_DOMAIN_SAVE_PAUSED, -1);
7263 if (flags & VIR_DOMAIN_SAVE_RUNNING)
7264 state = 1;
7265 else if (flags & VIR_DOMAIN_SAVE_PAUSED)
7266 state = 0;
7268 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7269 false, NULL, true, false);
7271 if (fd < 0)
7272 goto cleanup;
7274 if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0)
7275 goto cleanup;
7277 if (STREQ(data->xml, dxml) &&
7278 (state < 0 || state == data->header.was_running)) {
7279 /* no change to the XML */
7280 ret = 0;
7281 goto cleanup;
7284 if (state >= 0)
7285 data->header.was_running = state;
7287 if (!(newdef = qemuDomainSaveImageUpdateDef(driver, def, dxml)))
7288 goto cleanup;
7290 VIR_FREE(data->xml);
7292 if (!(data->xml = qemuDomainDefFormatXML(driver, newdef,
7293 VIR_DOMAIN_XML_INACTIVE |
7294 VIR_DOMAIN_XML_SECURE |
7295 VIR_DOMAIN_XML_MIGRATABLE)))
7296 goto cleanup;
7298 if (lseek(fd, 0, SEEK_SET) != 0) {
7299 virReportSystemError(errno, _("cannot seek in '%s'"), path);
7300 goto cleanup;
7303 if (virQEMUSaveDataWrite(data, fd, path) < 0)
7304 goto cleanup;
7306 if (VIR_CLOSE(fd) < 0) {
7307 virReportSystemError(errno, _("failed to write header data to '%s'"), path);
7308 goto cleanup;
7311 ret = 0;
7313 cleanup:
7314 virDomainDefFree(def);
7315 virDomainDefFree(newdef);
7316 VIR_FORCE_CLOSE(fd);
7317 virQEMUSaveDataFree(data);
7318 return ret;
7321 static char *
7322 qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
7324 virQEMUDriverPtr driver = dom->conn->privateData;
7325 virDomainObjPtr vm;
7326 char *path = NULL;
7327 char *ret = NULL;
7328 virDomainDefPtr def = NULL;
7329 int fd = -1;
7330 virQEMUSaveDataPtr data = NULL;
7332 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
7334 if (!(vm = qemuDomObjFromDomain(dom)))
7335 return ret;
7337 if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
7338 goto cleanup;
7340 if (!(path = qemuDomainManagedSavePath(driver, vm)))
7341 goto cleanup;
7343 if (!virFileExists(path)) {
7344 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7345 _("domain does not have managed save image"));
7346 goto cleanup;
7349 if ((fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7350 false, NULL, false, false)) < 0)
7351 goto cleanup;
7353 ret = qemuDomainDefFormatXML(driver, def, flags);
7355 cleanup:
7356 virQEMUSaveDataFree(data);
7357 virDomainDefFree(def);
7358 VIR_FORCE_CLOSE(fd);
7359 virDomainObjEndAPI(&vm);
7360 VIR_FREE(path);
7361 return ret;
7364 static int
7365 qemuDomainManagedSaveDefineXML(virDomainPtr dom, const char *dxml,
7366 unsigned int flags)
7368 virQEMUDriverPtr driver = dom->conn->privateData;
7369 virConnectPtr conn = dom->conn;
7370 virDomainObjPtr vm;
7371 char *path = NULL;
7372 int ret = -1;
7374 if (!(vm = qemuDomObjFromDomain(dom)))
7375 return -1;
7377 if (virDomainManagedSaveDefineXMLEnsureACL(conn, vm->def) < 0)
7378 goto cleanup;
7380 if (!(path = qemuDomainManagedSavePath(driver, vm)))
7381 goto cleanup;
7383 if (!virFileExists(path)) {
7384 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7385 _("domain does not have managed save image"));
7386 goto cleanup;
7389 ret = qemuDomainSaveImageDefineXML(conn, path, dxml, flags);
7391 cleanup:
7392 virDomainObjEndAPI(&vm);
7393 VIR_FREE(path);
7394 return ret;
7397 /* Return 0 on success, 1 if incomplete saved image was silently unlinked,
7398 * and -1 on failure with error raised. */
7399 static int
7400 qemuDomainObjRestore(virConnectPtr conn,
7401 virQEMUDriverPtr driver,
7402 virDomainObjPtr vm,
7403 const char *path,
7404 bool start_paused,
7405 bool bypass_cache,
7406 qemuDomainAsyncJob asyncJob)
7408 virDomainDefPtr def = NULL;
7409 qemuDomainObjPrivatePtr priv = vm->privateData;
7410 int fd = -1;
7411 int ret = -1;
7412 char *xmlout = NULL;
7413 virQEMUSaveDataPtr data = NULL;
7414 virFileWrapperFdPtr wrapperFd = NULL;
7416 fd = qemuDomainSaveImageOpen(driver, path, &def, &data,
7417 bypass_cache, &wrapperFd, false, true);
7418 if (fd < 0) {
7419 if (fd == -3)
7420 ret = 1;
7421 goto cleanup;
7424 if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
7425 int hookret;
7427 if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
7428 VIR_HOOK_QEMU_OP_RESTORE,
7429 VIR_HOOK_SUBOP_BEGIN,
7430 NULL, data->xml, &xmlout)) < 0)
7431 goto cleanup;
7433 if (hookret == 0 && !virStringIsEmpty(xmlout)) {
7434 virDomainDefPtr tmp;
7436 VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
7438 if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, xmlout)))
7439 goto cleanup;
7441 virDomainDefFree(def);
7442 def = tmp;
7443 priv->hookRun = true;
7447 if (STRNEQ(vm->def->name, def->name) ||
7448 memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
7449 char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
7450 char def_uuidstr[VIR_UUID_STRING_BUFLEN];
7451 virUUIDFormat(vm->def->uuid, vm_uuidstr);
7452 virUUIDFormat(def->uuid, def_uuidstr);
7453 virReportError(VIR_ERR_OPERATION_FAILED,
7454 _("cannot restore domain '%s' uuid %s from a file"
7455 " which belongs to domain '%s' uuid %s"),
7456 vm->def->name, vm_uuidstr,
7457 def->name, def_uuidstr);
7458 goto cleanup;
7461 virDomainObjAssignDef(vm, def, true, NULL);
7462 def = NULL;
7464 ret = qemuDomainSaveImageStartVM(conn, driver, vm, &fd, data, path,
7465 start_paused, asyncJob);
7467 cleanup:
7468 virQEMUSaveDataFree(data);
7469 VIR_FREE(xmlout);
7470 virDomainDefFree(def);
7471 VIR_FORCE_CLOSE(fd);
7472 if (virFileWrapperFdClose(wrapperFd) < 0)
7473 ret = -1;
7474 virFileWrapperFdFree(wrapperFd);
7475 return ret;
7479 static char
7480 *qemuDomainGetXMLDesc(virDomainPtr dom,
7481 unsigned int flags)
7483 virQEMUDriverPtr driver = dom->conn->privateData;
7484 virDomainObjPtr vm;
7485 char *ret = NULL;
7487 virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS | VIR_DOMAIN_XML_UPDATE_CPU,
7488 NULL);
7490 if (!(vm = qemuDomObjFromDomain(dom)))
7491 goto cleanup;
7493 if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
7494 goto cleanup;
7496 qemuDomainUpdateCurrentMemorySize(vm);
7498 if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
7499 flags |= QEMU_DOMAIN_FORMAT_LIVE_FLAGS;
7501 /* The CPU is already updated in the domain's live definition, we need to
7502 * ignore the VIR_DOMAIN_XML_UPDATE_CPU flag.
7504 if (virDomainObjIsActive(vm) &&
7505 !(flags & VIR_DOMAIN_XML_INACTIVE))
7506 flags &= ~VIR_DOMAIN_XML_UPDATE_CPU;
7508 ret = qemuDomainFormatXML(driver, vm, flags);
7510 cleanup:
7511 virDomainObjEndAPI(&vm);
7512 return ret;
7516 static char *qemuConnectDomainXMLFromNative(virConnectPtr conn,
7517 const char *format,
7518 const char *config,
7519 unsigned int flags)
7521 virQEMUDriverPtr driver = conn->privateData;
7522 virDomainDefPtr def = NULL;
7523 char *xml = NULL;
7524 virCapsPtr caps = NULL;
7526 virCheckFlags(0, NULL);
7528 if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
7529 goto cleanup;
7531 if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
7532 virReportError(VIR_ERR_INVALID_ARG,
7533 _("unsupported config type %s"), format);
7534 goto cleanup;
7537 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7538 goto cleanup;
7540 def = qemuParseCommandLineString(driver->qemuCapsCache,
7541 caps, driver->xmlopt, config,
7542 NULL, NULL, NULL);
7543 if (!def)
7544 goto cleanup;
7546 if (!def->name && VIR_STRDUP(def->name, "unnamed") < 0)
7547 goto cleanup;
7549 xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE);
7551 cleanup:
7552 virDomainDefFree(def);
7553 virObjectUnref(caps);
7554 return xml;
7557 static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
7558 const char *format,
7559 const char *xmlData,
7560 unsigned int flags)
7562 virQEMUDriverPtr driver = conn->privateData;
7563 virDomainObjPtr vm = NULL;
7564 virCommandPtr cmd = NULL;
7565 char *ret = NULL;
7566 size_t i;
7567 virQEMUDriverConfigPtr cfg;
7568 virCapsPtr caps = NULL;
7570 virCheckFlags(0, NULL);
7572 cfg = virQEMUDriverGetConfig(driver);
7574 if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
7575 goto cleanup;
7577 if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) {
7578 virReportError(VIR_ERR_INVALID_ARG,
7579 _("unsupported config type %s"), format);
7580 goto cleanup;
7583 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7584 goto cleanup;
7586 if (!(vm = virDomainObjNew(driver->xmlopt)))
7587 goto cleanup;
7589 if (!(vm->def = virDomainDefParseString(xmlData, caps, driver->xmlopt, NULL,
7590 VIR_DOMAIN_DEF_PARSE_INACTIVE |
7591 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE)))
7592 goto cleanup;
7594 /* Since we're just exporting args, we can't do bridge/network/direct
7595 * setups, since libvirt will normally create TAP/macvtap devices
7596 * directly. We convert those configs into generic 'ethernet'
7597 * config and assume the user has suitable 'ifup-qemu' scripts
7599 for (i = 0; i < vm->def->nnets; i++) {
7600 virDomainNetDefPtr net = vm->def->nets[i];
7601 unsigned int bootIndex = net->info.bootIndex;
7602 char *model = net->model;
7603 virMacAddr mac = net->mac;
7604 char *script = net->script;
7606 net->model = NULL;
7607 net->script = NULL;
7609 virDomainNetDefClear(net);
7611 net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
7612 net->info.bootIndex = bootIndex;
7613 net->model = model;
7614 net->mac = mac;
7615 net->script = script;
7618 if (!(cmd = qemuProcessCreatePretendCmd(driver, vm, NULL,
7619 qemuCheckFips(), true,
7620 VIR_QEMU_PROCESS_START_COLD)))
7621 goto cleanup;
7623 ret = virCommandToString(cmd, false);
7625 cleanup:
7626 virCommandFree(cmd);
7627 virObjectUnref(vm);
7628 virObjectUnref(caps);
7629 virObjectUnref(cfg);
7630 return ret;
7634 static int qemuConnectListDefinedDomains(virConnectPtr conn,
7635 char **const names, int nnames) {
7636 virQEMUDriverPtr driver = conn->privateData;
7637 int ret = -1;
7639 if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
7640 goto cleanup;
7642 ret = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
7643 virConnectListDefinedDomainsCheckACL,
7644 conn);
7646 cleanup:
7647 return ret;
7650 static int qemuConnectNumOfDefinedDomains(virConnectPtr conn)
7652 virQEMUDriverPtr driver = conn->privateData;
7653 int ret = -1;
7655 if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
7656 goto cleanup;
7658 ret = virDomainObjListNumOfDomains(driver->domains, false,
7659 virConnectNumOfDefinedDomainsCheckACL,
7660 conn);
7662 cleanup:
7663 return ret;
7667 static int
7668 qemuDomainObjStart(virConnectPtr conn,
7669 virQEMUDriverPtr driver,
7670 virDomainObjPtr vm,
7671 unsigned int flags,
7672 qemuDomainAsyncJob asyncJob)
7674 int ret = -1;
7675 char *managed_save;
7676 bool start_paused = (flags & VIR_DOMAIN_START_PAUSED) != 0;
7677 bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0;
7678 bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0;
7679 bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0;
7680 unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
7681 qemuDomainObjPrivatePtr priv = vm->privateData;
7683 start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
7684 start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0;
7687 * If there is a managed saved state restore it instead of starting
7688 * from scratch. The old state is removed once the restoring succeeded.
7690 managed_save = qemuDomainManagedSavePath(driver, vm);
7692 if (!managed_save)
7693 goto cleanup;
7695 if (virFileExists(managed_save)) {
7696 if (force_boot) {
7697 if (unlink(managed_save) < 0) {
7698 virReportSystemError(errno,
7699 _("cannot remove managed save file %s"),
7700 managed_save);
7701 goto cleanup;
7703 vm->hasManagedSave = false;
7704 } else {
7705 virDomainJobOperation op = priv->job.current->operation;
7706 priv->job.current->operation = VIR_DOMAIN_JOB_OPERATION_RESTORE;
7708 ret = qemuDomainObjRestore(conn, driver, vm, managed_save,
7709 start_paused, bypass_cache, asyncJob);
7711 if (ret == 0) {
7712 if (unlink(managed_save) < 0)
7713 VIR_WARN("Failed to remove the managed state %s", managed_save);
7714 else
7715 vm->hasManagedSave = false;
7717 goto cleanup;
7718 } else if (ret < 0) {
7719 VIR_WARN("Unable to restore from managed state %s. "
7720 "Maybe the file is corrupted?", managed_save);
7721 goto cleanup;
7722 } else {
7723 VIR_WARN("Ignoring incomplete managed state %s", managed_save);
7724 priv->job.current->operation = op;
7725 vm->hasManagedSave = false;
7730 ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
7731 NULL, -1, NULL, NULL,
7732 VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
7733 virDomainAuditStart(vm, "booted", ret >= 0);
7734 if (ret >= 0) {
7735 virObjectEventPtr event =
7736 virDomainEventLifecycleNewFromObj(vm,
7737 VIR_DOMAIN_EVENT_STARTED,
7738 VIR_DOMAIN_EVENT_STARTED_BOOTED);
7739 virObjectEventStateQueue(driver->domainEventState, event);
7740 if (start_paused) {
7741 event = virDomainEventLifecycleNewFromObj(vm,
7742 VIR_DOMAIN_EVENT_SUSPENDED,
7743 VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
7744 virObjectEventStateQueue(driver->domainEventState, event);
7748 cleanup:
7749 VIR_FREE(managed_save);
7750 return ret;
7753 static int
7754 qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
7756 virQEMUDriverPtr driver = dom->conn->privateData;
7757 virDomainObjPtr vm;
7758 int ret = -1;
7760 virCheckFlags(VIR_DOMAIN_START_PAUSED |
7761 VIR_DOMAIN_START_AUTODESTROY |
7762 VIR_DOMAIN_START_BYPASS_CACHE |
7763 VIR_DOMAIN_START_FORCE_BOOT, -1);
7765 virNWFilterReadLockFilterUpdates();
7767 if (!(vm = qemuDomObjFromDomain(dom)))
7768 goto cleanup;
7770 if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
7771 goto cleanup;
7773 if (qemuProcessBeginJob(driver, vm, VIR_DOMAIN_JOB_OPERATION_START,
7774 flags) < 0)
7775 goto cleanup;
7777 if (virDomainObjIsActive(vm)) {
7778 virReportError(VIR_ERR_OPERATION_INVALID,
7779 "%s", _("domain is already running"));
7780 goto endjob;
7783 if (qemuDomainObjStart(dom->conn, driver, vm, flags,
7784 QEMU_ASYNC_JOB_START) < 0)
7785 goto endjob;
7787 dom->id = vm->def->id;
7788 ret = 0;
7790 endjob:
7791 qemuProcessEndJob(driver, vm);
7793 cleanup:
7794 virDomainObjEndAPI(&vm);
7795 virNWFilterUnlockFilterUpdates();
7796 return ret;
7799 static int
7800 qemuDomainCreate(virDomainPtr dom)
7802 return qemuDomainCreateWithFlags(dom, 0);
7805 static virDomainPtr
7806 qemuDomainDefineXMLFlags(virConnectPtr conn,
7807 const char *xml,
7808 unsigned int flags)
7810 virQEMUDriverPtr driver = conn->privateData;
7811 virDomainDefPtr def = NULL;
7812 virDomainDefPtr oldDef = NULL;
7813 virDomainObjPtr vm = NULL;
7814 virDomainPtr dom = NULL;
7815 virObjectEventPtr event = NULL;
7816 virQEMUDriverConfigPtr cfg;
7817 virCapsPtr caps = NULL;
7818 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
7819 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
7821 virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
7823 if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
7824 parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
7826 cfg = virQEMUDriverGetConfig(driver);
7828 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
7829 goto cleanup;
7831 if (!(def = virDomainDefParseString(xml, caps, driver->xmlopt,
7832 NULL, parse_flags)))
7833 goto cleanup;
7835 if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
7836 goto cleanup;
7838 if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
7839 goto cleanup;
7841 if (!(vm = virDomainObjListAdd(driver->domains, def,
7842 driver->xmlopt,
7843 0, &oldDef)))
7844 goto cleanup;
7845 def = NULL;
7847 vm->persistent = 1;
7849 if (virDomainSaveConfig(cfg->configDir, driver->caps,
7850 vm->newDef ? vm->newDef : vm->def) < 0) {
7851 if (oldDef) {
7852 /* There is backup so this VM was defined before.
7853 * Just restore the backup. */
7854 VIR_INFO("Restoring domain '%s' definition", vm->def->name);
7855 if (virDomainObjIsActive(vm))
7856 vm->newDef = oldDef;
7857 else
7858 vm->def = oldDef;
7859 oldDef = NULL;
7860 } else {
7861 /* Brand new domain. Remove it */
7862 VIR_INFO("Deleting domain '%s'", vm->def->name);
7863 vm->persistent = 0;
7864 qemuDomainRemoveInactiveJob(driver, vm);
7866 goto cleanup;
7869 event = virDomainEventLifecycleNewFromObj(vm,
7870 VIR_DOMAIN_EVENT_DEFINED,
7871 !oldDef ?
7872 VIR_DOMAIN_EVENT_DEFINED_ADDED :
7873 VIR_DOMAIN_EVENT_DEFINED_UPDATED);
7875 VIR_INFO("Creating domain '%s'", vm->def->name);
7876 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
7878 cleanup:
7879 virDomainDefFree(oldDef);
7880 virDomainDefFree(def);
7881 virDomainObjEndAPI(&vm);
7882 virObjectEventStateQueue(driver->domainEventState, event);
7883 virObjectUnref(caps);
7884 virObjectUnref(cfg);
7885 return dom;
7888 static virDomainPtr
7889 qemuDomainDefineXML(virConnectPtr conn, const char *xml)
7891 return qemuDomainDefineXMLFlags(conn, xml, 0);
7894 static int
7895 qemuDomainUndefineFlags(virDomainPtr dom,
7896 unsigned int flags)
7898 virQEMUDriverPtr driver = dom->conn->privateData;
7899 virDomainObjPtr vm;
7900 virObjectEventPtr event = NULL;
7901 char *name = NULL;
7902 int ret = -1;
7903 int nsnapshots;
7904 virQEMUDriverConfigPtr cfg = NULL;
7906 virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE |
7907 VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA |
7908 VIR_DOMAIN_UNDEFINE_NVRAM |
7909 VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, -1);
7911 if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM) &&
7912 (flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
7913 virReportError(VIR_ERR_OPERATION_INVALID,
7914 "%s", _("cannot both keep and delete nvram"));
7915 return -1;
7918 if (!(vm = qemuDomObjFromDomain(dom)))
7919 return -1;
7921 cfg = virQEMUDriverGetConfig(driver);
7923 if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
7924 goto cleanup;
7926 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
7927 goto cleanup;
7929 if (!vm->persistent) {
7930 virReportError(VIR_ERR_OPERATION_INVALID,
7931 "%s", _("cannot undefine transient domain"));
7932 goto endjob;
7935 if (!virDomainObjIsActive(vm) &&
7936 (nsnapshots = virDomainSnapshotObjListNum(vm->snapshots, NULL, 0))) {
7937 if (!(flags & VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA)) {
7938 virReportError(VIR_ERR_OPERATION_INVALID,
7939 _("cannot delete inactive domain with %d "
7940 "snapshots"),
7941 nsnapshots);
7942 goto endjob;
7944 if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0)
7945 goto endjob;
7947 /* TODO: Restrict deletion if checkpoints exist? */
7949 name = qemuDomainManagedSavePath(driver, vm);
7950 if (name == NULL)
7951 goto endjob;
7953 if (virFileExists(name)) {
7954 if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
7955 if (unlink(name) < 0) {
7956 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7957 _("Failed to remove domain managed "
7958 "save image"));
7959 goto endjob;
7961 } else {
7962 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7963 _("Refusing to undefine while domain managed "
7964 "save image exists"));
7965 goto endjob;
7969 if (vm->def->os.loader &&
7970 vm->def->os.loader->nvram &&
7971 virFileExists(vm->def->os.loader->nvram)) {
7972 if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) {
7973 if (unlink(vm->def->os.loader->nvram) < 0) {
7974 virReportSystemError(errno,
7975 _("failed to remove nvram: %s"),
7976 vm->def->os.loader->nvram);
7977 goto endjob;
7979 } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) {
7980 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7981 _("cannot undefine domain with nvram"));
7982 goto endjob;
7986 if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
7987 goto endjob;
7989 event = virDomainEventLifecycleNewFromObj(vm,
7990 VIR_DOMAIN_EVENT_UNDEFINED,
7991 VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
7993 VIR_INFO("Undefining domain '%s'", vm->def->name);
7995 /* If the domain is active, keep it running but set it as transient.
7996 * domainDestroy and domainShutdown will take care of removing the
7997 * domain obj from the hash table.
7999 vm->persistent = 0;
8000 if (!virDomainObjIsActive(vm))
8001 qemuDomainRemoveInactive(driver, vm);
8003 ret = 0;
8004 endjob:
8005 qemuDomainObjEndJob(driver, vm);
8007 cleanup:
8008 VIR_FREE(name);
8009 virDomainObjEndAPI(&vm);
8010 virObjectEventStateQueue(driver->domainEventState, event);
8011 virObjectUnref(cfg);
8012 return ret;
8015 static int
8016 qemuDomainUndefine(virDomainPtr dom)
8018 return qemuDomainUndefineFlags(dom, 0);
8021 static int
8022 qemuDomainAttachDeviceLive(virDomainObjPtr vm,
8023 virDomainDeviceDefPtr dev,
8024 virQEMUDriverPtr driver)
8026 int ret = -1;
8027 const char *alias = NULL;
8029 switch ((virDomainDeviceType)dev->type) {
8030 case VIR_DOMAIN_DEVICE_DISK:
8031 qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
8032 ret = qemuDomainAttachDeviceDiskLive(driver, vm, dev);
8033 if (!ret) {
8034 alias = dev->data.disk->info.alias;
8035 dev->data.disk = NULL;
8037 break;
8039 case VIR_DOMAIN_DEVICE_CONTROLLER:
8040 ret = qemuDomainAttachControllerDevice(driver, vm, dev->data.controller);
8041 if (!ret) {
8042 alias = dev->data.controller->info.alias;
8043 dev->data.controller = NULL;
8045 break;
8047 case VIR_DOMAIN_DEVICE_LEASE:
8048 ret = qemuDomainAttachLease(driver, vm,
8049 dev->data.lease);
8050 if (ret == 0)
8051 dev->data.lease = NULL;
8052 break;
8054 case VIR_DOMAIN_DEVICE_NET:
8055 qemuDomainObjCheckNetTaint(driver, vm, dev->data.net, NULL);
8056 ret = qemuDomainAttachNetDevice(driver, vm, dev->data.net);
8057 if (!ret) {
8058 alias = dev->data.net->info.alias;
8059 dev->data.net = NULL;
8061 break;
8063 case VIR_DOMAIN_DEVICE_HOSTDEV:
8064 qemuDomainObjCheckHostdevTaint(driver, vm, dev->data.hostdev, NULL);
8065 ret = qemuDomainAttachHostDevice(driver, vm,
8066 dev->data.hostdev);
8067 if (!ret) {
8068 alias = dev->data.hostdev->info->alias;
8069 dev->data.hostdev = NULL;
8071 break;
8073 case VIR_DOMAIN_DEVICE_REDIRDEV:
8074 ret = qemuDomainAttachRedirdevDevice(driver, vm,
8075 dev->data.redirdev);
8076 if (!ret) {
8077 alias = dev->data.redirdev->info.alias;
8078 dev->data.redirdev = NULL;
8080 break;
8082 case VIR_DOMAIN_DEVICE_CHR:
8083 ret = qemuDomainAttachChrDevice(driver, vm,
8084 dev->data.chr);
8085 if (!ret) {
8086 alias = dev->data.chr->info.alias;
8087 dev->data.chr = NULL;
8089 break;
8091 case VIR_DOMAIN_DEVICE_RNG:
8092 ret = qemuDomainAttachRNGDevice(driver, vm,
8093 dev->data.rng);
8094 if (!ret) {
8095 alias = dev->data.rng->info.alias;
8096 dev->data.rng = NULL;
8098 break;
8100 case VIR_DOMAIN_DEVICE_MEMORY:
8101 /* note that qemuDomainAttachMemory always consumes dev->data.memory
8102 * and dispatches DeviceAdded event on success */
8103 ret = qemuDomainAttachMemory(driver, vm,
8104 dev->data.memory);
8105 dev->data.memory = NULL;
8106 break;
8108 case VIR_DOMAIN_DEVICE_SHMEM:
8109 ret = qemuDomainAttachShmemDevice(driver, vm,
8110 dev->data.shmem);
8111 if (!ret) {
8112 alias = dev->data.shmem->info.alias;
8113 dev->data.shmem = NULL;
8115 break;
8117 case VIR_DOMAIN_DEVICE_WATCHDOG:
8118 ret = qemuDomainAttachWatchdog(driver, vm,
8119 dev->data.watchdog);
8120 if (!ret) {
8121 alias = dev->data.watchdog->info.alias;
8122 dev->data.watchdog = NULL;
8124 break;
8126 case VIR_DOMAIN_DEVICE_INPUT:
8127 ret = qemuDomainAttachInputDevice(driver, vm, dev->data.input);
8128 if (ret == 0) {
8129 alias = dev->data.input->info.alias;
8130 dev->data.input = NULL;
8132 break;
8134 case VIR_DOMAIN_DEVICE_VSOCK:
8135 ret = qemuDomainAttachVsockDevice(driver, vm, dev->data.vsock);
8136 if (ret == 0) {
8137 alias = dev->data.vsock->info.alias;
8138 dev->data.vsock = NULL;
8140 break;
8142 case VIR_DOMAIN_DEVICE_NONE:
8143 case VIR_DOMAIN_DEVICE_FS:
8144 case VIR_DOMAIN_DEVICE_SOUND:
8145 case VIR_DOMAIN_DEVICE_VIDEO:
8146 case VIR_DOMAIN_DEVICE_GRAPHICS:
8147 case VIR_DOMAIN_DEVICE_HUB:
8148 case VIR_DOMAIN_DEVICE_SMARTCARD:
8149 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8150 case VIR_DOMAIN_DEVICE_NVRAM:
8151 case VIR_DOMAIN_DEVICE_TPM:
8152 case VIR_DOMAIN_DEVICE_PANIC:
8153 case VIR_DOMAIN_DEVICE_IOMMU:
8154 case VIR_DOMAIN_DEVICE_LAST:
8155 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8156 _("live attach of device '%s' is not supported"),
8157 virDomainDeviceTypeToString(dev->type));
8158 break;
8161 if (alias) {
8162 /* queue the event before the alias has a chance to get freed
8163 * if the domain disappears while qemuDomainUpdateDeviceList
8164 * is in monitor */
8165 virObjectEventPtr event;
8166 event = virDomainEventDeviceAddedNewFromObj(vm, alias);
8167 virObjectEventStateQueue(driver->domainEventState, event);
8170 if (ret == 0)
8171 ret = qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE);
8173 return ret;
8177 static int
8178 qemuDomainChangeDiskLive(virDomainObjPtr vm,
8179 virDomainDeviceDefPtr dev,
8180 virQEMUDriverPtr driver,
8181 bool force)
8183 virDomainDiskDefPtr disk = dev->data.disk;
8184 virDomainDiskDefPtr orig_disk = NULL;
8185 virDomainDeviceDef oldDev = { .type = dev->type };
8186 int ret = -1;
8188 if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
8189 disk->bus, disk->dst))) {
8190 virReportError(VIR_ERR_INTERNAL_ERROR,
8191 _("No device with bus '%s' and target '%s'"),
8192 virDomainDiskBusTypeToString(disk->bus),
8193 disk->dst);
8194 goto cleanup;
8197 oldDev.data.disk = orig_disk;
8198 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8199 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8200 true) < 0)
8201 goto cleanup;
8203 if (!qemuDomainDiskChangeSupported(disk, orig_disk))
8204 goto cleanup;
8206 if (!virStorageSourceIsSameLocation(disk->src, orig_disk->src)) {
8207 /* Disk source can be changed only for removable devices */
8208 if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
8209 disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
8210 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8211 _("disk source can be changed only in removable "
8212 "drives"));
8213 goto cleanup;
8216 if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
8217 dev->data.disk->src, force) < 0)
8218 goto cleanup;
8220 dev->data.disk->src = NULL;
8223 orig_disk->startupPolicy = dev->data.disk->startupPolicy;
8224 orig_disk->snapshot = dev->data.disk->snapshot;
8226 ret = 0;
8227 cleanup:
8228 return ret;
8231 static int
8232 qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
8233 virDomainDeviceDefPtr dev,
8234 virDomainPtr dom,
8235 bool force)
8237 virQEMUDriverPtr driver = dom->conn->privateData;
8238 virDomainDeviceDef oldDev = { .type = dev->type };
8239 int ret = -1;
8240 int idx;
8242 switch ((virDomainDeviceType)dev->type) {
8243 case VIR_DOMAIN_DEVICE_DISK:
8244 qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
8245 ret = qemuDomainChangeDiskLive(vm, dev, driver, force);
8246 break;
8248 case VIR_DOMAIN_DEVICE_GRAPHICS:
8249 if ((idx = qemuDomainFindGraphicsIndex(vm->def, dev->data.graphics)) >= 0) {
8250 oldDev.data.graphics = vm->def->graphics[idx];
8251 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8252 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8253 true) < 0)
8254 return -1;
8257 ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
8258 break;
8260 case VIR_DOMAIN_DEVICE_NET:
8261 if ((idx = virDomainNetFindIdx(vm->def, dev->data.net)) >= 0) {
8262 oldDev.data.net = vm->def->nets[idx];
8263 if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev,
8264 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8265 true) < 0)
8266 return -1;
8269 ret = qemuDomainChangeNet(driver, vm, dev);
8270 break;
8272 case VIR_DOMAIN_DEVICE_FS:
8273 case VIR_DOMAIN_DEVICE_INPUT:
8274 case VIR_DOMAIN_DEVICE_SOUND:
8275 case VIR_DOMAIN_DEVICE_VIDEO:
8276 case VIR_DOMAIN_DEVICE_WATCHDOG:
8277 case VIR_DOMAIN_DEVICE_HUB:
8278 case VIR_DOMAIN_DEVICE_SMARTCARD:
8279 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8280 case VIR_DOMAIN_DEVICE_NVRAM:
8281 case VIR_DOMAIN_DEVICE_RNG:
8282 case VIR_DOMAIN_DEVICE_SHMEM:
8283 case VIR_DOMAIN_DEVICE_LEASE:
8284 case VIR_DOMAIN_DEVICE_HOSTDEV:
8285 case VIR_DOMAIN_DEVICE_CONTROLLER:
8286 case VIR_DOMAIN_DEVICE_REDIRDEV:
8287 case VIR_DOMAIN_DEVICE_MEMORY:
8288 case VIR_DOMAIN_DEVICE_CHR:
8289 case VIR_DOMAIN_DEVICE_NONE:
8290 case VIR_DOMAIN_DEVICE_TPM:
8291 case VIR_DOMAIN_DEVICE_PANIC:
8292 case VIR_DOMAIN_DEVICE_IOMMU:
8293 case VIR_DOMAIN_DEVICE_VSOCK:
8294 case VIR_DOMAIN_DEVICE_LAST:
8295 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8296 _("live update of device '%s' is not supported"),
8297 virDomainDeviceTypeToString(dev->type));
8298 break;
8301 return ret;
8304 static int
8305 qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
8306 virDomainDeviceDefPtr dev,
8307 virCapsPtr caps,
8308 unsigned int parse_flags,
8309 virDomainXMLOptionPtr xmlopt)
8311 virDomainDiskDefPtr disk;
8312 virDomainNetDefPtr net;
8313 virDomainHostdevDefPtr hostdev;
8314 virDomainLeaseDefPtr lease;
8315 virDomainControllerDefPtr controller;
8316 virDomainFSDefPtr fs;
8317 virDomainRedirdevDefPtr redirdev;
8318 virDomainShmemDefPtr shmem;
8320 switch ((virDomainDeviceType)dev->type) {
8321 case VIR_DOMAIN_DEVICE_DISK:
8322 disk = dev->data.disk;
8323 if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
8324 virReportError(VIR_ERR_OPERATION_INVALID,
8325 _("target %s already exists"), disk->dst);
8326 return -1;
8328 if (virDomainDiskTranslateSourcePool(disk) < 0)
8329 return -1;
8330 if (qemuCheckDiskConfig(disk, NULL) < 0)
8331 return -1;
8332 if (virDomainDiskInsert(vmdef, disk))
8333 return -1;
8334 /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
8335 dev->data.disk = NULL;
8336 break;
8338 case VIR_DOMAIN_DEVICE_NET:
8339 net = dev->data.net;
8340 if (virDomainNetInsert(vmdef, net))
8341 return -1;
8342 dev->data.net = NULL;
8343 break;
8345 case VIR_DOMAIN_DEVICE_HOSTDEV:
8346 hostdev = dev->data.hostdev;
8347 if (virDomainHostdevFind(vmdef, hostdev, NULL) >= 0) {
8348 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8349 _("device is already in the domain configuration"));
8350 return -1;
8352 if (virDomainHostdevInsert(vmdef, hostdev))
8353 return -1;
8354 dev->data.hostdev = NULL;
8355 break;
8357 case VIR_DOMAIN_DEVICE_LEASE:
8358 lease = dev->data.lease;
8359 if (virDomainLeaseIndex(vmdef, lease) >= 0) {
8360 virReportError(VIR_ERR_OPERATION_INVALID,
8361 _("Lease %s in lockspace %s already exists"),
8362 lease->key, NULLSTR(lease->lockspace));
8363 return -1;
8365 if (virDomainLeaseInsert(vmdef, lease) < 0)
8366 return -1;
8368 /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
8369 dev->data.lease = NULL;
8370 break;
8372 case VIR_DOMAIN_DEVICE_CONTROLLER:
8373 controller = dev->data.controller;
8374 if (controller->idx != -1 &&
8375 virDomainControllerFind(vmdef, controller->type,
8376 controller->idx) >= 0) {
8377 virReportError(VIR_ERR_OPERATION_INVALID,
8378 _("controller index='%d' already exists"),
8379 controller->idx);
8380 return -1;
8383 if (virDomainControllerInsert(vmdef, controller) < 0)
8384 return -1;
8385 dev->data.controller = NULL;
8387 break;
8389 case VIR_DOMAIN_DEVICE_CHR:
8390 if (qemuDomainChrInsert(vmdef, dev->data.chr) < 0)
8391 return -1;
8392 dev->data.chr = NULL;
8393 break;
8395 case VIR_DOMAIN_DEVICE_FS:
8396 fs = dev->data.fs;
8397 if (virDomainFSIndexByName(vmdef, fs->dst) >= 0) {
8398 virReportError(VIR_ERR_OPERATION_INVALID,
8399 "%s", _("Target already exists"));
8400 return -1;
8403 if (virDomainFSInsert(vmdef, fs) < 0)
8404 return -1;
8405 dev->data.fs = NULL;
8406 break;
8408 case VIR_DOMAIN_DEVICE_RNG:
8409 if (dev->data.rng->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
8410 virDomainDefHasDeviceAddress(vmdef, &dev->data.rng->info)) {
8411 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8412 _("a device with the same address already exists "));
8413 return -1;
8416 if (VIR_APPEND_ELEMENT(vmdef->rngs, vmdef->nrngs, dev->data.rng) < 0)
8417 return -1;
8418 dev->data.rng = NULL;
8420 break;
8422 case VIR_DOMAIN_DEVICE_MEMORY:
8423 if (vmdef->nmems == vmdef->mem.memory_slots) {
8424 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8425 _("no free memory device slot available"));
8426 return -1;
8429 vmdef->mem.cur_balloon += dev->data.memory->size;
8431 if (virDomainMemoryInsert(vmdef, dev->data.memory) < 0)
8432 return -1;
8433 dev->data.memory = NULL;
8434 break;
8436 case VIR_DOMAIN_DEVICE_REDIRDEV:
8437 redirdev = dev->data.redirdev;
8439 if (VIR_APPEND_ELEMENT(vmdef->redirdevs, vmdef->nredirdevs, redirdev) < 0)
8440 return -1;
8441 dev->data.redirdev = NULL;
8442 break;
8444 case VIR_DOMAIN_DEVICE_SHMEM:
8445 shmem = dev->data.shmem;
8446 if (virDomainShmemDefFind(vmdef, shmem) >= 0) {
8447 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8448 _("device is already in the domain configuration"));
8449 return -1;
8451 if (virDomainShmemDefInsert(vmdef, shmem) < 0)
8452 return -1;
8453 dev->data.shmem = NULL;
8454 break;
8456 case VIR_DOMAIN_DEVICE_WATCHDOG:
8457 if (vmdef->watchdog) {
8458 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8459 _("domain already has a watchdog"));
8460 return -1;
8462 VIR_STEAL_PTR(vmdef->watchdog, dev->data.watchdog);
8463 break;
8465 case VIR_DOMAIN_DEVICE_INPUT:
8466 if (VIR_APPEND_ELEMENT(vmdef->inputs, vmdef->ninputs, dev->data.input) < 0)
8467 return -1;
8468 break;
8470 case VIR_DOMAIN_DEVICE_VSOCK:
8471 if (vmdef->vsock) {
8472 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
8473 _("domain already has a vsock device"));
8474 return -1;
8476 VIR_STEAL_PTR(vmdef->vsock, dev->data.vsock);
8477 break;
8479 case VIR_DOMAIN_DEVICE_SOUND:
8480 case VIR_DOMAIN_DEVICE_VIDEO:
8481 case VIR_DOMAIN_DEVICE_GRAPHICS:
8482 case VIR_DOMAIN_DEVICE_HUB:
8483 case VIR_DOMAIN_DEVICE_SMARTCARD:
8484 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8485 case VIR_DOMAIN_DEVICE_NVRAM:
8486 case VIR_DOMAIN_DEVICE_NONE:
8487 case VIR_DOMAIN_DEVICE_TPM:
8488 case VIR_DOMAIN_DEVICE_PANIC:
8489 case VIR_DOMAIN_DEVICE_IOMMU:
8490 case VIR_DOMAIN_DEVICE_LAST:
8491 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8492 _("persistent attach of device '%s' is not supported"),
8493 virDomainDeviceTypeToString(dev->type));
8494 return -1;
8497 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8498 return -1;
8500 return 0;
8504 static int
8505 qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
8506 virDomainDeviceDefPtr dev,
8507 virCapsPtr caps,
8508 unsigned int parse_flags,
8509 virDomainXMLOptionPtr xmlopt)
8511 virDomainDiskDefPtr disk, det_disk;
8512 virDomainNetDefPtr net;
8513 virDomainHostdevDefPtr hostdev, det_hostdev;
8514 virDomainLeaseDefPtr lease, det_lease;
8515 virDomainControllerDefPtr cont, det_cont;
8516 virDomainChrDefPtr chr;
8517 virDomainFSDefPtr fs;
8518 virDomainMemoryDefPtr mem;
8519 int idx;
8521 switch ((virDomainDeviceType)dev->type) {
8522 case VIR_DOMAIN_DEVICE_DISK:
8523 disk = dev->data.disk;
8524 if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk->dst))) {
8525 virReportError(VIR_ERR_DEVICE_MISSING,
8526 _("no target device %s"), disk->dst);
8527 return -1;
8529 virDomainDiskDefFree(det_disk);
8530 break;
8532 case VIR_DOMAIN_DEVICE_NET:
8533 net = dev->data.net;
8534 if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
8535 return -1;
8537 /* this is guaranteed to succeed */
8538 virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
8539 break;
8541 case VIR_DOMAIN_DEVICE_HOSTDEV: {
8542 hostdev = dev->data.hostdev;
8543 if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
8544 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8545 _("device not present in domain configuration"));
8546 return -1;
8548 virDomainHostdevRemove(vmdef, idx);
8549 virDomainHostdevDefFree(det_hostdev);
8550 break;
8553 case VIR_DOMAIN_DEVICE_LEASE:
8554 lease = dev->data.lease;
8555 if (!(det_lease = virDomainLeaseRemove(vmdef, lease))) {
8556 virReportError(VIR_ERR_DEVICE_MISSING,
8557 _("Lease %s in lockspace %s does not exist"),
8558 lease->key, NULLSTR(lease->lockspace));
8559 return -1;
8561 virDomainLeaseDefFree(det_lease);
8562 break;
8564 case VIR_DOMAIN_DEVICE_CONTROLLER:
8565 cont = dev->data.controller;
8566 if ((idx = virDomainControllerFind(vmdef, cont->type,
8567 cont->idx)) < 0) {
8568 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8569 _("device not present in domain configuration"));
8570 return -1;
8572 det_cont = virDomainControllerRemove(vmdef, idx);
8573 virDomainControllerDefFree(det_cont);
8575 break;
8577 case VIR_DOMAIN_DEVICE_CHR:
8578 if (!(chr = qemuDomainChrRemove(vmdef, dev->data.chr)))
8579 return -1;
8581 virDomainChrDefFree(chr);
8582 break;
8584 case VIR_DOMAIN_DEVICE_FS:
8585 fs = dev->data.fs;
8586 idx = virDomainFSIndexByName(vmdef, fs->dst);
8587 if (idx < 0) {
8588 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8589 _("no matching filesystem device was found"));
8590 return -1;
8593 fs = virDomainFSRemove(vmdef, idx);
8594 virDomainFSDefFree(fs);
8595 break;
8597 case VIR_DOMAIN_DEVICE_RNG:
8598 if ((idx = virDomainRNGFind(vmdef, dev->data.rng)) < 0) {
8599 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8600 _("no matching RNG device was found"));
8601 return -1;
8604 virDomainRNGDefFree(virDomainRNGRemove(vmdef, idx));
8605 break;
8607 case VIR_DOMAIN_DEVICE_MEMORY:
8608 if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
8609 dev->data.memory)) < 0) {
8610 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8611 _("matching memory device was not found"));
8612 return -1;
8614 mem = virDomainMemoryRemove(vmdef, idx);
8615 vmdef->mem.cur_balloon -= mem->size;
8616 virDomainMemoryDefFree(mem);
8617 break;
8619 case VIR_DOMAIN_DEVICE_REDIRDEV:
8620 if ((idx = virDomainRedirdevDefFind(vmdef,
8621 dev->data.redirdev)) < 0) {
8622 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8623 _("no matching redirdev was not found"));
8624 return -1;
8627 virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx));
8628 break;
8630 case VIR_DOMAIN_DEVICE_SHMEM:
8631 if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) {
8632 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8633 _("matching shmem device was not found"));
8634 return -1;
8637 virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx));
8638 break;
8641 case VIR_DOMAIN_DEVICE_WATCHDOG:
8642 if (!vmdef->watchdog) {
8643 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8644 _("domain has no watchdog"));
8645 return -1;
8647 virDomainWatchdogDefFree(vmdef->watchdog);
8648 vmdef->watchdog = NULL;
8649 break;
8651 case VIR_DOMAIN_DEVICE_INPUT:
8652 if ((idx = virDomainInputDefFind(vmdef, dev->data.input)) < 0) {
8653 virReportError(VIR_ERR_DEVICE_MISSING, "%s",
8654 _("matching input device not found"));
8655 return -1;
8657 VIR_DELETE_ELEMENT(vmdef->inputs, idx, vmdef->ninputs);
8658 break;
8660 case VIR_DOMAIN_DEVICE_VSOCK:
8661 if (!vmdef->vsock ||
8662 !virDomainVsockDefEquals(dev->data.vsock, vmdef->vsock)) {
8663 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
8664 _("matching vsock device not found"));
8665 return -1;
8667 virDomainVsockDefFree(vmdef->vsock);
8668 vmdef->vsock = NULL;
8669 break;
8671 case VIR_DOMAIN_DEVICE_SOUND:
8672 case VIR_DOMAIN_DEVICE_VIDEO:
8673 case VIR_DOMAIN_DEVICE_GRAPHICS:
8674 case VIR_DOMAIN_DEVICE_HUB:
8675 case VIR_DOMAIN_DEVICE_SMARTCARD:
8676 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8677 case VIR_DOMAIN_DEVICE_NVRAM:
8678 case VIR_DOMAIN_DEVICE_NONE:
8679 case VIR_DOMAIN_DEVICE_TPM:
8680 case VIR_DOMAIN_DEVICE_PANIC:
8681 case VIR_DOMAIN_DEVICE_IOMMU:
8682 case VIR_DOMAIN_DEVICE_LAST:
8683 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8684 _("persistent detach of device '%s' is not supported"),
8685 virDomainDeviceTypeToString(dev->type));
8686 return -1;
8689 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8690 return -1;
8692 return 0;
8695 static int
8696 qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
8697 virDomainDeviceDefPtr dev,
8698 virCapsPtr caps,
8699 unsigned int parse_flags,
8700 virDomainXMLOptionPtr xmlopt)
8702 virDomainDiskDefPtr newDisk;
8703 virDomainGraphicsDefPtr newGraphics;
8704 virDomainNetDefPtr net;
8705 virDomainDeviceDef oldDev = { .type = dev->type };
8706 int pos;
8708 switch ((virDomainDeviceType)dev->type) {
8709 case VIR_DOMAIN_DEVICE_DISK:
8710 newDisk = dev->data.disk;
8711 if ((pos = virDomainDiskIndexByName(vmdef, newDisk->dst, false)) < 0) {
8712 virReportError(VIR_ERR_INVALID_ARG,
8713 _("target %s doesn't exist."), newDisk->dst);
8714 return -1;
8717 oldDev.data.disk = vmdef->disks[pos];
8718 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8719 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8720 false) < 0)
8721 return -1;
8723 virDomainDiskDefFree(vmdef->disks[pos]);
8724 vmdef->disks[pos] = newDisk;
8725 dev->data.disk = NULL;
8726 break;
8728 case VIR_DOMAIN_DEVICE_GRAPHICS:
8729 newGraphics = dev->data.graphics;
8730 pos = qemuDomainFindGraphicsIndex(vmdef, newGraphics);
8731 if (pos < 0) {
8732 virReportError(VIR_ERR_INVALID_ARG,
8733 _("cannot find existing graphics type '%s' device to modify"),
8734 virDomainGraphicsTypeToString(newGraphics->type));
8735 return -1;
8738 oldDev.data.graphics = vmdef->graphics[pos];
8739 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8740 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8741 false) < 0)
8742 return -1;
8744 virDomainGraphicsDefFree(vmdef->graphics[pos]);
8745 vmdef->graphics[pos] = newGraphics;
8746 dev->data.graphics = NULL;
8747 break;
8749 case VIR_DOMAIN_DEVICE_NET:
8750 net = dev->data.net;
8751 if ((pos = virDomainNetFindIdx(vmdef, net)) < 0)
8752 return -1;
8754 oldDev.data.net = vmdef->nets[pos];
8755 if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
8756 VIR_DOMAIN_DEVICE_ACTION_UPDATE,
8757 false) < 0)
8758 return -1;
8760 virDomainNetDefFree(vmdef->nets[pos]);
8761 vmdef->nets[pos] = net;
8762 dev->data.net = NULL;
8763 break;
8765 case VIR_DOMAIN_DEVICE_FS:
8766 case VIR_DOMAIN_DEVICE_INPUT:
8767 case VIR_DOMAIN_DEVICE_SOUND:
8768 case VIR_DOMAIN_DEVICE_VIDEO:
8769 case VIR_DOMAIN_DEVICE_WATCHDOG:
8770 case VIR_DOMAIN_DEVICE_HUB:
8771 case VIR_DOMAIN_DEVICE_SMARTCARD:
8772 case VIR_DOMAIN_DEVICE_MEMBALLOON:
8773 case VIR_DOMAIN_DEVICE_NVRAM:
8774 case VIR_DOMAIN_DEVICE_RNG:
8775 case VIR_DOMAIN_DEVICE_SHMEM:
8776 case VIR_DOMAIN_DEVICE_LEASE:
8777 case VIR_DOMAIN_DEVICE_HOSTDEV:
8778 case VIR_DOMAIN_DEVICE_CONTROLLER:
8779 case VIR_DOMAIN_DEVICE_REDIRDEV:
8780 case VIR_DOMAIN_DEVICE_CHR:
8781 case VIR_DOMAIN_DEVICE_MEMORY:
8782 case VIR_DOMAIN_DEVICE_NONE:
8783 case VIR_DOMAIN_DEVICE_TPM:
8784 case VIR_DOMAIN_DEVICE_PANIC:
8785 case VIR_DOMAIN_DEVICE_IOMMU:
8786 case VIR_DOMAIN_DEVICE_VSOCK:
8787 case VIR_DOMAIN_DEVICE_LAST:
8788 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
8789 _("persistent update of device '%s' is not supported"),
8790 virDomainDeviceTypeToString(dev->type));
8791 return -1;
8794 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0)
8795 return -1;
8797 return 0;
8800 static int
8801 qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
8802 virQEMUDriverPtr driver,
8803 const char *xml,
8804 unsigned int flags)
8806 virDomainDefPtr vmdef = NULL;
8807 virQEMUDriverConfigPtr cfg = NULL;
8808 virDomainDeviceDefPtr devConf = NULL;
8809 virDomainDeviceDefPtr devLive = NULL;
8810 int ret = -1;
8811 virCapsPtr caps = NULL;
8812 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
8813 VIR_DOMAIN_DEF_PARSE_ABI_UPDATE;
8815 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8816 VIR_DOMAIN_AFFECT_CONFIG, -1);
8818 cfg = virQEMUDriverGetConfig(driver);
8820 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
8821 goto cleanup;
8823 /* The config and live post processing address auto-generation algorithms
8824 * rely on the correct vm->def or vm->newDef being passed, so call the
8825 * device parse based on which definition is in use */
8826 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8827 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
8828 if (!vmdef)
8829 goto cleanup;
8831 if (!(devConf = virDomainDeviceDefParse(xml, vmdef, caps,
8832 driver->xmlopt, parse_flags)))
8833 goto cleanup;
8835 if (virDomainDefCompatibleDevice(vmdef, devConf, NULL,
8836 VIR_DOMAIN_DEVICE_ACTION_ATTACH,
8837 false) < 0)
8838 goto cleanup;
8840 if ((ret = qemuDomainAttachDeviceConfig(vmdef, devConf, caps,
8841 parse_flags,
8842 driver->xmlopt)) < 0)
8843 goto cleanup;
8846 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
8847 if (!(devLive = virDomainDeviceDefParse(xml, vm->def, caps,
8848 driver->xmlopt, parse_flags)))
8849 goto cleanup;
8851 if (virDomainDeviceValidateAliasForHotplug(vm, devLive, flags) < 0)
8852 goto cleanup;
8854 if (virDomainDefCompatibleDevice(vm->def, devLive, NULL,
8855 VIR_DOMAIN_DEVICE_ACTION_ATTACH,
8856 true) < 0)
8857 goto cleanup;
8859 if ((ret = qemuDomainAttachDeviceLive(vm, devLive, driver)) < 0)
8860 goto cleanup;
8862 * update domain status forcibly because the domain status may be
8863 * changed even if we failed to attach the device. For example,
8864 * a new controller may be created.
8866 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
8867 ret = -1;
8868 goto cleanup;
8872 /* Finally, if no error until here, we can save config. */
8873 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8874 ret = virDomainSaveConfig(cfg->configDir, driver->caps, vmdef);
8875 if (!ret) {
8876 virDomainObjAssignDef(vm, vmdef, false, NULL);
8877 vmdef = NULL;
8881 cleanup:
8882 virDomainDefFree(vmdef);
8883 virDomainDeviceDefFree(devConf);
8884 virDomainDeviceDefFree(devLive);
8885 virObjectUnref(cfg);
8886 virObjectUnref(caps);
8888 return ret;
8891 static int
8892 qemuDomainAttachDeviceFlags(virDomainPtr dom,
8893 const char *xml,
8894 unsigned int flags)
8896 virQEMUDriverPtr driver = dom->conn->privateData;
8897 virDomainObjPtr vm = NULL;
8898 int ret = -1;
8900 virNWFilterReadLockFilterUpdates();
8902 if (!(vm = qemuDomObjFromDomain(dom)))
8903 goto cleanup;
8905 if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
8906 goto cleanup;
8908 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8909 goto cleanup;
8911 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
8912 goto endjob;
8914 if (qemuDomainAttachDeviceLiveAndConfig(vm, driver, xml, flags) < 0)
8915 goto endjob;
8917 ret = 0;
8919 endjob:
8920 qemuDomainObjEndJob(driver, vm);
8922 cleanup:
8923 virDomainObjEndAPI(&vm);
8924 virNWFilterUnlockFilterUpdates();
8925 return ret;
8928 static int qemuDomainAttachDevice(virDomainPtr dom, const char *xml)
8930 return qemuDomainAttachDeviceFlags(dom, xml,
8931 VIR_DOMAIN_AFFECT_LIVE);
8935 static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
8936 const char *xml,
8937 unsigned int flags)
8939 virQEMUDriverPtr driver = dom->conn->privateData;
8940 virDomainObjPtr vm = NULL;
8941 virDomainDefPtr vmdef = NULL;
8942 virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
8943 bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
8944 int ret = -1;
8945 virQEMUDriverConfigPtr cfg = NULL;
8946 virCapsPtr caps = NULL;
8947 unsigned int parse_flags = 0;
8949 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
8950 VIR_DOMAIN_AFFECT_CONFIG |
8951 VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);
8953 virNWFilterReadLockFilterUpdates();
8955 cfg = virQEMUDriverGetConfig(driver);
8957 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
8958 goto cleanup;
8960 if (!(vm = qemuDomObjFromDomain(dom)))
8961 goto cleanup;
8963 if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
8964 goto cleanup;
8966 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
8967 goto cleanup;
8969 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
8970 goto endjob;
8972 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
8973 !(flags & VIR_DOMAIN_AFFECT_LIVE))
8974 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
8976 dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
8977 caps, driver->xmlopt,
8978 parse_flags);
8979 if (dev == NULL)
8980 goto endjob;
8982 if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
8983 flags & VIR_DOMAIN_AFFECT_LIVE) {
8984 /* If we are affecting both CONFIG and LIVE
8985 * create a deep copy of device as adding
8986 * to CONFIG takes one instance.
8988 dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
8989 if (!dev_copy)
8990 goto endjob;
8993 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
8994 /* Make a copy for updated domain. */
8995 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
8996 if (!vmdef)
8997 goto endjob;
8999 /* virDomainDefCompatibleDevice call is delayed until we know the
9000 * device we're going to update. */
9001 if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps,
9002 parse_flags,
9003 driver->xmlopt)) < 0)
9004 goto endjob;
9007 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9008 /* virDomainDefCompatibleDevice call is delayed until we know the
9009 * device we're going to update. */
9010 if ((ret = qemuDomainUpdateDeviceLive(vm, dev_copy, dom, force)) < 0)
9011 goto endjob;
9013 * update domain status forcibly because the domain status may be
9014 * changed even if we failed to attach the device. For example,
9015 * a new controller may be created.
9017 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) {
9018 ret = -1;
9019 goto endjob;
9023 /* Finally, if no error until here, we can save config. */
9024 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9025 ret = virDomainSaveConfig(cfg->configDir, driver->caps, vmdef);
9026 if (!ret) {
9027 virDomainObjAssignDef(vm, vmdef, false, NULL);
9028 vmdef = NULL;
9032 endjob:
9033 qemuDomainObjEndJob(driver, vm);
9035 cleanup:
9036 virDomainDefFree(vmdef);
9037 if (dev != dev_copy)
9038 virDomainDeviceDefFree(dev_copy);
9039 virDomainDeviceDefFree(dev);
9040 virDomainObjEndAPI(&vm);
9041 virObjectUnref(caps);
9042 virObjectUnref(cfg);
9043 virNWFilterUnlockFilterUpdates();
9044 return ret;
9047 static int
9048 qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
9049 virDomainObjPtr vm,
9050 const char *xml,
9051 unsigned int flags)
9053 virCapsPtr caps = NULL;
9054 virQEMUDriverConfigPtr cfg = NULL;
9055 virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
9056 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
9057 virDomainDefPtr vmdef = NULL;
9058 int ret = -1;
9060 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9061 VIR_DOMAIN_AFFECT_CONFIG, -1);
9063 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
9064 goto cleanup;
9066 cfg = virQEMUDriverGetConfig(driver);
9068 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
9069 !(flags & VIR_DOMAIN_AFFECT_LIVE))
9070 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
9072 dev = dev_copy = virDomainDeviceDefParse(xml, vm->def,
9073 caps, driver->xmlopt,
9074 parse_flags);
9075 if (dev == NULL)
9076 goto cleanup;
9078 if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
9079 flags & VIR_DOMAIN_AFFECT_LIVE) {
9080 /* If we are affecting both CONFIG and LIVE
9081 * create a deep copy of device as adding
9082 * to CONFIG takes one instance.
9084 dev_copy = virDomainDeviceDefCopy(dev, vm->def, caps, driver->xmlopt);
9085 if (!dev_copy)
9086 goto cleanup;
9089 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9090 /* Make a copy for updated domain. */
9091 vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
9092 if (!vmdef)
9093 goto cleanup;
9095 if (qemuDomainDetachDeviceConfig(vmdef, dev, caps,
9096 parse_flags,
9097 driver->xmlopt) < 0)
9098 goto cleanup;
9101 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9102 int rc;
9104 if ((rc = qemuDomainDetachDeviceLive(vm, dev_copy, driver, false)) < 0)
9105 goto cleanup;
9107 if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
9108 goto cleanup;
9111 * update domain status forcibly because the domain status may be
9112 * changed even if we failed to attach the device. For example,
9113 * a new controller may be created.
9115 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, caps) < 0)
9116 goto cleanup;
9119 /* Finally, if no error until here, we can save config. */
9120 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
9121 if (virDomainSaveConfig(cfg->configDir, caps, vmdef) < 0)
9122 goto cleanup;
9124 virDomainObjAssignDef(vm, vmdef, false, NULL);
9125 vmdef = NULL;
9128 ret = 0;
9130 cleanup:
9131 virObjectUnref(caps);
9132 virObjectUnref(cfg);
9133 if (dev != dev_copy)
9134 virDomainDeviceDefFree(dev_copy);
9135 virDomainDeviceDefFree(dev);
9136 virDomainDefFree(vmdef);
9137 return ret;
9141 static int
9142 qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
9143 virDomainObjPtr vm,
9144 const char *alias,
9145 unsigned int flags)
9147 virCapsPtr caps = NULL;
9148 virQEMUDriverConfigPtr cfg = NULL;
9149 virDomainDefPtr def = NULL;
9150 virDomainDefPtr persistentDef = NULL;
9151 virDomainDefPtr vmdef = NULL;
9152 unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
9153 int ret = -1;
9155 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9156 VIR_DOMAIN_AFFECT_CONFIG, -1);
9158 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
9159 goto cleanup;
9161 cfg = virQEMUDriverGetConfig(driver);
9163 if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
9164 !(flags & VIR_DOMAIN_AFFECT_LIVE))
9165 parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
9167 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9168 goto cleanup;
9170 if (persistentDef) {
9171 virDomainDeviceDef dev;
9173 if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt)))
9174 goto cleanup;
9176 if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0)
9177 goto cleanup;
9179 if (qemuDomainDetachDeviceConfig(vmdef, &dev, caps,
9180 parse_flags, driver->xmlopt) < 0)
9181 goto cleanup;
9184 if (def) {
9185 virDomainDeviceDef dev;
9186 int rc;
9188 if (virDomainDefFindDevice(def, alias, &dev, true) < 0)
9189 goto cleanup;
9191 if ((rc = qemuDomainDetachDeviceLive(vm, &dev, driver, true)) < 0)
9192 goto cleanup;
9194 if (rc == 0 && qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
9195 goto cleanup;
9198 if (vmdef) {
9199 if (virDomainSaveConfig(cfg->configDir, caps, vmdef) < 0)
9200 goto cleanup;
9201 virDomainObjAssignDef(vm, vmdef, false, NULL);
9202 vmdef = NULL;
9205 ret = 0;
9206 cleanup:
9207 virDomainDefFree(vmdef);
9208 virObjectUnref(cfg);
9209 virObjectUnref(caps);
9210 return ret;
9214 static int
9215 qemuDomainDetachDeviceFlags(virDomainPtr dom,
9216 const char *xml,
9217 unsigned int flags)
9219 virQEMUDriverPtr driver = dom->conn->privateData;
9220 virDomainObjPtr vm = NULL;
9221 int ret = -1;
9223 if (!(vm = qemuDomObjFromDomain(dom)))
9224 goto cleanup;
9226 if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
9227 goto cleanup;
9229 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9230 goto cleanup;
9232 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9233 goto endjob;
9235 if (qemuDomainDetachDeviceLiveAndConfig(driver, vm, xml, flags) < 0)
9236 goto endjob;
9238 ret = 0;
9240 endjob:
9241 qemuDomainObjEndJob(driver, vm);
9243 cleanup:
9244 virDomainObjEndAPI(&vm);
9245 return ret;
9249 static int
9250 qemuDomainDetachDeviceAlias(virDomainPtr dom,
9251 const char *alias,
9252 unsigned int flags)
9254 virQEMUDriverPtr driver = dom->conn->privateData;
9255 virDomainObjPtr vm = NULL;
9256 int ret = -1;
9258 if (!(vm = qemuDomObjFromDomain(dom)))
9259 goto cleanup;
9261 if (virDomainDetachDeviceAliasEnsureACL(dom->conn, vm->def, flags) < 0)
9262 goto cleanup;
9264 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9265 goto cleanup;
9267 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
9268 goto endjob;
9270 if (qemuDomainDetachDeviceAliasLiveAndConfig(driver, vm, alias, flags) < 0)
9271 goto endjob;
9273 ret = 0;
9275 endjob:
9276 qemuDomainObjEndJob(driver, vm);
9278 cleanup:
9279 virDomainObjEndAPI(&vm);
9280 return ret;
9284 static int qemuDomainDetachDevice(virDomainPtr dom, const char *xml)
9286 return qemuDomainDetachDeviceFlags(dom, xml,
9287 VIR_DOMAIN_AFFECT_LIVE);
9290 static int qemuDomainGetAutostart(virDomainPtr dom,
9291 int *autostart)
9293 virDomainObjPtr vm;
9294 int ret = -1;
9296 if (!(vm = qemuDomObjFromDomain(dom)))
9297 goto cleanup;
9299 if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
9300 goto cleanup;
9302 *autostart = vm->autostart;
9303 ret = 0;
9305 cleanup:
9306 virDomainObjEndAPI(&vm);
9307 return ret;
9310 static int qemuDomainSetAutostart(virDomainPtr dom,
9311 int autostart)
9313 virQEMUDriverPtr driver = dom->conn->privateData;
9314 virDomainObjPtr vm;
9315 char *configFile = NULL, *autostartLink = NULL;
9316 int ret = -1;
9317 virQEMUDriverConfigPtr cfg = NULL;
9319 if (!(vm = qemuDomObjFromDomain(dom)))
9320 return -1;
9322 cfg = virQEMUDriverGetConfig(driver);
9324 if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
9325 goto cleanup;
9327 if (!vm->persistent) {
9328 virReportError(VIR_ERR_OPERATION_INVALID,
9329 "%s", _("cannot set autostart for transient domain"));
9330 goto cleanup;
9333 autostart = (autostart != 0);
9335 if (vm->autostart != autostart) {
9336 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9337 goto cleanup;
9339 if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
9340 goto endjob;
9342 if (!(autostartLink = virDomainConfigFile(cfg->autostartDir,
9343 vm->def->name)))
9344 goto endjob;
9346 if (autostart) {
9347 if (virFileMakePath(cfg->autostartDir) < 0) {
9348 virReportSystemError(errno,
9349 _("cannot create autostart directory %s"),
9350 cfg->autostartDir);
9351 goto endjob;
9354 if (symlink(configFile, autostartLink) < 0) {
9355 virReportSystemError(errno,
9356 _("Failed to create symlink '%s to '%s'"),
9357 autostartLink, configFile);
9358 goto endjob;
9360 } else {
9361 if (unlink(autostartLink) < 0 &&
9362 errno != ENOENT &&
9363 errno != ENOTDIR) {
9364 virReportSystemError(errno,
9365 _("Failed to delete symlink '%s'"),
9366 autostartLink);
9367 goto endjob;
9371 vm->autostart = autostart;
9373 endjob:
9374 qemuDomainObjEndJob(driver, vm);
9376 ret = 0;
9378 cleanup:
9379 VIR_FREE(configFile);
9380 VIR_FREE(autostartLink);
9381 virDomainObjEndAPI(&vm);
9382 virObjectUnref(cfg);
9383 return ret;
9387 static char *qemuDomainGetSchedulerType(virDomainPtr dom,
9388 int *nparams)
9390 char *ret = NULL;
9391 virDomainObjPtr vm = NULL;
9392 qemuDomainObjPrivatePtr priv;
9393 virQEMUDriverPtr driver = dom->conn->privateData;
9395 if (!(vm = qemuDomObjFromDomain(dom)))
9396 goto cleanup;
9398 priv = vm->privateData;
9400 if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
9401 goto cleanup;
9403 if (!virQEMUDriverIsPrivileged(driver)) {
9404 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9405 _("CPU tuning is not available in session mode"));
9406 goto cleanup;
9409 /* Domain not running, thus no cgroups - return defaults */
9410 if (!virDomainObjIsActive(vm)) {
9411 if (nparams)
9412 *nparams = 9;
9413 ignore_value(VIR_STRDUP(ret, "posix"));
9414 goto cleanup;
9417 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
9418 virReportError(VIR_ERR_OPERATION_INVALID,
9419 "%s", _("cgroup CPU controller is not mounted"));
9420 goto cleanup;
9423 if (nparams) {
9424 if (virCgroupSupportsCpuBW(priv->cgroup))
9425 *nparams = 9;
9426 else
9427 *nparams = 1;
9430 ignore_value(VIR_STRDUP(ret, "posix"));
9432 cleanup:
9433 virDomainObjEndAPI(&vm);
9434 return ret;
9437 /* blkioDeviceStr in the form of /device/path,weight,/device/path,weight
9438 * for example, /dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0,800
9440 static int
9441 qemuDomainParseBlkioDeviceStr(char *blkioDeviceStr, const char *type,
9442 virBlkioDevicePtr *dev, size_t *size)
9444 char *temp;
9445 int ndevices = 0;
9446 int nsep = 0;
9447 size_t i;
9448 virBlkioDevicePtr result = NULL;
9450 *dev = NULL;
9451 *size = 0;
9453 if (STREQ(blkioDeviceStr, ""))
9454 return 0;
9456 temp = blkioDeviceStr;
9457 while (temp) {
9458 temp = strchr(temp, ',');
9459 if (temp) {
9460 temp++;
9461 nsep++;
9465 /* A valid string must have even number of fields, hence an odd
9466 * number of commas. */
9467 if (!(nsep & 1))
9468 goto parse_error;
9470 ndevices = (nsep + 1) / 2;
9472 if (VIR_ALLOC_N(result, ndevices) < 0)
9473 return -1;
9475 i = 0;
9476 temp = blkioDeviceStr;
9477 while (temp) {
9478 char *p = temp;
9480 /* device path */
9481 p = strchr(p, ',');
9482 if (!p)
9483 goto parse_error;
9485 if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0)
9486 goto cleanup;
9488 /* value */
9489 temp = p + 1;
9491 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9492 if (virStrToLong_uip(temp, &p, 10, &result[i].weight) < 0)
9493 goto number_error;
9494 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9495 if (virStrToLong_uip(temp, &p, 10, &result[i].riops) < 0)
9496 goto number_error;
9497 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9498 if (virStrToLong_uip(temp, &p, 10, &result[i].wiops) < 0)
9499 goto number_error;
9500 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9501 if (virStrToLong_ullp(temp, &p, 10, &result[i].rbps) < 0)
9502 goto number_error;
9503 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9504 if (virStrToLong_ullp(temp, &p, 10, &result[i].wbps) < 0)
9505 goto number_error;
9506 } else {
9507 virReportError(VIR_ERR_INVALID_ARG,
9508 _("unknown parameter '%s'"), type);
9509 goto cleanup;
9512 i++;
9514 if (*p == '\0')
9515 break;
9516 else if (*p != ',')
9517 goto parse_error;
9518 temp = p + 1;
9521 if (!i)
9522 VIR_FREE(result);
9524 *dev = result;
9525 *size = i;
9527 return 0;
9529 parse_error:
9530 virReportError(VIR_ERR_INVALID_ARG,
9531 _("unable to parse blkio device '%s' '%s'"),
9532 type, blkioDeviceStr);
9533 goto cleanup;
9535 number_error:
9536 virReportError(VIR_ERR_INVALID_ARG,
9537 _("invalid value '%s' for parameter '%s' of device '%s'"),
9538 temp, type, result[i].path);
9540 cleanup:
9541 if (result) {
9542 virBlkioDeviceArrayClear(result, ndevices);
9543 VIR_FREE(result);
9545 return -1;
9548 /* Modify dest_array to reflect all blkio device changes described in
9549 * src_array. */
9550 static int
9551 qemuDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
9552 size_t *dest_size,
9553 virBlkioDevicePtr src_array,
9554 size_t src_size,
9555 const char *type)
9557 size_t i, j;
9558 virBlkioDevicePtr dest, src;
9560 for (i = 0; i < src_size; i++) {
9561 bool found = false;
9563 src = &src_array[i];
9564 for (j = 0; j < *dest_size; j++) {
9565 dest = &(*dest_array)[j];
9566 if (STREQ(src->path, dest->path)) {
9567 found = true;
9569 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9570 dest->weight = src->weight;
9571 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9572 dest->riops = src->riops;
9573 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9574 dest->wiops = src->wiops;
9575 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9576 dest->rbps = src->rbps;
9577 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9578 dest->wbps = src->wbps;
9579 } else {
9580 virReportError(VIR_ERR_INVALID_ARG, _("Unknown parameter %s"),
9581 type);
9582 return -1;
9584 break;
9587 if (!found) {
9588 if (!src->weight && !src->riops && !src->wiops && !src->rbps && !src->wbps)
9589 continue;
9590 if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0)
9591 return -1;
9592 dest = &(*dest_array)[*dest_size - 1];
9594 if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9595 dest->weight = src->weight;
9596 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9597 dest->riops = src->riops;
9598 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9599 dest->wiops = src->wiops;
9600 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9601 dest->rbps = src->rbps;
9602 } else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9603 dest->wbps = src->wbps;
9604 } else {
9605 *dest_size = *dest_size - 1;
9606 return -1;
9609 dest->path = src->path;
9610 src->path = NULL;
9614 return 0;
9617 static int
9618 qemuDomainSetBlkioParameters(virDomainPtr dom,
9619 virTypedParameterPtr params,
9620 int nparams,
9621 unsigned int flags)
9623 virQEMUDriverPtr driver = dom->conn->privateData;
9624 size_t i;
9625 virDomainObjPtr vm = NULL;
9626 virDomainDefPtr def;
9627 virDomainDefPtr persistentDef;
9628 int ret = -1;
9629 virQEMUDriverConfigPtr cfg = NULL;
9630 qemuDomainObjPrivatePtr priv;
9632 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9633 VIR_DOMAIN_AFFECT_CONFIG, -1);
9634 if (virTypedParamsValidate(params, nparams,
9635 VIR_DOMAIN_BLKIO_WEIGHT,
9636 VIR_TYPED_PARAM_UINT,
9637 VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
9638 VIR_TYPED_PARAM_STRING,
9639 VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS,
9640 VIR_TYPED_PARAM_STRING,
9641 VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS,
9642 VIR_TYPED_PARAM_STRING,
9643 VIR_DOMAIN_BLKIO_DEVICE_READ_BPS,
9644 VIR_TYPED_PARAM_STRING,
9645 VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS,
9646 VIR_TYPED_PARAM_STRING,
9647 NULL) < 0)
9648 return -1;
9650 if (!(vm = qemuDomObjFromDomain(dom)))
9651 return -1;
9653 priv = vm->privateData;
9654 cfg = virQEMUDriverGetConfig(driver);
9656 if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0)
9657 goto cleanup;
9659 if (!virQEMUDriverIsPrivileged(driver)) {
9660 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9661 _("Block I/O tuning is not available in session mode"));
9662 goto cleanup;
9665 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9666 goto cleanup;
9668 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9669 goto endjob;
9671 if (flags & VIR_DOMAIN_AFFECT_LIVE) {
9672 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
9673 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9674 _("blkio cgroup isn't mounted"));
9675 goto endjob;
9679 ret = 0;
9680 if (def) {
9681 for (i = 0; i < nparams; i++) {
9682 virTypedParameterPtr param = &params[i];
9684 if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
9685 if (virCgroupSetBlkioWeight(priv->cgroup, param->value.ui) < 0 ||
9686 virCgroupGetBlkioWeight(priv->cgroup, &def->blkio.weight) < 0)
9687 ret = -1;
9688 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) ||
9689 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) ||
9690 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) ||
9691 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) ||
9692 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9693 size_t ndevices;
9694 virBlkioDevicePtr devices = NULL;
9695 size_t j;
9697 if (qemuDomainParseBlkioDeviceStr(param->value.s,
9698 param->field,
9699 &devices,
9700 &ndevices) < 0) {
9701 ret = -1;
9702 continue;
9705 if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
9706 for (j = 0; j < ndevices; j++) {
9707 if (virCgroupSetBlkioDeviceWeight(priv->cgroup,
9708 devices[j].path,
9709 devices[j].weight) < 0 ||
9710 virCgroupGetBlkioDeviceWeight(priv->cgroup,
9711 devices[j].path,
9712 &devices[j].weight) < 0) {
9713 ret = -1;
9714 break;
9717 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
9718 for (j = 0; j < ndevices; j++) {
9719 if (virCgroupSetBlkioDeviceReadIops(priv->cgroup,
9720 devices[j].path,
9721 devices[j].riops) < 0 ||
9722 virCgroupGetBlkioDeviceReadIops(priv->cgroup,
9723 devices[j].path,
9724 &devices[j].riops) < 0) {
9725 ret = -1;
9726 break;
9729 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
9730 for (j = 0; j < ndevices; j++) {
9731 if (virCgroupSetBlkioDeviceWriteIops(priv->cgroup,
9732 devices[j].path,
9733 devices[j].wiops) < 0 ||
9734 virCgroupGetBlkioDeviceWriteIops(priv->cgroup,
9735 devices[j].path,
9736 &devices[j].wiops) < 0) {
9737 ret = -1;
9738 break;
9741 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
9742 for (j = 0; j < ndevices; j++) {
9743 if (virCgroupSetBlkioDeviceReadBps(priv->cgroup,
9744 devices[j].path,
9745 devices[j].rbps) < 0 ||
9746 virCgroupGetBlkioDeviceReadBps(priv->cgroup,
9747 devices[j].path,
9748 &devices[j].rbps) < 0) {
9749 ret = -1;
9750 break;
9753 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9754 for (j = 0; j < ndevices; j++) {
9755 if (virCgroupSetBlkioDeviceWriteBps(priv->cgroup,
9756 devices[j].path,
9757 devices[j].wbps) < 0 ||
9758 virCgroupGetBlkioDeviceWriteBps(priv->cgroup,
9759 devices[j].path,
9760 &devices[j].wbps) < 0) {
9761 ret = -1;
9762 break;
9765 } else {
9766 virReportError(VIR_ERR_INVALID_ARG, _("Unknown blkio parameter %s"),
9767 param->field);
9768 ret = -1;
9769 virBlkioDeviceArrayClear(devices, ndevices);
9770 VIR_FREE(devices);
9772 continue;
9775 if (j != ndevices ||
9776 qemuDomainMergeBlkioDevice(&def->blkio.devices,
9777 &def->blkio.ndevices,
9778 devices, ndevices, param->field) < 0)
9779 ret = -1;
9780 virBlkioDeviceArrayClear(devices, ndevices);
9781 VIR_FREE(devices);
9785 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
9786 goto endjob;
9788 if (ret < 0)
9789 goto endjob;
9790 if (persistentDef) {
9791 for (i = 0; i < nparams; i++) {
9792 virTypedParameterPtr param = &params[i];
9794 if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
9795 persistentDef->blkio.weight = param->value.ui;
9796 } else if (STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT) ||
9797 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS) ||
9798 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS) ||
9799 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS) ||
9800 STREQ(param->field, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
9801 virBlkioDevicePtr devices = NULL;
9802 size_t ndevices;
9804 if (qemuDomainParseBlkioDeviceStr(param->value.s,
9805 param->field,
9806 &devices,
9807 &ndevices) < 0) {
9808 ret = -1;
9809 continue;
9811 if (qemuDomainMergeBlkioDevice(&persistentDef->blkio.devices,
9812 &persistentDef->blkio.ndevices,
9813 devices, ndevices, param->field) < 0)
9814 ret = -1;
9815 virBlkioDeviceArrayClear(devices, ndevices);
9816 VIR_FREE(devices);
9820 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
9821 ret = -1;
9824 endjob:
9825 qemuDomainObjEndJob(driver, vm);
9827 cleanup:
9828 virDomainObjEndAPI(&vm);
9829 virObjectUnref(cfg);
9830 return ret;
9834 static int
9835 qemuDomainGetBlkioParameters(virDomainPtr dom,
9836 virTypedParameterPtr params,
9837 int *nparams,
9838 unsigned int flags)
9840 virQEMUDriverPtr driver = dom->conn->privateData;
9841 virDomainObjPtr vm = NULL;
9842 virDomainDefPtr def = NULL;
9843 virDomainDefPtr persistentDef = NULL;
9844 int maxparams = QEMU_NB_BLKIO_PARAM;
9845 unsigned int val;
9846 int ret = -1;
9847 qemuDomainObjPrivatePtr priv;
9849 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9850 VIR_DOMAIN_AFFECT_CONFIG |
9851 VIR_TYPED_PARAM_STRING_OKAY, -1);
9853 /* We blindly return a string, and let libvirt.c and
9854 * remote_driver.c do the filtering on behalf of older clients
9855 * that can't parse it. */
9856 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
9858 if (!(vm = qemuDomObjFromDomain(dom)))
9859 return -1;
9861 priv = vm->privateData;
9863 if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0)
9864 goto cleanup;
9866 if (!virQEMUDriverIsPrivileged(driver)) {
9867 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9868 _("Block I/O tuning is not available in session mode"));
9869 goto cleanup;
9872 if ((*nparams) == 0) {
9873 /* Current number of blkio parameters supported by cgroups */
9874 *nparams = QEMU_NB_BLKIO_PARAM;
9875 ret = 0;
9876 goto cleanup;
9877 } else if (*nparams < maxparams) {
9878 maxparams = *nparams;
9881 *nparams = 0;
9883 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9884 goto cleanup;
9886 if (def) {
9887 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
9888 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9889 _("blkio cgroup isn't mounted"));
9890 goto cleanup;
9893 /* fill blkio weight here */
9894 if (virCgroupGetBlkioWeight(priv->cgroup, &val) < 0)
9895 goto cleanup;
9896 if (virTypedParameterAssign(&(params[(*nparams)++]),
9897 VIR_DOMAIN_BLKIO_WEIGHT,
9898 VIR_TYPED_PARAM_UINT, val) < 0)
9899 goto cleanup;
9901 if (virDomainGetBlkioParametersAssignFromDef(def, params, nparams,
9902 maxparams) < 0)
9903 goto cleanup;
9905 } else if (persistentDef) {
9906 /* fill blkio weight here */
9907 if (virTypedParameterAssign(&(params[(*nparams)++]),
9908 VIR_DOMAIN_BLKIO_WEIGHT,
9909 VIR_TYPED_PARAM_UINT,
9910 persistentDef->blkio.weight) < 0)
9911 goto cleanup;
9913 if (virDomainGetBlkioParametersAssignFromDef(persistentDef, params,
9914 nparams, maxparams) < 0)
9915 goto cleanup;
9918 ret = 0;
9920 cleanup:
9921 virDomainObjEndAPI(&vm);
9922 return ret;
9925 static int
9926 qemuDomainSetMemoryParameters(virDomainPtr dom,
9927 virTypedParameterPtr params,
9928 int nparams,
9929 unsigned int flags)
9931 virQEMUDriverPtr driver = dom->conn->privateData;
9932 virDomainDefPtr def = NULL;
9933 virDomainDefPtr persistentDef = NULL;
9934 virDomainObjPtr vm = NULL;
9935 unsigned long long swap_hard_limit;
9936 unsigned long long hard_limit = 0;
9937 unsigned long long soft_limit = 0;
9938 bool set_swap_hard_limit = false;
9939 bool set_hard_limit = false;
9940 bool set_soft_limit = false;
9941 virQEMUDriverConfigPtr cfg = NULL;
9942 int rc;
9943 int ret = -1;
9944 qemuDomainObjPrivatePtr priv;
9946 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
9947 VIR_DOMAIN_AFFECT_CONFIG, -1);
9949 if (virTypedParamsValidate(params, nparams,
9950 VIR_DOMAIN_MEMORY_HARD_LIMIT,
9951 VIR_TYPED_PARAM_ULLONG,
9952 VIR_DOMAIN_MEMORY_SOFT_LIMIT,
9953 VIR_TYPED_PARAM_ULLONG,
9954 VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
9955 VIR_TYPED_PARAM_ULLONG,
9956 NULL) < 0)
9957 return -1;
9960 if (!(vm = qemuDomObjFromDomain(dom)))
9961 return -1;
9963 priv = vm->privateData;
9964 cfg = virQEMUDriverGetConfig(driver);
9966 if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0)
9967 goto cleanup;
9969 if (!virQEMUDriverIsPrivileged(driver)) {
9970 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9971 _("Memory tuning is not available in session mode"));
9972 goto cleanup;
9975 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9976 goto cleanup;
9978 /* QEMU and LXC implementation are identical */
9979 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
9980 goto endjob;
9982 if (def &&
9983 !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
9984 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
9985 _("cgroup memory controller is not mounted"));
9986 goto endjob;
9989 #define VIR_GET_LIMIT_PARAMETER(PARAM, VALUE) \
9990 if ((rc = virTypedParamsGetULLong(params, nparams, PARAM, &VALUE)) < 0) \
9991 goto endjob; \
9993 if (rc == 1) \
9994 set_ ## VALUE = true;
9996 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit)
9997 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit)
9998 VIR_GET_LIMIT_PARAMETER(VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit)
10000 #undef VIR_GET_LIMIT_PARAMETER
10002 /* Swap hard limit must be greater than hard limit. */
10003 if (set_swap_hard_limit || set_hard_limit) {
10004 unsigned long long mem_limit = vm->def->mem.hard_limit;
10005 unsigned long long swap_limit = vm->def->mem.swap_hard_limit;
10007 if (set_swap_hard_limit)
10008 swap_limit = swap_hard_limit;
10010 if (set_hard_limit)
10011 mem_limit = hard_limit;
10013 if (mem_limit > swap_limit) {
10014 virReportError(VIR_ERR_INVALID_ARG, "%s",
10015 _("memory hard_limit tunable value must be lower "
10016 "than or equal to swap_hard_limit"));
10017 goto endjob;
10021 #define VIR_SET_MEM_PARAMETER(FUNC, VALUE) \
10022 if (set_ ## VALUE) { \
10023 if (def) { \
10024 if ((rc = FUNC(priv->cgroup, VALUE)) < 0) \
10025 goto endjob; \
10026 def->mem.VALUE = VALUE; \
10029 if (persistentDef) \
10030 persistentDef->mem.VALUE = VALUE; \
10033 /* Soft limit doesn't clash with the others */
10034 VIR_SET_MEM_PARAMETER(virCgroupSetMemorySoftLimit, soft_limit);
10036 /* set hard limit before swap hard limit if decreasing it */
10037 if (def && def->mem.hard_limit > hard_limit) {
10038 VIR_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
10039 /* inhibit changing the limit a second time */
10040 set_hard_limit = false;
10043 VIR_SET_MEM_PARAMETER(virCgroupSetMemSwapHardLimit, swap_hard_limit);
10045 /* otherwise increase it after swap hard limit */
10046 VIR_SET_MEM_PARAMETER(virCgroupSetMemoryHardLimit, hard_limit);
10048 #undef VIR_SET_MEM_PARAMETER
10050 if (def &&
10051 virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10052 goto endjob;
10054 if (persistentDef &&
10055 virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10056 goto endjob;
10057 /* QEMU and LXC implementations are identical */
10059 ret = 0;
10061 endjob:
10062 qemuDomainObjEndJob(driver, vm);
10064 cleanup:
10065 virDomainObjEndAPI(&vm);
10066 virObjectUnref(cfg);
10067 return ret;
10071 #define QEMU_ASSIGN_MEM_PARAM(index, name, value) \
10072 if (index < *nparams && \
10073 virTypedParameterAssign(&params[index], name, VIR_TYPED_PARAM_ULLONG, \
10074 value) < 0) \
10075 goto cleanup
10077 static int
10078 qemuDomainGetMemoryParameters(virDomainPtr dom,
10079 virTypedParameterPtr params,
10080 int *nparams,
10081 unsigned int flags)
10083 virQEMUDriverPtr driver = dom->conn->privateData;
10084 virDomainObjPtr vm = NULL;
10085 virDomainDefPtr persistentDef = NULL;
10086 int ret = -1;
10087 qemuDomainObjPrivatePtr priv;
10088 unsigned long long swap_hard_limit, mem_hard_limit, mem_soft_limit;
10090 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10091 VIR_DOMAIN_AFFECT_CONFIG |
10092 VIR_TYPED_PARAM_STRING_OKAY, -1);
10094 if (!(vm = qemuDomObjFromDomain(dom)))
10095 return -1;
10097 priv = vm->privateData;
10099 if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0)
10100 goto cleanup;
10102 if (!virQEMUDriverIsPrivileged(driver)) {
10103 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10104 _("Memory tuning is not available in session mode"));
10105 goto cleanup;
10108 if (virDomainObjGetDefs(vm, flags, NULL, &persistentDef) < 0)
10109 goto cleanup;
10111 if ((*nparams) == 0) {
10112 /* Current number of memory parameters supported by cgroups */
10113 *nparams = QEMU_NB_MEM_PARAM;
10114 ret = 0;
10115 goto cleanup;
10118 if (persistentDef) {
10119 mem_hard_limit = persistentDef->mem.hard_limit;
10120 mem_soft_limit = persistentDef->mem.soft_limit;
10121 swap_hard_limit = persistentDef->mem.swap_hard_limit;
10122 } else {
10123 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
10124 virReportError(VIR_ERR_OPERATION_INVALID,
10125 "%s", _("cgroup memory controller is not mounted"));
10126 goto cleanup;
10129 if (virCgroupGetMemoryHardLimit(priv->cgroup, &mem_hard_limit) < 0)
10130 goto cleanup;
10132 if (virCgroupGetMemorySoftLimit(priv->cgroup, &mem_soft_limit) < 0)
10133 goto cleanup;
10135 if (virCgroupGetMemSwapHardLimit(priv->cgroup, &swap_hard_limit) < 0) {
10136 if (!virLastErrorIsSystemErrno(ENOENT) &&
10137 !virLastErrorIsSystemErrno(EOPNOTSUPP))
10138 goto cleanup;
10139 swap_hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
10143 QEMU_ASSIGN_MEM_PARAM(0, VIR_DOMAIN_MEMORY_HARD_LIMIT, mem_hard_limit);
10144 QEMU_ASSIGN_MEM_PARAM(1, VIR_DOMAIN_MEMORY_SOFT_LIMIT, mem_soft_limit);
10145 QEMU_ASSIGN_MEM_PARAM(2, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, swap_hard_limit);
10147 if (QEMU_NB_MEM_PARAM < *nparams)
10148 *nparams = QEMU_NB_MEM_PARAM;
10149 ret = 0;
10151 cleanup:
10152 virDomainObjEndAPI(&vm);
10153 return ret;
10155 #undef QEMU_ASSIGN_MEM_PARAM
10157 static int
10158 qemuDomainSetNumaParamsLive(virDomainObjPtr vm,
10159 virBitmapPtr nodeset)
10161 virCgroupPtr cgroup_temp = NULL;
10162 qemuDomainObjPrivatePtr priv = vm->privateData;
10163 char *nodeset_str = NULL;
10164 virDomainNumatuneMemMode mode;
10165 size_t i = 0;
10166 int ret = -1;
10168 if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
10169 mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
10170 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10171 _("change of nodeset for running domain "
10172 "requires strict numa mode"));
10173 goto cleanup;
10176 if (!virNumaNodesetIsAvailable(nodeset))
10177 goto cleanup;
10179 /* Ensure the cpuset string is formatted before passing to cgroup */
10180 if (!(nodeset_str = virBitmapFormat(nodeset)))
10181 goto cleanup;
10183 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
10184 false, &cgroup_temp) < 0 ||
10185 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10186 goto cleanup;
10187 virCgroupFree(&cgroup_temp);
10189 for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
10190 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
10192 if (!vcpu->online)
10193 continue;
10195 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
10196 false, &cgroup_temp) < 0 ||
10197 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10198 goto cleanup;
10199 virCgroupFree(&cgroup_temp);
10202 for (i = 0; i < vm->def->niothreadids; i++) {
10203 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
10204 vm->def->iothreadids[i]->iothread_id,
10205 false, &cgroup_temp) < 0 ||
10206 virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
10207 goto cleanup;
10208 virCgroupFree(&cgroup_temp);
10211 ret = 0;
10212 cleanup:
10213 VIR_FREE(nodeset_str);
10214 virCgroupFree(&cgroup_temp);
10216 return ret;
10219 static int
10220 qemuDomainSetNumaParameters(virDomainPtr dom,
10221 virTypedParameterPtr params,
10222 int nparams,
10223 unsigned int flags)
10225 virQEMUDriverPtr driver = dom->conn->privateData;
10226 size_t i;
10227 virDomainDefPtr def;
10228 virDomainDefPtr persistentDef;
10229 virDomainObjPtr vm = NULL;
10230 int ret = -1;
10231 virQEMUDriverConfigPtr cfg = NULL;
10232 qemuDomainObjPrivatePtr priv;
10233 virBitmapPtr nodeset = NULL;
10234 virDomainNumatuneMemMode config_mode;
10235 int mode = -1;
10237 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10238 VIR_DOMAIN_AFFECT_CONFIG, -1);
10240 if (virTypedParamsValidate(params, nparams,
10241 VIR_DOMAIN_NUMA_MODE,
10242 VIR_TYPED_PARAM_INT,
10243 VIR_DOMAIN_NUMA_NODESET,
10244 VIR_TYPED_PARAM_STRING,
10245 NULL) < 0)
10246 return -1;
10248 if (!(vm = qemuDomObjFromDomain(dom)))
10249 return -1;
10251 priv = vm->privateData;
10252 cfg = virQEMUDriverGetConfig(driver);
10254 if (virDomainSetNumaParametersEnsureACL(dom->conn, vm->def, flags) < 0)
10255 goto cleanup;
10257 for (i = 0; i < nparams; i++) {
10258 virTypedParameterPtr param = &params[i];
10260 if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) {
10261 mode = param->value.i;
10263 if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) {
10264 virReportError(VIR_ERR_INVALID_ARG,
10265 _("unsupported numatune mode: '%d'"), mode);
10266 goto cleanup;
10269 } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
10270 if (virBitmapParse(param->value.s, &nodeset,
10271 VIR_DOMAIN_CPUMASK_LEN) < 0)
10272 goto cleanup;
10274 if (virBitmapIsAllClear(nodeset)) {
10275 virReportError(VIR_ERR_OPERATION_INVALID,
10276 _("Invalid nodeset of 'numatune': %s"),
10277 param->value.s);
10278 goto cleanup;
10283 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10284 goto cleanup;
10286 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10287 goto endjob;
10289 if (def) {
10290 if (!virQEMUDriverIsPrivileged(driver)) {
10291 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
10292 _("NUMA tuning is not available in session mode"));
10293 goto endjob;
10296 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) {
10297 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10298 _("cgroup cpuset controller is not mounted"));
10299 goto endjob;
10302 if (mode != -1 &&
10303 virDomainNumatuneGetMode(def->numa, -1, &config_mode) == 0 &&
10304 config_mode != mode) {
10305 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10306 _("can't change numatune mode for running domain"));
10307 goto endjob;
10310 if (nodeset &&
10311 qemuDomainSetNumaParamsLive(vm, nodeset) < 0)
10312 goto endjob;
10314 if (virDomainNumatuneSet(def->numa,
10315 def->placement_mode ==
10316 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
10317 -1, mode, nodeset) < 0)
10318 goto endjob;
10320 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10321 goto endjob;
10324 if (persistentDef) {
10325 if (virDomainNumatuneSet(persistentDef->numa,
10326 persistentDef->placement_mode ==
10327 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
10328 -1, mode, nodeset) < 0)
10329 goto endjob;
10331 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10332 goto endjob;
10335 ret = 0;
10337 endjob:
10338 qemuDomainObjEndJob(driver, vm);
10340 cleanup:
10341 virBitmapFree(nodeset);
10342 virDomainObjEndAPI(&vm);
10343 virObjectUnref(cfg);
10344 return ret;
10347 static int
10348 qemuDomainGetNumaParameters(virDomainPtr dom,
10349 virTypedParameterPtr params,
10350 int *nparams,
10351 unsigned int flags)
10353 size_t i;
10354 virDomainObjPtr vm = NULL;
10355 virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
10356 qemuDomainObjPrivatePtr priv;
10357 char *nodeset = NULL;
10358 int ret = -1;
10359 virDomainDefPtr def = NULL;
10360 bool live = false;
10361 virBitmapPtr autoNodeset = NULL;
10363 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10364 VIR_DOMAIN_AFFECT_CONFIG |
10365 VIR_TYPED_PARAM_STRING_OKAY, -1);
10367 if (!(vm = qemuDomObjFromDomain(dom)))
10368 return -1;
10369 priv = vm->privateData;
10371 if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
10372 goto cleanup;
10374 if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
10375 goto cleanup;
10377 if (live)
10378 autoNodeset = priv->autoNodeset;
10380 if ((*nparams) == 0) {
10381 *nparams = QEMU_NB_NUMA_PARAM;
10382 ret = 0;
10383 goto cleanup;
10386 for (i = 0; i < QEMU_NB_NUMA_PARAM && i < *nparams; i++) {
10387 virMemoryParameterPtr param = &params[i];
10389 switch (i) {
10390 case 0: /* fill numa mode here */
10391 ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
10393 if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
10394 VIR_TYPED_PARAM_INT, tmpmode) < 0)
10395 goto cleanup;
10397 break;
10399 case 1: /* fill numa nodeset here */
10400 nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, -1);
10401 if (!nodeset ||
10402 virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
10403 VIR_TYPED_PARAM_STRING, nodeset) < 0)
10404 goto cleanup;
10406 nodeset = NULL;
10407 break;
10409 /* coverity[dead_error_begin] */
10410 default:
10411 break;
10412 /* should not hit here */
10416 if (*nparams > QEMU_NB_NUMA_PARAM)
10417 *nparams = QEMU_NB_NUMA_PARAM;
10418 ret = 0;
10420 cleanup:
10421 VIR_FREE(nodeset);
10422 virDomainObjEndAPI(&vm);
10423 return ret;
10426 static int
10427 qemuSetGlobalBWLive(virCgroupPtr cgroup, unsigned long long period,
10428 long long quota)
10430 if (period == 0 && quota == 0)
10431 return 0;
10433 if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
10434 return -1;
10436 return 0;
10439 static int
10440 qemuDomainSetPerfEvents(virDomainPtr dom,
10441 virTypedParameterPtr params,
10442 int nparams,
10443 unsigned int flags)
10445 virQEMUDriverPtr driver = dom->conn->privateData;
10446 size_t i;
10447 virDomainObjPtr vm = NULL;
10448 virQEMUDriverConfigPtr cfg = NULL;
10449 qemuDomainObjPrivatePtr priv;
10450 virDomainDefPtr def;
10451 virDomainDefPtr persistentDef;
10452 int ret = -1;
10453 virPerfEventType type;
10454 bool enabled;
10456 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10457 VIR_DOMAIN_AFFECT_CONFIG, -1);
10459 if (virTypedParamsValidate(params, nparams,
10460 VIR_PERF_PARAM_CMT, VIR_TYPED_PARAM_BOOLEAN,
10461 VIR_PERF_PARAM_MBMT, VIR_TYPED_PARAM_BOOLEAN,
10462 VIR_PERF_PARAM_MBML, VIR_TYPED_PARAM_BOOLEAN,
10463 VIR_PERF_PARAM_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10464 VIR_PERF_PARAM_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
10465 VIR_PERF_PARAM_CACHE_REFERENCES, VIR_TYPED_PARAM_BOOLEAN,
10466 VIR_PERF_PARAM_CACHE_MISSES, VIR_TYPED_PARAM_BOOLEAN,
10467 VIR_PERF_PARAM_BRANCH_INSTRUCTIONS, VIR_TYPED_PARAM_BOOLEAN,
10468 VIR_PERF_PARAM_BRANCH_MISSES, VIR_TYPED_PARAM_BOOLEAN,
10469 VIR_PERF_PARAM_BUS_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10470 VIR_PERF_PARAM_STALLED_CYCLES_FRONTEND, VIR_TYPED_PARAM_BOOLEAN,
10471 VIR_PERF_PARAM_STALLED_CYCLES_BACKEND, VIR_TYPED_PARAM_BOOLEAN,
10472 VIR_PERF_PARAM_REF_CPU_CYCLES, VIR_TYPED_PARAM_BOOLEAN,
10473 VIR_PERF_PARAM_CPU_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
10474 VIR_PERF_PARAM_TASK_CLOCK, VIR_TYPED_PARAM_BOOLEAN,
10475 VIR_PERF_PARAM_PAGE_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10476 VIR_PERF_PARAM_CONTEXT_SWITCHES, VIR_TYPED_PARAM_BOOLEAN,
10477 VIR_PERF_PARAM_CPU_MIGRATIONS, VIR_TYPED_PARAM_BOOLEAN,
10478 VIR_PERF_PARAM_PAGE_FAULTS_MIN, VIR_TYPED_PARAM_BOOLEAN,
10479 VIR_PERF_PARAM_PAGE_FAULTS_MAJ, VIR_TYPED_PARAM_BOOLEAN,
10480 VIR_PERF_PARAM_ALIGNMENT_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10481 VIR_PERF_PARAM_EMULATION_FAULTS, VIR_TYPED_PARAM_BOOLEAN,
10482 NULL) < 0)
10483 return -1;
10485 if (!(vm = qemuDomObjFromDomain(dom)))
10486 return -1;
10488 cfg = virQEMUDriverGetConfig(driver);
10489 priv = vm->privateData;
10491 if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
10492 goto cleanup;
10494 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10495 goto cleanup;
10497 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10498 goto endjob;
10500 if (def) {
10501 for (i = 0; i < nparams; i++) {
10502 virTypedParameterPtr param = &params[i];
10503 enabled = param->value.b;
10504 type = virPerfEventTypeFromString(param->field);
10506 if (!enabled && virPerfEventDisable(priv->perf, type) < 0)
10507 goto endjob;
10508 if (enabled && virPerfEventEnable(priv->perf, type, vm->pid) < 0)
10509 goto endjob;
10511 def->perf.events[type] = enabled ?
10512 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
10515 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10516 goto endjob;
10519 if (persistentDef) {
10520 for (i = 0; i < nparams; i++) {
10521 virTypedParameterPtr param = &params[i];
10522 enabled = param->value.b;
10523 type = virPerfEventTypeFromString(param->field);
10525 persistentDef->perf.events[type] = enabled ?
10526 VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO;
10529 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
10530 goto endjob;
10533 ret = 0;
10535 endjob:
10536 qemuDomainObjEndJob(driver, vm);
10538 cleanup:
10539 virDomainObjEndAPI(&vm);
10540 virObjectUnref(cfg);
10541 return ret;
10544 static int
10545 qemuDomainGetPerfEvents(virDomainPtr dom,
10546 virTypedParameterPtr *params,
10547 int *nparams,
10548 unsigned int flags)
10550 virQEMUDriverPtr driver = dom->conn->privateData;
10551 virDomainObjPtr vm = NULL;
10552 qemuDomainObjPrivatePtr priv;
10553 virDomainDefPtr def;
10554 virTypedParameterPtr par = NULL;
10555 int maxpar = 0;
10556 int npar = 0;
10557 size_t i;
10558 int ret = -1;
10560 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10561 VIR_DOMAIN_AFFECT_CONFIG |
10562 VIR_TYPED_PARAM_STRING_OKAY, -1);
10564 if (!(vm = qemuDomObjFromDomain(dom)))
10565 goto cleanup;
10567 if (virDomainGetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
10568 goto cleanup;
10570 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
10571 goto cleanup;
10573 if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
10574 goto endjob;
10576 if (!(def = virDomainObjGetOneDef(vm, flags)))
10577 goto endjob;
10579 priv = vm->privateData;
10581 for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
10582 bool perf_enabled;
10584 if (flags & VIR_DOMAIN_AFFECT_CONFIG)
10585 perf_enabled = def->perf.events[i] == VIR_TRISTATE_BOOL_YES;
10586 else
10587 perf_enabled = virPerfEventIsEnabled(priv->perf, i);
10589 if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
10590 virPerfEventTypeToString(i),
10591 perf_enabled) < 0)
10592 goto endjob;
10595 *params = par;
10596 *nparams = npar;
10597 par = NULL;
10598 npar = 0;
10599 ret = 0;
10601 endjob:
10602 qemuDomainObjEndJob(driver, vm);
10604 cleanup:
10605 virDomainObjEndAPI(&vm);
10606 virTypedParamsFree(par, npar);
10607 return ret;
10610 static int
10611 qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
10612 unsigned long long period, long long quota)
10614 size_t i;
10615 virCgroupPtr cgroup_vcpu = NULL;
10617 if (period == 0 && quota == 0)
10618 return 0;
10620 if (!qemuDomainHasVcpuPids(vm))
10621 return 0;
10623 for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
10624 virDomainVcpuDefPtr vcpu = virDomainDefGetVcpu(vm->def, i);
10626 if (!vcpu->online)
10627 continue;
10629 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_VCPU, i,
10630 false, &cgroup_vcpu) < 0)
10631 goto cleanup;
10633 if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
10634 goto cleanup;
10636 virCgroupFree(&cgroup_vcpu);
10639 return 0;
10641 cleanup:
10642 virCgroupFree(&cgroup_vcpu);
10643 return -1;
10646 static int
10647 qemuSetEmulatorBandwidthLive(virCgroupPtr cgroup,
10648 unsigned long long period,
10649 long long quota)
10651 virCgroupPtr cgroup_emulator = NULL;
10653 if (period == 0 && quota == 0)
10654 return 0;
10656 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
10657 false, &cgroup_emulator) < 0)
10658 goto cleanup;
10660 if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
10661 goto cleanup;
10663 virCgroupFree(&cgroup_emulator);
10664 return 0;
10666 cleanup:
10667 virCgroupFree(&cgroup_emulator);
10668 return -1;
10672 static int
10673 qemuSetIOThreadsBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
10674 unsigned long long period, long long quota)
10676 size_t i;
10677 virCgroupPtr cgroup_iothread = NULL;
10679 if (period == 0 && quota == 0)
10680 return 0;
10682 if (!vm->def->niothreadids)
10683 return 0;
10685 for (i = 0; i < vm->def->niothreadids; i++) {
10686 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_IOTHREAD,
10687 vm->def->iothreadids[i]->iothread_id,
10688 false, &cgroup_iothread) < 0)
10689 goto cleanup;
10691 if (qemuSetupCgroupVcpuBW(cgroup_iothread, period, quota) < 0)
10692 goto cleanup;
10694 virCgroupFree(&cgroup_iothread);
10697 return 0;
10699 cleanup:
10700 virCgroupFree(&cgroup_iothread);
10701 return -1;
10705 #define SCHED_RANGE_CHECK(VAR, NAME, MIN, MAX) \
10706 if (((VAR) > 0 && (VAR) < (MIN)) || (VAR) > (MAX)) { \
10707 virReportError(VIR_ERR_INVALID_ARG, \
10708 _("value of '%s' is out of range [%lld, %lld]"), \
10709 NAME, MIN, MAX); \
10710 rc = -1; \
10711 goto endjob; \
10714 static int
10715 qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,
10716 virTypedParameterPtr params,
10717 int nparams,
10718 unsigned int flags)
10720 virQEMUDriverPtr driver = dom->conn->privateData;
10721 size_t i;
10722 virDomainObjPtr vm = NULL;
10723 virDomainDefPtr def = NULL;
10724 virDomainDefPtr persistentDef = NULL;
10725 virDomainDefPtr persistentDefCopy = NULL;
10726 unsigned long long value_ul;
10727 long long value_l;
10728 int ret = -1;
10729 int rc;
10730 virQEMUDriverConfigPtr cfg = NULL;
10731 virCapsPtr caps = NULL;
10732 qemuDomainObjPrivatePtr priv;
10733 virObjectEventPtr event = NULL;
10734 virTypedParameterPtr eventParams = NULL;
10735 int eventNparams = 0;
10736 int eventMaxNparams = 0;
10738 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
10739 VIR_DOMAIN_AFFECT_CONFIG, -1);
10740 if (virTypedParamsValidate(params, nparams,
10741 VIR_DOMAIN_SCHEDULER_CPU_SHARES,
10742 VIR_TYPED_PARAM_ULLONG,
10743 VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
10744 VIR_TYPED_PARAM_ULLONG,
10745 VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
10746 VIR_TYPED_PARAM_LLONG,
10747 VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
10748 VIR_TYPED_PARAM_ULLONG,
10749 VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
10750 VIR_TYPED_PARAM_LLONG,
10751 VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
10752 VIR_TYPED_PARAM_ULLONG,
10753 VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
10754 VIR_TYPED_PARAM_LLONG,
10755 VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
10756 VIR_TYPED_PARAM_ULLONG,
10757 VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
10758 VIR_TYPED_PARAM_LLONG,
10759 NULL) < 0)
10760 return -1;
10762 if (!(vm = qemuDomObjFromDomain(dom)))
10763 return -1;
10765 priv = vm->privateData;
10766 cfg = virQEMUDriverGetConfig(driver);
10768 if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
10769 goto cleanup;
10771 if (!virQEMUDriverIsPrivileged(driver)) {
10772 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10773 _("CPU tuning is not available in session mode"));
10774 goto cleanup;
10777 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
10778 goto cleanup;
10780 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
10781 goto cleanup;
10783 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
10784 goto endjob;
10786 if (persistentDef) {
10787 /* Make a copy for updated domain. */
10788 if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps,
10789 driver->xmlopt)))
10790 goto endjob;
10793 if (def &&
10794 !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
10795 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
10796 _("cgroup CPU controller is not mounted"));
10797 goto endjob;
10800 for (i = 0; i < nparams; i++) {
10801 virTypedParameterPtr param = &params[i];
10802 value_ul = param->value.ul;
10803 value_l = param->value.l;
10805 if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
10806 if (def) {
10807 unsigned long long val;
10808 if (virCgroupSetCpuShares(priv->cgroup, value_ul) < 0)
10809 goto endjob;
10811 if (virCgroupGetCpuShares(priv->cgroup, &val) < 0)
10812 goto endjob;
10814 def->cputune.shares = val;
10815 def->cputune.sharesSpecified = true;
10817 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10818 &eventMaxNparams,
10819 VIR_DOMAIN_TUNABLE_CPU_CPU_SHARES,
10820 val) < 0)
10821 goto endjob;
10824 if (persistentDef) {
10825 persistentDefCopy->cputune.shares = value_ul;
10826 persistentDefCopy->cputune.sharesSpecified = true;
10830 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
10831 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
10832 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10834 if (def && value_ul) {
10835 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, value_ul, 0)))
10836 goto endjob;
10838 def->cputune.period = value_ul;
10840 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10841 &eventMaxNparams,
10842 VIR_DOMAIN_TUNABLE_CPU_VCPU_PERIOD,
10843 value_ul) < 0)
10844 goto endjob;
10847 if (persistentDef)
10848 persistentDefCopy->cputune.period = value_ul;
10850 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
10851 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
10852 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10854 if (def && value_l) {
10855 if ((rc = qemuSetVcpusBWLive(vm, priv->cgroup, 0, value_l)))
10856 goto endjob;
10858 def->cputune.quota = value_l;
10860 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
10861 &eventMaxNparams,
10862 VIR_DOMAIN_TUNABLE_CPU_VCPU_QUOTA,
10863 value_l) < 0)
10864 goto endjob;
10867 if (persistentDef)
10868 persistentDefCopy->cputune.quota = value_l;
10870 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD)) {
10871 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
10872 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10874 if (def && value_ul) {
10875 if ((rc = qemuSetGlobalBWLive(priv->cgroup, value_ul, 0)))
10876 goto endjob;
10878 def->cputune.global_period = value_ul;
10880 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10881 &eventMaxNparams,
10882 VIR_DOMAIN_TUNABLE_CPU_GLOBAL_PERIOD,
10883 value_ul) < 0)
10884 goto endjob;
10887 if (persistentDef)
10888 persistentDefCopy->cputune.global_period = value_ul;
10890 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA)) {
10891 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
10892 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10894 if (def && value_l) {
10895 if ((rc = qemuSetGlobalBWLive(priv->cgroup, 0, value_l)))
10896 goto endjob;
10898 def->cputune.global_quota = value_l;
10900 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
10901 &eventMaxNparams,
10902 VIR_DOMAIN_TUNABLE_CPU_GLOBAL_QUOTA,
10903 value_l) < 0)
10904 goto endjob;
10907 if (persistentDef)
10908 persistentDefCopy->cputune.global_quota = value_l;
10910 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD)) {
10911 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
10912 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10914 if (def && value_ul) {
10915 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
10916 value_ul, 0)))
10917 goto endjob;
10919 def->cputune.emulator_period = value_ul;
10921 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10922 &eventMaxNparams,
10923 VIR_DOMAIN_TUNABLE_CPU_EMULATOR_PERIOD,
10924 value_ul) < 0)
10925 goto endjob;
10928 if (persistentDef)
10929 persistentDefCopy->cputune.emulator_period = value_ul;
10931 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA)) {
10932 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
10933 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10935 if (def && value_l) {
10936 if ((rc = qemuSetEmulatorBandwidthLive(priv->cgroup,
10937 0, value_l)))
10938 goto endjob;
10940 def->cputune.emulator_quota = value_l;
10942 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
10943 &eventMaxNparams,
10944 VIR_DOMAIN_TUNABLE_CPU_EMULATOR_QUOTA,
10945 value_l) < 0)
10946 goto endjob;
10949 if (persistentDef)
10950 persistentDefCopy->cputune.emulator_quota = value_l;
10952 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD)) {
10953 SCHED_RANGE_CHECK(value_ul, VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
10954 QEMU_SCHED_MIN_PERIOD, QEMU_SCHED_MAX_PERIOD);
10956 if (def && value_ul) {
10957 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, value_ul, 0)))
10958 goto endjob;
10960 def->cputune.iothread_period = value_ul;
10962 if (virTypedParamsAddULLong(&eventParams, &eventNparams,
10963 &eventMaxNparams,
10964 VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_PERIOD,
10965 value_ul) < 0)
10966 goto endjob;
10969 if (persistentDef)
10970 persistentDefCopy->cputune.iothread_period = value_ul;
10972 } else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA)) {
10973 SCHED_RANGE_CHECK(value_l, VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
10974 QEMU_SCHED_MIN_QUOTA, QEMU_SCHED_MAX_QUOTA);
10976 if (def && value_l) {
10977 if ((rc = qemuSetIOThreadsBWLive(vm, priv->cgroup, 0, value_l)))
10978 goto endjob;
10980 def->cputune.iothread_quota = value_l;
10982 if (virTypedParamsAddLLong(&eventParams, &eventNparams,
10983 &eventMaxNparams,
10984 VIR_DOMAIN_TUNABLE_CPU_IOTHREAD_QUOTA,
10985 value_l) < 0)
10986 goto endjob;
10989 if (persistentDef)
10990 persistentDefCopy->cputune.iothread_quota = value_l;
10994 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
10995 goto endjob;
10997 if (eventNparams) {
10998 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
10999 eventNparams = 0;
11000 virObjectEventStateQueue(driver->domainEventState, event);
11003 if (persistentDef) {
11004 rc = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDefCopy);
11005 if (rc < 0)
11006 goto endjob;
11008 virDomainObjAssignDef(vm, persistentDefCopy, false, NULL);
11009 persistentDefCopy = NULL;
11012 ret = 0;
11014 endjob:
11015 qemuDomainObjEndJob(driver, vm);
11017 cleanup:
11018 virDomainDefFree(persistentDefCopy);
11019 virDomainObjEndAPI(&vm);
11020 if (eventNparams)
11021 virTypedParamsFree(eventParams, eventNparams);
11022 virObjectUnref(caps);
11023 virObjectUnref(cfg);
11024 return ret;
11026 #undef SCHED_RANGE_CHECK
11028 static int
11029 qemuDomainSetSchedulerParameters(virDomainPtr dom,
11030 virTypedParameterPtr params,
11031 int nparams)
11033 return qemuDomainSetSchedulerParametersFlags(dom,
11034 params,
11035 nparams,
11036 VIR_DOMAIN_AFFECT_CURRENT);
11039 static int
11040 qemuGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
11041 long long *quota)
11043 if (virCgroupGetCpuCfsPeriod(cgroup, period) < 0)
11044 return -1;
11046 if (virCgroupGetCpuCfsQuota(cgroup, quota) < 0)
11047 return -1;
11049 return 0;
11052 static int
11053 qemuGetVcpusBWLive(virDomainObjPtr vm,
11054 unsigned long long *period, long long *quota)
11056 virCgroupPtr cgroup_vcpu = NULL;
11057 qemuDomainObjPrivatePtr priv = NULL;
11058 int rc;
11059 int ret = -1;
11061 priv = vm->privateData;
11062 if (!qemuDomainHasVcpuPids(vm)) {
11063 /* We do not create sub dir for each vcpu */
11064 rc = qemuGetVcpuBWLive(priv->cgroup, period, quota);
11065 if (rc < 0)
11066 goto cleanup;
11068 if (*quota > 0)
11069 *quota /= virDomainDefGetVcpus(vm->def);
11070 goto out;
11073 /* get period and quota for vcpu0 */
11074 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, 0,
11075 false, &cgroup_vcpu) < 0)
11076 goto cleanup;
11078 rc = qemuGetVcpuBWLive(cgroup_vcpu, period, quota);
11079 if (rc < 0)
11080 goto cleanup;
11082 out:
11083 ret = 0;
11085 cleanup:
11086 virCgroupFree(&cgroup_vcpu);
11087 return ret;
11090 static int
11091 qemuGetEmulatorBandwidthLive(virCgroupPtr cgroup,
11092 unsigned long long *period,
11093 long long *quota)
11095 virCgroupPtr cgroup_emulator = NULL;
11096 int ret = -1;
11098 /* get period and quota for emulator */
11099 if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
11100 false, &cgroup_emulator) < 0)
11101 goto cleanup;
11103 if (qemuGetVcpuBWLive(cgroup_emulator, period, quota) < 0)
11104 goto cleanup;
11106 ret = 0;
11108 cleanup:
11109 virCgroupFree(&cgroup_emulator);
11110 return ret;
11113 static int
11114 qemuGetIOThreadsBWLive(virDomainObjPtr vm,
11115 unsigned long long *period, long long *quota)
11117 virCgroupPtr cgroup_iothread = NULL;
11118 qemuDomainObjPrivatePtr priv = NULL;
11119 int rc;
11120 int ret = -1;
11122 priv = vm->privateData;
11123 if (!vm->def->niothreadids) {
11124 /* We do not create sub dir for each iothread */
11125 if ((rc = qemuGetVcpuBWLive(priv->cgroup, period, quota)) < 0)
11126 goto cleanup;
11128 goto out;
11131 /* get period and quota for the "first" IOThread */
11132 if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
11133 vm->def->iothreadids[0]->iothread_id,
11134 false, &cgroup_iothread) < 0)
11135 goto cleanup;
11137 rc = qemuGetVcpuBWLive(cgroup_iothread, period, quota);
11138 if (rc < 0)
11139 goto cleanup;
11141 out:
11142 ret = 0;
11144 cleanup:
11145 virCgroupFree(&cgroup_iothread);
11146 return ret;
11150 static int
11151 qemuGetGlobalBWLive(virCgroupPtr cgroup, unsigned long long *period,
11152 long long *quota)
11154 if (qemuGetVcpuBWLive(cgroup, period, quota) < 0)
11155 return -1;
11157 return 0;
11160 static int
11161 qemuDomainGetSchedulerParametersFlags(virDomainPtr dom,
11162 virTypedParameterPtr params,
11163 int *nparams,
11164 unsigned int flags)
11166 virQEMUDriverPtr driver = dom->conn->privateData;
11167 virDomainObjPtr vm = NULL;
11168 virDomainCputune data = {0};
11169 int ret = -1;
11170 bool cpu_bw_status = true;
11171 virDomainDefPtr persistentDef;
11172 virDomainDefPtr def;
11173 qemuDomainObjPrivatePtr priv;
11174 int maxparams = *nparams;
11176 *nparams = 0;
11178 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11179 VIR_DOMAIN_AFFECT_CONFIG |
11180 VIR_TYPED_PARAM_STRING_OKAY, -1);
11182 if (!(vm = qemuDomObjFromDomain(dom)))
11183 goto cleanup;
11185 priv = vm->privateData;
11187 if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
11188 goto cleanup;
11190 if (!virQEMUDriverIsPrivileged(driver)) {
11191 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
11192 _("CPU tuning is not available in session mode"));
11193 goto cleanup;
11196 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
11197 goto cleanup;
11199 if (persistentDef) {
11200 data = persistentDef->cputune;
11201 } else if (def) {
11202 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
11203 virReportError(VIR_ERR_OPERATION_INVALID,
11204 "%s", _("cgroup CPU controller is not mounted"));
11205 goto cleanup;
11208 if (virCgroupGetCpuShares(priv->cgroup, &data.shares) < 0)
11209 goto cleanup;
11211 if (virCgroupSupportsCpuBW(priv->cgroup)) {
11212 if (maxparams > 1 &&
11213 qemuGetVcpusBWLive(vm, &data.period, &data.quota) < 0)
11214 goto cleanup;
11216 if (maxparams > 3 &&
11217 qemuGetEmulatorBandwidthLive(priv->cgroup, &data.emulator_period,
11218 &data.emulator_quota) < 0)
11219 goto cleanup;
11221 if (maxparams > 5 &&
11222 qemuGetGlobalBWLive(priv->cgroup, &data.global_period,
11223 &data.global_quota) < 0)
11224 goto cleanup;
11226 if (maxparams > 7 &&
11227 qemuGetIOThreadsBWLive(vm, &data.iothread_period,
11228 &data.iothread_quota) < 0)
11229 goto cleanup;
11230 } else {
11231 cpu_bw_status = false;
11235 #define QEMU_SCHED_ASSIGN(param, name, type) \
11236 if (*nparams < maxparams && \
11237 virTypedParameterAssign(&(params[(*nparams)++]), \
11238 VIR_DOMAIN_SCHEDULER_ ## name, \
11239 VIR_TYPED_PARAM_ ## type, \
11240 data.param) < 0) \
11241 goto cleanup
11243 QEMU_SCHED_ASSIGN(shares, CPU_SHARES, ULLONG);
11245 if (cpu_bw_status) {
11246 QEMU_SCHED_ASSIGN(period, VCPU_PERIOD, ULLONG);
11247 QEMU_SCHED_ASSIGN(quota, VCPU_QUOTA, LLONG);
11249 QEMU_SCHED_ASSIGN(emulator_period, EMULATOR_PERIOD, ULLONG);
11250 QEMU_SCHED_ASSIGN(emulator_quota, EMULATOR_QUOTA, LLONG);
11252 QEMU_SCHED_ASSIGN(global_period, GLOBAL_PERIOD, ULLONG);
11253 QEMU_SCHED_ASSIGN(global_quota, GLOBAL_QUOTA, LLONG);
11255 QEMU_SCHED_ASSIGN(iothread_period, IOTHREAD_PERIOD, ULLONG);
11256 QEMU_SCHED_ASSIGN(iothread_quota, IOTHREAD_QUOTA, LLONG);
11259 #undef QEMU_SCHED_ASSIGN
11261 ret = 0;
11263 cleanup:
11264 virDomainObjEndAPI(&vm);
11265 return ret;
11268 static int
11269 qemuDomainGetSchedulerParameters(virDomainPtr dom,
11270 virTypedParameterPtr params,
11271 int *nparams)
11273 return qemuDomainGetSchedulerParametersFlags(dom, params, nparams,
11274 VIR_DOMAIN_AFFECT_CURRENT);
11278 * Resize a block device while a guest is running. Resize to a lower size
11279 * is supported, but should be used with extreme caution. Note that it
11280 * only supports to resize image files, it can't resize block devices
11281 * like LVM volumes.
11283 static int
11284 qemuDomainBlockResize(virDomainPtr dom,
11285 const char *path,
11286 unsigned long long size,
11287 unsigned int flags)
11289 virQEMUDriverPtr driver = dom->conn->privateData;
11290 virDomainObjPtr vm;
11291 qemuDomainObjPrivatePtr priv;
11292 int ret = -1;
11293 char *device = NULL;
11294 const char *nodename = NULL;
11295 virDomainDiskDefPtr disk = NULL;
11297 virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
11299 /* We prefer operating on bytes. */
11300 if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
11301 if (size > ULLONG_MAX / 1024) {
11302 virReportError(VIR_ERR_OVERFLOW,
11303 _("size must be less than %llu"),
11304 ULLONG_MAX / 1024);
11305 return -1;
11307 size *= 1024;
11310 if (!(vm = qemuDomObjFromDomain(dom)))
11311 goto cleanup;
11313 priv = vm->privateData;
11315 if (virDomainBlockResizeEnsureACL(dom->conn, vm->def) < 0)
11316 goto cleanup;
11318 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
11319 goto cleanup;
11321 if (virDomainObjCheckActive(vm) < 0)
11322 goto endjob;
11324 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
11325 virReportError(VIR_ERR_INVALID_ARG,
11326 _("disk '%s' was not found in the domain config"), path);
11327 goto endjob;
11330 /* qcow2 and qed must be sized on 512 byte blocks/sectors,
11331 * so adjust size if necessary to round up.
11333 if (disk->src->format == VIR_STORAGE_FILE_QCOW2 ||
11334 disk->src->format == VIR_STORAGE_FILE_QED)
11335 size = VIR_ROUND_UP(size, 512);
11337 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
11338 if (virStorageSourceIsEmpty(disk->src) || disk->src->readonly) {
11339 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
11340 _("can't resize empty or readonly disk '%s'"),
11341 disk->dst);
11342 goto endjob;
11345 nodename = disk->src->nodeformat;
11346 } else {
11347 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
11348 goto endjob;
11351 qemuDomainObjEnterMonitor(driver, vm);
11352 if (qemuMonitorBlockResize(priv->mon, device, nodename, size) < 0) {
11353 ignore_value(qemuDomainObjExitMonitor(driver, vm));
11354 goto endjob;
11356 if (qemuDomainObjExitMonitor(driver, vm) < 0)
11357 goto endjob;
11359 ret = 0;
11361 endjob:
11362 qemuDomainObjEndJob(driver, vm);
11364 cleanup:
11365 VIR_FREE(device);
11366 virDomainObjEndAPI(&vm);
11367 return ret;
11371 static int
11372 qemuDomainBlockStatsGatherTotals(qemuBlockStatsPtr data,
11373 qemuBlockStatsPtr total)
11375 #define QEMU_BLOCK_STAT_TOTAL(NAME) \
11376 if (data->NAME > 0) \
11377 total->NAME += data->NAME
11379 QEMU_BLOCK_STAT_TOTAL(wr_bytes);
11380 QEMU_BLOCK_STAT_TOTAL(wr_req);
11381 QEMU_BLOCK_STAT_TOTAL(rd_bytes);
11382 QEMU_BLOCK_STAT_TOTAL(rd_req);
11383 QEMU_BLOCK_STAT_TOTAL(flush_req);
11384 QEMU_BLOCK_STAT_TOTAL(wr_total_times);
11385 QEMU_BLOCK_STAT_TOTAL(rd_total_times);
11386 QEMU_BLOCK_STAT_TOTAL(flush_total_times);
11387 #undef QEMU_BLOCK_STAT_TOTAL
11388 return 0;
11393 * qemuDomainBlocksStatsGather:
11394 * @driver: driver object
11395 * @vm: domain object
11396 * @path: to gather the statistics for
11397 * @capacity: refresh capacity of the backing image
11398 * @retstats: returns pointer to structure holding the stats
11400 * Gathers the block statistics for use in qemuDomainBlockStats* APIs.
11402 * Returns -1 on error; number of filled block statistics on success.
11404 static int
11405 qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
11406 virDomainObjPtr vm,
11407 const char *path,
11408 bool capacity,
11409 qemuBlockStatsPtr *retstats)
11411 qemuDomainObjPrivatePtr priv = vm->privateData;
11412 bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
11413 virDomainDiskDefPtr disk = NULL;
11414 virHashTablePtr blockstats = NULL;
11415 qemuBlockStatsPtr stats;
11416 size_t i;
11417 int nstats;
11418 int rc = 0;
11419 const char *entryname = NULL;
11420 int ret = -1;
11422 if (*path) {
11423 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
11424 virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
11425 goto cleanup;
11428 if (blockdev) {
11429 entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
11430 } else {
11431 if (!disk->info.alias) {
11432 virReportError(VIR_ERR_INTERNAL_ERROR,
11433 _("missing disk device alias name for %s"), disk->dst);
11434 goto cleanup;
11437 entryname = disk->info.alias;
11441 qemuDomainObjEnterMonitor(driver, vm);
11442 nstats = qemuMonitorGetAllBlockStatsInfo(priv->mon, &blockstats, false);
11444 if (capacity && nstats >= 0) {
11445 if (blockdev)
11446 rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, blockstats);
11447 else
11448 rc = qemuMonitorBlockStatsUpdateCapacity(priv->mon, blockstats, false);
11451 if (qemuDomainObjExitMonitor(driver, vm) < 0 || nstats < 0 || rc < 0)
11452 goto cleanup;
11454 if (VIR_ALLOC(*retstats) < 0)
11455 goto cleanup;
11457 if (entryname) {
11458 if (!(stats = virHashLookup(blockstats, entryname))) {
11459 virReportError(VIR_ERR_INTERNAL_ERROR,
11460 _("cannot find statistics for device '%s'"), entryname);
11461 goto cleanup;
11464 **retstats = *stats;
11466 if (blockdev) {
11467 /* capacity are reported only per node-name so we need to transfer them */
11468 qemuBlockStatsPtr capstats;
11470 if (disk && disk->src &&
11471 (capstats = virHashLookup(blockstats, disk->src->nodeformat))) {
11472 (*retstats)->capacity = capstats->capacity;
11473 (*retstats)->physical = capstats->physical;
11474 (*retstats)->wr_highest_offset = capstats->wr_highest_offset;
11475 (*retstats)->wr_highest_offset_valid = capstats->wr_highest_offset_valid;
11476 (*retstats)->write_threshold = capstats->write_threshold;
11479 } else {
11480 for (i = 0; i < vm->def->ndisks; i++) {
11481 disk = vm->def->disks[i];
11482 entryname = disk->info.alias;
11484 if (blockdev)
11485 entryname = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
11487 if (!entryname)
11488 continue;
11490 if (!(stats = virHashLookup(blockstats, entryname))) {
11491 virReportError(VIR_ERR_INTERNAL_ERROR,
11492 _("cannot find statistics for device '%s'"), entryname);
11493 goto cleanup;
11496 qemuDomainBlockStatsGatherTotals(stats, *retstats);
11500 ret = nstats;
11502 cleanup:
11503 virHashFree(blockstats);
11504 return ret;
11508 /* This uses the 'info blockstats' monitor command which was
11509 * integrated into both qemu & kvm in late 2007. If the command is
11510 * not supported we detect this and return the appropriate error.
11512 static int
11513 qemuDomainBlockStats(virDomainPtr dom,
11514 const char *path,
11515 virDomainBlockStatsPtr stats)
11517 virQEMUDriverPtr driver = dom->conn->privateData;
11518 qemuBlockStatsPtr blockstats = NULL;
11519 int ret = -1;
11520 virDomainObjPtr vm;
11522 if (!(vm = qemuDomObjFromDomain(dom)))
11523 goto cleanup;
11525 if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
11526 goto cleanup;
11528 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
11529 goto cleanup;
11531 if (virDomainObjCheckActive(vm) < 0)
11532 goto endjob;
11534 if (qemuDomainBlocksStatsGather(driver, vm, path, false, &blockstats) < 0)
11535 goto endjob;
11537 stats->rd_req = blockstats->rd_req;
11538 stats->rd_bytes = blockstats->rd_bytes;
11539 stats->wr_req = blockstats->wr_req;
11540 stats->wr_bytes = blockstats->wr_bytes;
11541 /* qemu doesn't report the error count */
11542 stats->errs = -1;
11544 ret = 0;
11546 endjob:
11547 qemuDomainObjEndJob(driver, vm);
11549 cleanup:
11550 virDomainObjEndAPI(&vm);
11551 VIR_FREE(blockstats);
11552 return ret;
11556 static int
11557 qemuDomainBlockStatsFlags(virDomainPtr dom,
11558 const char *path,
11559 virTypedParameterPtr params,
11560 int *nparams,
11561 unsigned int flags)
11563 virQEMUDriverPtr driver = dom->conn->privateData;
11564 virDomainObjPtr vm;
11565 qemuBlockStatsPtr blockstats = NULL;
11566 int nstats;
11567 int ret = -1;
11569 VIR_DEBUG("params=%p, flags=0x%x", params, flags);
11571 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
11573 /* We don't return strings, and thus trivially support this flag. */
11574 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
11576 if (!(vm = qemuDomObjFromDomain(dom)))
11577 goto cleanup;
11579 if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
11580 goto cleanup;
11582 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
11583 goto cleanup;
11585 if (virDomainObjCheckActive(vm) < 0)
11586 goto endjob;
11588 if ((nstats = qemuDomainBlocksStatsGather(driver, vm, path, false,
11589 &blockstats)) < 0)
11590 goto endjob;
11592 /* return count of supported stats */
11593 if (*nparams == 0) {
11594 *nparams = nstats;
11595 ret = 0;
11596 goto endjob;
11599 nstats = 0;
11601 #define QEMU_BLOCK_STATS_ASSIGN_PARAM(VAR, NAME) \
11602 if (nstats < *nparams && (blockstats->VAR) != -1) { \
11603 if (virTypedParameterAssign(params + nstats, NAME, \
11604 VIR_TYPED_PARAM_LLONG, (blockstats->VAR)) < 0) \
11605 goto endjob; \
11606 nstats++; \
11609 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
11610 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);
11612 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
11613 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ);
11615 QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_req, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);
11617 QEMU_BLOCK_STATS_ASSIGN_PARAM(wr_total_times,
11618 VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES);
11619 QEMU_BLOCK_STATS_ASSIGN_PARAM(rd_total_times,
11620 VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES);
11621 QEMU_BLOCK_STATS_ASSIGN_PARAM(flush_total_times,
11622 VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES);
11623 #undef QEMU_BLOCK_STATS_ASSIGN_PARAM
11625 ret = 0;
11626 *nparams = nstats;
11628 endjob:
11629 qemuDomainObjEndJob(driver, vm);
11631 cleanup:
11632 VIR_FREE(blockstats);
11633 virDomainObjEndAPI(&vm);
11634 return ret;
11637 static int
11638 qemuDomainInterfaceStats(virDomainPtr dom,
11639 const char *device,
11640 virDomainInterfaceStatsPtr stats)
11642 virDomainObjPtr vm;
11643 virDomainNetDefPtr net = NULL;
11644 int ret = -1;
11646 if (!(vm = qemuDomObjFromDomain(dom)))
11647 goto cleanup;
11649 if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0)
11650 goto cleanup;
11652 if (virDomainObjCheckActive(vm) < 0)
11653 goto cleanup;
11655 if (!(net = virDomainNetFind(vm->def, device)))
11656 goto cleanup;
11658 if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
11659 if (virNetDevOpenvswitchInterfaceStats(net->ifname, stats) < 0)
11660 goto cleanup;
11661 } else {
11662 if (virNetDevTapInterfaceStats(net->ifname, stats,
11663 !virDomainNetTypeSharesHostView(net)) < 0)
11664 goto cleanup;
11667 ret = 0;
11668 cleanup:
11669 virDomainObjEndAPI(&vm);
11670 return ret;
11673 static int
11674 qemuDomainSetInterfaceParameters(virDomainPtr dom,
11675 const char *device,
11676 virTypedParameterPtr params,
11677 int nparams,
11678 unsigned int flags)
11680 virQEMUDriverPtr driver = dom->conn->privateData;
11681 size_t i;
11682 virDomainObjPtr vm = NULL;
11683 virDomainDefPtr def;
11684 virDomainDefPtr persistentDef;
11685 int ret = -1;
11686 virDomainNetDefPtr net = NULL, persistentNet = NULL;
11687 virNetDevBandwidthPtr bandwidth = NULL, newBandwidth = NULL;
11688 virQEMUDriverConfigPtr cfg = NULL;
11689 bool inboundSpecified = false, outboundSpecified = false;
11690 int actualType;
11691 bool qosSupported = true;
11693 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11694 VIR_DOMAIN_AFFECT_CONFIG, -1);
11695 if (virTypedParamsValidate(params, nparams,
11696 VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
11697 VIR_TYPED_PARAM_UINT,
11698 VIR_DOMAIN_BANDWIDTH_IN_PEAK,
11699 VIR_TYPED_PARAM_UINT,
11700 VIR_DOMAIN_BANDWIDTH_IN_BURST,
11701 VIR_TYPED_PARAM_UINT,
11702 VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
11703 VIR_TYPED_PARAM_UINT,
11704 VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
11705 VIR_TYPED_PARAM_UINT,
11706 VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
11707 VIR_TYPED_PARAM_UINT,
11708 VIR_DOMAIN_BANDWIDTH_OUT_BURST,
11709 VIR_TYPED_PARAM_UINT,
11710 NULL) < 0)
11711 return -1;
11713 if (!(vm = qemuDomObjFromDomain(dom)))
11714 return -1;
11716 cfg = virQEMUDriverGetConfig(driver);
11718 if (virDomainSetInterfaceParametersEnsureACL(dom->conn, vm->def, flags) < 0)
11719 goto cleanup;
11721 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
11722 goto cleanup;
11724 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
11725 goto endjob;
11727 if (def &&
11728 !(net = virDomainNetFind(vm->def, device)))
11729 goto endjob;
11731 if (persistentDef &&
11732 !(persistentNet = virDomainNetFind(persistentDef, device)))
11733 goto endjob;
11735 if (net) {
11736 actualType = virDomainNetGetActualType(net);
11737 qosSupported = virNetDevSupportBandwidth(actualType);
11740 if (qosSupported && persistentNet) {
11741 actualType = virDomainNetGetActualType(persistentNet);
11742 qosSupported = virNetDevSupportBandwidth(actualType);
11745 if (!qosSupported) {
11746 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11747 _("setting bandwidth on interfaces of "
11748 "type '%s' is not implemented yet"),
11749 virDomainNetTypeToString(actualType));
11750 goto endjob;
11753 if ((VIR_ALLOC(bandwidth) < 0) ||
11754 (VIR_ALLOC(bandwidth->in) < 0) ||
11755 (VIR_ALLOC(bandwidth->out) < 0))
11756 goto endjob;
11758 for (i = 0; i < nparams; i++) {
11759 virTypedParameterPtr param = &params[i];
11761 if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE)) {
11762 bandwidth->in->average = param->value.ui;
11763 inboundSpecified = true;
11764 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_PEAK)) {
11765 bandwidth->in->peak = param->value.ui;
11766 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_BURST)) {
11767 bandwidth->in->burst = param->value.ui;
11768 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_IN_FLOOR)) {
11769 bandwidth->in->floor = param->value.ui;
11770 inboundSpecified = true;
11771 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE)) {
11772 bandwidth->out->average = param->value.ui;
11773 outboundSpecified = true;
11774 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK)) {
11775 bandwidth->out->peak = param->value.ui;
11776 } else if (STREQ(param->field, VIR_DOMAIN_BANDWIDTH_OUT_BURST)) {
11777 bandwidth->out->burst = param->value.ui;
11781 /* average or floor are mandatory, peak and burst are optional.
11782 * So if no average or floor is given, we free inbound/outbound
11783 * here which causes inbound/outbound to not be set. */
11784 if (!bandwidth->in->average && !bandwidth->in->floor)
11785 VIR_FREE(bandwidth->in);
11786 if (!bandwidth->out->average)
11787 VIR_FREE(bandwidth->out);
11789 if (net) {
11790 if (VIR_ALLOC(newBandwidth) < 0)
11791 goto endjob;
11793 /* virNetDevBandwidthSet() will clear any previous value of
11794 * bandwidth parameters, so merge with old bandwidth parameters
11795 * here to prevent them from being lost. */
11796 if (bandwidth->in ||
11797 (!inboundSpecified && net->bandwidth && net->bandwidth->in)) {
11798 if (VIR_ALLOC(newBandwidth->in) < 0)
11799 goto endjob;
11801 memcpy(newBandwidth->in,
11802 bandwidth->in ? bandwidth->in : net->bandwidth->in,
11803 sizeof(*newBandwidth->in));
11805 if (bandwidth->out ||
11806 (!outboundSpecified && net->bandwidth && net->bandwidth->out)) {
11807 if (VIR_ALLOC(newBandwidth->out) < 0)
11808 goto endjob;
11810 memcpy(newBandwidth->out,
11811 bandwidth->out ? bandwidth->out : net->bandwidth->out,
11812 sizeof(*newBandwidth->out));
11815 if (!virDomainNetBandwidthChangeAllowed(net, newBandwidth))
11816 goto endjob;
11818 if (virNetDevBandwidthSet(net->ifname, newBandwidth, false,
11819 !virDomainNetTypeSharesHostView(net)) < 0 ||
11820 virDomainNetBandwidthUpdate(net, newBandwidth) < 0) {
11821 ignore_value(virNetDevBandwidthSet(net->ifname,
11822 net->bandwidth,
11823 false,
11824 !virDomainNetTypeSharesHostView(net)));
11825 goto endjob;
11828 virNetDevBandwidthFree(net->bandwidth);
11829 if (newBandwidth->in || newBandwidth->out) {
11830 net->bandwidth = newBandwidth;
11831 newBandwidth = NULL;
11832 } else {
11833 net->bandwidth = NULL;
11836 if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
11837 virNetDevBandwidthFree(net->data.network.actual->bandwidth);
11838 if (virNetDevBandwidthCopy(&net->data.network.actual->bandwidth,
11839 net->bandwidth) < 0)
11840 goto endjob;
11843 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
11844 goto endjob;
11847 if (persistentNet) {
11848 if (!persistentNet->bandwidth) {
11849 persistentNet->bandwidth = bandwidth;
11850 bandwidth = NULL;
11851 } else {
11852 if (bandwidth->in) {
11853 VIR_FREE(persistentNet->bandwidth->in);
11854 persistentNet->bandwidth->in = bandwidth->in;
11855 bandwidth->in = NULL;
11856 } else if (inboundSpecified) {
11857 VIR_FREE(persistentNet->bandwidth->in);
11859 if (bandwidth->out) {
11860 VIR_FREE(persistentNet->bandwidth->out);
11861 persistentNet->bandwidth->out = bandwidth->out;
11862 bandwidth->out = NULL;
11863 } else if (outboundSpecified) {
11864 VIR_FREE(persistentNet->bandwidth->out);
11868 if (virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef) < 0)
11869 goto endjob;
11872 ret = 0;
11874 endjob:
11875 qemuDomainObjEndJob(driver, vm);
11877 cleanup:
11878 virNetDevBandwidthFree(bandwidth);
11879 virNetDevBandwidthFree(newBandwidth);
11880 virDomainObjEndAPI(&vm);
11881 virObjectUnref(cfg);
11882 return ret;
11885 static int
11886 qemuDomainGetInterfaceParameters(virDomainPtr dom,
11887 const char *device,
11888 virTypedParameterPtr params,
11889 int *nparams,
11890 unsigned int flags)
11892 size_t i;
11893 virDomainObjPtr vm = NULL;
11894 virDomainDefPtr def = NULL;
11895 virDomainNetDefPtr net = NULL;
11896 int ret = -1;
11898 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
11899 VIR_DOMAIN_AFFECT_CONFIG |
11900 VIR_TYPED_PARAM_STRING_OKAY, -1);
11902 if (!(vm = qemuDomObjFromDomain(dom)))
11903 return -1;
11905 if (virDomainGetInterfaceParametersEnsureACL(dom->conn, vm->def) < 0)
11906 goto cleanup;
11908 if (!(def = virDomainObjGetOneDef(vm, flags)))
11909 goto cleanup;
11911 if ((*nparams) == 0) {
11912 *nparams = QEMU_NB_BANDWIDTH_PARAM;
11913 ret = 0;
11914 goto cleanup;
11917 if (!(net = virDomainNetFind(def, device)))
11918 goto cleanup;
11920 for (i = 0; i < *nparams && i < QEMU_NB_BANDWIDTH_PARAM; i++) {
11921 switch (i) {
11922 case 0: /* inbound.average */
11923 if (virTypedParameterAssign(&params[i],
11924 VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
11925 VIR_TYPED_PARAM_UINT, 0) < 0)
11926 goto cleanup;
11927 if (net->bandwidth && net->bandwidth->in)
11928 params[i].value.ui = net->bandwidth->in->average;
11929 break;
11930 case 1: /* inbound.peak */
11931 if (virTypedParameterAssign(&params[i],
11932 VIR_DOMAIN_BANDWIDTH_IN_PEAK,
11933 VIR_TYPED_PARAM_UINT, 0) < 0)
11934 goto cleanup;
11935 if (net->bandwidth && net->bandwidth->in)
11936 params[i].value.ui = net->bandwidth->in->peak;
11937 break;
11938 case 2: /* inbound.burst */
11939 if (virTypedParameterAssign(&params[i],
11940 VIR_DOMAIN_BANDWIDTH_IN_BURST,
11941 VIR_TYPED_PARAM_UINT, 0) < 0)
11942 goto cleanup;
11943 if (net->bandwidth && net->bandwidth->in)
11944 params[i].value.ui = net->bandwidth->in->burst;
11945 break;
11946 case 3: /* inbound.floor */
11947 if (virTypedParameterAssign(&params[i],
11948 VIR_DOMAIN_BANDWIDTH_IN_FLOOR,
11949 VIR_TYPED_PARAM_UINT, 0) < 0)
11950 goto cleanup;
11951 if (net->bandwidth && net->bandwidth->in)
11952 params[i].value.ui = net->bandwidth->in->floor;
11953 break;
11954 case 4: /* outbound.average */
11955 if (virTypedParameterAssign(&params[i],
11956 VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
11957 VIR_TYPED_PARAM_UINT, 0) < 0)
11958 goto cleanup;
11959 if (net->bandwidth && net->bandwidth->out)
11960 params[i].value.ui = net->bandwidth->out->average;
11961 break;
11962 case 5: /* outbound.peak */
11963 if (virTypedParameterAssign(&params[i],
11964 VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
11965 VIR_TYPED_PARAM_UINT, 0) < 0)
11966 goto cleanup;
11967 if (net->bandwidth && net->bandwidth->out)
11968 params[i].value.ui = net->bandwidth->out->peak;
11969 break;
11970 case 6: /* outbound.burst */
11971 if (virTypedParameterAssign(&params[i],
11972 VIR_DOMAIN_BANDWIDTH_OUT_BURST,
11973 VIR_TYPED_PARAM_UINT, 0) < 0)
11974 goto cleanup;
11975 if (net->bandwidth && net->bandwidth->out)
11976 params[i].value.ui = net->bandwidth->out->burst;
11977 break;
11978 /* coverity[dead_error_begin] */
11979 default:
11980 break;
11981 /* should not hit here */
11985 if (*nparams > QEMU_NB_BANDWIDTH_PARAM)
11986 *nparams = QEMU_NB_BANDWIDTH_PARAM;
11987 ret = 0;
11989 cleanup:
11990 virDomainObjEndAPI(&vm);
11991 return ret;
11994 /* This functions assumes that job QEMU_JOB_QUERY is started by a caller */
11995 static int
11996 qemuDomainMemoryStatsInternal(virQEMUDriverPtr driver,
11997 virDomainObjPtr vm,
11998 virDomainMemoryStatPtr stats,
11999 unsigned int nr_stats)
12002 int ret = -1;
12003 long rss;
12005 if (virDomainObjCheckActive(vm) < 0)
12006 return -1;
12008 if (virDomainDefHasMemballoon(vm->def)) {
12009 qemuDomainObjEnterMonitor(driver, vm);
12010 ret = qemuMonitorGetMemoryStats(qemuDomainGetMonitor(vm),
12011 vm->def->memballoon, stats, nr_stats);
12012 if (qemuDomainObjExitMonitor(driver, vm) < 0)
12013 ret = -1;
12015 if (ret < 0 || ret >= nr_stats)
12016 return ret;
12017 } else {
12018 ret = 0;
12021 if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) {
12022 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
12023 _("cannot get RSS for domain"));
12024 } else {
12025 stats[ret].tag = VIR_DOMAIN_MEMORY_STAT_RSS;
12026 stats[ret].val = rss;
12027 ret++;
12030 return ret;
12033 static int
12034 qemuDomainMemoryStats(virDomainPtr dom,
12035 virDomainMemoryStatPtr stats,
12036 unsigned int nr_stats,
12037 unsigned int flags)
12039 virQEMUDriverPtr driver = dom->conn->privateData;
12040 virDomainObjPtr vm;
12041 int ret = -1;
12043 virCheckFlags(0, -1);
12045 if (!(vm = qemuDomObjFromDomain(dom)))
12046 goto cleanup;
12048 if (virDomainMemoryStatsEnsureACL(dom->conn, vm->def) < 0)
12049 goto cleanup;
12051 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12052 goto cleanup;
12054 ret = qemuDomainMemoryStatsInternal(driver, vm, stats, nr_stats);
12056 qemuDomainObjEndJob(driver, vm);
12058 cleanup:
12059 virDomainObjEndAPI(&vm);
12060 return ret;
12063 static int
12064 qemuDomainBlockPeek(virDomainPtr dom,
12065 const char *path,
12066 unsigned long long offset, size_t size,
12067 void *buffer,
12068 unsigned int flags)
12070 virQEMUDriverPtr driver = dom->conn->privateData;
12071 virDomainDiskDefPtr disk = NULL;
12072 virDomainObjPtr vm;
12073 char *tmpbuf = NULL;
12074 ssize_t nread;
12075 int ret = -1;
12077 virCheckFlags(0, -1);
12079 if (!(vm = qemuDomObjFromDomain(dom)))
12080 goto cleanup;
12082 if (virDomainBlockPeekEnsureACL(dom->conn, vm->def) < 0)
12083 goto cleanup;
12085 /* Check the path belongs to this domain. */
12086 if (!(disk = virDomainDiskByName(vm->def, path, true))) {
12087 virReportError(VIR_ERR_INVALID_ARG,
12088 _("invalid disk or path '%s'"), path);
12089 goto cleanup;
12092 if (disk->src->format != VIR_STORAGE_FILE_RAW) {
12093 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
12094 _("peeking is only supported for disk with 'raw' format not '%s'"),
12095 virStorageFileFormatTypeToString(disk->src->format));
12096 goto cleanup;
12099 if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) < 0)
12100 goto cleanup;
12102 if ((nread = virStorageFileRead(disk->src, offset, size, &tmpbuf)) < 0) {
12103 if (nread == -2) {
12104 virReportError(VIR_ERR_INTERNAL_ERROR,
12105 _("storage file reading is not supported for "
12106 "storage type %s (protocol: %s)"),
12107 virStorageTypeToString(disk->src->type),
12108 virStorageNetProtocolTypeToString(disk->src->protocol));
12110 goto cleanup;
12113 if (nread < size) {
12114 virReportError(VIR_ERR_INVALID_ARG,
12115 _("'%s' starting from %llu has only %zd bytes available"),
12116 path, offset, nread);
12117 goto cleanup;
12120 memcpy(buffer, tmpbuf, size);
12122 ret = 0;
12124 cleanup:
12125 if (disk)
12126 virStorageFileDeinit(disk->src);
12127 virDomainObjEndAPI(&vm);
12128 VIR_FREE(tmpbuf);
12129 return ret;
12132 static int
12133 qemuDomainMemoryPeek(virDomainPtr dom,
12134 unsigned long long offset, size_t size,
12135 void *buffer,
12136 unsigned int flags)
12138 virQEMUDriverPtr driver = dom->conn->privateData;
12139 virDomainObjPtr vm;
12140 char *tmp = NULL;
12141 int fd = -1, ret = -1;
12142 qemuDomainObjPrivatePtr priv;
12143 virQEMUDriverConfigPtr cfg = NULL;
12145 virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);
12147 if (!(vm = qemuDomObjFromDomain(dom)))
12148 goto cleanup;
12150 cfg = virQEMUDriverGetConfig(driver);
12152 if (virDomainMemoryPeekEnsureACL(dom->conn, vm->def) < 0)
12153 goto cleanup;
12155 if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) {
12156 virReportError(VIR_ERR_INVALID_ARG,
12157 "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL"));
12158 goto cleanup;
12161 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12162 goto cleanup;
12164 if (virDomainObjCheckActive(vm) < 0)
12165 goto endjob;
12167 if (virAsprintf(&tmp, "%s/qemu.mem.XXXXXX", cfg->cacheDir) < 0)
12168 goto endjob;
12170 /* Create a temporary filename. */
12171 if ((fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
12172 virReportSystemError(errno,
12173 _("mkostemp(\"%s\") failed"), tmp);
12174 goto endjob;
12177 qemuSecuritySetSavedStateLabel(driver, vm, tmp);
12179 priv = vm->privateData;
12180 qemuDomainObjEnterMonitor(driver, vm);
12181 if (flags == VIR_MEMORY_VIRTUAL) {
12182 if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
12183 ignore_value(qemuDomainObjExitMonitor(driver, vm));
12184 goto endjob;
12186 } else {
12187 if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
12188 ignore_value(qemuDomainObjExitMonitor(driver, vm));
12189 goto endjob;
12192 if (qemuDomainObjExitMonitor(driver, vm) < 0)
12193 goto endjob;
12195 /* Read the memory file into buffer. */
12196 if (saferead(fd, buffer, size) == (ssize_t)-1) {
12197 virReportSystemError(errno,
12198 _("failed to read temporary file "
12199 "created with template %s"), tmp);
12200 goto endjob;
12203 ret = 0;
12205 endjob:
12206 qemuDomainObjEndJob(driver, vm);
12208 cleanup:
12209 VIR_FORCE_CLOSE(fd);
12210 if (tmp)
12211 unlink(tmp);
12212 VIR_FREE(tmp);
12213 virDomainObjEndAPI(&vm);
12214 virObjectUnref(cfg);
12215 return ret;
12220 * @driver: qemu driver data
12221 * @cfg: driver configuration data
12222 * @vm: domain object
12223 * @src: storage source data
12224 * @ret_fd: pointer to return open'd file descriptor
12225 * @ret_sb: pointer to return stat buffer (local or remote)
12227 * For local storage, open the file using qemuOpenFile and then use
12228 * fstat() to grab the stat struct data for the caller.
12230 * For remote storage, attempt to access the file and grab the stat
12231 * struct data if the remote connection supports it.
12233 * Returns 0 on success with @ret_fd and @ret_sb populated, -1 on failure
12235 static int
12236 qemuDomainStorageOpenStat(virQEMUDriverPtr driver,
12237 virQEMUDriverConfigPtr cfg,
12238 virDomainObjPtr vm,
12239 virStorageSourcePtr src,
12240 int *ret_fd,
12241 struct stat *ret_sb)
12243 if (virStorageSourceIsLocalStorage(src)) {
12244 if ((*ret_fd = qemuOpenFile(driver, vm, src->path, O_RDONLY,
12245 NULL)) < 0)
12246 return -1;
12248 if (fstat(*ret_fd, ret_sb) < 0) {
12249 virReportSystemError(errno, _("cannot stat file '%s'"), src->path);
12250 VIR_FORCE_CLOSE(*ret_fd);
12251 return -1;
12253 } else {
12254 if (virStorageFileInitAs(src, cfg->user, cfg->group) < 0)
12255 return -1;
12257 if (virStorageFileStat(src, ret_sb) < 0) {
12258 virStorageFileDeinit(src);
12259 virReportSystemError(errno, _("failed to stat remote file '%s'"),
12260 NULLSTR(src->path));
12261 return -1;
12265 return 0;
12270 * @src: storage source data
12271 * @fd: file descriptor to close for local
12273 * If local, then just close the file descriptor.
12274 * else remote, then tear down the storage driver backend connection.
12276 static void
12277 qemuDomainStorageCloseStat(virStorageSourcePtr src,
12278 int *fd)
12280 if (virStorageSourceIsLocalStorage(src))
12281 VIR_FORCE_CLOSE(*fd);
12282 else
12283 virStorageFileDeinit(src);
12287 static int
12288 qemuDomainStorageUpdatePhysical(virQEMUDriverPtr driver,
12289 virQEMUDriverConfigPtr cfg,
12290 virDomainObjPtr vm,
12291 virStorageSourcePtr src)
12293 int ret;
12294 int fd = -1;
12295 struct stat sb;
12297 if (virStorageSourceIsEmpty(src))
12298 return 0;
12300 if (qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb) < 0)
12301 return -1;
12303 ret = virStorageSourceUpdatePhysicalSize(src, fd, &sb);
12305 qemuDomainStorageCloseStat(src, &fd);
12307 return ret;
12312 * @driver: qemu driver data
12313 * @cfg: driver configuration data
12314 * @vm: domain object
12315 * @src: storage source data
12317 * Refresh the capacity and allocation limits of a given storage source.
12319 * Assumes that the caller has already obtained a domain job and only
12320 * called for an offline domain. Being offline is particularly important
12321 * since reading a file while qemu is writing it risks the reader seeing
12322 * bogus data or avoiding opening a file in order to get stat data.
12324 * We always want to check current on-disk statistics (as users have been
12325 * known to change offline images behind our backs).
12327 * For read-only disks, nothing should be changing unless the user has
12328 * requested a block-commit action. For read-write disks, we know some
12329 * special cases: capacity should not change without a block-resize (where
12330 * capacity is the only stat that requires reading a file, and even then,
12331 * only for non-raw files); and physical size of a raw image or of a
12332 * block device should likewise not be changing without block-resize.
12333 * On the other hand, allocation of a raw file can change (if the file
12334 * is sparse, but the amount of sparseness changes due to writes or
12335 * punching holes), and physical size of a non-raw file can change.
12337 * Returns 0 on success, -1 on failure
12339 static int
12340 qemuStorageLimitsRefresh(virQEMUDriverPtr driver,
12341 virQEMUDriverConfigPtr cfg,
12342 virDomainObjPtr vm,
12343 virStorageSourcePtr src)
12345 int ret = -1;
12346 int fd = -1;
12347 struct stat sb;
12348 char *buf = NULL;
12349 ssize_t len;
12351 if (qemuDomainStorageOpenStat(driver, cfg, vm, src, &fd, &sb) < 0)
12352 goto cleanup;
12354 if (virStorageSourceIsLocalStorage(src)) {
12355 if ((len = virFileReadHeaderFD(fd, VIR_STORAGE_MAX_HEADER, &buf)) < 0) {
12356 virReportSystemError(errno, _("cannot read header '%s'"),
12357 src->path);
12358 goto cleanup;
12360 } else {
12361 if ((len = virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, &buf)) < 0)
12362 goto cleanup;
12365 if (virStorageSourceUpdateBackingSizes(src, fd, &sb) < 0)
12366 goto cleanup;
12368 if (virStorageSourceUpdateCapacity(src, buf, len, false) < 0)
12369 goto cleanup;
12371 /* If guest is not using raw disk format and is on a host block
12372 * device, then leave the value unspecified, so caller knows to
12373 * query the highest allocated extent from QEMU
12375 if (virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK &&
12376 src->format != VIR_STORAGE_FILE_RAW &&
12377 S_ISBLK(sb.st_mode))
12378 src->allocation = 0;
12380 ret = 0;
12382 cleanup:
12383 VIR_FREE(buf);
12384 qemuDomainStorageCloseStat(src, &fd);
12385 return ret;
12389 static int
12390 qemuDomainGetBlockInfo(virDomainPtr dom,
12391 const char *path,
12392 virDomainBlockInfoPtr info,
12393 unsigned int flags)
12395 virQEMUDriverPtr driver = dom->conn->privateData;
12396 virDomainObjPtr vm;
12397 int ret = -1;
12398 virDomainDiskDefPtr disk;
12399 virQEMUDriverConfigPtr cfg = NULL;
12400 qemuBlockStatsPtr entry = NULL;
12402 virCheckFlags(0, -1);
12404 if (!(vm = qemuDomObjFromDomain(dom)))
12405 return -1;
12407 cfg = virQEMUDriverGetConfig(driver);
12409 if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0)
12410 goto cleanup;
12412 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
12413 goto cleanup;
12415 if (!(disk = virDomainDiskByName(vm->def, path, false))) {
12416 virReportError(VIR_ERR_INVALID_ARG,
12417 _("invalid path %s not assigned to domain"), path);
12418 goto endjob;
12421 if (virStorageSourceIsEmpty(disk->src)) {
12422 virReportError(VIR_ERR_INVALID_ARG,
12423 _("disk '%s' does not currently have a source assigned"),
12424 path);
12425 goto endjob;
12428 /* for inactive domains we have to peek into the files */
12429 if (!virDomainObjIsActive(vm)) {
12430 if ((qemuStorageLimitsRefresh(driver, cfg, vm, disk->src)) < 0)
12431 goto endjob;
12433 info->capacity = disk->src->capacity;
12434 info->allocation = disk->src->allocation;
12435 info->physical = disk->src->physical;
12437 ret = 0;
12438 goto endjob;
12441 if (qemuDomainBlocksStatsGather(driver, vm, path, true, &entry) < 0)
12442 goto endjob;
12444 if (!entry->wr_highest_offset_valid) {
12445 info->allocation = entry->physical;
12446 } else {
12447 if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_FILE &&
12448 disk->src->format == VIR_STORAGE_FILE_QCOW2)
12449 info->allocation = entry->physical;
12450 else
12451 info->allocation = entry->wr_highest_offset;
12454 /* Unlike GetStatsBlock, this API has defined the expected return values
12455 * for allocation and physical slightly differently.
12457 * Having a zero for either or if they're the same is an indication that
12458 * there's a sparse file backing this device. In this case, we'll force
12459 * the setting of physical based on the on disk file size.
12461 * Additionally, if qemu hasn't written to the file yet, then set the
12462 * allocation to whatever qemu returned for physical (e.g. the "actual-
12463 * size" from the json query) as that will match the expected allocation
12464 * value for this API. NB: May still be 0 for block. */
12465 if (entry->physical == 0 || info->allocation == 0 ||
12466 info->allocation == entry->physical) {
12467 if (info->allocation == 0)
12468 info->allocation = entry->physical;
12470 if (qemuDomainStorageUpdatePhysical(driver, cfg, vm, disk->src) == 0) {
12471 info->physical = disk->src->physical;
12472 } else {
12473 virResetLastError();
12474 info->physical = entry->physical;
12476 } else {
12477 info->physical = entry->physical;
12480 info->capacity = entry->capacity;
12482 ret = 0;
12484 endjob:
12485 qemuDomainObjEndJob(driver, vm);
12486 cleanup:
12487 VIR_FREE(entry);
12488 virDomainObjEndAPI(&vm);
12489 virObjectUnref(cfg);
12490 return ret;
12494 static int
12495 qemuConnectDomainEventRegister(virConnectPtr conn,
12496 virConnectDomainEventCallback callback,
12497 void *opaque,
12498 virFreeCallback freecb)
12500 virQEMUDriverPtr driver = conn->privateData;
12501 int ret = -1;
12503 if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
12504 goto cleanup;
12506 if (virDomainEventStateRegister(conn,
12507 driver->domainEventState,
12508 callback, opaque, freecb) < 0)
12509 goto cleanup;
12511 ret = 0;
12513 cleanup:
12514 return ret;
12518 static int
12519 qemuConnectDomainEventDeregister(virConnectPtr conn,
12520 virConnectDomainEventCallback callback)
12522 virQEMUDriverPtr driver = conn->privateData;
12523 int ret = -1;
12525 if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
12526 goto cleanup;
12528 if (virDomainEventStateDeregister(conn,
12529 driver->domainEventState,
12530 callback) < 0)
12531 goto cleanup;
12533 ret = 0;
12535 cleanup:
12536 return ret;
12540 static int
12541 qemuConnectDomainEventRegisterAny(virConnectPtr conn,
12542 virDomainPtr dom,
12543 int eventID,
12544 virConnectDomainEventGenericCallback callback,
12545 void *opaque,
12546 virFreeCallback freecb)
12548 virQEMUDriverPtr driver = conn->privateData;
12549 int ret = -1;
12551 if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
12552 goto cleanup;
12554 if (virDomainEventStateRegisterID(conn,
12555 driver->domainEventState,
12556 dom, eventID,
12557 callback, opaque, freecb, &ret) < 0)
12558 ret = -1;
12560 cleanup:
12561 return ret;
12565 static int
12566 qemuConnectDomainEventDeregisterAny(virConnectPtr conn,
12567 int callbackID)
12569 virQEMUDriverPtr driver = conn->privateData;
12570 int ret = -1;
12572 if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
12573 goto cleanup;
12575 if (virObjectEventStateDeregisterID(conn,
12576 driver->domainEventState,
12577 callbackID, true) < 0)
12578 goto cleanup;
12580 ret = 0;
12582 cleanup:
12583 return ret;
12587 /*******************************************************************
12588 * Migration Protocol Version 2
12589 *******************************************************************/
12591 /* Prepare is the first step, and it runs on the destination host.
12593 * This version starts an empty VM listening on a localhost TCP port, and
12594 * sets up the corresponding virStream to handle the incoming data.
12596 static int
12597 qemuDomainMigratePrepareTunnel(virConnectPtr dconn,
12598 virStreamPtr st,
12599 unsigned long flags,
12600 const char *dname,
12601 unsigned long resource ATTRIBUTE_UNUSED,
12602 const char *dom_xml)
12604 virQEMUDriverPtr driver = dconn->privateData;
12605 virDomainDefPtr def = NULL;
12606 char *origname = NULL;
12607 qemuMigrationParamsPtr migParams = NULL;
12608 int ret = -1;
12610 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12612 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
12613 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12614 _("PrepareTunnel called but no TUNNELLED flag set"));
12615 goto cleanup;
12618 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12619 QEMU_MIGRATION_DESTINATION)))
12620 goto cleanup;
12622 if (virLockManagerPluginUsesState(driver->lockManager)) {
12623 virReportError(VIR_ERR_INTERNAL_ERROR,
12624 _("Cannot use migrate v2 protocol with lock manager %s"),
12625 virLockManagerPluginGetName(driver->lockManager));
12626 goto cleanup;
12629 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
12630 goto cleanup;
12632 if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0)
12633 goto cleanup;
12635 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
12636 NULL, 0, NULL, NULL, /* No cookies in v2 */
12637 st, &def, origname, migParams, flags);
12639 cleanup:
12640 qemuMigrationParamsFree(migParams);
12641 VIR_FREE(origname);
12642 virDomainDefFree(def);
12643 return ret;
12646 /* Prepare is the first step, and it runs on the destination host.
12648 * This starts an empty VM listening on a TCP port.
12650 static int ATTRIBUTE_NONNULL(5)
12651 qemuDomainMigratePrepare2(virConnectPtr dconn,
12652 char **cookie ATTRIBUTE_UNUSED,
12653 int *cookielen ATTRIBUTE_UNUSED,
12654 const char *uri_in,
12655 char **uri_out,
12656 unsigned long flags,
12657 const char *dname,
12658 unsigned long resource ATTRIBUTE_UNUSED,
12659 const char *dom_xml)
12661 virQEMUDriverPtr driver = dconn->privateData;
12662 virDomainDefPtr def = NULL;
12663 char *origname = NULL;
12664 qemuMigrationParamsPtr migParams = NULL;
12665 int ret = -1;
12667 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12669 if (flags & VIR_MIGRATE_TUNNELLED) {
12670 /* this is a logical error; we never should have gotten here with
12671 * VIR_MIGRATE_TUNNELLED set
12673 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12674 _("Tunnelled migration requested but invalid "
12675 "RPC method called"));
12676 goto cleanup;
12679 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12680 QEMU_MIGRATION_DESTINATION)))
12681 goto cleanup;
12683 if (virLockManagerPluginUsesState(driver->lockManager)) {
12684 virReportError(VIR_ERR_INTERNAL_ERROR,
12685 _("Cannot use migrate v2 protocol with lock manager %s"),
12686 virLockManagerPluginGetName(driver->lockManager));
12687 goto cleanup;
12690 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
12691 goto cleanup;
12693 if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0)
12694 goto cleanup;
12696 /* Do not use cookies in v2 protocol, since the cookie
12697 * length was not sufficiently large, causing failures
12698 * migrating between old & new libvirtd
12700 ret = qemuMigrationDstPrepareDirect(driver, dconn,
12701 NULL, 0, NULL, NULL, /* No cookies */
12702 uri_in, uri_out,
12703 &def, origname, NULL, 0, NULL, 0,
12704 migParams, flags);
12706 cleanup:
12707 qemuMigrationParamsFree(migParams);
12708 VIR_FREE(origname);
12709 virDomainDefFree(def);
12710 return ret;
12714 /* Perform is the second step, and it runs on the source host. */
12715 static int
12716 qemuDomainMigratePerform(virDomainPtr dom,
12717 const char *cookie,
12718 int cookielen,
12719 const char *uri,
12720 unsigned long flags,
12721 const char *dname,
12722 unsigned long resource)
12724 virQEMUDriverPtr driver = dom->conn->privateData;
12725 virDomainObjPtr vm;
12726 int ret = -1;
12727 const char *dconnuri = NULL;
12728 qemuMigrationParamsPtr migParams = NULL;
12730 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12732 if (virLockManagerPluginUsesState(driver->lockManager)) {
12733 virReportError(VIR_ERR_INTERNAL_ERROR,
12734 _("Cannot use migrate v2 protocol with lock manager %s"),
12735 virLockManagerPluginGetName(driver->lockManager));
12736 goto cleanup;
12739 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12740 QEMU_MIGRATION_SOURCE)))
12741 goto cleanup;
12743 if (!(vm = qemuDomObjFromDomain(dom)))
12744 goto cleanup;
12746 if (virDomainMigratePerformEnsureACL(dom->conn, vm->def) < 0) {
12747 virDomainObjEndAPI(&vm);
12748 goto cleanup;
12751 if (flags & VIR_MIGRATE_PEER2PEER)
12752 VIR_STEAL_PTR(dconnuri, uri);
12754 /* Do not output cookies in v2 protocol, since the cookie
12755 * length was not sufficiently large, causing failures
12756 * migrating between old & new libvirtd.
12758 * Consume any cookie we were able to decode though
12760 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, NULL,
12761 NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0,
12762 migParams, cookie, cookielen,
12763 NULL, NULL, /* No output cookies in v2 */
12764 flags, dname, resource, false);
12766 cleanup:
12767 qemuMigrationParamsFree(migParams);
12768 return ret;
12772 /* Finish is the third and final step, and it runs on the destination host. */
12773 static virDomainPtr
12774 qemuDomainMigrateFinish2(virConnectPtr dconn,
12775 const char *dname,
12776 const char *cookie ATTRIBUTE_UNUSED,
12777 int cookielen ATTRIBUTE_UNUSED,
12778 const char *uri ATTRIBUTE_UNUSED,
12779 unsigned long flags,
12780 int retcode)
12782 virQEMUDriverPtr driver = dconn->privateData;
12783 virDomainObjPtr vm;
12784 virDomainPtr dom = NULL;
12786 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12788 vm = virDomainObjListFindByName(driver->domains, dname);
12789 if (!vm) {
12790 virReportError(VIR_ERR_NO_DOMAIN,
12791 _("no domain with matching name '%s'"), dname);
12792 qemuMigrationDstErrorReport(driver, dname);
12793 goto cleanup;
12796 if (virDomainMigrateFinish2EnsureACL(dconn, vm->def) < 0) {
12797 virDomainObjEndAPI(&vm);
12798 goto cleanup;
12801 /* Do not use cookies in v2 protocol, since the cookie
12802 * length was not sufficiently large, causing failures
12803 * migrating between old & new libvirtd
12805 dom = qemuMigrationDstFinish(driver, dconn, vm,
12806 NULL, 0, NULL, NULL, /* No cookies */
12807 flags, retcode, false);
12809 cleanup:
12810 return dom;
12814 /*******************************************************************
12815 * Migration Protocol Version 3
12816 *******************************************************************/
12818 static char *
12819 qemuDomainMigrateBegin3(virDomainPtr domain,
12820 const char *xmlin,
12821 char **cookieout,
12822 int *cookieoutlen,
12823 unsigned long flags,
12824 const char *dname,
12825 unsigned long resource ATTRIBUTE_UNUSED)
12827 virDomainObjPtr vm;
12829 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12831 if (!(vm = qemuDomObjFromDomain(domain)))
12832 return NULL;
12834 if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) {
12835 virDomainObjEndAPI(&vm);
12836 return NULL;
12839 return qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
12840 cookieout, cookieoutlen, 0, NULL, flags);
12843 static char *
12844 qemuDomainMigrateBegin3Params(virDomainPtr domain,
12845 virTypedParameterPtr params,
12846 int nparams,
12847 char **cookieout,
12848 int *cookieoutlen,
12849 unsigned int flags)
12851 const char *xmlin = NULL;
12852 const char *dname = NULL;
12853 const char **migrate_disks = NULL;
12854 int nmigrate_disks;
12855 char *ret = NULL;
12856 virDomainObjPtr vm;
12858 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
12859 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
12860 goto cleanup;
12862 if (virTypedParamsGetString(params, nparams,
12863 VIR_MIGRATE_PARAM_DEST_XML,
12864 &xmlin) < 0 ||
12865 virTypedParamsGetString(params, nparams,
12866 VIR_MIGRATE_PARAM_DEST_NAME,
12867 &dname) < 0)
12868 goto cleanup;
12870 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
12871 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
12872 &migrate_disks);
12874 if (nmigrate_disks < 0)
12875 goto cleanup;
12877 if (!(vm = qemuDomObjFromDomain(domain)))
12878 goto cleanup;
12880 if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
12881 virDomainObjEndAPI(&vm);
12882 goto cleanup;
12885 ret = qemuMigrationSrcBegin(domain->conn, vm, xmlin, dname,
12886 cookieout, cookieoutlen,
12887 nmigrate_disks, migrate_disks, flags);
12889 cleanup:
12890 VIR_FREE(migrate_disks);
12891 return ret;
12895 static int
12896 qemuDomainMigratePrepare3(virConnectPtr dconn,
12897 const char *cookiein,
12898 int cookieinlen,
12899 char **cookieout,
12900 int *cookieoutlen,
12901 const char *uri_in,
12902 char **uri_out,
12903 unsigned long flags,
12904 const char *dname,
12905 unsigned long resource ATTRIBUTE_UNUSED,
12906 const char *dom_xml)
12908 virQEMUDriverPtr driver = dconn->privateData;
12909 virDomainDefPtr def = NULL;
12910 char *origname = NULL;
12911 qemuMigrationParamsPtr migParams = NULL;
12912 int ret = -1;
12914 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
12916 if (flags & VIR_MIGRATE_TUNNELLED) {
12917 /* this is a logical error; we never should have gotten here with
12918 * VIR_MIGRATE_TUNNELLED set
12920 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12921 _("Tunnelled migration requested but invalid "
12922 "RPC method called"));
12923 goto cleanup;
12926 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
12927 QEMU_MIGRATION_DESTINATION)))
12928 goto cleanup;
12930 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
12931 goto cleanup;
12933 if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0)
12934 goto cleanup;
12936 ret = qemuMigrationDstPrepareDirect(driver, dconn,
12937 cookiein, cookieinlen,
12938 cookieout, cookieoutlen,
12939 uri_in, uri_out,
12940 &def, origname, NULL, 0, NULL, 0,
12941 migParams, flags);
12943 cleanup:
12944 qemuMigrationParamsFree(migParams);
12945 VIR_FREE(origname);
12946 virDomainDefFree(def);
12947 return ret;
12950 static int
12951 qemuDomainMigratePrepare3Params(virConnectPtr dconn,
12952 virTypedParameterPtr params,
12953 int nparams,
12954 const char *cookiein,
12955 int cookieinlen,
12956 char **cookieout,
12957 int *cookieoutlen,
12958 char **uri_out,
12959 unsigned int flags)
12961 virQEMUDriverPtr driver = dconn->privateData;
12962 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
12963 virDomainDefPtr def = NULL;
12964 const char *dom_xml = NULL;
12965 const char *dname = NULL;
12966 const char *uri_in = NULL;
12967 const char *listenAddress = cfg->migrationAddress;
12968 int nbdPort = 0;
12969 int nmigrate_disks;
12970 const char **migrate_disks = NULL;
12971 char *origname = NULL;
12972 qemuMigrationParamsPtr migParams = NULL;
12973 int ret = -1;
12975 virCheckFlagsGoto(QEMU_MIGRATION_FLAGS, cleanup);
12976 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
12977 goto cleanup;
12979 if (virTypedParamsGetString(params, nparams,
12980 VIR_MIGRATE_PARAM_DEST_XML,
12981 &dom_xml) < 0 ||
12982 virTypedParamsGetString(params, nparams,
12983 VIR_MIGRATE_PARAM_DEST_NAME,
12984 &dname) < 0 ||
12985 virTypedParamsGetString(params, nparams,
12986 VIR_MIGRATE_PARAM_URI,
12987 &uri_in) < 0 ||
12988 virTypedParamsGetString(params, nparams,
12989 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
12990 &listenAddress) < 0 ||
12991 virTypedParamsGetInt(params, nparams,
12992 VIR_MIGRATE_PARAM_DISKS_PORT,
12993 &nbdPort) < 0)
12994 goto cleanup;
12996 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
12997 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
12998 &migrate_disks);
13000 if (nmigrate_disks < 0)
13001 goto cleanup;
13003 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13004 QEMU_MIGRATION_DESTINATION)))
13005 goto cleanup;
13007 if (flags & VIR_MIGRATE_TUNNELLED) {
13008 /* this is a logical error; we never should have gotten here with
13009 * VIR_MIGRATE_TUNNELLED set
13011 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13012 _("Tunnelled migration requested but invalid "
13013 "RPC method called"));
13014 goto cleanup;
13017 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13018 goto cleanup;
13020 if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
13021 goto cleanup;
13023 ret = qemuMigrationDstPrepareDirect(driver, dconn,
13024 cookiein, cookieinlen,
13025 cookieout, cookieoutlen,
13026 uri_in, uri_out,
13027 &def, origname, listenAddress,
13028 nmigrate_disks, migrate_disks, nbdPort,
13029 migParams, flags);
13031 cleanup:
13032 qemuMigrationParamsFree(migParams);
13033 VIR_FREE(migrate_disks);
13034 VIR_FREE(origname);
13035 virDomainDefFree(def);
13036 virObjectUnref(cfg);
13037 return ret;
13041 static int
13042 qemuDomainMigratePrepareTunnel3(virConnectPtr dconn,
13043 virStreamPtr st,
13044 const char *cookiein,
13045 int cookieinlen,
13046 char **cookieout,
13047 int *cookieoutlen,
13048 unsigned long flags,
13049 const char *dname,
13050 unsigned long resource ATTRIBUTE_UNUSED,
13051 const char *dom_xml)
13053 virQEMUDriverPtr driver = dconn->privateData;
13054 virDomainDefPtr def = NULL;
13055 char *origname = NULL;
13056 qemuMigrationParamsPtr migParams = NULL;
13057 int ret = -1;
13059 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13061 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
13062 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13063 _("PrepareTunnel called but no TUNNELLED flag set"));
13064 goto cleanup;
13067 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
13068 QEMU_MIGRATION_DESTINATION)))
13069 goto cleanup;
13071 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13072 goto cleanup;
13074 if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0)
13075 goto cleanup;
13077 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
13078 cookiein, cookieinlen,
13079 cookieout, cookieoutlen,
13080 st, &def, origname, migParams, flags);
13082 cleanup:
13083 qemuMigrationParamsFree(migParams);
13084 VIR_FREE(origname);
13085 virDomainDefFree(def);
13086 return ret;
13089 static int
13090 qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
13091 virStreamPtr st,
13092 virTypedParameterPtr params,
13093 int nparams,
13094 const char *cookiein,
13095 int cookieinlen,
13096 char **cookieout,
13097 int *cookieoutlen,
13098 unsigned int flags)
13100 virQEMUDriverPtr driver = dconn->privateData;
13101 virDomainDefPtr def = NULL;
13102 const char *dom_xml = NULL;
13103 const char *dname = NULL;
13104 char *origname = NULL;
13105 qemuMigrationParamsPtr migParams = NULL;
13106 int ret = -1;
13108 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13109 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13110 return -1;
13112 if (virTypedParamsGetString(params, nparams,
13113 VIR_MIGRATE_PARAM_DEST_XML,
13114 &dom_xml) < 0 ||
13115 virTypedParamsGetString(params, nparams,
13116 VIR_MIGRATE_PARAM_DEST_NAME,
13117 &dname) < 0)
13118 return -1;
13120 if (!(flags & VIR_MIGRATE_TUNNELLED)) {
13121 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13122 _("PrepareTunnel called but no TUNNELLED flag set"));
13123 goto cleanup;
13126 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13127 QEMU_MIGRATION_DESTINATION)))
13128 goto cleanup;
13130 if (!(def = qemuMigrationAnyPrepareDef(driver, dom_xml, dname, &origname)))
13131 goto cleanup;
13133 if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
13134 goto cleanup;
13136 ret = qemuMigrationDstPrepareTunnel(driver, dconn,
13137 cookiein, cookieinlen,
13138 cookieout, cookieoutlen,
13139 st, &def, origname, migParams, flags);
13141 cleanup:
13142 qemuMigrationParamsFree(migParams);
13143 VIR_FREE(origname);
13144 virDomainDefFree(def);
13145 return ret;
13149 static int
13150 qemuDomainMigratePerform3(virDomainPtr dom,
13151 const char *xmlin,
13152 const char *cookiein,
13153 int cookieinlen,
13154 char **cookieout,
13155 int *cookieoutlen,
13156 const char *dconnuri,
13157 const char *uri,
13158 unsigned long flags,
13159 const char *dname,
13160 unsigned long resource)
13162 virQEMUDriverPtr driver = dom->conn->privateData;
13163 virDomainObjPtr vm;
13164 qemuMigrationParamsPtr migParams = NULL;
13165 int ret = -1;
13167 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13169 if (!(migParams = qemuMigrationParamsFromFlags(NULL, 0, flags,
13170 QEMU_MIGRATION_SOURCE)))
13171 goto cleanup;
13173 if (!(vm = qemuDomObjFromDomain(dom)))
13174 goto cleanup;
13176 if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) {
13177 virDomainObjEndAPI(&vm);
13178 goto cleanup;
13181 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, xmlin, NULL,
13182 dconnuri, uri, NULL, NULL, 0, NULL, 0,
13183 migParams,
13184 cookiein, cookieinlen,
13185 cookieout, cookieoutlen,
13186 flags, dname, resource, true);
13188 cleanup:
13189 qemuMigrationParamsFree(migParams);
13190 return ret;
13193 static int
13194 qemuDomainMigratePerform3Params(virDomainPtr dom,
13195 const char *dconnuri,
13196 virTypedParameterPtr params,
13197 int nparams,
13198 const char *cookiein,
13199 int cookieinlen,
13200 char **cookieout,
13201 int *cookieoutlen,
13202 unsigned int flags)
13204 virQEMUDriverPtr driver = dom->conn->privateData;
13205 virDomainObjPtr vm;
13206 const char *dom_xml = NULL;
13207 const char *persist_xml = NULL;
13208 const char *dname = NULL;
13209 const char *uri = NULL;
13210 const char *graphicsuri = NULL;
13211 const char *listenAddress = NULL;
13212 int nmigrate_disks;
13213 const char **migrate_disks = NULL;
13214 unsigned long long bandwidth = 0;
13215 int nbdPort = 0;
13216 qemuMigrationParamsPtr migParams = NULL;
13217 int ret = -1;
13219 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13220 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13221 return ret;
13223 if (virTypedParamsGetString(params, nparams,
13224 VIR_MIGRATE_PARAM_DEST_XML,
13225 &dom_xml) < 0 ||
13226 virTypedParamsGetString(params, nparams,
13227 VIR_MIGRATE_PARAM_DEST_NAME,
13228 &dname) < 0 ||
13229 virTypedParamsGetString(params, nparams,
13230 VIR_MIGRATE_PARAM_URI,
13231 &uri) < 0 ||
13232 virTypedParamsGetULLong(params, nparams,
13233 VIR_MIGRATE_PARAM_BANDWIDTH,
13234 &bandwidth) < 0 ||
13235 virTypedParamsGetString(params, nparams,
13236 VIR_MIGRATE_PARAM_GRAPHICS_URI,
13237 &graphicsuri) < 0 ||
13238 virTypedParamsGetString(params, nparams,
13239 VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
13240 &listenAddress) < 0 ||
13241 virTypedParamsGetInt(params, nparams,
13242 VIR_MIGRATE_PARAM_DISKS_PORT,
13243 &nbdPort) < 0 ||
13244 virTypedParamsGetString(params, nparams,
13245 VIR_MIGRATE_PARAM_PERSIST_XML,
13246 &persist_xml) < 0)
13247 goto cleanup;
13249 nmigrate_disks = virTypedParamsGetStringList(params, nparams,
13250 VIR_MIGRATE_PARAM_MIGRATE_DISKS,
13251 &migrate_disks);
13253 if (nmigrate_disks < 0)
13254 goto cleanup;
13256 if (!(migParams = qemuMigrationParamsFromFlags(params, nparams, flags,
13257 QEMU_MIGRATION_SOURCE)))
13258 goto cleanup;
13260 if (!(vm = qemuDomObjFromDomain(dom)))
13261 goto cleanup;
13263 if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0) {
13264 virDomainObjEndAPI(&vm);
13265 goto cleanup;
13268 ret = qemuMigrationSrcPerform(driver, dom->conn, vm, dom_xml, persist_xml,
13269 dconnuri, uri, graphicsuri, listenAddress,
13270 nmigrate_disks, migrate_disks, nbdPort,
13271 migParams,
13272 cookiein, cookieinlen, cookieout, cookieoutlen,
13273 flags, dname, bandwidth, true);
13274 cleanup:
13275 qemuMigrationParamsFree(migParams);
13276 VIR_FREE(migrate_disks);
13277 return ret;
13281 static virDomainPtr
13282 qemuDomainMigrateFinish3(virConnectPtr dconn,
13283 const char *dname,
13284 const char *cookiein,
13285 int cookieinlen,
13286 char **cookieout,
13287 int *cookieoutlen,
13288 const char *dconnuri ATTRIBUTE_UNUSED,
13289 const char *uri ATTRIBUTE_UNUSED,
13290 unsigned long flags,
13291 int cancelled)
13293 virQEMUDriverPtr driver = dconn->privateData;
13294 virDomainObjPtr vm;
13296 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
13298 if (!dname) {
13299 virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
13300 return NULL;
13303 vm = virDomainObjListFindByName(driver->domains, dname);
13304 if (!vm) {
13305 virReportError(VIR_ERR_NO_DOMAIN,
13306 _("no domain with matching name '%s'"), dname);
13307 qemuMigrationDstErrorReport(driver, dname);
13308 return NULL;
13311 if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) {
13312 virDomainObjEndAPI(&vm);
13313 return NULL;
13316 return qemuMigrationDstFinish(driver, dconn, vm,
13317 cookiein, cookieinlen,
13318 cookieout, cookieoutlen,
13319 flags, cancelled, true);
13322 static virDomainPtr
13323 qemuDomainMigrateFinish3Params(virConnectPtr dconn,
13324 virTypedParameterPtr params,
13325 int nparams,
13326 const char *cookiein,
13327 int cookieinlen,
13328 char **cookieout,
13329 int *cookieoutlen,
13330 unsigned int flags,
13331 int cancelled)
13333 virQEMUDriverPtr driver = dconn->privateData;
13334 virDomainObjPtr vm;
13335 const char *dname = NULL;
13337 virCheckFlags(QEMU_MIGRATION_FLAGS, NULL);
13338 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13339 return NULL;
13341 if (virTypedParamsGetString(params, nparams,
13342 VIR_MIGRATE_PARAM_DEST_NAME,
13343 &dname) < 0)
13344 return NULL;
13346 if (!dname) {
13347 virReportError(VIR_ERR_NO_DOMAIN, "%s", _("missing domain name"));
13348 return NULL;
13351 vm = virDomainObjListFindByName(driver->domains, dname);
13352 if (!vm) {
13353 virReportError(VIR_ERR_NO_DOMAIN,
13354 _("no domain with matching name '%s'"), dname);
13355 qemuMigrationDstErrorReport(driver, dname);
13356 return NULL;
13359 if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
13360 virDomainObjEndAPI(&vm);
13361 return NULL;
13364 return qemuMigrationDstFinish(driver, dconn, vm,
13365 cookiein, cookieinlen,
13366 cookieout, cookieoutlen,
13367 flags, cancelled, true);
13371 static int
13372 qemuDomainMigrateConfirm3(virDomainPtr domain,
13373 const char *cookiein,
13374 int cookieinlen,
13375 unsigned long flags,
13376 int cancelled)
13378 virDomainObjPtr vm;
13380 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13382 if (!(vm = qemuDomObjFromDomain(domain)))
13383 return -1;
13385 if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) {
13386 virDomainObjEndAPI(&vm);
13387 return -1;
13390 return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
13391 flags, cancelled);
13394 static int
13395 qemuDomainMigrateConfirm3Params(virDomainPtr domain,
13396 virTypedParameterPtr params,
13397 int nparams,
13398 const char *cookiein,
13399 int cookieinlen,
13400 unsigned int flags,
13401 int cancelled)
13403 virDomainObjPtr vm;
13405 virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
13407 if (virTypedParamsValidate(params, nparams, QEMU_MIGRATION_PARAMETERS) < 0)
13408 return -1;
13410 if (!(vm = qemuDomObjFromDomain(domain)))
13411 return -1;
13413 if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
13414 virDomainObjEndAPI(&vm);
13415 return -1;
13418 return qemuMigrationSrcConfirm(domain->conn->privateData, vm, cookiein, cookieinlen,
13419 flags, cancelled);
13423 static int
13424 qemuNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
13425 unsigned *domain,
13426 unsigned *bus,
13427 unsigned *slot,
13428 unsigned *function)
13430 virNodeDevCapsDefPtr cap;
13431 int ret = -1;
13433 cap = def->caps;
13434 while (cap) {
13435 if (cap->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
13436 *domain = cap->data.pci_dev.domain;
13437 *bus = cap->data.pci_dev.bus;
13438 *slot = cap->data.pci_dev.slot;
13439 *function = cap->data.pci_dev.function;
13440 break;
13443 cap = cap->next;
13446 if (!cap) {
13447 virReportError(VIR_ERR_INVALID_ARG,
13448 _("device %s is not a PCI device"), def->name);
13449 goto out;
13452 ret = 0;
13453 out:
13454 return ret;
13457 static int
13458 qemuNodeDeviceDetachFlags(virNodeDevicePtr dev,
13459 const char *driverName,
13460 unsigned int flags)
13462 virQEMUDriverPtr driver = dev->conn->privateData;
13463 virPCIDevicePtr pci = NULL;
13464 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13465 int ret = -1;
13466 virNodeDeviceDefPtr def = NULL;
13467 char *xml = NULL;
13468 bool legacy = qemuHostdevHostSupportsPassthroughLegacy();
13469 bool vfio = qemuHostdevHostSupportsPassthroughVFIO();
13470 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13472 virCheckFlags(0, -1);
13474 xml = virNodeDeviceGetXMLDesc(dev, 0);
13475 if (!xml)
13476 goto cleanup;
13478 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13479 if (!def)
13480 goto cleanup;
13482 if (virNodeDeviceDetachFlagsEnsureACL(dev->conn, def) < 0)
13483 goto cleanup;
13485 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13486 goto cleanup;
13488 pci = virPCIDeviceNew(domain, bus, slot, function);
13489 if (!pci)
13490 goto cleanup;
13492 if (!driverName) {
13493 if (vfio) {
13494 driverName = "vfio";
13495 } else if (legacy) {
13496 driverName = "kvm";
13497 } else {
13498 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
13499 _("neither VFIO nor KVM device assignment is "
13500 "currently supported on this system"));
13501 goto cleanup;
13505 if (STREQ(driverName, "vfio")) {
13506 if (!vfio) {
13507 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13508 _("VFIO device assignment is currently not "
13509 "supported on this system"));
13510 goto cleanup;
13512 virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_VFIO);
13513 } else if (STREQ(driverName, "kvm")) {
13514 if (!legacy) {
13515 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
13516 _("KVM device assignment is currently not "
13517 "supported on this system"));
13518 goto cleanup;
13520 virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_KVM);
13521 } else {
13522 virReportError(VIR_ERR_INVALID_ARG,
13523 _("unknown driver name '%s'"), driverName);
13524 goto cleanup;
13527 ret = virHostdevPCINodeDeviceDetach(hostdev_mgr, pci);
13528 cleanup:
13529 virPCIDeviceFree(pci);
13530 virNodeDeviceDefFree(def);
13531 VIR_FREE(xml);
13532 return ret;
13535 static int
13536 qemuNodeDeviceDettach(virNodeDevicePtr dev)
13538 return qemuNodeDeviceDetachFlags(dev, NULL, 0);
13541 static int
13542 qemuNodeDeviceReAttach(virNodeDevicePtr dev)
13544 virQEMUDriverPtr driver = dev->conn->privateData;
13545 virPCIDevicePtr pci = NULL;
13546 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13547 int ret = -1;
13548 virNodeDeviceDefPtr def = NULL;
13549 char *xml = NULL;
13550 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13552 xml = virNodeDeviceGetXMLDesc(dev, 0);
13553 if (!xml)
13554 goto cleanup;
13556 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13557 if (!def)
13558 goto cleanup;
13560 if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0)
13561 goto cleanup;
13563 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13564 goto cleanup;
13566 pci = virPCIDeviceNew(domain, bus, slot, function);
13567 if (!pci)
13568 goto cleanup;
13570 ret = virHostdevPCINodeDeviceReAttach(hostdev_mgr, pci);
13572 virPCIDeviceFree(pci);
13573 cleanup:
13574 virNodeDeviceDefFree(def);
13575 VIR_FREE(xml);
13576 return ret;
13579 static int
13580 qemuNodeDeviceReset(virNodeDevicePtr dev)
13582 virQEMUDriverPtr driver = dev->conn->privateData;
13583 virPCIDevicePtr pci;
13584 unsigned domain = 0, bus = 0, slot = 0, function = 0;
13585 int ret = -1;
13586 virNodeDeviceDefPtr def = NULL;
13587 char *xml = NULL;
13588 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
13590 xml = virNodeDeviceGetXMLDesc(dev, 0);
13591 if (!xml)
13592 goto cleanup;
13594 def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
13595 if (!def)
13596 goto cleanup;
13598 if (virNodeDeviceResetEnsureACL(dev->conn, def) < 0)
13599 goto cleanup;
13601 if (qemuNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
13602 goto cleanup;
13604 pci = virPCIDeviceNew(domain, bus, slot, function);
13605 if (!pci)
13606 goto cleanup;
13608 ret = virHostdevPCINodeDeviceReset(hostdev_mgr, pci);
13610 virPCIDeviceFree(pci);
13611 cleanup:
13612 virNodeDeviceDefFree(def);
13613 VIR_FREE(xml);
13614 return ret;
13617 static int
13618 qemuConnectCompareCPU(virConnectPtr conn,
13619 const char *xmlDesc,
13620 unsigned int flags)
13622 virQEMUDriverPtr driver = conn->privateData;
13623 int ret = VIR_CPU_COMPARE_ERROR;
13624 virCapsPtr caps = NULL;
13625 bool failIncompatible;
13627 virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
13628 VIR_CPU_COMPARE_ERROR);
13630 if (virConnectCompareCPUEnsureACL(conn) < 0)
13631 goto cleanup;
13633 failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
13635 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
13636 goto cleanup;
13638 ret = virCPUCompareXML(caps->host.arch, caps->host.cpu,
13639 xmlDesc, failIncompatible);
13641 cleanup:
13642 virObjectUnref(caps);
13643 return ret;
13647 static int
13648 qemuConnectCompareHypervisorCPU(virConnectPtr conn,
13649 const char *emulator,
13650 const char *archStr,
13651 const char *machine,
13652 const char *virttypeStr,
13653 const char *xmlCPU,
13654 unsigned int flags)
13656 int ret = VIR_CPU_COMPARE_ERROR;
13657 virQEMUDriverPtr driver = conn->privateData;
13658 virQEMUCapsPtr qemuCaps = NULL;
13659 bool failIncompatible;
13660 virCPUDefPtr hvCPU;
13661 virArch arch;
13662 virDomainVirtType virttype;
13664 virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
13665 VIR_CPU_COMPARE_ERROR);
13667 if (virConnectCompareHypervisorCPUEnsureACL(conn) < 0)
13668 goto cleanup;
13670 failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
13672 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
13673 emulator,
13674 archStr,
13675 virttypeStr,
13676 machine,
13677 &arch, &virttype, NULL);
13678 if (!qemuCaps)
13679 goto cleanup;
13681 hvCPU = virQEMUCapsGetHostModel(qemuCaps, virttype,
13682 VIR_QEMU_CAPS_HOST_CPU_REPORTED);
13684 if (!hvCPU || hvCPU->fallback != VIR_CPU_FALLBACK_FORBID) {
13685 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13686 _("QEMU '%s' does not support reporting CPU model for "
13687 "virttype '%s'"),
13688 virQEMUCapsGetBinary(qemuCaps),
13689 virDomainVirtTypeToString(virttype));
13690 goto cleanup;
13693 if (ARCH_IS_X86(arch)) {
13694 ret = virCPUCompareXML(arch, hvCPU, xmlCPU, failIncompatible);
13695 } else {
13696 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13697 _("comparing with the hypervisor CPU is not supported "
13698 "for arch %s"), virArchToString(arch));
13701 cleanup:
13702 virObjectUnref(qemuCaps);
13703 return ret;
13707 static char *
13708 qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
13709 const char **xmlCPUs,
13710 unsigned int ncpus,
13711 unsigned int flags)
13713 virCPUDefPtr *cpus = NULL;
13714 virCPUDefPtr baseline = NULL;
13715 virCPUDefPtr cpu = NULL;
13716 char *cpustr = NULL;
13718 virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
13719 VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
13721 if (virConnectBaselineCPUEnsureACL(conn) < 0)
13722 goto cleanup;
13724 if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
13725 goto cleanup;
13727 if (!(baseline = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL,
13728 !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE))))
13729 goto cleanup;
13731 if (!(cpu = virCPUDefCopyWithoutModel(baseline)))
13732 goto cleanup;
13734 if (virCPUDefCopyModelFilter(cpu, baseline, false,
13735 virQEMUCapsCPUFilterFeatures,
13736 &cpus[0]->arch) < 0)
13737 goto cleanup;
13739 if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
13740 virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
13741 goto cleanup;
13743 cpustr = virCPUDefFormat(cpu, NULL);
13745 cleanup:
13746 virCPUDefListFree(cpus);
13747 virCPUDefFree(baseline);
13748 virCPUDefFree(cpu);
13750 return cpustr;
13754 static char *
13755 qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
13756 const char *emulator,
13757 const char *archStr,
13758 const char *machine,
13759 const char *virttypeStr,
13760 const char **xmlCPUs,
13761 unsigned int ncpus,
13762 unsigned int flags)
13764 virQEMUDriverPtr driver = conn->privateData;
13765 virCPUDefPtr *cpus = NULL;
13766 virQEMUCapsPtr qemuCaps = NULL;
13767 virArch arch;
13768 virDomainVirtType virttype;
13769 virDomainCapsCPUModelsPtr cpuModels;
13770 bool migratable;
13771 virCPUDefPtr cpu = NULL;
13772 char *cpustr = NULL;
13773 char **features = NULL;
13775 virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
13776 VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
13778 if (virConnectBaselineHypervisorCPUEnsureACL(conn) < 0)
13779 goto cleanup;
13781 migratable = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
13783 if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_AUTO)))
13784 goto cleanup;
13786 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
13787 emulator,
13788 archStr,
13789 virttypeStr,
13790 machine,
13791 &arch, &virttype, NULL);
13792 if (!qemuCaps)
13793 goto cleanup;
13795 if (!(cpuModels = virQEMUCapsGetCPUDefinitions(qemuCaps, virttype)) ||
13796 cpuModels->nmodels == 0) {
13797 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13798 _("QEMU '%s' does not support any CPU models for "
13799 "virttype '%s'"),
13800 virQEMUCapsGetBinary(qemuCaps),
13801 virDomainVirtTypeToString(virttype));
13802 goto cleanup;
13805 if (ARCH_IS_X86(arch)) {
13806 int rc = virQEMUCapsGetCPUFeatures(qemuCaps, virttype,
13807 migratable, &features);
13808 if (rc < 0)
13809 goto cleanup;
13810 if (features && rc == 0) {
13811 /* We got only migratable features from QEMU if we asked for them,
13812 * no further filtering in virCPUBaseline is desired. */
13813 migratable = false;
13816 if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
13817 (const char **)features, migratable)))
13818 goto cleanup;
13819 } else {
13820 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
13821 _("computing baseline hypervisor CPU is not supported "
13822 "for arch %s"), virArchToString(arch));
13823 goto cleanup;
13826 cpu->fallback = VIR_CPU_FALLBACK_FORBID;
13828 if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
13829 virCPUExpandFeatures(arch, cpu) < 0)
13830 goto cleanup;
13832 cpustr = virCPUDefFormat(cpu, NULL);
13834 cleanup:
13835 virCPUDefListFree(cpus);
13836 virCPUDefFree(cpu);
13837 virObjectUnref(qemuCaps);
13838 virStringListFree(features);
13840 return cpustr;
13844 static int
13845 qemuDomainGetJobInfoMigrationStats(virQEMUDriverPtr driver,
13846 virDomainObjPtr vm,
13847 qemuDomainJobInfoPtr jobInfo)
13849 qemuDomainObjPrivatePtr priv = vm->privateData;
13850 bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
13852 if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE ||
13853 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_MIGRATING ||
13854 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED ||
13855 jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
13856 if (events &&
13857 jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
13858 qemuMigrationAnyFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE,
13859 jobInfo, NULL) < 0)
13860 return -1;
13862 if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
13863 jobInfo->statsType == QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION &&
13864 qemuMigrationSrcFetchMirrorStats(driver, vm, QEMU_ASYNC_JOB_NONE,
13865 jobInfo) < 0)
13866 return -1;
13868 if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
13869 return -1;
13872 return 0;
13876 static int
13877 qemuDomainGetJobInfoDumpStats(virQEMUDriverPtr driver,
13878 virDomainObjPtr vm,
13879 qemuDomainJobInfoPtr jobInfo)
13881 qemuDomainObjPrivatePtr priv = vm->privateData;
13882 qemuMonitorDumpStats stats = { 0 };
13883 int rc;
13885 if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
13886 return -1;
13888 rc = qemuMonitorQueryDump(priv->mon, &stats);
13890 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
13891 return -1;
13893 jobInfo->stats.dump = stats;
13895 if (qemuDomainJobInfoUpdateTime(jobInfo) < 0)
13896 return -1;
13898 switch (jobInfo->stats.dump.status) {
13899 case QEMU_MONITOR_DUMP_STATUS_NONE:
13900 case QEMU_MONITOR_DUMP_STATUS_FAILED:
13901 case QEMU_MONITOR_DUMP_STATUS_LAST:
13902 virReportError(VIR_ERR_OPERATION_FAILED,
13903 _("dump query failed, status=%d"),
13904 jobInfo->stats.dump.status);
13905 return -1;
13906 break;
13908 case QEMU_MONITOR_DUMP_STATUS_ACTIVE:
13909 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE;
13910 VIR_DEBUG("dump active, bytes written='%llu' remaining='%llu'",
13911 jobInfo->stats.dump.completed,
13912 jobInfo->stats.dump.total -
13913 jobInfo->stats.dump.completed);
13914 break;
13916 case QEMU_MONITOR_DUMP_STATUS_COMPLETED:
13917 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED;
13918 VIR_DEBUG("dump completed, bytes written='%llu'",
13919 jobInfo->stats.dump.completed);
13920 break;
13923 return 0;
13927 static int
13928 qemuDomainGetJobStatsInternal(virQEMUDriverPtr driver,
13929 virDomainObjPtr vm,
13930 bool completed,
13931 qemuDomainJobInfoPtr jobInfo)
13933 qemuDomainObjPrivatePtr priv = vm->privateData;
13934 int ret = -1;
13936 if (completed) {
13937 if (priv->job.completed && !priv->job.current)
13938 *jobInfo = *priv->job.completed;
13939 else
13940 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_NONE;
13942 return 0;
13945 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
13946 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
13947 _("migration statistics are available only on "
13948 "the source host"));
13949 return -1;
13952 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
13953 return -1;
13955 if (virDomainObjCheckActive(vm) < 0)
13956 goto cleanup;
13958 if (!priv->job.current) {
13959 jobInfo->status = QEMU_DOMAIN_JOB_STATUS_NONE;
13960 ret = 0;
13961 goto cleanup;
13963 *jobInfo = *priv->job.current;
13965 switch (jobInfo->statsType) {
13966 case QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION:
13967 case QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP:
13968 if (qemuDomainGetJobInfoMigrationStats(driver, vm, jobInfo) < 0)
13969 goto cleanup;
13970 break;
13972 case QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP:
13973 if (qemuDomainGetJobInfoDumpStats(driver, vm, jobInfo) < 0)
13974 goto cleanup;
13975 break;
13977 case QEMU_DOMAIN_JOB_STATS_TYPE_NONE:
13978 break;
13981 ret = 0;
13983 cleanup:
13984 qemuDomainObjEndJob(driver, vm);
13985 return ret;
13989 static int
13990 qemuDomainGetJobInfo(virDomainPtr dom,
13991 virDomainJobInfoPtr info)
13993 virQEMUDriverPtr driver = dom->conn->privateData;
13994 qemuDomainJobInfo jobInfo;
13995 virDomainObjPtr vm;
13996 int ret = -1;
13998 if (!(vm = qemuDomObjFromDomain(dom)))
13999 goto cleanup;
14001 if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0)
14002 goto cleanup;
14004 if (qemuDomainGetJobStatsInternal(driver, vm, false, &jobInfo) < 0)
14005 goto cleanup;
14007 if (jobInfo.status == QEMU_DOMAIN_JOB_STATUS_NONE) {
14008 memset(info, 0, sizeof(*info));
14009 info->type = VIR_DOMAIN_JOB_NONE;
14010 ret = 0;
14011 goto cleanup;
14014 ret = qemuDomainJobInfoToInfo(&jobInfo, info);
14016 cleanup:
14017 virDomainObjEndAPI(&vm);
14018 return ret;
14022 static int
14023 qemuDomainGetJobStats(virDomainPtr dom,
14024 int *type,
14025 virTypedParameterPtr *params,
14026 int *nparams,
14027 unsigned int flags)
14029 virQEMUDriverPtr driver = dom->conn->privateData;
14030 virDomainObjPtr vm;
14031 qemuDomainObjPrivatePtr priv;
14032 qemuDomainJobInfo jobInfo;
14033 bool completed = !!(flags & VIR_DOMAIN_JOB_STATS_COMPLETED);
14034 int ret = -1;
14036 virCheckFlags(VIR_DOMAIN_JOB_STATS_COMPLETED, -1);
14038 if (!(vm = qemuDomObjFromDomain(dom)))
14039 goto cleanup;
14041 if (virDomainGetJobStatsEnsureACL(dom->conn, vm->def) < 0)
14042 goto cleanup;
14044 priv = vm->privateData;
14045 if (qemuDomainGetJobStatsInternal(driver, vm, completed, &jobInfo) < 0)
14046 goto cleanup;
14048 if (jobInfo.status == QEMU_DOMAIN_JOB_STATUS_NONE) {
14049 *type = VIR_DOMAIN_JOB_NONE;
14050 *params = NULL;
14051 *nparams = 0;
14052 ret = 0;
14053 goto cleanup;
14056 ret = qemuDomainJobInfoToParams(&jobInfo, type, params, nparams);
14058 if (completed && ret == 0)
14059 VIR_FREE(priv->job.completed);
14061 cleanup:
14062 virDomainObjEndAPI(&vm);
14063 return ret;
14067 static int qemuDomainAbortJob(virDomainPtr dom)
14069 virQEMUDriverPtr driver = dom->conn->privateData;
14070 virDomainObjPtr vm;
14071 int ret = -1;
14072 qemuDomainObjPrivatePtr priv;
14073 int reason;
14075 if (!(vm = qemuDomObjFromDomain(dom)))
14076 goto cleanup;
14078 if (virDomainAbortJobEnsureACL(dom->conn, vm->def) < 0)
14079 goto cleanup;
14081 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0)
14082 goto cleanup;
14084 if (virDomainObjCheckActive(vm) < 0)
14085 goto endjob;
14087 priv = vm->privateData;
14089 if (!priv->job.asyncJob) {
14090 virReportError(VIR_ERR_OPERATION_INVALID,
14091 "%s", _("no job is active on the domain"));
14092 goto endjob;
14095 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
14096 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14097 _("cannot abort incoming migration;"
14098 " use virDomainDestroy instead"));
14099 goto endjob;
14102 if (priv->job.asyncJob == QEMU_ASYNC_JOB_DUMP &&
14103 priv->job.apiFlags & VIR_DUMP_MEMORY_ONLY) {
14104 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14105 _("cannot abort memory-only dump"));
14106 goto endjob;
14109 if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT &&
14110 (priv->job.current->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY ||
14111 (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
14112 reason == VIR_DOMAIN_PAUSED_POSTCOPY))) {
14113 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14114 _("cannot abort migration in post-copy mode"));
14115 goto endjob;
14118 VIR_DEBUG("Cancelling job at client request");
14119 qemuDomainObjAbortAsyncJob(vm);
14120 qemuDomainObjEnterMonitor(driver, vm);
14121 ret = qemuMonitorMigrateCancel(priv->mon);
14122 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14123 ret = -1;
14125 endjob:
14126 qemuDomainObjEndJob(driver, vm);
14128 cleanup:
14129 virDomainObjEndAPI(&vm);
14130 return ret;
14134 static int
14135 qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
14136 unsigned long long downtime,
14137 unsigned int flags)
14139 virQEMUDriverPtr driver = dom->conn->privateData;
14140 virDomainObjPtr vm;
14141 qemuDomainObjPrivatePtr priv;
14142 int ret = -1;
14144 virCheckFlags(0, -1);
14146 if (!(vm = qemuDomObjFromDomain(dom)))
14147 goto cleanup;
14149 if (virDomainMigrateSetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
14150 goto cleanup;
14152 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14153 goto cleanup;
14155 if (virDomainObjCheckActive(vm) < 0)
14156 goto endjob;
14158 priv = vm->privateData;
14160 VIR_DEBUG("Setting migration downtime to %llums", downtime);
14161 qemuDomainObjEnterMonitor(driver, vm);
14162 ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
14163 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14164 ret = -1;
14166 endjob:
14167 qemuDomainObjEndJob(driver, vm);
14169 cleanup:
14170 virDomainObjEndAPI(&vm);
14171 return ret;
14175 static int
14176 qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
14177 unsigned long long *downtime,
14178 unsigned int flags)
14180 virQEMUDriverPtr driver = dom->conn->privateData;
14181 virDomainObjPtr vm;
14182 qemuMigrationParamsPtr migParams = NULL;
14183 int ret = -1;
14184 int rc;
14186 virCheckFlags(0, -1);
14188 if (!(vm = qemuDomObjFromDomain(dom)))
14189 return -1;
14191 if (virDomainMigrateGetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0)
14192 goto cleanup;
14194 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14195 goto cleanup;
14197 if (virDomainObjCheckActive(vm) < 0)
14198 goto endjob;
14200 if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
14201 &migParams) < 0)
14202 goto endjob;
14204 if ((rc = qemuMigrationParamsGetULL(migParams,
14205 QEMU_MIGRATION_PARAM_DOWNTIME_LIMIT,
14206 downtime)) < 0) {
14207 goto endjob;
14210 if (rc == 1) {
14211 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14212 _("Querying migration downtime is not supported by "
14213 "QEMU binary"));
14214 goto endjob;
14217 ret = 0;
14219 endjob:
14220 qemuDomainObjEndJob(driver, vm);
14222 cleanup:
14223 qemuMigrationParamsFree(migParams);
14224 virDomainObjEndAPI(&vm);
14225 return ret;
14229 static int
14230 qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
14231 unsigned long long *cacheSize,
14232 unsigned int flags)
14234 virQEMUDriverPtr driver = dom->conn->privateData;
14235 virDomainObjPtr vm;
14236 qemuDomainObjPrivatePtr priv;
14237 int ret = -1;
14239 virCheckFlags(0, -1);
14241 if (!(vm = qemuDomObjFromDomain(dom)))
14242 goto cleanup;
14244 if (virDomainMigrateGetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
14245 goto cleanup;
14247 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14248 goto cleanup;
14250 if (virDomainObjCheckActive(vm) < 0)
14251 goto endjob;
14253 priv = vm->privateData;
14255 if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
14256 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
14257 _("Compressed migration is not supported by "
14258 "QEMU binary"));
14259 goto endjob;
14262 qemuDomainObjEnterMonitor(driver, vm);
14264 ret = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize);
14266 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14267 ret = -1;
14269 endjob:
14270 qemuDomainObjEndJob(driver, vm);
14272 cleanup:
14273 virDomainObjEndAPI(&vm);
14274 return ret;
14277 static int
14278 qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
14279 unsigned long long cacheSize,
14280 unsigned int flags)
14282 virQEMUDriverPtr driver = dom->conn->privateData;
14283 virDomainObjPtr vm;
14284 qemuDomainObjPrivatePtr priv;
14285 int ret = -1;
14287 virCheckFlags(0, -1);
14289 if (!(vm = qemuDomObjFromDomain(dom)))
14290 goto cleanup;
14292 if (virDomainMigrateSetCompressionCacheEnsureACL(dom->conn, vm->def) < 0)
14293 goto cleanup;
14295 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14296 goto cleanup;
14298 if (virDomainObjCheckActive(vm) < 0)
14299 goto endjob;
14301 priv = vm->privateData;
14303 if (!qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_XBZRLE)) {
14304 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
14305 _("Compressed migration is not supported by "
14306 "QEMU binary"));
14307 goto endjob;
14310 qemuDomainObjEnterMonitor(driver, vm);
14312 VIR_DEBUG("Setting compression cache to %llu B", cacheSize);
14313 ret = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize);
14315 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14316 ret = -1;
14318 endjob:
14319 qemuDomainObjEndJob(driver, vm);
14321 cleanup:
14322 virDomainObjEndAPI(&vm);
14323 return ret;
14326 static int
14327 qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
14328 unsigned long bandwidth,
14329 unsigned int flags)
14331 virQEMUDriverPtr driver = dom->conn->privateData;
14332 virDomainObjPtr vm;
14333 qemuDomainObjPrivatePtr priv;
14334 bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
14335 VIR_AUTOPTR(qemuMigrationParams) migParams = NULL;
14336 unsigned long long max;
14337 int ret = -1;
14339 virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
14341 if (!(vm = qemuDomObjFromDomain(dom)))
14342 goto cleanup;
14344 priv = vm->privateData;
14346 if (virDomainMigrateSetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
14347 goto cleanup;
14349 if (postcopy)
14350 max = ULLONG_MAX / 1024 / 1024;
14351 else
14352 max = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
14354 if (bandwidth > max) {
14355 virReportError(VIR_ERR_OVERFLOW,
14356 _("bandwidth must be less than %llu"), max + 1);
14357 goto cleanup;
14360 if (!postcopy && !virDomainObjIsActive(vm)) {
14361 priv->migMaxBandwidth = bandwidth;
14362 ret = 0;
14363 goto cleanup;
14366 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14367 goto cleanup;
14369 if (virDomainObjCheckActive(vm) < 0)
14370 goto endjob;
14372 VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
14374 if (postcopy) {
14375 if (!(migParams = qemuMigrationParamsNew()))
14376 goto endjob;
14378 if (qemuMigrationParamsSetULL(migParams,
14379 QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
14380 bandwidth * 1024 * 1024) < 0)
14381 goto endjob;
14383 if (qemuMigrationParamsApply(driver, vm, QEMU_ASYNC_JOB_NONE,
14384 migParams) < 0)
14385 goto endjob;
14386 } else {
14387 int rc;
14389 qemuDomainObjEnterMonitor(driver, vm);
14390 rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
14391 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
14392 goto endjob;
14394 priv->migMaxBandwidth = bandwidth;
14397 ret = 0;
14399 endjob:
14400 qemuDomainObjEndJob(driver, vm);
14402 cleanup:
14403 virDomainObjEndAPI(&vm);
14404 return ret;
14408 static int
14409 qemuDomainMigrationGetPostcopyBandwidth(virQEMUDriverPtr driver,
14410 virDomainObjPtr vm,
14411 unsigned long *bandwidth)
14413 VIR_AUTOPTR(qemuMigrationParams) migParams = NULL;
14414 unsigned long long bw;
14415 int rc;
14416 int ret = -1;
14418 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
14419 return -1;
14421 if (virDomainObjCheckActive(vm) < 0)
14422 goto cleanup;
14424 if (qemuMigrationParamsFetch(driver, vm, QEMU_ASYNC_JOB_NONE,
14425 &migParams) < 0)
14426 goto cleanup;
14428 if ((rc = qemuMigrationParamsGetULL(migParams,
14429 QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
14430 &bw)) < 0)
14431 goto cleanup;
14433 if (rc == 1) {
14434 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14435 _("querying maximum post-copy migration speed is "
14436 "not supported by QEMU binary"));
14437 goto cleanup;
14440 /* QEMU reports B/s while we use MiB/s */
14441 bw /= 1024 * 1024;
14443 if (bw > ULONG_MAX) {
14444 virReportError(VIR_ERR_OVERFLOW,
14445 _("bandwidth %llu is greater than %lu which is the "
14446 "maximum value supported by this API"),
14447 bw, ULONG_MAX);
14448 goto cleanup;
14451 *bandwidth = bw;
14452 ret = 0;
14454 cleanup:
14455 qemuDomainObjEndJob(driver, vm);
14456 return ret;
14460 static int
14461 qemuDomainMigrateGetMaxSpeed(virDomainPtr dom,
14462 unsigned long *bandwidth,
14463 unsigned int flags)
14465 virQEMUDriverPtr driver = dom->conn->privateData;
14466 virDomainObjPtr vm;
14467 qemuDomainObjPrivatePtr priv;
14468 bool postcopy = !!(flags & VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY);
14469 int ret = -1;
14471 virCheckFlags(VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY, -1);
14473 if (!(vm = qemuDomObjFromDomain(dom)))
14474 goto cleanup;
14476 priv = vm->privateData;
14478 if (virDomainMigrateGetMaxSpeedEnsureACL(dom->conn, vm->def) < 0)
14479 goto cleanup;
14481 if (postcopy) {
14482 if (qemuDomainMigrationGetPostcopyBandwidth(driver, vm, bandwidth) < 0)
14483 goto cleanup;
14484 } else {
14485 *bandwidth = priv->migMaxBandwidth;
14488 ret = 0;
14490 cleanup:
14491 virDomainObjEndAPI(&vm);
14492 return ret;
14496 static int
14497 qemuDomainMigrateStartPostCopy(virDomainPtr dom,
14498 unsigned int flags)
14500 virQEMUDriverPtr driver = dom->conn->privateData;
14501 virDomainObjPtr vm;
14502 qemuDomainObjPrivatePtr priv;
14503 int ret = -1;
14505 virCheckFlags(0, -1);
14507 if (!(vm = qemuDomObjFromDomain(dom)))
14508 goto cleanup;
14510 if (virDomainMigrateStartPostCopyEnsureACL(dom->conn, vm->def) < 0)
14511 goto cleanup;
14513 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0)
14514 goto cleanup;
14516 if (virDomainObjCheckActive(vm) < 0)
14517 goto endjob;
14519 priv = vm->privateData;
14521 if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) {
14522 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14523 _("post-copy can only be started while "
14524 "outgoing migration is in progress"));
14525 goto endjob;
14528 if (!(priv->job.apiFlags & VIR_MIGRATE_POSTCOPY)) {
14529 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
14530 _("switching to post-copy requires migration to be "
14531 "started with VIR_MIGRATE_POSTCOPY flag"));
14532 goto endjob;
14535 VIR_DEBUG("Starting post-copy");
14536 qemuDomainObjEnterMonitor(driver, vm);
14537 ret = qemuMonitorMigrateStartPostCopy(priv->mon);
14538 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14539 ret = -1;
14541 endjob:
14542 qemuDomainObjEndJob(driver, vm);
14544 cleanup:
14545 virDomainObjEndAPI(&vm);
14546 return ret;
14550 /* Return -1 if request is not sent to agent due to misconfig, -2 if request
14551 * is sent but failed, and number of frozen filesystems on success. If -2 is
14552 * returned, FSThaw should be called revert the quiesced status. */
14553 static int
14554 qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
14555 virDomainObjPtr vm,
14556 const char **mountpoints,
14557 unsigned int nmountpoints)
14559 qemuAgentPtr agent;
14560 int frozen;
14562 if (!qemuDomainAgentAvailable(vm, true))
14563 return -1;
14565 agent = qemuDomainObjEnterAgent(vm);
14566 frozen = qemuAgentFSFreeze(agent, mountpoints, nmountpoints);
14567 qemuDomainObjExitAgent(vm, agent);
14568 return frozen < 0 ? -2 : frozen;
14572 /* Return -1 on error, otherwise number of thawed filesystems. */
14573 static int
14574 qemuDomainSnapshotFSThaw(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
14575 virDomainObjPtr vm,
14576 bool report)
14578 qemuAgentPtr agent;
14579 int thawed;
14580 virErrorPtr err = NULL;
14582 if (!qemuDomainAgentAvailable(vm, report))
14583 return -1;
14585 agent = qemuDomainObjEnterAgent(vm);
14586 if (!report)
14587 err = virSaveLastError();
14588 thawed = qemuAgentFSThaw(agent);
14589 if (!report)
14590 virSetError(err);
14591 qemuDomainObjExitAgent(vm, agent);
14593 virFreeError(err);
14595 return thawed;
14599 /* The domain is expected to be locked and inactive. */
14600 static int
14601 qemuDomainSnapshotCreateInactiveInternal(virQEMUDriverPtr driver,
14602 virDomainObjPtr vm,
14603 virDomainMomentObjPtr snap)
14605 return qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-c", false);
14609 /* The domain is expected to be locked and inactive. */
14610 static int
14611 qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
14612 virDomainObjPtr vm,
14613 virDomainMomentObjPtr snap,
14614 bool reuse)
14616 size_t i;
14617 virDomainSnapshotDiskDefPtr snapdisk;
14618 virDomainDiskDefPtr defdisk;
14619 virCommandPtr cmd = NULL;
14620 const char *qemuImgPath;
14621 virBitmapPtr created = NULL;
14622 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
14623 int ret = -1;
14624 virBuffer buf = VIR_BUFFER_INITIALIZER;
14625 virDomainSnapshotDefPtr snapdef = virDomainSnapshotObjGetDef(snap);
14627 if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
14628 goto cleanup;
14630 if (!(created = virBitmapNew(snapdef->ndisks)))
14631 goto cleanup;
14633 /* If reuse is true, then qemuDomainSnapshotPrepare already
14634 * ensured that the new files exist, and it was up to the user to
14635 * create them correctly. */
14636 for (i = 0; i < snapdef->ndisks && !reuse; i++) {
14637 snapdisk = &(snapdef->disks[i]);
14638 defdisk = snapdef->common.dom->disks[snapdisk->idx];
14639 if (snapdisk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)
14640 continue;
14642 if (!snapdisk->src->format)
14643 snapdisk->src->format = VIR_STORAGE_FILE_QCOW2;
14645 /* creates cmd line args: qemu-img create -f qcow2 -o */
14646 if (!(cmd = virCommandNewArgList(qemuImgPath,
14647 "create",
14648 "-f",
14649 virStorageFileFormatTypeToString(snapdisk->src->format),
14650 "-o",
14651 NULL)))
14652 goto cleanup;
14654 /* adds cmd line arg: backing_fmt=format,backing_file=/path/to/backing/file */
14655 virBufferAsprintf(&buf, "backing_fmt=%s,backing_file=",
14656 virStorageFileFormatTypeToString(defdisk->src->format));
14657 virQEMUBuildBufferEscapeComma(&buf, defdisk->src->path);
14658 virCommandAddArgBuffer(cmd, &buf);
14660 /* adds cmd line args: /path/to/target/file */
14661 virQEMUBuildBufferEscapeComma(&buf, snapdisk->src->path);
14662 virCommandAddArgBuffer(cmd, &buf);
14664 /* If the target does not exist, we're going to create it possibly */
14665 if (!virFileExists(snapdisk->src->path))
14666 ignore_value(virBitmapSetBit(created, i));
14668 if (virCommandRun(cmd, NULL) < 0)
14669 goto cleanup;
14671 virCommandFree(cmd);
14672 cmd = NULL;
14675 /* update disk definitions */
14676 for (i = 0; i < snapdef->ndisks; i++) {
14677 snapdisk = &(snapdef->disks[i]);
14678 defdisk = vm->def->disks[snapdisk->idx];
14680 if (snapdisk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
14681 VIR_FREE(defdisk->src->path);
14682 if (VIR_STRDUP(defdisk->src->path, snapdisk->src->path) < 0) {
14683 /* we cannot rollback here in a sane way */
14684 goto cleanup;
14686 defdisk->src->format = snapdisk->src->format;
14688 if (virDomainSaveConfig(cfg->configDir, driver->caps, vm->def) < 0)
14689 goto cleanup;
14693 ret = 0;
14695 cleanup:
14696 virBufferFreeAndReset(&buf);
14697 virCommandFree(cmd);
14699 /* unlink images if creation has failed */
14700 if (ret < 0 && created) {
14701 ssize_t bit = -1;
14702 while ((bit = virBitmapNextSetBit(created, bit)) >= 0) {
14703 snapdisk = &(snapdef->disks[bit]);
14704 if (unlink(snapdisk->src->path) < 0)
14705 VIR_WARN("Failed to remove snapshot image '%s'",
14706 snapdisk->src->path);
14709 virBitmapFree(created);
14710 virObjectUnref(cfg);
14712 return ret;
14716 /* The domain is expected to be locked and active. */
14717 static int
14718 qemuDomainSnapshotCreateActiveInternal(virQEMUDriverPtr driver,
14719 virDomainObjPtr vm,
14720 virDomainMomentObjPtr snap,
14721 unsigned int flags)
14723 qemuDomainObjPrivatePtr priv = vm->privateData;
14724 virObjectEventPtr event = NULL;
14725 bool resume = false;
14726 virDomainSnapshotDefPtr snapdef = virDomainSnapshotObjGetDef(snap);
14727 int ret = -1;
14729 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
14730 goto cleanup;
14732 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
14733 /* savevm monitor command pauses the domain emitting an event which
14734 * confuses libvirt since it's not notified when qemu resumes the
14735 * domain. Thus we stop and start CPUs ourselves.
14737 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE,
14738 QEMU_ASYNC_JOB_SNAPSHOT) < 0)
14739 goto cleanup;
14741 resume = true;
14742 if (!virDomainObjIsActive(vm)) {
14743 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
14744 _("guest unexpectedly quit"));
14745 goto cleanup;
14749 if (qemuDomainObjEnterMonitorAsync(driver, vm,
14750 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
14751 resume = false;
14752 goto cleanup;
14755 ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
14756 if (qemuDomainObjExitMonitor(driver, vm) < 0)
14757 ret = -1;
14758 if (ret < 0)
14759 goto cleanup;
14761 if (!(snapdef->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
14762 goto cleanup;
14764 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
14765 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
14766 VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
14767 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
14768 QEMU_ASYNC_JOB_SNAPSHOT, 0);
14769 virDomainAuditStop(vm, "from-snapshot");
14770 resume = false;
14773 cleanup:
14774 if (resume && virDomainObjIsActive(vm) &&
14775 qemuProcessStartCPUs(driver, vm,
14776 VIR_DOMAIN_RUNNING_UNPAUSED,
14777 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
14778 event = virDomainEventLifecycleNewFromObj(vm,
14779 VIR_DOMAIN_EVENT_SUSPENDED,
14780 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
14781 if (virGetLastErrorCode() == VIR_ERR_OK) {
14782 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
14783 _("resuming after snapshot failed"));
14787 virObjectEventStateQueue(driver->domainEventState, event);
14789 return ret;
14793 static int
14794 qemuDomainSnapshotPrepareDiskShared(virDomainSnapshotDiskDefPtr snapdisk,
14795 virDomainDiskDefPtr domdisk)
14797 if (!domdisk->src->shared || domdisk->src->readonly)
14798 return 0;
14800 if (!qemuBlockStorageSourceSupportsConcurrentAccess(snapdisk->src)) {
14801 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14802 _("shared access for disk '%s' requires use of "
14803 "supported storage format"), domdisk->dst);
14804 return -1;
14807 return 0;
14811 static int
14812 qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
14813 virDomainDiskDefPtr domdisk)
14815 int domDiskType = virStorageSourceGetActualType(domdisk->src);
14816 int snapDiskType = virStorageSourceGetActualType(snapdisk->src);
14818 switch ((virStorageType)domDiskType) {
14819 case VIR_STORAGE_TYPE_BLOCK:
14820 case VIR_STORAGE_TYPE_FILE:
14821 break;
14823 case VIR_STORAGE_TYPE_NETWORK:
14824 switch ((virStorageNetProtocol) domdisk->src->protocol) {
14825 case VIR_STORAGE_NET_PROTOCOL_NONE:
14826 case VIR_STORAGE_NET_PROTOCOL_NBD:
14827 case VIR_STORAGE_NET_PROTOCOL_RBD:
14828 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
14829 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
14830 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
14831 case VIR_STORAGE_NET_PROTOCOL_HTTP:
14832 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
14833 case VIR_STORAGE_NET_PROTOCOL_FTP:
14834 case VIR_STORAGE_NET_PROTOCOL_FTPS:
14835 case VIR_STORAGE_NET_PROTOCOL_TFTP:
14836 case VIR_STORAGE_NET_PROTOCOL_SSH:
14837 case VIR_STORAGE_NET_PROTOCOL_VXHS:
14838 case VIR_STORAGE_NET_PROTOCOL_LAST:
14839 virReportError(VIR_ERR_INTERNAL_ERROR,
14840 _("external inactive snapshots are not supported on "
14841 "'network' disks using '%s' protocol"),
14842 virStorageNetProtocolTypeToString(domdisk->src->protocol));
14843 return -1;
14845 break;
14847 case VIR_STORAGE_TYPE_DIR:
14848 case VIR_STORAGE_TYPE_VOLUME:
14849 case VIR_STORAGE_TYPE_NONE:
14850 case VIR_STORAGE_TYPE_LAST:
14851 virReportError(VIR_ERR_INTERNAL_ERROR,
14852 _("external inactive snapshots are not supported on "
14853 "'%s' disks"), virStorageTypeToString(domDiskType));
14854 return -1;
14857 switch ((virStorageType)snapDiskType) {
14858 case VIR_STORAGE_TYPE_BLOCK:
14859 case VIR_STORAGE_TYPE_FILE:
14860 break;
14862 case VIR_STORAGE_TYPE_NETWORK:
14863 case VIR_STORAGE_TYPE_DIR:
14864 case VIR_STORAGE_TYPE_VOLUME:
14865 case VIR_STORAGE_TYPE_NONE:
14866 case VIR_STORAGE_TYPE_LAST:
14867 virReportError(VIR_ERR_INTERNAL_ERROR,
14868 _("external inactive snapshots are not supported on "
14869 "'%s' disks"), virStorageTypeToString(snapDiskType));
14870 return -1;
14873 if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
14874 return -1;
14876 return 0;
14880 static int
14881 qemuDomainSnapshotPrepareDiskExternalActive(virDomainSnapshotDiskDefPtr snapdisk,
14882 virDomainDiskDefPtr domdisk)
14884 int actualType = virStorageSourceGetActualType(snapdisk->src);
14886 if (domdisk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
14887 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
14888 _("external active snapshots are not supported on scsi "
14889 "passthrough devices"));
14890 return -1;
14893 switch ((virStorageType)actualType) {
14894 case VIR_STORAGE_TYPE_BLOCK:
14895 case VIR_STORAGE_TYPE_FILE:
14896 break;
14898 case VIR_STORAGE_TYPE_NETWORK:
14899 switch ((virStorageNetProtocol) snapdisk->src->protocol) {
14900 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
14901 break;
14903 case VIR_STORAGE_NET_PROTOCOL_NONE:
14904 case VIR_STORAGE_NET_PROTOCOL_NBD:
14905 case VIR_STORAGE_NET_PROTOCOL_RBD:
14906 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
14907 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
14908 case VIR_STORAGE_NET_PROTOCOL_HTTP:
14909 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
14910 case VIR_STORAGE_NET_PROTOCOL_FTP:
14911 case VIR_STORAGE_NET_PROTOCOL_FTPS:
14912 case VIR_STORAGE_NET_PROTOCOL_TFTP:
14913 case VIR_STORAGE_NET_PROTOCOL_SSH:
14914 case VIR_STORAGE_NET_PROTOCOL_VXHS:
14915 case VIR_STORAGE_NET_PROTOCOL_LAST:
14916 virReportError(VIR_ERR_INTERNAL_ERROR,
14917 _("external active snapshots are not supported on "
14918 "'network' disks using '%s' protocol"),
14919 virStorageNetProtocolTypeToString(snapdisk->src->protocol));
14920 return -1;
14923 break;
14925 case VIR_STORAGE_TYPE_DIR:
14926 case VIR_STORAGE_TYPE_VOLUME:
14927 case VIR_STORAGE_TYPE_NONE:
14928 case VIR_STORAGE_TYPE_LAST:
14929 virReportError(VIR_ERR_INTERNAL_ERROR,
14930 _("external active snapshots are not supported on "
14931 "'%s' disks"), virStorageTypeToString(actualType));
14932 return -1;
14935 if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
14936 return -1;
14938 return 0;
14942 static int
14943 qemuDomainSnapshotPrepareDiskExternal(virDomainDiskDefPtr disk,
14944 virDomainSnapshotDiskDefPtr snapdisk,
14945 bool active,
14946 bool reuse)
14948 int ret = -1;
14949 struct stat st;
14951 if (disk->src->readonly) {
14952 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14953 _("external snapshot for readonly disk %s "
14954 "is not supported"), disk->dst);
14955 return -1;
14958 if (qemuTranslateSnapshotDiskSourcePool(snapdisk) < 0)
14959 return -1;
14961 if (!active) {
14962 if (virDomainDiskTranslateSourcePool(disk) < 0)
14963 return -1;
14965 if (qemuDomainSnapshotPrepareDiskExternalInactive(snapdisk, disk) < 0)
14966 return -1;
14967 } else {
14968 if (qemuDomainSnapshotPrepareDiskExternalActive(snapdisk, disk) < 0)
14969 return -1;
14972 if (virStorageFileInit(snapdisk->src) < 0)
14973 return -1;
14975 if (virStorageFileStat(snapdisk->src, &st) < 0) {
14976 if (errno != ENOENT) {
14977 virReportSystemError(errno,
14978 _("unable to stat for disk %s: %s"),
14979 snapdisk->name, snapdisk->src->path);
14980 goto cleanup;
14981 } else if (reuse) {
14982 virReportSystemError(errno,
14983 _("missing existing file for disk %s: %s"),
14984 snapdisk->name, snapdisk->src->path);
14985 goto cleanup;
14987 } else if (!S_ISBLK(st.st_mode) && st.st_size && !reuse) {
14988 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14989 _("external snapshot file for disk %s already "
14990 "exists and is not a block device: %s"),
14991 snapdisk->name, snapdisk->src->path);
14992 goto cleanup;
14995 ret = 0;
14997 cleanup:
14998 virStorageFileDeinit(snapdisk->src);
14999 return ret;
15003 static int
15004 qemuDomainSnapshotPrepareDiskInternal(virDomainDiskDefPtr disk,
15005 bool active)
15007 int actualType;
15009 /* active disks are handled by qemu itself so no need to worry about those */
15010 if (active)
15011 return 0;
15013 if (virDomainDiskTranslateSourcePool(disk) < 0)
15014 return -1;
15016 actualType = virStorageSourceGetActualType(disk->src);
15018 switch ((virStorageType)actualType) {
15019 case VIR_STORAGE_TYPE_BLOCK:
15020 case VIR_STORAGE_TYPE_FILE:
15021 return 0;
15023 case VIR_STORAGE_TYPE_NETWORK:
15024 switch ((virStorageNetProtocol) disk->src->protocol) {
15025 case VIR_STORAGE_NET_PROTOCOL_NONE:
15026 case VIR_STORAGE_NET_PROTOCOL_NBD:
15027 case VIR_STORAGE_NET_PROTOCOL_RBD:
15028 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
15029 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
15030 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
15031 case VIR_STORAGE_NET_PROTOCOL_HTTP:
15032 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
15033 case VIR_STORAGE_NET_PROTOCOL_FTP:
15034 case VIR_STORAGE_NET_PROTOCOL_FTPS:
15035 case VIR_STORAGE_NET_PROTOCOL_TFTP:
15036 case VIR_STORAGE_NET_PROTOCOL_SSH:
15037 case VIR_STORAGE_NET_PROTOCOL_VXHS:
15038 case VIR_STORAGE_NET_PROTOCOL_LAST:
15039 virReportError(VIR_ERR_INTERNAL_ERROR,
15040 _("internal inactive snapshots are not supported on "
15041 "'network' disks using '%s' protocol"),
15042 virStorageNetProtocolTypeToString(disk->src->protocol));
15043 return -1;
15045 break;
15047 case VIR_STORAGE_TYPE_DIR:
15048 case VIR_STORAGE_TYPE_VOLUME:
15049 case VIR_STORAGE_TYPE_NONE:
15050 case VIR_STORAGE_TYPE_LAST:
15051 virReportError(VIR_ERR_INTERNAL_ERROR,
15052 _("internal inactive snapshots are not supported on "
15053 "'%s' disks"), virStorageTypeToString(actualType));
15054 return -1;
15057 return 0;
15061 static int
15062 qemuDomainSnapshotPrepare(virDomainObjPtr vm,
15063 virDomainSnapshotDefPtr def,
15064 unsigned int *flags)
15066 int ret = -1;
15067 size_t i;
15068 bool active = virDomainObjIsActive(vm);
15069 bool reuse = (*flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
15070 bool found_internal = false;
15071 bool forbid_internal = false;
15072 int external = 0;
15074 for (i = 0; i < def->ndisks; i++) {
15075 virDomainSnapshotDiskDefPtr disk = &def->disks[i];
15076 virDomainDiskDefPtr dom_disk = vm->def->disks[i];
15078 if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
15079 qemuDomainDiskBlockJobIsActive(dom_disk))
15080 goto cleanup;
15082 switch ((virDomainSnapshotLocation) disk->snapshot) {
15083 case VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL:
15084 found_internal = true;
15086 if (def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT && active) {
15087 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15088 _("active qemu domains require external disk "
15089 "snapshots; disk %s requested internal"),
15090 disk->name);
15091 goto cleanup;
15094 if (qemuDomainSnapshotPrepareDiskInternal(dom_disk,
15095 active) < 0)
15096 goto cleanup;
15098 if (vm->def->disks[i]->src->format > 0 &&
15099 vm->def->disks[i]->src->format != VIR_STORAGE_FILE_QCOW2) {
15100 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15101 _("internal snapshot for disk %s unsupported "
15102 "for storage type %s"),
15103 disk->name,
15104 virStorageFileFormatTypeToString(
15105 vm->def->disks[i]->src->format));
15106 goto cleanup;
15108 break;
15110 case VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:
15111 if (!disk->src->format) {
15112 disk->src->format = VIR_STORAGE_FILE_QCOW2;
15113 } else if (disk->src->format != VIR_STORAGE_FILE_QCOW2 &&
15114 disk->src->format != VIR_STORAGE_FILE_QED) {
15115 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15116 _("external snapshot format for disk %s "
15117 "is unsupported: %s"),
15118 disk->name,
15119 virStorageFileFormatTypeToString(disk->src->format));
15120 goto cleanup;
15123 if (qemuDomainSnapshotPrepareDiskExternal(dom_disk, disk,
15124 active, reuse) < 0)
15125 goto cleanup;
15127 external++;
15128 break;
15130 case VIR_DOMAIN_SNAPSHOT_LOCATION_NONE:
15131 /* Remember seeing a disk that has snapshot disabled */
15132 if (!virStorageSourceIsEmpty(dom_disk->src) &&
15133 !dom_disk->src->readonly)
15134 forbid_internal = true;
15135 break;
15137 case VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT:
15138 case VIR_DOMAIN_SNAPSHOT_LOCATION_LAST:
15139 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
15140 _("unexpected code path"));
15141 goto cleanup;
15145 if (!found_internal && !external &&
15146 def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
15147 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15148 _("nothing selected for snapshot"));
15149 goto cleanup;
15152 /* internal snapshot requires a disk image to store the memory image to, and
15153 * also disks can't be excluded from an internal snapshot*/
15154 if ((def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL && !found_internal) ||
15155 (found_internal && forbid_internal)) {
15156 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15157 _("internal and full system snapshots require all "
15158 "disks to be selected for snapshot"));
15159 goto cleanup;
15162 /* disk snapshot requires at least one disk */
15163 if (def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT && !external) {
15164 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15165 _("disk-only snapshots require at least "
15166 "one disk to be selected for snapshot"));
15167 goto cleanup;
15170 /* For now, we don't allow mixing internal and external disks.
15171 * XXX technically, we could mix internal and external disks for
15172 * offline snapshots */
15173 if ((found_internal && external) ||
15174 (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL && external) ||
15175 (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL && found_internal)) {
15176 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
15177 _("mixing internal and external targets for a snapshot "
15178 "is not yet supported"));
15179 goto cleanup;
15182 /* internal snapshots + pflash based loader have the following problems:
15183 * - if the variable store is raw, the snapshot fails
15184 * - allowing a qcow2 image as the varstore would make it eligible to receive
15185 * the vmstate dump, which would make it huge
15186 * - offline snapshot would not snapshot the varstore at all
15188 * Avoid the issues by forbidding internal snapshot with pflash completely.
15190 if (found_internal &&
15191 vm->def->os.loader &&
15192 vm->def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH) {
15193 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15194 _("internal snapshots of a VM with pflash based "
15195 "firmware are not supported"));
15196 goto cleanup;
15199 /* Alter flags to let later users know what we learned. */
15200 if (external && !active)
15201 *flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY;
15203 ret = 0;
15205 cleanup:
15206 return ret;
15210 struct _qemuDomainSnapshotDiskData {
15211 virStorageSourcePtr src;
15212 bool initialized; /* @src was initialized in the storage driver */
15213 bool created; /* @src was created by the snapshot code */
15214 bool prepared; /* @src was prepared using qemuDomainDiskChainElementPrepare */
15215 virDomainDiskDefPtr disk;
15216 char *relPath; /* relative path component to fill into original disk */
15218 virStorageSourcePtr persistsrc;
15219 virDomainDiskDefPtr persistdisk;
15222 typedef struct _qemuDomainSnapshotDiskData qemuDomainSnapshotDiskData;
15223 typedef qemuDomainSnapshotDiskData *qemuDomainSnapshotDiskDataPtr;
15226 static void
15227 qemuDomainSnapshotDiskDataFree(qemuDomainSnapshotDiskDataPtr data,
15228 size_t ndata,
15229 virQEMUDriverPtr driver,
15230 virDomainObjPtr vm)
15232 size_t i;
15234 if (!data)
15235 return;
15237 for (i = 0; i < ndata; i++) {
15238 /* on success of the snapshot the 'src' and 'persistsrc' properties will
15239 * be set to NULL by qemuDomainSnapshotUpdateDiskSources */
15240 if (data[i].src) {
15241 if (data[i].initialized)
15242 virStorageFileDeinit(data[i].src);
15244 if (data[i].prepared)
15245 qemuDomainDiskChainElementRevoke(driver, vm, data[i].src);
15247 virObjectUnref(data[i].src);
15249 virObjectUnref(data[i].persistsrc);
15250 VIR_FREE(data[i].relPath);
15253 VIR_FREE(data);
15258 * qemuDomainSnapshotDiskDataCollect:
15260 * Collects and prepares a list of structures that hold information about disks
15261 * that are selected for the snapshot.
15263 static qemuDomainSnapshotDiskDataPtr
15264 qemuDomainSnapshotDiskDataCollect(virQEMUDriverPtr driver,
15265 virDomainObjPtr vm,
15266 virDomainMomentObjPtr snap,
15267 bool reuse)
15269 size_t i;
15270 qemuDomainSnapshotDiskDataPtr ret;
15271 qemuDomainSnapshotDiskDataPtr dd;
15272 char *backingStoreStr;
15273 virDomainSnapshotDefPtr snapdef = virDomainSnapshotObjGetDef(snap);
15275 if (VIR_ALLOC_N(ret, snapdef->ndisks) < 0)
15276 return NULL;
15278 for (i = 0; i < snapdef->ndisks; i++) {
15279 if (snapdef->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
15280 continue;
15282 dd = ret + i;
15284 dd->disk = vm->def->disks[i];
15286 if (!(dd->src = virStorageSourceCopy(snapdef->disks[i].src, false)))
15287 goto error;
15289 if (virStorageSourceInitChainElement(dd->src, dd->disk->src, false) < 0)
15290 goto error;
15292 if (qemuDomainStorageFileInit(driver, vm, dd->src, NULL) < 0)
15293 goto error;
15295 dd->initialized = true;
15297 /* relative backing store paths need to be updated so that relative
15298 * block commit still works */
15299 if (reuse) {
15300 if (virStorageFileGetBackingStoreStr(dd->src, &backingStoreStr) < 0)
15301 goto error;
15302 if (backingStoreStr != NULL) {
15303 if (virStorageIsRelative(backingStoreStr))
15304 VIR_STEAL_PTR(dd->relPath, backingStoreStr);
15305 else
15306 VIR_FREE(backingStoreStr);
15310 /* Note that it's unsafe to assume that the disks in the persistent
15311 * definition match up with the disks in the live definition just by
15312 * checking that the target name is the same. We've done that
15313 * historically this way though. */
15314 if (vm->newDef &&
15315 (dd->persistdisk = virDomainDiskByName(vm->newDef, dd->disk->dst,
15316 false))) {
15318 if (!(dd->persistsrc = virStorageSourceCopy(dd->src, false)))
15319 goto error;
15321 if (virStorageSourceInitChainElement(dd->persistsrc,
15322 dd->persistdisk->src, false) < 0)
15323 goto error;
15327 return ret;
15329 error:
15330 qemuDomainSnapshotDiskDataFree(ret, snapdef->ndisks, driver, vm);
15331 return NULL;
15335 static void
15336 qemuDomainSnapshotUpdateDiskSourcesRenumber(virStorageSourcePtr src)
15338 virStorageSourcePtr next;
15339 unsigned int idx = 1;
15341 for (next = src->backingStore; virStorageSourceIsBacking(next); next = next->backingStore)
15342 next->id = idx++;
15347 * qemuDomainSnapshotUpdateDiskSources:
15348 * @dd: snapshot disk data object
15349 * @persist: set to true if persistent config of the VM was changed
15351 * Updates disk definition after a successful snapshot.
15353 static void
15354 qemuDomainSnapshotUpdateDiskSources(qemuDomainSnapshotDiskDataPtr dd,
15355 bool *persist)
15357 if (!dd->src)
15358 return;
15360 /* storage driver access won'd be needed */
15361 if (dd->initialized)
15362 virStorageFileDeinit(dd->src);
15364 /* the old disk image is now readonly */
15365 dd->disk->src->readonly = true;
15367 VIR_STEAL_PTR(dd->disk->src->relPath, dd->relPath);
15368 VIR_STEAL_PTR(dd->src->backingStore, dd->disk->src);
15369 VIR_STEAL_PTR(dd->disk->src, dd->src);
15371 /* fix numbering of disks */
15372 qemuDomainSnapshotUpdateDiskSourcesRenumber(dd->disk->src);
15374 if (dd->persistdisk) {
15375 VIR_STEAL_PTR(dd->persistsrc->backingStore, dd->persistdisk->src);
15376 VIR_STEAL_PTR(dd->persistdisk->src, dd->persistsrc);
15377 *persist = true;
15382 static int
15383 qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
15384 virDomainObjPtr vm,
15385 qemuDomainSnapshotDiskDataPtr dd,
15386 virJSONValuePtr actions,
15387 bool reuse)
15389 int ret = -1;
15391 if (qemuBlockSnapshotAddLegacy(actions, dd->disk, dd->src, reuse) < 0)
15392 goto cleanup;
15394 /* pre-create the image file so that we can label it before handing it to qemu */
15395 if (!reuse && dd->src->type != VIR_STORAGE_TYPE_BLOCK) {
15396 if (virStorageFileCreate(dd->src) < 0) {
15397 virReportSystemError(errno, _("failed to create image file '%s'"),
15398 NULLSTR(dd->src->path));
15399 goto cleanup;
15401 dd->created = true;
15404 /* set correct security, cgroup and locking options on the new image */
15405 if (qemuDomainDiskChainElementPrepare(driver, vm, dd->src, false, true) < 0) {
15406 qemuDomainDiskChainElementRevoke(driver, vm, dd->src);
15407 goto cleanup;
15410 dd->prepared = true;
15412 ret = 0;
15414 cleanup:
15415 return ret;
15419 /* The domain is expected to be locked and active. */
15420 static int
15421 qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
15422 virDomainObjPtr vm,
15423 virDomainMomentObjPtr snap,
15424 unsigned int flags,
15425 qemuDomainAsyncJob asyncJob)
15427 qemuDomainObjPrivatePtr priv = vm->privateData;
15428 virJSONValuePtr actions = NULL;
15429 bool do_transaction = false;
15430 int ret = 0;
15431 size_t i;
15432 bool persist = false;
15433 bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
15434 virQEMUDriverConfigPtr cfg = NULL;
15435 qemuDomainSnapshotDiskDataPtr diskdata = NULL;
15436 virErrorPtr orig_err = NULL;
15437 virDomainSnapshotDefPtr snapdef = virDomainSnapshotObjGetDef(snap);
15439 if (virDomainObjCheckActive(vm) < 0)
15440 return -1;
15442 if (!(actions = virJSONValueNewArray()))
15443 return -1;
15445 /* prepare a list of objects to use in the vm definition so that we don't
15446 * have to roll back later */
15447 if (!(diskdata = qemuDomainSnapshotDiskDataCollect(driver, vm, snap, reuse)))
15448 goto cleanup;
15450 cfg = virQEMUDriverGetConfig(driver);
15452 /* Based on earlier qemuDomainSnapshotPrepare, all disks in this list are
15453 * now either VIR_DOMAIN_SNAPSHOT_LOCATION_NONE, or
15454 * VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL with a valid file name and
15455 * qcow2 format. */
15456 for (i = 0; i < snapdef->ndisks; i++) {
15457 if (!diskdata[i].src)
15458 continue;
15460 ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
15461 &diskdata[i],
15462 actions, reuse);
15464 if (ret < 0)
15465 goto error;
15467 do_transaction = true;
15470 if (do_transaction) {
15471 if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
15472 goto cleanup;
15474 ret = qemuMonitorTransaction(priv->mon, &actions);
15476 if (qemuDomainObjExitMonitor(driver, vm) < 0)
15477 ret = -1;
15479 for (i = 0; i < snapdef->ndisks; i++) {
15480 qemuDomainSnapshotDiskDataPtr dd = &diskdata[i];
15482 if (!dd->src)
15483 continue;
15485 virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", ret >= 0);
15487 if (ret == 0)
15488 qemuDomainSnapshotUpdateDiskSources(dd, &persist);
15491 if (ret < 0)
15492 goto error;
15495 error:
15496 if (ret < 0) {
15497 orig_err = virSaveLastError();
15498 for (i = 0; i < snapdef->ndisks; i++) {
15499 if (!diskdata[i].src)
15500 continue;
15502 if (diskdata[i].prepared)
15503 qemuDomainDiskChainElementRevoke(driver, vm, diskdata[i].src);
15505 if (diskdata[i].created &&
15506 virStorageFileUnlink(diskdata[i].src) < 0)
15507 VIR_WARN("Unable to remove just-created %s", diskdata[i].src->path);
15509 } else {
15510 /* on successful snapshot we need to remove locks from the now-old
15511 * disks and if the VM is paused release locks on the images since qemu
15512 * stopped using them*/
15513 bool paused = virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING;
15515 for (i = 0; i < snapdef->ndisks; i++) {
15516 if (!diskdata[i].disk)
15517 continue;
15519 if (paused)
15520 virDomainLockImageDetach(driver->lockManager, vm,
15521 diskdata[i].disk->src);
15523 virDomainLockImageDetach(driver->lockManager, vm,
15524 diskdata[i].disk->src->backingStore);
15528 if (ret == 0 || !do_transaction) {
15529 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0 ||
15530 (persist && virDomainSaveConfig(cfg->configDir, driver->caps,
15531 vm->newDef) < 0))
15532 ret = -1;
15535 cleanup:
15536 qemuDomainSnapshotDiskDataFree(diskdata, snapdef->ndisks, driver, vm);
15537 virJSONValueFree(actions);
15538 virObjectUnref(cfg);
15540 if (orig_err) {
15541 virSetError(orig_err);
15542 virFreeError(orig_err);
15545 return ret;
15549 static int
15550 qemuDomainSnapshotCreateActiveExternal(virQEMUDriverPtr driver,
15551 virDomainObjPtr vm,
15552 virDomainMomentObjPtr snap,
15553 unsigned int flags)
15555 virObjectEventPtr event;
15556 bool resume = false;
15557 int ret = -1;
15558 qemuDomainObjPrivatePtr priv = vm->privateData;
15559 char *xml = NULL;
15560 virDomainSnapshotDefPtr snapdef = virDomainSnapshotObjGetDef(snap);
15561 bool memory = snapdef->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
15562 bool memory_unlink = false;
15563 int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
15564 bool pmsuspended = false;
15565 virQEMUDriverConfigPtr cfg = NULL;
15566 int compressed;
15567 char *compressedpath = NULL;
15568 virQEMUSaveDataPtr data = NULL;
15570 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DISK_SNAPSHOT) ||
15571 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_TRANSACTION)) {
15572 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15573 _("live disk snapshot not supported with this "
15574 "QEMU binary"));
15575 return -1;
15578 /* If quiesce was requested, then issue a freeze command, and a
15579 * counterpart thaw command when it is actually sent to agent.
15580 * The command will fail if the guest is paused or the guest agent
15581 * is not running, or is already quiesced. */
15582 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
15583 int freeze;
15585 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
15586 goto cleanup;
15588 if (virDomainObjCheckActive(vm) < 0) {
15589 qemuDomainObjEndAgentJob(vm);
15590 goto cleanup;
15593 freeze = qemuDomainSnapshotFSFreeze(driver, vm, NULL, 0);
15594 qemuDomainObjEndAgentJob(vm);
15596 if (freeze < 0) {
15597 /* the helper reported the error */
15598 if (freeze == -2)
15599 thaw = -1; /* the command is sent but agent failed */
15600 goto cleanup;
15602 thaw = 1;
15605 /* We need to track what state the guest is in, since taking the
15606 * snapshot may alter that state and we must restore it later. */
15607 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PMSUSPENDED) {
15608 pmsuspended = true;
15609 } else if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
15610 /* For full system external snapshots (those with memory), the guest
15611 * must pause (either by libvirt up front, or by qemu after
15612 * _LIVE converges). */
15613 if (memory)
15614 resume = true;
15616 if (memory && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE)) {
15617 if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SNAPSHOT,
15618 QEMU_ASYNC_JOB_SNAPSHOT) < 0)
15619 goto cleanup;
15621 if (!virDomainObjIsActive(vm)) {
15622 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
15623 _("guest unexpectedly quit"));
15624 goto cleanup;
15627 resume = true;
15631 /* do the memory snapshot if necessary */
15632 if (memory) {
15633 /* check if migration is possible */
15634 if (!qemuMigrationSrcIsAllowed(driver, vm, false, 0))
15635 goto cleanup;
15637 priv->job.current->statsType = QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP;
15639 /* allow the migration job to be cancelled or the domain to be paused */
15640 qemuDomainObjSetAsyncJobMask(vm, (QEMU_JOB_DEFAULT_MASK |
15641 JOB_MASK(QEMU_JOB_SUSPEND) |
15642 JOB_MASK(QEMU_JOB_MIGRATION_OP)));
15644 cfg = virQEMUDriverGetConfig(driver);
15645 if ((compressed = qemuGetCompressionProgram(cfg->snapshotImageFormat,
15646 &compressedpath,
15647 "snapshot", false)) < 0)
15648 goto cleanup;
15650 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
15651 true, true)) ||
15652 !(snapdef->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
15653 goto cleanup;
15655 if (!(data = virQEMUSaveDataNew(xml,
15656 (qemuDomainSaveCookiePtr) snapdef->cookie,
15657 resume, compressed, driver->xmlopt)))
15658 goto cleanup;
15659 xml = NULL;
15661 if ((ret = qemuDomainSaveMemory(driver, vm, snapdef->file, data,
15662 compressedpath, 0,
15663 QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
15664 goto cleanup;
15666 /* the memory image was created, remove it on errors */
15667 memory_unlink = true;
15669 /* forbid any further manipulation */
15670 qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_DEFAULT_MASK);
15673 /* the domain is now paused if a memory snapshot was requested */
15675 if ((ret = qemuDomainSnapshotCreateDiskActive(driver, vm, snap, flags,
15676 QEMU_ASYNC_JOB_SNAPSHOT)) < 0)
15677 goto cleanup;
15679 /* the snapshot is complete now */
15680 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
15681 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
15682 VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
15683 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
15684 QEMU_ASYNC_JOB_SNAPSHOT, 0);
15685 virDomainAuditStop(vm, "from-snapshot");
15686 resume = false;
15687 thaw = 0;
15688 virObjectEventStateQueue(driver->domainEventState, event);
15689 } else if (memory && pmsuspended) {
15690 /* qemu 1.3 is unable to save a domain in pm-suspended (S3)
15691 * state; so we must emit an event stating that it was
15692 * converted to paused. */
15693 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
15694 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
15695 event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
15696 VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT);
15697 virObjectEventStateQueue(driver->domainEventState, event);
15700 ret = 0;
15702 cleanup:
15703 if (resume && virDomainObjIsActive(vm) &&
15704 qemuProcessStartCPUs(driver, vm,
15705 VIR_DOMAIN_RUNNING_UNPAUSED,
15706 QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
15707 event = virDomainEventLifecycleNewFromObj(vm,
15708 VIR_DOMAIN_EVENT_SUSPENDED,
15709 VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
15710 virObjectEventStateQueue(driver->domainEventState, event);
15711 if (virGetLastErrorCode() == VIR_ERR_OK) {
15712 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
15713 _("resuming after snapshot failed"));
15716 ret = -1;
15719 if (thaw != 0 &&
15720 qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) >= 0 &&
15721 virDomainObjIsActive(vm)) {
15722 if (qemuDomainSnapshotFSThaw(driver, vm, ret == 0 && thaw > 0) < 0) {
15723 /* helper reported the error, if it was needed */
15724 if (thaw > 0)
15725 ret = -1;
15728 qemuDomainObjEndAgentJob(vm);
15731 virQEMUSaveDataFree(data);
15732 VIR_FREE(xml);
15733 VIR_FREE(compressedpath);
15734 virObjectUnref(cfg);
15735 if (memory_unlink && ret < 0)
15736 unlink(snapdef->file);
15738 return ret;
15742 static virDomainSnapshotPtr
15743 qemuDomainSnapshotCreateXML(virDomainPtr domain,
15744 const char *xmlDesc,
15745 unsigned int flags)
15747 virQEMUDriverPtr driver = domain->conn->privateData;
15748 virDomainObjPtr vm = NULL;
15749 char *xml = NULL;
15750 virDomainMomentObjPtr snap = NULL;
15751 virDomainSnapshotPtr snapshot = NULL;
15752 virDomainSnapshotDefPtr def = NULL;
15753 virDomainMomentObjPtr current = NULL;
15754 bool update_current = true;
15755 bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
15756 unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
15757 virDomainMomentObjPtr other = NULL;
15758 int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
15759 bool align_match = true;
15760 virQEMUDriverConfigPtr cfg = NULL;
15761 virCapsPtr caps = NULL;
15762 qemuDomainObjPrivatePtr priv;
15763 virDomainSnapshotState state;
15765 virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
15766 VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
15767 VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
15768 VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
15769 VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
15770 VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
15771 VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
15772 VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
15773 VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);
15775 VIR_REQUIRE_FLAG_RET(VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE,
15776 VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY,
15777 NULL);
15778 VIR_EXCLUSIVE_FLAGS_RET(VIR_DOMAIN_SNAPSHOT_CREATE_LIVE,
15779 VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE,
15780 NULL);
15782 if ((redefine && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
15783 (flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA))
15784 update_current = false;
15785 if (redefine)
15786 parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
15788 if (!(vm = qemuDomObjFromDomain(domain)))
15789 goto cleanup;
15791 cfg = virQEMUDriverGetConfig(driver);
15793 if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0)
15794 goto cleanup;
15796 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
15797 goto cleanup;
15799 if (qemuProcessAutoDestroyActive(driver, vm)) {
15800 virReportError(VIR_ERR_OPERATION_INVALID,
15801 "%s", _("domain is marked for auto destroy"));
15802 goto cleanup;
15805 if (!vm->persistent && (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT)) {
15806 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
15807 _("cannot halt after transient domain snapshot"));
15808 goto cleanup;
15810 if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) ||
15811 !virDomainObjIsActive(vm))
15812 parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE;
15814 if (!(def = virDomainSnapshotDefParseString(xmlDesc, caps, driver->xmlopt,
15815 NULL, parse_flags)))
15816 goto cleanup;
15818 /* reject snapshot names containing slashes or starting with dot as
15819 * snapshot definitions are saved in files named by the snapshot name */
15820 if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
15821 if (strchr(def->common.name, '/')) {
15822 virReportError(VIR_ERR_XML_DETAIL,
15823 _("invalid snapshot name '%s': "
15824 "name can't contain '/'"),
15825 def->common.name);
15826 goto cleanup;
15829 if (def->common.name[0] == '.') {
15830 virReportError(VIR_ERR_XML_DETAIL,
15831 _("invalid snapshot name '%s': "
15832 "name can't start with '.'"),
15833 def->common.name);
15834 goto cleanup;
15838 /* reject the VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag where not supported */
15839 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE &&
15840 (!virDomainObjIsActive(vm) ||
15841 def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)) {
15842 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15843 _("live snapshot creation is supported only "
15844 "during full system snapshots"));
15845 goto cleanup;
15848 /* allow snapshots only in certain states */
15849 state = redefine ? def->state : vm->state.state;
15850 switch (state) {
15851 /* valid states */
15852 case VIR_DOMAIN_SNAPSHOT_RUNNING:
15853 case VIR_DOMAIN_SNAPSHOT_PAUSED:
15854 case VIR_DOMAIN_SNAPSHOT_SHUTDOWN:
15855 case VIR_DOMAIN_SNAPSHOT_SHUTOFF:
15856 case VIR_DOMAIN_SNAPSHOT_CRASHED:
15857 break;
15859 case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT:
15860 if (!redefine) {
15861 virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"),
15862 virDomainSnapshotStateTypeToString(state));
15863 goto cleanup;
15865 break;
15867 case VIR_DOMAIN_SNAPSHOT_PMSUSPENDED:
15868 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15869 _("qemu doesn't support taking snapshots of "
15870 "PMSUSPENDED guests"));
15871 goto cleanup;
15873 /* invalid states */
15874 case VIR_DOMAIN_SNAPSHOT_NOSTATE:
15875 case VIR_DOMAIN_SNAPSHOT_BLOCKED: /* invalid state, unused in qemu */
15876 case VIR_DOMAIN_SNAPSHOT_LAST:
15877 virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid domain state %s"),
15878 virDomainSnapshotStateTypeToString(state));
15879 goto cleanup;
15882 /* We are going to modify the domain below. Internal snapshots would use
15883 * a regular job, so we need to set the job mask to disallow query as
15884 * 'savevm' blocks the monitor. External snapshot will then modify the
15885 * job mask appropriately. */
15886 if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_SNAPSHOT,
15887 VIR_DOMAIN_JOB_OPERATION_SNAPSHOT, flags) < 0)
15888 goto cleanup;
15890 qemuDomainObjSetAsyncJobMask(vm, QEMU_JOB_NONE);
15892 priv = vm->privateData;
15894 if (redefine) {
15895 if (virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
15896 driver->xmlopt,
15897 &update_current, flags) < 0)
15898 goto endjob;
15899 } else {
15900 /* Easiest way to clone inactive portion of vm->def is via
15901 * conversion in and back out of xml. */
15902 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
15903 true, true)) ||
15904 !(def->common.dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL,
15905 VIR_DOMAIN_DEF_PARSE_INACTIVE |
15906 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
15907 goto endjob;
15909 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
15910 align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
15911 align_match = false;
15912 if (virDomainObjIsActive(vm))
15913 def->state = VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT;
15914 else
15915 def->state = VIR_DOMAIN_SNAPSHOT_SHUTOFF;
15916 def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
15917 } else if (def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
15918 def->state = virDomainObjGetState(vm, NULL);
15919 align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
15920 align_match = false;
15921 } else {
15922 def->state = virDomainObjGetState(vm, NULL);
15924 if (virDomainObjIsActive(vm) &&
15925 def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
15926 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
15927 _("internal snapshot of a running VM "
15928 "must include the memory state"));
15929 goto endjob;
15932 def->memory = (def->state == VIR_DOMAIN_SNAPSHOT_SHUTOFF ?
15933 VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
15934 VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL);
15936 if (virDomainSnapshotAlignDisks(def, align_location,
15937 align_match) < 0 ||
15938 qemuDomainSnapshotPrepare(vm, def, &flags) < 0)
15939 goto endjob;
15942 if (!snap) {
15943 if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
15944 goto endjob;
15946 def = NULL;
15949 current = virDomainSnapshotGetCurrent(vm->snapshots);
15950 if (current) {
15951 if (!redefine &&
15952 VIR_STRDUP(snap->def->parent, current->def->name) < 0)
15953 goto endjob;
15954 if (update_current) {
15955 virDomainSnapshotSetCurrent(vm->snapshots, NULL);
15956 if (qemuDomainSnapshotWriteMetadata(vm, current,
15957 driver->caps, driver->xmlopt,
15958 cfg->snapshotDir) < 0)
15959 goto endjob;
15963 /* actually do the snapshot */
15964 if (redefine) {
15965 /* XXX Should we validate that the redefined snapshot even
15966 * makes sense, such as checking that qemu-img recognizes the
15967 * snapshot name in at least one of the domain's disks? */
15968 } else if (virDomainObjIsActive(vm)) {
15969 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ||
15970 virDomainSnapshotObjGetDef(snap)->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
15971 /* external full system or disk snapshot */
15972 if (qemuDomainSnapshotCreateActiveExternal(driver,
15973 vm, snap, flags) < 0)
15974 goto endjob;
15975 } else {
15976 /* internal full system */
15977 if (qemuDomainSnapshotCreateActiveInternal(driver,
15978 vm, snap, flags) < 0)
15979 goto endjob;
15981 } else {
15982 /* inactive; qemuDomainSnapshotPrepare guaranteed that we
15983 * aren't mixing internal and external, and altered flags to
15984 * contain DISK_ONLY if there is an external disk. */
15985 if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
15986 bool reuse = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
15988 if (qemuDomainSnapshotCreateInactiveExternal(driver, vm, snap,
15989 reuse) < 0)
15990 goto endjob;
15991 } else {
15992 if (qemuDomainSnapshotCreateInactiveInternal(driver, vm, snap) < 0)
15993 goto endjob;
15997 /* If we fail after this point, there's not a whole lot we can
15998 * do; we've successfully taken the snapshot, and we are now running
15999 * on it, so we have to go forward the best we can
16001 snapshot = virGetDomainSnapshot(domain, snap->def->name);
16003 endjob:
16004 if (snapshot && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
16005 if (update_current)
16006 virDomainSnapshotSetCurrent(vm->snapshots, snap);
16007 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
16008 driver->xmlopt,
16009 cfg->snapshotDir) < 0) {
16010 /* if writing of metadata fails, error out rather than trying
16011 * to silently carry on without completing the snapshot */
16012 virObjectUnref(snapshot);
16013 snapshot = NULL;
16014 virReportError(VIR_ERR_INTERNAL_ERROR,
16015 _("unable to save metadata for snapshot %s"),
16016 snap->def->name);
16017 virDomainSnapshotObjListRemove(vm->snapshots, snap);
16018 } else {
16019 other = virDomainSnapshotFindByName(vm->snapshots,
16020 snap->def->parent);
16021 virDomainMomentSetParent(snap, other);
16023 } else if (snap) {
16024 virDomainSnapshotObjListRemove(vm->snapshots, snap);
16027 qemuDomainObjEndAsyncJob(driver, vm);
16029 cleanup:
16030 virDomainObjEndAPI(&vm);
16031 virDomainSnapshotDefFree(def);
16032 VIR_FREE(xml);
16033 virObjectUnref(caps);
16034 virObjectUnref(cfg);
16035 return snapshot;
16039 static int
16040 qemuDomainSnapshotListNames(virDomainPtr domain,
16041 char **names,
16042 int nameslen,
16043 unsigned int flags)
16045 virDomainObjPtr vm = NULL;
16046 int n = -1;
16048 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16049 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16050 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16052 if (!(vm = qemuDomObjFromDomain(domain)))
16053 return -1;
16055 if (virDomainSnapshotListNamesEnsureACL(domain->conn, vm->def) < 0)
16056 goto cleanup;
16058 n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen,
16059 flags);
16061 cleanup:
16062 virDomainObjEndAPI(&vm);
16063 return n;
16067 static int
16068 qemuDomainSnapshotNum(virDomainPtr domain,
16069 unsigned int flags)
16071 virDomainObjPtr vm = NULL;
16072 int n = -1;
16074 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16075 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16076 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16078 if (!(vm = qemuDomObjFromDomain(domain)))
16079 return -1;
16081 if (virDomainSnapshotNumEnsureACL(domain->conn, vm->def) < 0)
16082 goto cleanup;
16084 n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags);
16086 cleanup:
16087 virDomainObjEndAPI(&vm);
16088 return n;
16092 static int
16093 qemuDomainListAllSnapshots(virDomainPtr domain,
16094 virDomainSnapshotPtr **snaps,
16095 unsigned int flags)
16097 virDomainObjPtr vm = NULL;
16098 int n = -1;
16100 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
16101 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16102 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16104 if (!(vm = qemuDomObjFromDomain(domain)))
16105 return -1;
16107 if (virDomainListAllSnapshotsEnsureACL(domain->conn, vm->def) < 0)
16108 goto cleanup;
16110 n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags);
16112 cleanup:
16113 virDomainObjEndAPI(&vm);
16114 return n;
16118 static int
16119 qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
16120 char **names,
16121 int nameslen,
16122 unsigned int flags)
16124 virDomainObjPtr vm = NULL;
16125 virDomainMomentObjPtr snap = NULL;
16126 int n = -1;
16128 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16129 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16130 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16132 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16133 return -1;
16135 if (virDomainSnapshotListChildrenNamesEnsureACL(snapshot->domain->conn, vm->def) < 0)
16136 goto cleanup;
16138 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16139 goto cleanup;
16141 n = virDomainSnapshotObjListGetNames(vm->snapshots, snap, names, nameslen,
16142 flags);
16144 cleanup:
16145 virDomainObjEndAPI(&vm);
16146 return n;
16150 static int
16151 qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
16152 unsigned int flags)
16154 virDomainObjPtr vm = NULL;
16155 virDomainMomentObjPtr snap = NULL;
16156 int n = -1;
16158 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16159 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16160 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16162 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16163 return -1;
16165 if (virDomainSnapshotNumChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
16166 goto cleanup;
16168 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16169 goto cleanup;
16171 n = virDomainSnapshotObjListNum(vm->snapshots, snap, flags);
16173 cleanup:
16174 virDomainObjEndAPI(&vm);
16175 return n;
16179 static int
16180 qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
16181 virDomainSnapshotPtr **snaps,
16182 unsigned int flags)
16184 virDomainObjPtr vm = NULL;
16185 virDomainMomentObjPtr snap = NULL;
16186 int n = -1;
16188 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
16189 VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL |
16190 VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
16192 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16193 return -1;
16195 if (virDomainSnapshotListAllChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0)
16196 goto cleanup;
16198 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16199 goto cleanup;
16201 n = virDomainListSnapshots(vm->snapshots, snap, snapshot->domain, snaps,
16202 flags);
16204 cleanup:
16205 virDomainObjEndAPI(&vm);
16206 return n;
16210 static virDomainSnapshotPtr
16211 qemuDomainSnapshotLookupByName(virDomainPtr domain,
16212 const char *name,
16213 unsigned int flags)
16215 virDomainObjPtr vm;
16216 virDomainMomentObjPtr snap = NULL;
16217 virDomainSnapshotPtr snapshot = NULL;
16219 virCheckFlags(0, NULL);
16221 if (!(vm = qemuDomObjFromDomain(domain)))
16222 return NULL;
16224 if (virDomainSnapshotLookupByNameEnsureACL(domain->conn, vm->def) < 0)
16225 goto cleanup;
16227 if (!(snap = qemuSnapObjFromName(vm, name)))
16228 goto cleanup;
16230 snapshot = virGetDomainSnapshot(domain, snap->def->name);
16232 cleanup:
16233 virDomainObjEndAPI(&vm);
16234 return snapshot;
16238 static int
16239 qemuDomainHasCurrentSnapshot(virDomainPtr domain,
16240 unsigned int flags)
16242 virDomainObjPtr vm;
16243 int ret = -1;
16245 virCheckFlags(0, -1);
16247 if (!(vm = qemuDomObjFromDomain(domain)))
16248 return -1;
16250 if (virDomainHasCurrentSnapshotEnsureACL(domain->conn, vm->def) < 0)
16251 goto cleanup;
16253 ret = (virDomainSnapshotGetCurrent(vm->snapshots) != NULL);
16255 cleanup:
16256 virDomainObjEndAPI(&vm);
16257 return ret;
16261 static virDomainSnapshotPtr
16262 qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
16263 unsigned int flags)
16265 virDomainObjPtr vm;
16266 virDomainMomentObjPtr snap = NULL;
16267 virDomainSnapshotPtr parent = NULL;
16269 virCheckFlags(0, NULL);
16271 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16272 return NULL;
16274 if (virDomainSnapshotGetParentEnsureACL(snapshot->domain->conn, vm->def) < 0)
16275 goto cleanup;
16277 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16278 goto cleanup;
16280 if (!snap->def->parent) {
16281 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
16282 _("snapshot '%s' does not have a parent"),
16283 snap->def->name);
16284 goto cleanup;
16287 parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);
16289 cleanup:
16290 virDomainObjEndAPI(&vm);
16291 return parent;
16295 static virDomainSnapshotPtr
16296 qemuDomainSnapshotCurrent(virDomainPtr domain,
16297 unsigned int flags)
16299 virDomainObjPtr vm;
16300 virDomainSnapshotPtr snapshot = NULL;
16301 const char *name;
16303 virCheckFlags(0, NULL);
16305 if (!(vm = qemuDomObjFromDomain(domain)))
16306 return NULL;
16308 if (virDomainSnapshotCurrentEnsureACL(domain->conn, vm->def) < 0)
16309 goto cleanup;
16311 name = virDomainSnapshotGetCurrentName(vm->snapshots);
16312 if (!name) {
16313 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
16314 _("the domain does not have a current snapshot"));
16315 goto cleanup;
16318 snapshot = virGetDomainSnapshot(domain, name);
16320 cleanup:
16321 virDomainObjEndAPI(&vm);
16322 return snapshot;
16326 static char *
16327 qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
16328 unsigned int flags)
16330 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
16331 virDomainObjPtr vm = NULL;
16332 char *xml = NULL;
16333 virDomainMomentObjPtr snap = NULL;
16334 char uuidstr[VIR_UUID_STRING_BUFLEN];
16336 virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
16338 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16339 return NULL;
16341 if (virDomainSnapshotGetXMLDescEnsureACL(snapshot->domain->conn, vm->def, flags) < 0)
16342 goto cleanup;
16344 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16345 goto cleanup;
16347 virUUIDFormat(snapshot->domain->uuid, uuidstr);
16349 xml = virDomainSnapshotDefFormat(uuidstr, virDomainSnapshotObjGetDef(snap),
16350 driver->caps, driver->xmlopt,
16351 virDomainSnapshotFormatConvertXMLFlags(flags));
16353 cleanup:
16354 virDomainObjEndAPI(&vm);
16355 return xml;
16359 static int
16360 qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
16361 unsigned int flags)
16363 virDomainObjPtr vm = NULL;
16364 int ret = -1;
16365 virDomainMomentObjPtr snap = NULL;
16367 virCheckFlags(0, -1);
16369 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16370 return -1;
16372 if (virDomainSnapshotIsCurrentEnsureACL(snapshot->domain->conn, vm->def) < 0)
16373 goto cleanup;
16375 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16376 goto cleanup;
16378 ret = snap == virDomainSnapshotGetCurrent(vm->snapshots);
16380 cleanup:
16381 virDomainObjEndAPI(&vm);
16382 return ret;
16386 static int
16387 qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
16388 unsigned int flags)
16390 virDomainObjPtr vm = NULL;
16391 int ret = -1;
16392 virDomainMomentObjPtr snap = NULL;
16394 virCheckFlags(0, -1);
16396 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16397 return -1;
16399 if (virDomainSnapshotHasMetadataEnsureACL(snapshot->domain->conn, vm->def) < 0)
16400 goto cleanup;
16402 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16403 goto cleanup;
16405 /* XXX Someday, we should recognize internal snapshots in qcow2
16406 * images that are not tied to a libvirt snapshot; if we ever do
16407 * that, then we would have a reason to return 0 here. */
16408 ret = 1;
16410 cleanup:
16411 virDomainObjEndAPI(&vm);
16412 return ret;
16416 /* The domain is expected to be locked and inactive. */
16417 static int
16418 qemuDomainSnapshotRevertInactive(virQEMUDriverPtr driver,
16419 virDomainObjPtr vm,
16420 virDomainMomentObjPtr snap)
16422 /* Try all disks, but report failure if we skipped any. */
16423 int ret = qemuDomainSnapshotForEachQcow2(driver, vm, snap, "-a", true);
16424 return ret > 0 ? -1 : ret;
16428 static int
16429 qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
16430 unsigned int flags)
16432 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
16433 virDomainObjPtr vm = NULL;
16434 int ret = -1;
16435 virDomainMomentObjPtr snap = NULL;
16436 virDomainMomentObjPtr current = NULL;
16437 virDomainSnapshotDefPtr snapdef;
16438 virObjectEventPtr event = NULL;
16439 virObjectEventPtr event2 = NULL;
16440 int detail;
16441 qemuDomainObjPrivatePtr priv;
16442 int rc;
16443 virDomainDefPtr config = NULL;
16444 virQEMUDriverConfigPtr cfg = NULL;
16445 virCapsPtr caps = NULL;
16446 bool was_stopped = false;
16447 qemuDomainSaveCookiePtr cookie;
16448 virCPUDefPtr origCPU = NULL;
16449 unsigned int start_flags = VIR_QEMU_PROCESS_START_GEN_VMID;
16450 qemuDomainAsyncJob jobType = QEMU_ASYNC_JOB_START;
16452 virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16453 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
16454 VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1);
16456 /* We have the following transitions, which create the following events:
16457 * 1. inactive -> inactive: none
16458 * 2. inactive -> running: EVENT_STARTED
16459 * 3. inactive -> paused: EVENT_STARTED, EVENT_PAUSED
16460 * 4. running -> inactive: EVENT_STOPPED
16461 * 5. running -> running: none
16462 * 6. running -> paused: EVENT_PAUSED
16463 * 7. paused -> inactive: EVENT_STOPPED
16464 * 8. paused -> running: EVENT_RESUMED
16465 * 9. paused -> paused: none
16466 * Also, several transitions occur even if we fail partway through,
16467 * and use of FORCE can cause multiple transitions.
16470 virNWFilterReadLockFilterUpdates();
16472 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16473 goto cleanup;
16475 cfg = virQEMUDriverGetConfig(driver);
16477 if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0)
16478 goto cleanup;
16480 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
16481 goto cleanup;
16483 if (qemuDomainHasBlockjob(vm, false)) {
16484 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16485 _("domain has active block job"));
16486 goto cleanup;
16489 if (qemuProcessBeginJob(driver, vm,
16490 VIR_DOMAIN_JOB_OPERATION_SNAPSHOT_REVERT,
16491 flags) < 0)
16492 goto cleanup;
16494 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16495 goto endjob;
16496 snapdef = virDomainSnapshotObjGetDef(snap);
16498 if (!vm->persistent &&
16499 snapdef->state != VIR_DOMAIN_SNAPSHOT_RUNNING &&
16500 snapdef->state != VIR_DOMAIN_SNAPSHOT_PAUSED &&
16501 (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16502 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) == 0) {
16503 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16504 _("transient domain needs to request run or pause "
16505 "to revert to inactive snapshot"));
16506 goto endjob;
16509 if (virDomainSnapshotIsExternal(snap)) {
16510 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
16511 _("revert to external snapshot not supported yet"));
16512 goto endjob;
16515 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
16516 if (!snap->def->dom) {
16517 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
16518 _("snapshot '%s' lacks domain '%s' rollback info"),
16519 snap->def->name, vm->def->name);
16520 goto endjob;
16522 if (virDomainObjIsActive(vm) &&
16523 !(snapdef->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
16524 snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED) &&
16525 (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16526 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
16527 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
16528 _("must respawn qemu to start inactive snapshot"));
16529 goto endjob;
16533 current = virDomainSnapshotGetCurrent(vm->snapshots);
16534 if (current) {
16535 virDomainSnapshotSetCurrent(vm->snapshots, NULL);
16536 if (qemuDomainSnapshotWriteMetadata(vm, current,
16537 driver->caps, driver->xmlopt,
16538 cfg->snapshotDir) < 0)
16539 goto endjob;
16540 /* XXX Should we restore the current snapshot after this point
16541 * in the failure cases where we know there was no change? */
16544 /* Prepare to copy the snapshot inactive xml as the config of this
16545 * domain.
16547 * XXX Should domain snapshots track live xml rather
16548 * than inactive xml? */
16549 if (snap->def->dom) {
16550 config = virDomainDefCopy(snap->def->dom, caps,
16551 driver->xmlopt, NULL, true);
16552 if (!config)
16553 goto endjob;
16556 cookie = (qemuDomainSaveCookiePtr) snapdef->cookie;
16558 switch ((virDomainSnapshotState) snapdef->state) {
16559 case VIR_DOMAIN_SNAPSHOT_RUNNING:
16560 case VIR_DOMAIN_SNAPSHOT_PAUSED:
16562 start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
16564 /* Transitions 2, 3, 5, 6, 8, 9 */
16565 /* When using the loadvm monitor command, qemu does not know
16566 * whether to pause or run the reverted domain, and just stays
16567 * in the same state as before the monitor command, whether
16568 * that is paused or running. We always pause before loadvm,
16569 * to have finer control. */
16570 if (virDomainObjIsActive(vm)) {
16571 /* Transitions 5, 6, 8, 9 */
16572 /* Check for ABI compatibility. We need to do this check against
16573 * the migratable XML or it will always fail otherwise */
16574 if (config) {
16575 bool compatible;
16577 /* Replace the CPU in config and put the original one in priv
16578 * once we're done. When we have the updated CPU def in the
16579 * cookie, we don't want to replace the CPU in migratable def
16580 * when doing ABI checks to make sure the current CPU exactly
16581 * matches the one used at the time the snapshot was taken.
16583 if (cookie && cookie->cpu && config->cpu) {
16584 origCPU = config->cpu;
16585 if (!(config->cpu = virCPUDefCopy(cookie->cpu)))
16586 goto endjob;
16588 compatible = qemuDomainDefCheckABIStability(driver, vm->def,
16589 config);
16590 } else {
16591 compatible = qemuDomainCheckABIStability(driver, vm, config);
16594 /* If using VM GenID, there is no way currently to change
16595 * the genid for the running guest, so set an error,
16596 * mark as incompatible, and don't allow change of genid
16597 * if the revert force flag would start the guest again. */
16598 if (compatible && config->genidRequested) {
16599 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
16600 _("domain genid update requires restart"));
16601 compatible = false;
16602 start_flags &= ~VIR_QEMU_PROCESS_START_GEN_VMID;
16605 if (!compatible) {
16606 virErrorPtr err = virGetLastError();
16608 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
16609 /* Re-spawn error using correct category. */
16610 if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
16611 virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
16612 err->str2);
16613 goto endjob;
16615 virResetError(err);
16616 qemuProcessStop(driver, vm,
16617 VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
16618 QEMU_ASYNC_JOB_START, 0);
16619 virDomainAuditStop(vm, "from-snapshot");
16620 detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
16621 event = virDomainEventLifecycleNewFromObj(vm,
16622 VIR_DOMAIN_EVENT_STOPPED,
16623 detail);
16624 virObjectEventStateQueue(driver->domainEventState, event);
16625 /* Start after stop won't be an async start job, so
16626 * reset to none */
16627 jobType = QEMU_ASYNC_JOB_NONE;
16628 goto load;
16632 priv = vm->privateData;
16633 if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
16634 /* Transitions 5, 6 */
16635 if (qemuProcessStopCPUs(driver, vm,
16636 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT,
16637 QEMU_ASYNC_JOB_START) < 0)
16638 goto endjob;
16639 /* Create an event now in case the restore fails, so
16640 * that user will be alerted that they are now paused.
16641 * If restore later succeeds, we might replace this. */
16642 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16643 event = virDomainEventLifecycleNewFromObj(vm,
16644 VIR_DOMAIN_EVENT_SUSPENDED,
16645 detail);
16646 if (!virDomainObjIsActive(vm)) {
16647 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16648 _("guest unexpectedly quit"));
16649 goto endjob;
16653 if (qemuDomainObjEnterMonitorAsync(driver, vm,
16654 QEMU_ASYNC_JOB_START) < 0)
16655 goto endjob;
16656 rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
16657 if (qemuDomainObjExitMonitor(driver, vm) < 0)
16658 goto endjob;
16659 if (rc < 0) {
16660 /* XXX resume domain if it was running before the
16661 * failed loadvm attempt? */
16662 goto endjob;
16664 if (config) {
16665 virDomainObjAssignDef(vm, config, false, NULL);
16666 virCPUDefFree(priv->origCPU);
16667 VIR_STEAL_PTR(priv->origCPU, origCPU);
16669 } else {
16670 /* Transitions 2, 3 */
16671 load:
16672 was_stopped = true;
16673 if (config)
16674 virDomainObjAssignDef(vm, config, false, NULL);
16676 /* No cookie means libvirt which saved the domain was too old to
16677 * mess up the CPU definitions.
16679 if (cookie &&
16680 qemuDomainFixupCPUs(vm, &cookie->cpu) < 0)
16681 goto cleanup;
16683 rc = qemuProcessStart(snapshot->domain->conn, driver, vm,
16684 cookie ? cookie->cpu : NULL,
16685 jobType, NULL, -1, NULL, snap,
16686 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
16687 start_flags);
16688 virDomainAuditStart(vm, "from-snapshot", rc >= 0);
16689 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16690 event = virDomainEventLifecycleNewFromObj(vm,
16691 VIR_DOMAIN_EVENT_STARTED,
16692 detail);
16693 if (rc < 0)
16694 goto endjob;
16697 /* Touch up domain state. */
16698 if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
16699 (snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED ||
16700 (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
16701 /* Transitions 3, 6, 9 */
16702 virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
16703 VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
16704 if (was_stopped) {
16705 /* Transition 3, use event as-is and add event2 */
16706 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16707 event2 = virDomainEventLifecycleNewFromObj(vm,
16708 VIR_DOMAIN_EVENT_SUSPENDED,
16709 detail);
16710 } /* else transition 6 and 9 use event as-is */
16711 } else {
16712 /* Transitions 2, 5, 8 */
16713 if (!virDomainObjIsActive(vm)) {
16714 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
16715 _("guest unexpectedly quit"));
16716 goto endjob;
16718 rc = qemuProcessStartCPUs(driver, vm,
16719 VIR_DOMAIN_RUNNING_FROM_SNAPSHOT,
16720 jobType);
16721 if (rc < 0)
16722 goto endjob;
16723 virObjectUnref(event);
16724 event = NULL;
16725 if (was_stopped) {
16726 /* Transition 2 */
16727 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16728 event = virDomainEventLifecycleNewFromObj(vm,
16729 VIR_DOMAIN_EVENT_STARTED,
16730 detail);
16733 break;
16735 case VIR_DOMAIN_SNAPSHOT_SHUTDOWN:
16736 case VIR_DOMAIN_SNAPSHOT_SHUTOFF:
16737 case VIR_DOMAIN_SNAPSHOT_CRASHED:
16738 /* Transitions 1, 4, 7 */
16739 /* Newer qemu -loadvm refuses to revert to the state of a snapshot
16740 * created by qemu-img snapshot -c. If the domain is running, we
16741 * must take it offline; then do the revert using qemu-img.
16744 if (virDomainObjIsActive(vm)) {
16745 /* Transitions 4, 7 */
16746 qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
16747 QEMU_ASYNC_JOB_START, 0);
16748 virDomainAuditStop(vm, "from-snapshot");
16749 detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
16750 event = virDomainEventLifecycleNewFromObj(vm,
16751 VIR_DOMAIN_EVENT_STOPPED,
16752 detail);
16755 if (qemuDomainSnapshotRevertInactive(driver, vm, snap) < 0) {
16756 qemuDomainRemoveInactive(driver, vm);
16757 qemuProcessEndJob(driver, vm);
16758 goto cleanup;
16760 if (config)
16761 virDomainObjAssignDef(vm, config, false, NULL);
16763 if (flags & (VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
16764 VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
16765 /* Flush first event, now do transition 2 or 3 */
16766 bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;
16768 start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
16770 virObjectEventStateQueue(driver->domainEventState, event);
16771 rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
16772 QEMU_ASYNC_JOB_START, NULL, -1, NULL, NULL,
16773 VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
16774 start_flags);
16775 virDomainAuditStart(vm, "from-snapshot", rc >= 0);
16776 if (rc < 0) {
16777 qemuDomainRemoveInactive(driver, vm);
16778 qemuProcessEndJob(driver, vm);
16779 goto cleanup;
16781 detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
16782 event = virDomainEventLifecycleNewFromObj(vm,
16783 VIR_DOMAIN_EVENT_STARTED,
16784 detail);
16785 if (paused) {
16786 detail = VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT;
16787 event2 = virDomainEventLifecycleNewFromObj(vm,
16788 VIR_DOMAIN_EVENT_SUSPENDED,
16789 detail);
16792 break;
16794 case VIR_DOMAIN_SNAPSHOT_PMSUSPENDED:
16795 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
16796 _("qemu doesn't support reversion of snapshot taken in "
16797 "PMSUSPENDED state"));
16798 goto endjob;
16800 case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT:
16801 /* Rejected earlier as an external snapshot */
16802 case VIR_DOMAIN_SNAPSHOT_NOSTATE:
16803 case VIR_DOMAIN_SNAPSHOT_BLOCKED:
16804 case VIR_DOMAIN_SNAPSHOT_LAST:
16805 virReportError(VIR_ERR_INTERNAL_ERROR,
16806 _("Invalid target domain state '%s'. Refusing "
16807 "snapshot reversion"),
16808 virDomainSnapshotStateTypeToString(snapdef->state));
16809 goto endjob;
16812 ret = 0;
16814 endjob:
16815 qemuProcessEndJob(driver, vm);
16817 cleanup:
16818 if (ret == 0) {
16819 virDomainSnapshotSetCurrent(vm->snapshots, snap);
16820 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
16821 driver->xmlopt,
16822 cfg->snapshotDir) < 0) {
16823 virDomainSnapshotSetCurrent(vm->snapshots, NULL);
16824 ret = -1;
16826 } else if (snap) {
16827 virDomainSnapshotSetCurrent(vm->snapshots, NULL);
16829 if (ret == 0 && config && vm->persistent &&
16830 !(ret = virDomainSaveConfig(cfg->configDir, driver->caps,
16831 vm->newDef ? vm->newDef : vm->def))) {
16832 detail = VIR_DOMAIN_EVENT_DEFINED_FROM_SNAPSHOT;
16833 virObjectEventStateQueue(driver->domainEventState,
16834 virDomainEventLifecycleNewFromObj(vm,
16835 VIR_DOMAIN_EVENT_DEFINED,
16836 detail));
16838 virObjectEventStateQueue(driver->domainEventState, event);
16839 virObjectEventStateQueue(driver->domainEventState, event2);
16840 virDomainObjEndAPI(&vm);
16841 virObjectUnref(caps);
16842 virObjectUnref(cfg);
16843 virNWFilterUnlockFilterUpdates();
16844 virCPUDefFree(origCPU);
16846 return ret;
16850 typedef struct _virQEMUMomentReparent virQEMUMomentReparent;
16851 typedef virQEMUMomentReparent *virQEMUMomentReparentPtr;
16852 struct _virQEMUMomentReparent {
16853 const char *dir;
16854 virDomainMomentObjPtr parent;
16855 virDomainObjPtr vm;
16856 virCapsPtr caps;
16857 virDomainXMLOptionPtr xmlopt;
16858 int err;
16859 int (*writeMetadata)(virDomainObjPtr, virDomainMomentObjPtr,
16860 virCapsPtr, virDomainXMLOptionPtr, const char *);
16864 static int
16865 qemuDomainMomentReparentChildren(void *payload,
16866 const void *name ATTRIBUTE_UNUSED,
16867 void *data)
16869 virDomainMomentObjPtr moment = payload;
16870 virQEMUMomentReparentPtr rep = data;
16872 if (rep->err < 0)
16873 return 0;
16875 VIR_FREE(moment->def->parent);
16877 if (rep->parent->def &&
16878 VIR_STRDUP(moment->def->parent, rep->parent->def->name) < 0) {
16879 rep->err = -1;
16880 return 0;
16883 rep->err = rep->writeMetadata(rep->vm, moment, rep->caps, rep->xmlopt,
16884 rep->dir);
16885 return 0;
16889 static int
16890 qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
16891 unsigned int flags)
16893 virQEMUDriverPtr driver = snapshot->domain->conn->privateData;
16894 virDomainObjPtr vm = NULL;
16895 int ret = -1;
16896 virDomainMomentObjPtr snap = NULL;
16897 virQEMUMomentRemove rem;
16898 virQEMUMomentReparent rep;
16899 bool metadata_only = !!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY);
16900 int external = 0;
16901 virQEMUDriverConfigPtr cfg = NULL;
16903 virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
16904 VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY |
16905 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, -1);
16907 if (!(vm = qemuDomObjFromSnapshot(snapshot)))
16908 return -1;
16910 cfg = virQEMUDriverGetConfig(driver);
16912 if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, vm->def) < 0)
16913 goto cleanup;
16915 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
16916 goto cleanup;
16918 if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
16919 goto endjob;
16921 if (!metadata_only) {
16922 if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
16923 virDomainSnapshotIsExternal(snap))
16924 external++;
16925 if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
16926 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY))
16927 virDomainMomentForEachDescendant(snap,
16928 qemuDomainSnapshotCountExternal,
16929 &external);
16930 if (external) {
16931 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
16932 _("deletion of %d external disk snapshots not "
16933 "supported yet"), external);
16934 goto endjob;
16938 if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
16939 VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
16940 rem.driver = driver;
16941 rem.vm = vm;
16942 rem.metadata_only = metadata_only;
16943 rem.err = 0;
16944 rem.current = virDomainSnapshotGetCurrent(vm->snapshots);
16945 rem.found = false;
16946 rem.momentDiscard = qemuDomainSnapshotDiscard;
16947 virDomainMomentForEachDescendant(snap, qemuDomainMomentDiscardAll,
16948 &rem);
16949 if (rem.err < 0)
16950 goto endjob;
16951 if (rem.found) {
16952 virDomainSnapshotSetCurrent(vm->snapshots, snap);
16953 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
16954 if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->caps,
16955 driver->xmlopt,
16956 cfg->snapshotDir) < 0) {
16957 virReportError(VIR_ERR_INTERNAL_ERROR,
16958 _("failed to set snapshot '%s' as current"),
16959 snap->def->name);
16960 virDomainSnapshotSetCurrent(vm->snapshots, NULL);
16961 goto endjob;
16965 } else if (snap->nchildren) {
16966 rep.dir = cfg->snapshotDir;
16967 rep.parent = snap->parent;
16968 rep.vm = vm;
16969 rep.err = 0;
16970 rep.caps = driver->caps;
16971 rep.xmlopt = driver->xmlopt;
16972 rep.writeMetadata = qemuDomainSnapshotWriteMetadata;
16973 virDomainMomentForEachChild(snap,
16974 qemuDomainMomentReparentChildren,
16975 &rep);
16976 if (rep.err < 0)
16977 goto endjob;
16978 virDomainMomentMoveChildren(snap, snap->parent);
16981 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) {
16982 virDomainMomentDropChildren(snap);
16983 ret = 0;
16984 } else {
16985 ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only);
16988 endjob:
16989 qemuDomainObjEndJob(driver, vm);
16991 cleanup:
16992 virDomainObjEndAPI(&vm);
16993 virObjectUnref(cfg);
16994 return ret;
16998 /* Called prior to job lock */
16999 static virDomainCheckpointDefPtr
17000 qemuDomainCheckpointDefParseString(virQEMUDriverPtr driver, virCapsPtr caps,
17001 const char *xmlDesc, unsigned int flags)
17003 virDomainCheckpointDefPtr def = NULL;
17004 virDomainCheckpointDefPtr ret = NULL;
17005 unsigned int parse_flags = 0;
17007 if (flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE)
17008 parse_flags |= VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
17009 if (!(def = virDomainCheckpointDefParseString(xmlDesc, caps, driver->xmlopt,
17010 NULL, parse_flags)))
17011 goto cleanup;
17013 /* reject checkpoint names containing slashes or starting with dot as
17014 * checkpoint definitions are saved in files named by the checkpoint name */
17015 if (!(flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA)) {
17016 if (strchr(def->common.name, '/')) {
17017 virReportError(VIR_ERR_XML_DETAIL,
17018 _("invalid checkpoint name '%s': "
17019 "name can't contain '/'"),
17020 def->common.name);
17021 goto cleanup;
17024 if (def->common.name[0] == '.') {
17025 virReportError(VIR_ERR_XML_DETAIL,
17026 _("invalid checkpoint name '%s': "
17027 "name can't start with '.'"),
17028 def->common.name);
17029 goto cleanup;
17033 VIR_STEAL_PTR(ret, def);
17035 cleanup:
17036 virDomainCheckpointDefFree(def);
17037 return ret;
17041 /* Called inside job lock */
17042 static int
17043 qemuDomainCheckpointPrepare(virQEMUDriverPtr driver, virCapsPtr caps,
17044 virDomainObjPtr vm,
17045 virDomainCheckpointDefPtr def)
17047 int ret = -1;
17048 size_t i;
17049 char *xml = NULL;
17050 qemuDomainObjPrivatePtr priv = vm->privateData;
17052 /* Easiest way to clone inactive portion of vm->def is via
17053 * conversion in and back out of xml. */
17054 if (!(xml = qemuDomainDefFormatLive(driver, vm->def, priv->origCPU,
17055 true, true)) ||
17056 !(def->common.dom = virDomainDefParseString(xml, caps, driver->xmlopt, NULL,
17057 VIR_DOMAIN_DEF_PARSE_INACTIVE |
17058 VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
17059 goto cleanup;
17061 if (virDomainCheckpointAlignDisks(def) < 0 ||
17062 qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
17063 goto cleanup;
17065 for (i = 0; i < def->ndisks; i++) {
17066 virDomainCheckpointDiskDefPtr disk = &def->disks[i];
17068 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17069 continue;
17071 /* We want to name temporary bitmap after disk name during
17072 * incremental backup, which is not possible if that is a
17073 * persistent bitmap name. We can also make life easier by
17074 * enforcing bitmap names match checkpoint name, although this
17075 * is not technically necessary. */
17076 if (STREQ(disk->name, disk->bitmap)) {
17077 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17078 _("checkpoint for disk %s must have distinct bitmap name"),
17079 disk->name);
17080 goto cleanup;
17082 if (STRNEQ(disk->bitmap, def->common.name)) {
17083 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17084 _("disk %s bitmap should match checkpoint name %s"),
17085 disk->name, def->common.name);
17086 goto cleanup;
17089 if (vm->def->disks[i]->src->format > 0 &&
17090 vm->def->disks[i]->src->format != VIR_STORAGE_FILE_QCOW2) {
17091 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17092 _("checkpoint for disk %s unsupported "
17093 "for storage type %s"),
17094 disk->name,
17095 virStorageFileFormatTypeToString(
17096 vm->def->disks[i]->src->format));
17097 goto cleanup;
17101 ret = 0;
17103 cleanup:
17104 VIR_FREE(xml);
17105 return ret;
17108 static int
17109 qemuDomainCheckpointAddActions(virDomainObjPtr vm,
17110 virJSONValuePtr actions,
17111 virDomainMomentObjPtr old_current,
17112 virDomainCheckpointDefPtr def)
17114 size_t i, j;
17115 int ret = -1;
17116 virDomainCheckpointDefPtr olddef;
17118 olddef = virDomainCheckpointObjGetDef(old_current);
17119 for (i = 0; i < def->ndisks; i++) {
17120 virDomainCheckpointDiskDef *disk = &def->disks[i];
17121 const char *node;
17123 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17124 continue;
17125 node = qemuBlockNodeLookup(vm, disk->name);
17126 if (qemuMonitorJSONTransactionAdd(actions,
17127 "block-dirty-bitmap-add",
17128 "s:node", node,
17129 "s:name", disk->bitmap,
17130 "b:persistent", true,
17131 NULL) < 0)
17132 goto cleanup;
17133 if (old_current) {
17134 for (j = 0; j < olddef->ndisks; j++) {
17135 virDomainCheckpointDiskDef *disk2;
17137 disk2 = &olddef->disks[j];
17138 if (STRNEQ(disk->name, disk2->name))
17139 continue;
17140 if (disk2->type == VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP &&
17141 qemuMonitorJSONTransactionAdd(actions,
17142 "block-dirty-bitmap-disable",
17143 "s:node", node,
17144 "s:name", disk2->bitmap,
17145 NULL) < 0)
17146 goto cleanup;
17150 ret = 0;
17152 cleanup:
17153 return ret;
17156 static virDomainCheckpointPtr
17157 qemuDomainCheckpointCreateXML(virDomainPtr domain,
17158 const char *xmlDesc,
17159 unsigned int flags)
17161 virQEMUDriverPtr driver = domain->conn->privateData;
17162 virDomainObjPtr vm = NULL;
17163 char *xml = NULL;
17164 virDomainMomentObjPtr chk = NULL;
17165 virDomainCheckpointPtr checkpoint = NULL;
17166 virDomainCheckpointDefPtr def = NULL;
17167 virDomainMomentObjPtr current = NULL;
17168 bool update_current = true;
17169 bool redefine = flags & VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE;
17170 unsigned int parse_flags = 0;
17171 virDomainMomentObjPtr other = NULL;
17172 virQEMUDriverConfigPtr cfg = NULL;
17173 virCapsPtr caps = NULL;
17174 qemuDomainObjPrivatePtr priv;
17175 virJSONValuePtr actions = NULL;
17176 int ret;
17178 virCheckFlags(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE |
17179 VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT |
17180 VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, NULL);
17181 /* TODO: VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE */
17183 if (redefine)
17184 parse_flags |= VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE;
17185 if ((redefine && !(flags & VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT)) ||
17186 (flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA))
17187 update_current = false;
17189 if (!(vm = qemuDomObjFromDomain(domain)))
17190 goto cleanup;
17192 priv = vm->privateData;
17193 cfg = virQEMUDriverGetConfig(driver);
17195 if (virDomainCheckpointCreateXMLEnsureACL(domain->conn, vm->def, flags) < 0)
17196 goto cleanup;
17198 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17199 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17200 _("qemu binary lacks persistent bitmaps support"));
17201 goto cleanup;
17204 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
17205 goto cleanup;
17207 if (qemuProcessAutoDestroyActive(driver, vm)) {
17208 virReportError(VIR_ERR_OPERATION_INVALID,
17209 "%s", _("domain is marked for auto destroy"));
17210 goto cleanup;
17213 if (!virDomainObjIsActive(vm)) {
17214 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17215 _("cannot create checkpoint for inactive domain"));
17216 goto cleanup;
17219 if (!(def = qemuDomainCheckpointDefParseString(driver, caps, xmlDesc,
17220 parse_flags)))
17221 goto cleanup;
17223 /* We are going to modify the domain below. */
17224 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17225 goto cleanup;
17227 if (redefine) {
17228 if (virDomainCheckpointRedefinePrep(domain, vm, &def, &chk,
17229 driver->xmlopt,
17230 &update_current) < 0)
17231 goto endjob;
17232 } else if (qemuDomainCheckpointPrepare(driver, caps, vm, def) < 0) {
17233 goto endjob;
17236 if (!chk) {
17237 if (!(chk = virDomainCheckpointAssignDef(vm->checkpoints, def)))
17238 goto endjob;
17240 def = NULL;
17243 other = virDomainCheckpointGetCurrent(vm->checkpoints);
17244 if (other) {
17245 if (!redefine &&
17246 VIR_STRDUP(chk->def->parent, other->def->name) < 0)
17247 goto endjob;
17248 if (update_current) {
17249 virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
17250 if (qemuDomainCheckpointWriteMetadata(vm, current,
17251 driver->caps, driver->xmlopt,
17252 cfg->checkpointDir) < 0)
17253 goto endjob;
17257 /* actually do the checkpoint */
17258 if (redefine) {
17259 /* XXX Should we validate that the redefined checkpoint even
17260 * makes sense, such as checking that qemu-img recognizes the
17261 * checkpoint bitmap name in at least one of the domain's disks? */
17262 } else {
17263 if (!(actions = virJSONValueNewArray()))
17264 goto endjob;
17265 if (qemuDomainCheckpointAddActions(vm, actions, other,
17266 virDomainCheckpointObjGetDef(chk)) < 0)
17267 goto endjob;
17268 qemuDomainObjEnterMonitor(driver, vm);
17269 ret = qemuMonitorTransaction(priv->mon, &actions);
17270 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
17271 goto endjob;
17274 /* If we fail after this point, there's not a whole lot we can do;
17275 * we've successfully created the checkpoint, so we have to go
17276 * forward the best we can.
17278 checkpoint = virGetDomainCheckpoint(domain, chk->def->name);
17280 endjob:
17281 if (checkpoint && !(flags & VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA)) {
17282 if (update_current)
17283 virDomainCheckpointSetCurrent(vm->checkpoints, chk);
17284 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
17285 driver->xmlopt,
17286 cfg->checkpointDir) < 0) {
17287 /* if writing of metadata fails, error out rather than trying
17288 * to silently carry on without completing the checkpoint */
17289 virObjectUnref(checkpoint);
17290 checkpoint = NULL;
17291 virReportError(VIR_ERR_INTERNAL_ERROR,
17292 _("unable to save metadata for checkpoint %s"),
17293 chk->def->name);
17294 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
17295 } else {
17296 other = virDomainCheckpointFindByName(vm->checkpoints,
17297 chk->def->parent);
17298 virDomainMomentSetParent(chk, other);
17300 } else if (chk) {
17301 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
17304 qemuDomainObjEndJob(driver, vm);
17306 cleanup:
17307 virJSONValueFree(actions);
17308 virDomainObjEndAPI(&vm);
17309 virDomainCheckpointDefFree(def);
17310 VIR_FREE(xml);
17311 virObjectUnref(caps);
17312 virObjectUnref(cfg);
17313 return checkpoint;
17317 static int
17318 qemuDomainListAllCheckpoints(virDomainPtr domain,
17319 virDomainCheckpointPtr **chks,
17320 unsigned int flags)
17322 virDomainObjPtr vm = NULL;
17323 int n = -1;
17325 virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS |
17326 VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
17327 VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
17329 if (!(vm = qemuDomObjFromDomain(domain)))
17330 return -1;
17332 if (virDomainListAllCheckpointsEnsureACL(domain->conn, vm->def) < 0)
17333 goto cleanup;
17335 n = virDomainListCheckpoints(vm->checkpoints, NULL, domain, chks, flags);
17337 cleanup:
17338 virDomainObjEndAPI(&vm);
17339 return n;
17343 static int
17344 qemuDomainCheckpointListAllChildren(virDomainCheckpointPtr checkpoint,
17345 virDomainCheckpointPtr **chks,
17346 unsigned int flags)
17348 virDomainObjPtr vm = NULL;
17349 virDomainMomentObjPtr chk = NULL;
17350 int n = -1;
17352 virCheckFlags(VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS |
17353 VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL |
17354 VIR_DOMAIN_CHECKPOINT_FILTERS_ALL, -1);
17356 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17357 return -1;
17359 if (virDomainCheckpointListAllChildrenEnsureACL(checkpoint->domain->conn,
17360 vm->def) < 0)
17361 goto cleanup;
17363 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17364 goto cleanup;
17366 n = virDomainListCheckpoints(vm->checkpoints, chk, checkpoint->domain,
17367 chks, flags);
17369 cleanup:
17370 virDomainObjEndAPI(&vm);
17371 return n;
17375 static virDomainCheckpointPtr
17376 qemuDomainCheckpointLookupByName(virDomainPtr domain,
17377 const char *name,
17378 unsigned int flags)
17380 virDomainObjPtr vm;
17381 virDomainMomentObjPtr chk = NULL;
17382 virDomainCheckpointPtr checkpoint = NULL;
17384 virCheckFlags(0, NULL);
17386 if (!(vm = qemuDomObjFromDomain(domain)))
17387 return NULL;
17389 if (virDomainCheckpointLookupByNameEnsureACL(domain->conn, vm->def) < 0)
17390 goto cleanup;
17392 if (!(chk = qemuCheckObjFromName(vm, name)))
17393 goto cleanup;
17395 checkpoint = virGetDomainCheckpoint(domain, chk->def->name);
17397 cleanup:
17398 virDomainObjEndAPI(&vm);
17399 return checkpoint;
17403 static int
17404 qemuDomainHasCurrentCheckpoint(virDomainPtr domain,
17405 unsigned int flags)
17407 virDomainObjPtr vm;
17408 int ret = -1;
17410 virCheckFlags(0, -1);
17412 if (!(vm = qemuDomObjFromDomain(domain)))
17413 return -1;
17415 if (virDomainHasCurrentCheckpointEnsureACL(domain->conn, vm->def) < 0)
17416 goto cleanup;
17418 ret = (virDomainCheckpointGetCurrent(vm->checkpoints) != NULL);
17420 cleanup:
17421 virDomainObjEndAPI(&vm);
17422 return ret;
17426 static virDomainCheckpointPtr
17427 qemuDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint,
17428 unsigned int flags)
17430 virDomainObjPtr vm;
17431 virDomainMomentObjPtr chk = NULL;
17432 virDomainCheckpointPtr parent = NULL;
17434 virCheckFlags(0, NULL);
17436 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17437 return NULL;
17439 if (virDomainCheckpointGetParentEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17440 goto cleanup;
17442 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17443 goto cleanup;
17445 if (!chk->def->parent) {
17446 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
17447 _("checkpoint '%s' does not have a parent"),
17448 chk->def->name);
17449 goto cleanup;
17452 parent = virGetDomainCheckpoint(checkpoint->domain, chk->def->parent);
17454 cleanup:
17455 virDomainObjEndAPI(&vm);
17456 return parent;
17460 static virDomainCheckpointPtr
17461 qemuDomainCheckpointCurrent(virDomainPtr domain,
17462 unsigned int flags)
17464 virDomainObjPtr vm;
17465 virDomainCheckpointPtr checkpoint = NULL;
17466 const char *name;
17468 virCheckFlags(0, NULL);
17470 if (!(vm = qemuDomObjFromDomain(domain)))
17471 return NULL;
17473 if (virDomainCheckpointCurrentEnsureACL(domain->conn, vm->def) < 0)
17474 goto cleanup;
17476 name = virDomainCheckpointGetCurrentName(vm->checkpoints);
17477 if (!name) {
17478 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT, "%s",
17479 _("the domain does not have a current checkpoint"));
17480 goto cleanup;
17483 checkpoint = virGetDomainCheckpoint(domain, name);
17485 cleanup:
17486 virDomainObjEndAPI(&vm);
17487 return checkpoint;
17491 static char *
17492 qemuDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint,
17493 unsigned int flags)
17495 virQEMUDriverPtr driver = checkpoint->domain->conn->privateData;
17496 virDomainObjPtr vm = NULL;
17497 char *xml = NULL;
17498 virDomainMomentObjPtr chk = NULL;
17499 qemuDomainObjPrivatePtr priv;
17500 int rc;
17501 size_t i;
17502 virDomainCheckpointDefPtr chkdef;
17504 virCheckFlags(VIR_DOMAIN_CHECKPOINT_XML_SECURE |
17505 VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN |
17506 VIR_DOMAIN_CHECKPOINT_XML_SIZE, NULL);
17508 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17509 return NULL;
17511 if (virDomainCheckpointGetXMLDescEnsureACL(checkpoint->domain->conn, vm->def, flags) < 0)
17512 goto cleanup;
17514 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17515 goto cleanup;
17516 chkdef = virDomainCheckpointObjGetDef(chk);
17518 if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE) {
17519 /* TODO: for non-current checkpoint, this requires a QMP sequence per
17520 disk, since the stat of one bitmap in isolation is too low,
17521 and merely adding bitmap sizes may be too high:
17522 block-dirty-bitmap-create tmp
17523 for each bitmap from checkpoint to current:
17524 add bitmap to src_list
17525 block-dirty-bitmap-merge dst=tmp src_list
17526 query-block and read tmp size
17527 block-dirty-bitmap-remove tmp
17528 So for now, go with simpler query-blocks only for current.
17530 if (virDomainCheckpointGetCurrent(vm->checkpoints) != chk) {
17531 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
17532 _("cannot compute size for non-current checkpoint '%s'"),
17533 checkpoint->name);
17534 goto cleanup;
17537 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
17538 goto cleanup;
17540 if (virDomainObjCheckActive(vm) < 0)
17541 goto endjob;
17543 if (qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
17544 goto endjob;
17546 /* TODO: Shouldn't need to recompute node names. */
17547 for (i = 0; i < chkdef->ndisks; i++) {
17548 virDomainCheckpointDiskDef *disk = &chkdef->disks[i];
17550 if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
17551 continue;
17552 VIR_FREE(chk->def->dom->disks[disk->idx]->src->nodeformat);
17553 if (VIR_STRDUP(chk->def->dom->disks[disk->idx]->src->nodeformat,
17554 qemuBlockNodeLookup(vm, disk->name)) < 0)
17555 goto endjob;
17558 priv = vm->privateData;
17559 qemuDomainObjEnterMonitor(driver, vm);
17560 rc = qemuMonitorUpdateCheckpointSize(priv->mon, chkdef);
17561 if (qemuDomainObjExitMonitor(driver, vm) < 0)
17562 goto endjob;
17563 if (rc < 0)
17564 goto endjob;
17567 xml = virDomainCheckpointDefFormat(chkdef, driver->caps, driver->xmlopt,
17568 flags);
17570 endjob:
17571 if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE)
17572 qemuDomainObjEndJob(driver, vm);
17574 cleanup:
17575 virDomainObjEndAPI(&vm);
17576 return xml;
17580 static int
17581 qemuDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint,
17582 unsigned int flags)
17584 virDomainObjPtr vm = NULL;
17585 int ret = -1;
17586 virDomainMomentObjPtr chk = NULL;
17588 virCheckFlags(0, -1);
17590 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17591 return -1;
17593 if (virDomainCheckpointIsCurrentEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17594 goto cleanup;
17596 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17597 goto cleanup;
17599 ret = chk == virDomainCheckpointGetCurrent(vm->checkpoints);
17601 cleanup:
17602 virDomainObjEndAPI(&vm);
17603 return ret;
17607 static int
17608 qemuDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint,
17609 unsigned int flags)
17611 virDomainObjPtr vm = NULL;
17612 int ret = -1;
17613 virDomainMomentObjPtr chk = NULL;
17615 virCheckFlags(0, -1);
17617 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17618 return -1;
17620 if (virDomainCheckpointHasMetadataEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17621 goto cleanup;
17623 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17624 goto cleanup;
17626 /* XXX Someday, we should recognize internal bitmaps in qcow2
17627 * images that are not tied to a libvirt checkpoint; if we ever do
17628 * that, then we would have a reason to return 0 here. */
17629 ret = 1;
17631 cleanup:
17632 virDomainObjEndAPI(&vm);
17633 return ret;
17637 static int
17638 qemuDomainCheckpointDelete(virDomainCheckpointPtr checkpoint,
17639 unsigned int flags)
17641 virQEMUDriverPtr driver = checkpoint->domain->conn->privateData;
17642 virDomainObjPtr vm = NULL;
17643 qemuDomainObjPrivatePtr priv;
17644 int ret = -1;
17645 virDomainMomentObjPtr chk = NULL;
17646 virQEMUMomentRemove rem;
17647 virQEMUMomentReparent rep;
17648 bool metadata_only = !!(flags & VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY);
17649 virQEMUDriverConfigPtr cfg = NULL;
17651 virCheckFlags(VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
17652 VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY |
17653 VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY, -1);
17655 if (!(vm = qemuDomObjFromCheckpoint(checkpoint)))
17656 return -1;
17658 cfg = virQEMUDriverGetConfig(driver);
17660 if (virDomainCheckpointDeleteEnsureACL(checkpoint->domain->conn, vm->def) < 0)
17661 goto cleanup;
17663 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17664 goto cleanup;
17666 priv = vm->privateData;
17667 if (!metadata_only) {
17668 /* Until qemu-img supports offline bitmap deletion, we are stuck
17669 * with requiring a running guest */
17670 if (!virDomainObjIsActive(vm)) {
17671 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17672 _("cannot delete checkpoint for inactive domain"));
17673 goto endjob;
17675 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17676 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17677 _("qemu binary lacks persistent bitmaps support"));
17678 goto endjob;
17682 if (!(chk = qemuCheckObjFromCheckpoint(vm, checkpoint)))
17683 goto endjob;
17685 if (flags & (VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN |
17686 VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY)) {
17687 rem.driver = driver;
17688 rem.vm = vm;
17689 rem.metadata_only = metadata_only;
17690 rem.err = 0;
17691 rem.current = virDomainCheckpointGetCurrent(vm->checkpoints);
17692 rem.found = false;
17693 rem.momentDiscard = qemuDomainCheckpointDiscard;
17694 virDomainMomentForEachDescendant(chk, qemuDomainMomentDiscardAll,
17695 &rem);
17696 if (rem.err < 0)
17697 goto endjob;
17698 if (rem.found) {
17699 virDomainCheckpointSetCurrent(vm->checkpoints, chk);
17700 if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
17701 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
17702 driver->xmlopt,
17703 cfg->checkpointDir) < 0) {
17704 virReportError(VIR_ERR_INTERNAL_ERROR,
17705 _("failed to set checkpoint '%s' as current"),
17706 chk->def->name);
17707 virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
17708 goto endjob;
17712 } else if (chk->nchildren) {
17713 rep.dir = cfg->checkpointDir;
17714 rep.parent = chk->parent;
17715 rep.vm = vm;
17716 rep.err = 0;
17717 rep.caps = driver->caps;
17718 rep.xmlopt = driver->xmlopt;
17719 rep.writeMetadata = qemuDomainCheckpointWriteMetadata;
17720 virDomainMomentForEachChild(chk, qemuDomainMomentReparentChildren,
17721 &rep);
17722 if (rep.err < 0)
17723 goto endjob;
17724 virDomainMomentMoveChildren(chk, chk->parent);
17727 if (flags & VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY) {
17728 virDomainMomentDropChildren(chk);
17729 ret = 0;
17730 } else {
17731 ret = qemuDomainCheckpointDiscard(driver, vm, chk, true, metadata_only);
17734 endjob:
17735 qemuDomainObjEndJob(driver, vm);
17737 cleanup:
17738 virDomainObjEndAPI(&vm);
17739 virObjectUnref(cfg);
17740 return ret;
17743 static int
17744 qemuDomainBackupPrepare(virQEMUDriverPtr driver, virDomainObjPtr vm,
17745 virDomainBackupDefPtr def,
17746 virDomainMomentObjPtr chk)
17748 int ret = -1;
17749 size_t i;
17750 virDomainCheckpointDefPtr chkdef = virDomainCheckpointObjGetDef(chk);
17752 if (chk && def->ndisks != chkdef->ndisks) {
17753 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
17754 _("inconsistency between backup and checkpoint disks"));
17755 goto cleanup;
17757 if (qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
17758 goto cleanup;
17759 for (i = 0; i < def->ndisks; i++) {
17760 virDomainBackupDiskDef *disk = &def->disks[i];
17761 virStorageSourcePtr src = vm->def->disks[disk->idx]->src;
17763 /* For now, insist that atomic checkpoint affect same disks as
17764 * those being backed up. */
17765 if (!disk->store) {
17766 if (chk &&
17767 chkdef->disks[i].type != VIR_DOMAIN_CHECKPOINT_TYPE_NONE) {
17768 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
17769 _("disk %s requested checkpoint without backup"),
17770 disk->name);
17771 goto cleanup;
17773 continue;
17775 if (chk &&
17776 chkdef->disks[i].type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP) {
17777 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
17778 _("disk %s requested backup without checkpoint"),
17779 disk->name);
17780 goto cleanup;
17782 if (virAsprintf(&disk->store->nodeformat, "tmp-%s", disk->name) < 0)
17783 goto cleanup;
17784 if (!disk->store->format)
17785 disk->store->format = VIR_STORAGE_FILE_QCOW2;
17786 if (def->incremental) {
17787 if (src->format != VIR_STORAGE_FILE_QCOW2) {
17788 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
17789 _("incremental backup of %s requires qcow2"),
17790 disk->name);
17791 goto cleanup;
17795 ret = 0;
17796 cleanup:
17797 return ret;
17800 /* Called while monitor lock is held. Best-effort cleanup. */
17801 static int
17802 qemuDomainBackupDiskCleanup(virQEMUDriverPtr driver, virDomainObjPtr vm,
17803 virDomainBackupDiskDef *disk, bool push,
17804 bool incremental, bool completed)
17806 qemuDomainObjPrivatePtr priv = vm->privateData;
17807 const char *node = vm->def->disks[disk->idx]->src->nodeformat;
17808 int ret = 0;
17810 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_EXPORT) {
17811 /* No real need to use nbd-server-remove, since we will
17812 * shortly be calling nbd-server-stop. */
17814 if (incremental && disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_BITMAP &&
17815 qemuMonitorDeleteBitmap(priv->mon, node, disk->name) < 0) {
17816 VIR_WARN("Unable to remove temp bitmap for disk %s after backup",
17817 disk->name);
17818 ret = -1;
17820 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_READY &&
17821 qemuMonitorBlockdevDel(priv->mon, disk->store->nodeformat) < 0) {
17822 VIR_WARN("Unable to remove %s disk %s after backup",
17823 push ? "target" : "scratch", disk->name);
17824 ret = -1;
17826 if (disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_LABEL)
17827 qemuDomainDiskChainElementRevoke(driver, vm, disk->store);
17828 if ((!push || !completed) &&
17829 disk->state >= VIR_DOMAIN_BACKUP_DISK_STATE_CREATED &&
17830 disk->store->detected && unlink(disk->store->path) < 0) {
17831 VIR_WARN("Unable to unlink %s disk %s after backup",
17832 push ? "failed target" : "scratch", disk->store->path);
17833 ret = -1;
17835 return ret;
17838 static int
17839 qemuDomainBackupBegin(virDomainPtr domain, const char *diskXml,
17840 const char *checkpointXml, unsigned int flags)
17842 virQEMUDriverPtr driver = domain->conn->privateData;
17843 virDomainObjPtr vm = NULL;
17844 virDomainBackupDefPtr def = NULL;
17845 virQEMUDriverConfigPtr cfg = NULL;
17846 virCapsPtr caps = NULL;
17847 qemuDomainObjPrivatePtr priv;
17848 int ret = -1;
17849 virJSONValuePtr json = NULL;
17850 bool job_started = false;
17851 bool nbd_running = false;
17852 bool push;
17853 const char *mode;
17854 size_t i;
17855 struct timeval tv;
17856 char *suffix = NULL;
17857 virCommandPtr cmd = NULL;
17858 const char *qemuImgPath;
17859 virDomainCheckpointDefPtr chkdef = NULL;
17860 virDomainMomentObjPtr chk = NULL;
17861 virDomainMomentObjPtr other = NULL;
17862 virDomainMomentObjPtr parent = NULL;
17863 virDomainMomentObjPtr current;
17864 virJSONValuePtr arr = NULL;
17866 virCheckFlags(VIR_DOMAIN_BACKUP_BEGIN_NO_METADATA, -1);
17867 /* TODO: VIR_DOMAIN_BACKUP_BEGIN_QUIESCE */
17869 if (!(vm = qemuDomObjFromDomain(domain)))
17870 goto cleanup;
17872 priv = vm->privateData;
17873 cfg = virQEMUDriverGetConfig(driver);
17875 if (virDomainBackupBeginEnsureACL(domain->conn, vm->def, flags) < 0)
17876 goto cleanup;
17878 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
17879 goto cleanup;
17881 if (qemuProcessAutoDestroyActive(driver, vm)) {
17882 virReportError(VIR_ERR_OPERATION_INVALID,
17883 "%s", _("domain is marked for auto destroy"));
17884 goto cleanup;
17887 if (!virDomainObjIsActive(vm)) {
17888 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17889 _("cannot perform disk backup for inactive domain"));
17890 goto cleanup;
17892 if (!(def = virDomainBackupDefParseString(diskXml, driver->xmlopt, 0)))
17893 goto cleanup;
17895 if (checkpointXml) {
17896 if (!(chkdef = qemuDomainCheckpointDefParseString(driver, caps,
17897 checkpointXml, 0)) ||
17898 VIR_STRDUP(suffix, chkdef->common.name) < 0)
17899 goto cleanup;
17900 } else {
17901 gettimeofday(&tv, NULL);
17902 if (virAsprintf(&suffix, "%lld", (long long)tv.tv_sec) < 0)
17903 goto cleanup;
17906 push = def->type == VIR_DOMAIN_BACKUP_TYPE_PUSH;
17907 if (!push) {
17908 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_BITMAP)) {
17909 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17910 _("qemu binary lacks pull-mode backup support"));
17911 goto cleanup;
17913 if (!def->server ||
17914 def->server->transport != VIR_STORAGE_NET_HOST_TRANS_TCP) {
17915 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
17916 _("<domainbackup> must specify TCP server for now"));
17917 goto cleanup;
17920 current = virDomainCheckpointGetCurrent(vm->checkpoints);
17921 if (def->incremental) {
17922 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17923 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17924 _("qemu binary lacks persistent bitmaps support"));
17925 goto cleanup;
17927 for (other = current; other;
17928 other = other->def->parent ?
17929 virDomainCheckpointFindByName(vm->checkpoints,
17930 other->def->parent) : NULL)
17931 if (STREQ(other->def->name, def->incremental))
17932 break;
17933 if (!other) {
17934 virReportError(VIR_ERR_OPERATION_INVALID,
17935 _("could not locate checkpoint '%s' for incremental backup"),
17936 def->incremental);
17937 goto cleanup;
17941 if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
17942 goto cleanup;
17944 /* We are going to modify the domain below. */
17945 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
17946 goto cleanup;
17948 if (priv->backup) {
17949 virReportError(VIR_ERR_OPERATION_INVALID,
17950 "%s", _("another backup job is already running"));
17951 goto endjob;
17954 if (chkdef) {
17955 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BITMAP_MERGE)) {
17956 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
17957 _("qemu binary lacks persistent bitmaps support"));
17958 goto endjob;
17961 if (qemuDomainCheckpointPrepare(driver, caps, vm, chkdef) < 0)
17962 goto endjob;
17963 if (!(chk = virDomainCheckpointAssignDef(vm->checkpoints, chkdef)))
17964 goto endjob;
17965 chkdef = NULL;
17966 if (current) {
17967 parent = current;
17968 if (VIR_STRDUP(chk->def->parent, parent->def->name) < 0)
17969 goto endjob;
17970 if (qemuDomainCheckpointWriteMetadata(vm, parent, driver->caps,
17971 driver->xmlopt,
17972 cfg->checkpointDir) < 0)
17973 goto endjob;
17977 if (virDomainBackupAlignDisks(def, vm->def, suffix) < 0 ||
17978 qemuDomainBackupPrepare(driver, vm, def, chk) < 0)
17979 goto endjob;
17981 /* actually start the checkpoint. 2x2 array of push/pull, full/incr,
17982 plus additional tweak if checkpoint requested */
17983 qemuDomainObjEnterMonitor(driver, vm);
17984 /* - push/pull: blockdev-add per <disk>
17985 - incr: bitmap-add of tmp, bitmap-merge per <disk> */
17986 for (i = 0; i < def->ndisks; i++) {
17987 virDomainBackupDiskDef *disk = &def->disks[i];
17988 virJSONValuePtr file;
17989 virStorageSourcePtr src = vm->def->disks[disk->idx]->src;
17990 const char *node = src->nodeformat;
17992 if (!disk->store)
17993 continue;
17994 if (qemuDomainStorageFileInit(driver, vm, disk->store, src) < 0)
17995 goto endmon;
17996 if (disk->store->detected) {
17997 if (virStorageFileCreate(disk->store) < 0) {
17998 virReportSystemError(errno,
17999 _("failed to create image file '%s'"),
18000 NULLSTR(disk->store->path));
18001 goto endmon;
18003 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_CREATED;
18005 if (qemuDomainDiskChainElementPrepare(driver, vm, disk->store, false,
18006 true) < 0)
18007 goto endmon;
18008 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_LABEL;
18009 if (disk->store->detected) {
18010 virBuffer buf = VIR_BUFFER_INITIALIZER;
18012 /* Force initialization of scratch/target file to new qcow2 */
18013 if (!(cmd = virCommandNewArgList(qemuImgPath,
18014 "create",
18015 "-f",
18016 virStorageFileFormatTypeToString(disk->store->format),
18017 "-o",
18018 NULL)))
18019 goto endmon;
18020 virBufferAsprintf(&buf, "backing_fmt=%s,backing_file=",
18021 virStorageFileFormatTypeToString(src->format));
18022 virQEMUBuildBufferEscapeComma(&buf, src->path);
18023 virCommandAddArgBuffer(cmd, &buf);
18025 virQEMUBuildBufferEscapeComma(&buf, disk->store->path);
18026 virCommandAddArgBuffer(cmd, &buf);
18027 if (virCommandRun(cmd, NULL) < 0)
18028 goto endmon;
18029 virCommandFree(cmd);
18030 cmd = NULL;
18033 /* FIXME: allow non-local files for push destinations */
18034 if (virJSONValueObjectCreate(&file,
18035 "s:driver", "file",
18036 "s:filename", disk->store->path,
18037 NULL) < 0)
18038 goto endmon;
18039 if (virJSONValueObjectCreate(&json,
18040 "s:driver", virStorageFileFormatTypeToString(disk->store->format),
18041 "s:node-name", disk->store->nodeformat,
18042 "a:file", &file,
18043 "s:backing", node, NULL) < 0) {
18044 virJSONValueFree(file);
18045 goto endmon;
18047 if (qemuMonitorBlockdevAdd(priv->mon, json) < 0)
18048 goto endmon;
18049 json = NULL;
18050 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_READY;
18052 if (def->incremental) {
18053 if (!(arr = virJSONValueNewArray()))
18054 goto endmon;
18055 if (qemuMonitorAddBitmap(priv->mon, node, disk->name, false) < 0) {
18056 virJSONValueFree(arr);
18057 goto endmon;
18059 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_BITMAP;
18060 for (other = parent ? parent : current; other;
18061 other = other->def->parent ?
18062 virDomainCheckpointFindByName(vm->checkpoints,
18063 other->def->parent) : NULL) {
18064 if (virJSONValueArrayAppendString(arr, other->def->name) < 0) {
18065 virJSONValueFree(arr);
18066 goto endmon;
18068 if (STREQ(other->def->name, def->incremental))
18069 break;
18071 if (qemuMonitorMergeBitmaps(priv->mon, node, disk->name, &arr) < 0)
18072 goto endmon;
18076 /* - transaction, containing:
18077 - push+full: blockdev-backup sync:full
18078 - push+incr: blockdev-backup sync:incremental bitmap:tmp
18079 - pull+full: blockdev-backup sync:none
18080 - pull+incr: blockdev-backup sync:none, bitmap-disable of tmp
18081 - if checkpoint: bitmap-disable of old, bitmap-add of new
18083 if (!(json = virJSONValueNewArray()))
18084 goto endmon;
18085 if (push)
18086 mode = def->incremental ? "incremental" : "full";
18087 else
18088 mode = "none";
18089 for (i = 0; i < def->ndisks; i++) {
18090 virDomainBackupDiskDef *disk = &def->disks[i];
18091 const char *node;
18092 const char *push_bitmap = NULL;
18094 if (!disk->store)
18095 continue;
18096 node = qemuBlockNodeLookup(vm, disk->name);
18097 if (push && def->incremental)
18098 push_bitmap = disk->name;
18099 if (qemuMonitorJSONTransactionAdd(json,
18100 "blockdev-backup",
18101 "s:device", node,
18102 "s:target", disk->store->nodeformat,
18103 "s:sync", mode,
18104 "S:bitmap", push_bitmap,
18105 "s:job-id", disk->name,
18106 NULL) < 0)
18107 goto endmon;
18108 if (def->incremental && !push &&
18109 qemuMonitorJSONTransactionAdd(json,
18110 "block-dirty-bitmap-disable",
18111 "s:node", node,
18112 "s:name", disk->name,
18113 NULL) < 0)
18114 goto endmon;
18116 if (chk && qemuDomainCheckpointAddActions(vm, json, parent,
18117 virDomainCheckpointObjGetDef(chk)) < 0)
18118 goto endmon;
18119 if (qemuMonitorTransaction(priv->mon, &json) < 0)
18120 goto endmon;
18121 job_started = true;
18122 if (chk) {
18123 if (qemuDomainCheckpointWriteMetadata(vm, chk, driver->caps,
18124 driver->xmlopt,
18125 cfg->checkpointDir) < 0) {
18126 virReportError(VIR_ERR_INTERNAL_ERROR,
18127 _("unable to save metadata for checkpoint %s"),
18128 chk->def->name);
18129 virDomainCheckpointObjListRemove(vm->checkpoints, chk);
18130 goto endmon;
18132 virDomainCheckpointSetCurrent(vm->checkpoints, chk);
18133 other = virDomainCheckpointFindByName(vm->checkpoints,
18134 chk->def->parent);
18135 chk->parent = other;
18136 other->nchildren++;
18137 chk->sibling = other->first_child;
18138 other->first_child = chk;
18142 - pull: nbd-server-start with <server> from user (or autogenerate server)
18143 - pull: nbd-server-add per <disk>, including bitmap for incr
18145 if (!push) {
18146 if (qemuMonitorNBDServerStart(priv->mon, def->server->name,
18147 def->server->port, NULL) < 0)
18148 goto endmon;
18149 nbd_running = true;
18150 for (i = 0; i < def->ndisks; i++) {
18151 virDomainBackupDiskDef *disk = &def->disks[i];
18153 if (!disk->store)
18154 continue;
18155 if (qemuMonitorNBDServerAdd(priv->mon, disk->store->nodeformat,
18156 disk->name, false,
18157 def->incremental ? disk->name :
18158 NULL) < 0)
18159 goto endmon;
18160 disk->state = VIR_DOMAIN_BACKUP_DISK_STATE_EXPORT;
18164 ret = 0;
18165 endmon:
18166 /* Best effort cleanup if we fail partway through */
18167 if (ret < 0) {
18168 virErrorPtr save_err = virSaveLastError();
18170 if (nbd_running &&
18171 qemuMonitorNBDServerStop(priv->mon) < 0)
18172 VIR_WARN("Unable to stop NBD server on vm %s after backup job",
18173 vm->def->name);
18174 for (i = 0; i < def->ndisks; i++) {
18175 virDomainBackupDiskDef *disk = &def->disks[i];
18177 if (!disk->store)
18178 continue;
18179 if (job_started &&
18180 qemuMonitorBlockJobCancel(priv->mon, disk->name) < 0)
18181 VIR_WARN("Unable to stop backup job %s on vm %s after failure",
18182 disk->name, vm->def->name);
18183 qemuDomainBackupDiskCleanup(driver, vm, disk, push,
18184 !!def->incremental, false);
18186 virSetError(save_err);
18187 virFreeError(save_err);
18189 if (qemuDomainObjExitMonitor(driver, vm) < 0)
18190 ret = -1;
18191 if (ret < 0)
18192 goto endjob;
18194 VIR_STEAL_PTR(priv->backup, def);
18195 ret = priv->backup->id = 1; /* Hard-coded job id for now */
18196 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm,
18197 driver->caps) < 0)
18198 VIR_WARN("Unable to save status on vm %s after backup job",
18199 vm->def->name);
18201 endjob:
18202 qemuDomainObjEndJob(driver, vm);
18204 cleanup:
18205 virJSONValueFree(arr);
18206 virDomainCheckpointDefFree(chkdef);
18207 virCommandFree(cmd);
18208 VIR_FREE(suffix);
18209 virJSONValueFree(json);
18210 virDomainObjEndAPI(&vm);
18211 virDomainBackupDefFree(def);
18212 virObjectUnref(caps);
18213 virObjectUnref(cfg);
18214 return ret;
18217 static char *qemuDomainBackupGetXMLDesc(virDomainPtr domain, int id,
18218 unsigned int flags)
18220 virDomainObjPtr vm = NULL;
18221 char *xml = NULL;
18222 qemuDomainObjPrivatePtr priv;
18223 virBuffer buf = VIR_BUFFER_INITIALIZER;
18225 virCheckFlags(0, NULL);
18227 if (!(vm = qemuDomObjFromDomain(domain)))
18228 return NULL;
18230 if (virDomainBackupGetXMLDescEnsureACL(domain->conn, vm->def) < 0)
18231 goto cleanup;
18233 /* TODO: Allow more than one hard-coded job id */
18234 priv = vm->privateData;
18235 if (id != 1 || !priv->backup) {
18236 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
18237 _("no domain backup job with id '%d'"), id);
18238 goto cleanup;
18241 if (virDomainBackupDefFormat(&buf, priv->backup, false) < 0)
18242 goto cleanup;
18243 xml = virBufferContentAndReset(&buf);
18245 cleanup:
18246 virDomainObjEndAPI(&vm);
18247 return xml;
18250 static int qemuDomainBackupEnd(virDomainPtr domain, int id, unsigned int flags)
18252 virQEMUDriverPtr driver = domain->conn->privateData;
18253 virQEMUDriverConfigPtr cfg = NULL;
18254 virDomainObjPtr vm = NULL;
18255 int ret = -1;
18256 virDomainBackupDefPtr backup = NULL;
18257 qemuDomainObjPrivatePtr priv;
18258 bool want_abort = flags & VIR_DOMAIN_BACKUP_END_ABORT;
18259 virDomainBackupDefPtr def;
18260 size_t i;
18261 bool push = true;
18262 bool completed = true;
18264 virCheckFlags(VIR_DOMAIN_BACKUP_END_ABORT, -1);
18266 if (!(vm = qemuDomObjFromDomain(domain)))
18267 return -1;
18269 cfg = virQEMUDriverGetConfig(driver);
18270 if (virDomainBackupEndEnsureACL(domain->conn, vm->def) < 0)
18271 goto cleanup;
18273 /* TODO: Allow more than one hard-coded job id */
18274 priv = vm->privateData;
18275 if (id != 1 || !priv->backup) {
18276 virReportError(VIR_ERR_NO_DOMAIN_CHECKPOINT,
18277 _("no domain backup job with id '%d'"), id);
18278 goto cleanup;
18281 def = priv->backup;
18282 if (def->type != VIR_DOMAIN_BACKUP_TYPE_PUSH) {
18283 want_abort = false;
18284 push = false;
18287 /* We are going to modify the domain below. */
18288 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18289 goto cleanup;
18291 qemuDomainObjEnterMonitor(driver, vm);
18292 if (push) {
18293 for (i = 0; i < def->ndisks; i++) {
18294 virDomainBackupDiskDef *disk = &def->disks[i];
18296 if (!disk->store)
18297 continue;
18298 if (disk->state != VIR_DOMAIN_BACKUP_DISK_STATE_COMPLETE)
18299 completed = false;
18301 } else {
18302 ret = qemuMonitorNBDServerStop(priv->mon);
18304 if (!completed && !want_abort) {
18305 virReportError(VIR_ERR_OPERATION_INVALID,
18306 _("backup job id '%d' not complete yet"), id);
18307 } else {
18308 for (i = 0; i < def->ndisks; i++) {
18309 virDomainBackupDiskDef *disk = &def->disks[i];
18311 if (!disk->store)
18312 continue;
18313 if (!push || disk->state < VIR_DOMAIN_BACKUP_DISK_STATE_COMPLETE) {
18314 if (qemuMonitorBlockJobCancel(priv->mon,
18315 disk->name) < 0 &&
18316 !want_abort) {
18317 ret = -1;
18318 continue;
18321 if (qemuDomainBackupDiskCleanup(driver, vm, disk, push,
18322 !!def->incremental, completed) < 0)
18323 ret = -1;
18326 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
18327 ret = -1;
18328 goto endjob;
18331 VIR_STEAL_PTR(backup, priv->backup);
18332 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm,
18333 driver->caps) < 0)
18334 VIR_WARN("Unable to save status on vm %s after backup job",
18335 vm->def->name);
18337 ret = want_abort ? 0 : 1;
18339 endjob:
18340 qemuDomainObjEndJob(driver, vm);
18342 cleanup:
18343 virDomainBackupDefFree(backup);
18344 virDomainObjEndAPI(&vm);
18345 return ret;
18348 static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
18349 char **result, unsigned int flags)
18351 virQEMUDriverPtr driver = domain->conn->privateData;
18352 virDomainObjPtr vm = NULL;
18353 int ret = -1;
18354 qemuDomainObjPrivatePtr priv;
18355 bool hmp;
18357 virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
18359 if (!(vm = qemuDomObjFromDomain(domain)))
18360 goto cleanup;
18362 if (virDomainQemuMonitorCommandEnsureACL(domain->conn, vm->def) < 0)
18363 goto cleanup;
18365 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
18366 goto cleanup;
18368 if (virDomainObjCheckActive(vm) < 0)
18369 goto endjob;
18371 priv = vm->privateData;
18373 qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_MONITOR, NULL);
18375 hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
18377 qemuDomainObjEnterMonitor(driver, vm);
18378 ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
18379 if (qemuDomainObjExitMonitor(driver, vm) < 0)
18380 ret = -1;
18382 endjob:
18383 qemuDomainObjEndJob(driver, vm);
18385 cleanup:
18386 virDomainObjEndAPI(&vm);
18387 return ret;
18391 static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn,
18392 unsigned int pid_value,
18393 unsigned int flags)
18395 virQEMUDriverPtr driver = conn->privateData;
18396 virDomainObjPtr vm = NULL;
18397 virDomainDefPtr def = NULL;
18398 virDomainPtr dom = NULL;
18399 virDomainChrSourceDefPtr monConfig = NULL;
18400 bool monJSON = false;
18401 pid_t pid = pid_value;
18402 char *pidfile = NULL;
18403 virQEMUCapsPtr qemuCaps = NULL;
18404 virCapsPtr caps = NULL;
18406 virCheckFlags(0, NULL);
18408 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
18409 goto cleanup;
18411 if (!(def = qemuParseCommandLinePid(driver->qemuCapsCache,
18412 caps, driver->xmlopt, pid,
18413 &pidfile, &monConfig, &monJSON)))
18414 goto cleanup;
18416 if (virDomainQemuAttachEnsureACL(conn, def) < 0)
18417 goto cleanup;
18419 if (!monConfig) {
18420 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18421 _("No monitor connection for pid %u"), pid_value);
18422 goto cleanup;
18424 if (monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
18425 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18426 _("Cannot connect to monitor connection of type '%s' "
18427 "for pid %u"),
18428 virDomainChrTypeToString(monConfig->type),
18429 pid_value);
18430 goto cleanup;
18433 if (!(def->name) &&
18434 virAsprintf(&def->name, "attach-pid-%u", pid_value) < 0)
18435 goto cleanup;
18437 if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
18438 def->emulator)))
18439 goto cleanup;
18441 if (qemuAssignDeviceAliases(def, qemuCaps) < 0)
18442 goto cleanup;
18444 if (!(vm = virDomainObjListAdd(driver->domains, def,
18445 driver->xmlopt,
18446 VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
18447 VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
18448 NULL)))
18449 goto cleanup;
18451 def = NULL;
18453 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) {
18454 qemuDomainRemoveInactive(driver, vm);
18455 goto cleanup;
18458 if (qemuProcessAttach(conn, driver, vm, pid,
18459 pidfile, monConfig, monJSON) < 0) {
18460 monConfig = NULL;
18461 qemuDomainRemoveInactive(driver, vm);
18462 qemuDomainObjEndJob(driver, vm);
18463 goto cleanup;
18466 monConfig = NULL;
18468 if (qemuProcessAttach(conn, driver, vm, pid,
18469 pidfile, monConfig, monJSON) < 0) {
18470 qemuDomainRemoveInactive(driver, vm);
18471 qemuDomainObjEndJob(driver, vm);
18472 goto cleanup;
18475 dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
18477 qemuDomainObjEndJob(driver, vm);
18479 cleanup:
18480 virDomainDefFree(def);
18481 virObjectUnref(monConfig);
18482 virDomainObjEndAPI(&vm);
18483 VIR_FREE(pidfile);
18484 virObjectUnref(caps);
18485 virObjectUnref(qemuCaps);
18486 return dom;
18490 static int
18491 qemuDomainOpenConsole(virDomainPtr dom,
18492 const char *dev_name,
18493 virStreamPtr st,
18494 unsigned int flags)
18496 virDomainObjPtr vm = NULL;
18497 int ret = -1;
18498 size_t i;
18499 virDomainChrDefPtr chr = NULL;
18500 qemuDomainObjPrivatePtr priv;
18502 virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
18503 VIR_DOMAIN_CONSOLE_FORCE, -1);
18505 if (!(vm = qemuDomObjFromDomain(dom)))
18506 goto cleanup;
18508 if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
18509 goto cleanup;
18511 if (virDomainObjCheckActive(vm) < 0)
18512 goto cleanup;
18514 priv = vm->privateData;
18516 if (dev_name) {
18517 for (i = 0; !chr && i < vm->def->nconsoles; i++) {
18518 if (vm->def->consoles[i]->info.alias &&
18519 STREQ(dev_name, vm->def->consoles[i]->info.alias))
18520 chr = vm->def->consoles[i];
18522 for (i = 0; !chr && i < vm->def->nserials; i++) {
18523 if (STREQ(dev_name, vm->def->serials[i]->info.alias))
18524 chr = vm->def->serials[i];
18526 for (i = 0; !chr && i < vm->def->nparallels; i++) {
18527 if (STREQ(dev_name, vm->def->parallels[i]->info.alias))
18528 chr = vm->def->parallels[i];
18530 } else {
18531 if (vm->def->nconsoles)
18532 chr = vm->def->consoles[0];
18533 else if (vm->def->nserials)
18534 chr = vm->def->serials[0];
18537 if (!chr) {
18538 virReportError(VIR_ERR_INTERNAL_ERROR,
18539 _("cannot find character device %s"),
18540 NULLSTR(dev_name));
18541 goto cleanup;
18544 if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
18545 virReportError(VIR_ERR_INTERNAL_ERROR,
18546 _("character device %s is not using a PTY"),
18547 dev_name ? dev_name : NULLSTR(chr->info.alias));
18548 goto cleanup;
18551 /* handle mutually exclusive access to console devices */
18552 ret = virChrdevOpen(priv->devs,
18553 chr->source,
18555 (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
18557 if (ret == 1) {
18558 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
18559 _("Active console session exists for this domain"));
18560 ret = -1;
18563 cleanup:
18564 virDomainObjEndAPI(&vm);
18565 return ret;
18568 static int
18569 qemuDomainOpenChannel(virDomainPtr dom,
18570 const char *name,
18571 virStreamPtr st,
18572 unsigned int flags)
18574 virDomainObjPtr vm = NULL;
18575 int ret = -1;
18576 size_t i;
18577 virDomainChrDefPtr chr = NULL;
18578 qemuDomainObjPrivatePtr priv;
18580 virCheckFlags(VIR_DOMAIN_CHANNEL_FORCE, -1);
18582 if (!(vm = qemuDomObjFromDomain(dom)))
18583 goto cleanup;
18585 if (virDomainOpenChannelEnsureACL(dom->conn, vm->def) < 0)
18586 goto cleanup;
18588 if (virDomainObjCheckActive(vm) < 0)
18589 goto cleanup;
18591 priv = vm->privateData;
18593 if (name) {
18594 for (i = 0; !chr && i < vm->def->nchannels; i++) {
18595 if (STREQ(name, vm->def->channels[i]->info.alias))
18596 chr = vm->def->channels[i];
18598 if (vm->def->channels[i]->targetType == \
18599 VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
18600 STREQ_NULLABLE(name, vm->def->channels[i]->target.name))
18601 chr = vm->def->channels[i];
18603 } else {
18604 if (vm->def->nchannels)
18605 chr = vm->def->channels[0];
18608 if (!chr) {
18609 virReportError(VIR_ERR_INTERNAL_ERROR,
18610 _("cannot find channel %s"),
18611 NULLSTR(name));
18612 goto cleanup;
18615 if (chr->source->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
18616 virReportError(VIR_ERR_INTERNAL_ERROR,
18617 _("channel %s is not using a UNIX socket"),
18618 name ? name : NULLSTR(chr->info.alias));
18619 goto cleanup;
18622 /* handle mutually exclusive access to channel devices */
18623 ret = virChrdevOpen(priv->devs,
18624 chr->source,
18626 (flags & VIR_DOMAIN_CHANNEL_FORCE) != 0);
18628 if (ret == 1) {
18629 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
18630 _("Active channel stream exists for this domain"));
18631 ret = -1;
18634 cleanup:
18635 virDomainObjEndAPI(&vm);
18636 return ret;
18640 /* Called while holding the VM job lock, to implement a block job
18641 * abort with pivot; this updates the VM definition as appropriate, on
18642 * either success or failure. */
18643 static int
18644 qemuDomainBlockPivot(virQEMUDriverPtr driver,
18645 virDomainObjPtr vm,
18646 qemuBlockJobDataPtr job,
18647 virDomainDiskDefPtr disk)
18649 int ret = -1;
18650 qemuDomainObjPrivatePtr priv = vm->privateData;
18652 if (!disk->mirror) {
18653 virReportError(VIR_ERR_OPERATION_INVALID,
18654 _("pivot of disk '%s' requires an active copy job"),
18655 disk->dst);
18656 goto cleanup;
18659 if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY) {
18660 virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
18661 _("disk '%s' not ready for pivot yet"),
18662 disk->dst);
18663 goto cleanup;
18666 /* Attempt the pivot. Record the attempt now, to prevent duplicate
18667 * attempts; but the actual disk change will be made when emitting
18668 * the event.
18669 * XXX On libvirtd restarts, if we missed the qemu event, we need
18670 * to double check what state qemu is in.
18671 * XXX We should be using qemu's rerror flag to make sure the job
18672 * remains alive until we know its final state.
18673 * XXX If the abort command is synchronous but the qemu event says
18674 * that pivot failed, we need to reflect that failure into the
18675 * overall return value. */
18676 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT;
18677 qemuDomainObjEnterMonitor(driver, vm);
18678 ret = qemuMonitorDrivePivot(priv->mon, job->name);
18679 if (qemuDomainObjExitMonitor(driver, vm) < 0) {
18680 ret = -1;
18681 goto cleanup;
18684 if (ret < 0) {
18685 /* The pivot failed. The block job in QEMU remains in the synchronised
18686 * phase. Reset the state we changed and return the error to the user */
18687 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
18690 cleanup:
18691 return ret;
18695 /* bandwidth in MiB/s per public API. Caller must lock vm beforehand,
18696 * and not access it afterwards. */
18697 static int
18698 qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
18699 virDomainObjPtr vm,
18700 const char *path,
18701 const char *base,
18702 unsigned long bandwidth,
18703 unsigned int flags)
18705 qemuDomainObjPrivatePtr priv = vm->privateData;
18706 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
18707 char *device = NULL;
18708 virDomainDiskDefPtr disk;
18709 virStorageSourcePtr baseSource = NULL;
18710 unsigned int baseIndex = 0;
18711 char *basePath = NULL;
18712 char *backingPath = NULL;
18713 unsigned long long speed = bandwidth;
18714 qemuBlockJobDataPtr job = NULL;
18715 int ret = -1;
18717 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
18718 virReportError(VIR_ERR_INVALID_ARG, "%s",
18719 _("flag VIR_DOMAIN_BLOCK_REBASE_RELATIVE is valid only "
18720 "with non-null base"));
18721 goto cleanup;
18724 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18725 goto cleanup;
18727 if (virDomainObjCheckActive(vm) < 0)
18728 goto endjob;
18730 if (qemuDomainSupportsBlockJobs(vm) < 0)
18731 goto endjob;
18733 if (!(disk = qemuDomainDiskByName(vm->def, path)))
18734 goto endjob;
18736 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
18737 goto endjob;
18739 if (qemuDomainDiskBlockJobIsActive(disk))
18740 goto endjob;
18742 if (base &&
18743 (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
18744 !(baseSource = virStorageFileChainLookup(disk->src, disk->src,
18745 base, baseIndex, NULL))))
18746 goto endjob;
18748 if (baseSource) {
18749 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
18750 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
18751 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
18752 _("this QEMU binary doesn't support relative "
18753 "block pull/rebase"));
18754 goto endjob;
18757 if (virStorageFileGetRelativeBackingPath(disk->src->backingStore,
18758 baseSource,
18759 &backingPath) < 0)
18760 goto endjob;
18762 if (!backingPath) {
18763 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
18764 _("can't keep relative backing relationship"));
18765 goto endjob;
18770 /* Convert bandwidth MiB to bytes, if needed */
18771 if (!(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) {
18772 if (speed > LLONG_MAX >> 20) {
18773 virReportError(VIR_ERR_OVERFLOW,
18774 _("bandwidth must be less than %llu"),
18775 LLONG_MAX >> 20);
18776 goto endjob;
18778 speed <<= 20;
18781 if (!(job = qemuBlockJobDiskNew(disk, QEMU_BLOCKJOB_TYPE_PULL, device)))
18782 goto endjob;
18784 qemuDomainObjEnterMonitor(driver, vm);
18785 if (baseSource)
18786 basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
18787 baseSource);
18788 if (!baseSource || basePath)
18789 ret = qemuMonitorBlockStream(priv->mon, device, basePath, backingPath,
18790 speed);
18791 if (qemuDomainObjExitMonitor(driver, vm) < 0)
18792 ret = -1;
18794 if (ret < 0)
18795 goto endjob;
18797 qemuBlockJobStarted(job);
18799 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
18800 VIR_WARN("Unable to save status on vm %s after state change",
18801 vm->def->name);
18803 endjob:
18804 qemuDomainObjEndJob(driver, vm);
18806 cleanup:
18807 qemuBlockJobStartupFinalize(job);
18808 virObjectUnref(cfg);
18809 VIR_FREE(basePath);
18810 VIR_FREE(backingPath);
18811 VIR_FREE(device);
18812 virDomainObjEndAPI(&vm);
18813 return ret;
18817 static int
18818 qemuDomainBlockJobAbort(virDomainPtr dom,
18819 const char *path,
18820 unsigned int flags)
18822 virQEMUDriverPtr driver = dom->conn->privateData;
18823 virDomainDiskDefPtr disk = NULL;
18824 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
18825 bool pivot = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT);
18826 bool async = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC);
18827 qemuBlockJobDataPtr job = NULL;
18828 virDomainObjPtr vm;
18829 int ret = -1;
18831 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
18832 VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
18834 if (!(vm = qemuDomObjFromDomain(dom)))
18835 return -1;
18837 if (virDomainBlockJobAbortEnsureACL(dom->conn, vm->def) < 0)
18838 goto cleanup;
18840 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
18841 goto cleanup;
18843 if (virDomainObjCheckActive(vm) < 0)
18844 goto endjob;
18846 if (qemuDomainSupportsBlockJobs(vm) < 0)
18847 goto endjob;
18849 if (!(disk = qemuDomainDiskByName(vm->def, path)))
18850 goto endjob;
18852 if (!(job = qemuBlockJobDiskGetJob(disk))) {
18853 virReportError(VIR_ERR_INVALID_ARG,
18854 _("disk %s does not have an active block job"), disk->dst);
18855 goto endjob;
18858 if (disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_NONE &&
18859 disk->mirrorState != VIR_DOMAIN_DISK_MIRROR_STATE_READY) {
18860 virReportError(VIR_ERR_OPERATION_INVALID,
18861 _("another job on disk '%s' is still being ended"),
18862 disk->dst);
18863 goto endjob;
18866 if (!async)
18867 qemuBlockJobSyncBegin(job);
18869 if (pivot) {
18870 if ((ret = qemuDomainBlockPivot(driver, vm, job, disk)) < 0)
18871 goto endjob;
18872 } else {
18873 if (disk->mirror)
18874 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_ABORT;
18876 qemuDomainObjEnterMonitor(driver, vm);
18877 ret = qemuMonitorBlockJobCancel(qemuDomainGetMonitor(vm), job->name);
18878 if (qemuDomainObjExitMonitor(driver, vm) < 0) {
18879 ret = -1;
18880 goto endjob;
18883 if (ret < 0) {
18884 if (disk->mirror)
18885 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
18886 goto endjob;
18890 ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps));
18893 * With the ABORT_ASYNC flag we don't need to do anything, the event will
18894 * come from qemu and will update the XML as appropriate, but without the
18895 * ABORT_ASYNC flag, we must block to guarantee synchronous operation. We
18896 * do the waiting while still holding the VM job, to prevent newly
18897 * scheduled block jobs from confusing us. */
18898 if (!async) {
18899 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
18900 while (qemuBlockJobIsRunning(job)) {
18901 if (virDomainObjWait(vm) < 0) {
18902 ret = -1;
18903 goto endjob;
18905 qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
18909 endjob:
18910 if (job && !async)
18911 qemuBlockJobSyncEnd(vm, job, QEMU_ASYNC_JOB_NONE);
18912 qemuDomainObjEndJob(driver, vm);
18914 cleanup:
18915 virObjectUnref(job);
18916 virObjectUnref(cfg);
18917 virDomainObjEndAPI(&vm);
18918 return ret;
18922 static int
18923 qemuBlockJobInfoTranslate(qemuMonitorBlockJobInfoPtr rawInfo,
18924 virDomainBlockJobInfoPtr info,
18925 virDomainDiskDefPtr disk,
18926 bool reportBytes)
18928 info->cur = rawInfo->cur;
18929 info->end = rawInfo->end;
18931 /* Fix job completeness reporting. If cur == end mgmt
18932 * applications think job is completed. Except when both cur
18933 * and end are zero, in which case qemu hasn't started the
18934 * job yet. */
18935 if (!info->cur && !info->end) {
18936 if (rawInfo->ready > 0) {
18937 info->cur = info->end = 1;
18938 } else if (!rawInfo->ready) {
18939 info->end = 1;
18943 /* If qemu reports that it's not ready yet don't make the job go to
18944 * cur == end as some apps wrote code polling this instead of waiting for
18945 * the ready event */
18946 if (rawInfo->ready == 0 &&
18947 info->cur == info->end &&
18948 info->cur > 0)
18949 info->cur -= 1;
18951 info->type = rawInfo->type;
18952 if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT &&
18953 disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT)
18954 info->type = disk->mirrorJob;
18956 if (rawInfo->bandwidth && !reportBytes)
18957 rawInfo->bandwidth = VIR_DIV_UP(rawInfo->bandwidth, 1024 * 1024);
18958 info->bandwidth = rawInfo->bandwidth;
18959 if (info->bandwidth != rawInfo->bandwidth) {
18960 virReportError(VIR_ERR_OVERFLOW,
18961 _("bandwidth %llu cannot be represented in result"),
18962 rawInfo->bandwidth);
18963 return -1;
18966 return 0;
18970 static int
18971 qemuDomainGetBlockJobInfo(virDomainPtr dom,
18972 const char *path,
18973 virDomainBlockJobInfoPtr info,
18974 unsigned int flags)
18976 virQEMUDriverPtr driver = dom->conn->privateData;
18977 virDomainObjPtr vm;
18978 virDomainDiskDefPtr disk;
18979 int ret = -1;
18980 qemuMonitorBlockJobInfo rawInfo;
18982 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
18984 if (!(vm = qemuDomObjFromDomain(dom)))
18985 return -1;
18987 if (virDomainGetBlockJobInfoEnsureACL(dom->conn, vm->def) < 0)
18988 goto cleanup;
18991 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
18992 goto cleanup;
18994 if (virDomainObjCheckActive(vm) < 0)
18995 goto endjob;
18997 if (qemuDomainSupportsBlockJobs(vm) < 0)
18998 goto endjob;
19000 if (!(disk = virDomainDiskByName(vm->def, path, true))) {
19001 virReportError(VIR_ERR_INVALID_ARG,
19002 _("disk %s not found in the domain"), path);
19003 goto endjob;
19006 qemuDomainObjEnterMonitor(driver, vm);
19007 ret = qemuMonitorGetBlockJobInfo(qemuDomainGetMonitor(vm),
19008 disk->info.alias, &rawInfo);
19009 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19010 ret = -1;
19011 if (ret <= 0)
19012 goto endjob;
19014 if (qemuBlockJobInfoTranslate(&rawInfo, info, disk,
19015 flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES) < 0) {
19016 ret = -1;
19017 goto endjob;
19020 /* Snoop block copy operations, so future cancel operations can
19021 * avoid checking if pivot is safe. Save the change to XML, but
19022 * we can ignore failure because it is only an optimization. We
19023 * hold the vm lock, so modifying the in-memory representation is
19024 * safe, even if we are a query rather than a modify job. */
19025 if (disk->mirror &&
19026 rawInfo.ready != 0 &&
19027 info->cur == info->end && !disk->mirrorState) {
19028 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
19030 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
19031 ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps));
19032 virObjectUnref(cfg);
19034 endjob:
19035 qemuDomainObjEndJob(driver, vm);
19037 cleanup:
19038 virDomainObjEndAPI(&vm);
19039 return ret;
19043 static int
19044 qemuDomainBlockJobSetSpeed(virDomainPtr dom,
19045 const char *path,
19046 unsigned long bandwidth,
19047 unsigned int flags)
19049 virQEMUDriverPtr driver = dom->conn->privateData;
19050 virDomainDiskDefPtr disk;
19051 int ret = -1;
19052 virDomainObjPtr vm;
19053 char *device = NULL;
19054 unsigned long long speed = bandwidth;
19056 virCheckFlags(VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES, -1);
19058 /* Convert bandwidth MiB to bytes, if needed */
19059 if (!(flags & VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES)) {
19060 if (speed > LLONG_MAX >> 20) {
19061 virReportError(VIR_ERR_OVERFLOW,
19062 _("bandwidth must be less than %llu"),
19063 LLONG_MAX >> 20);
19064 return -1;
19066 speed <<= 20;
19069 if (!(vm = qemuDomObjFromDomain(dom)))
19070 return -1;
19072 if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0)
19073 goto cleanup;
19075 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19076 goto cleanup;
19078 if (virDomainObjCheckActive(vm) < 0)
19079 goto endjob;
19081 if (qemuDomainSupportsBlockJobs(vm) < 0)
19082 goto endjob;
19084 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19085 goto endjob;
19087 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19088 goto endjob;
19090 qemuDomainObjEnterMonitor(driver, vm);
19091 ret = qemuMonitorBlockJobSetSpeed(qemuDomainGetMonitor(vm),
19092 device,
19093 speed);
19094 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19095 ret = -1;
19097 endjob:
19098 qemuDomainObjEndJob(driver, vm);
19100 cleanup:
19101 VIR_FREE(device);
19102 virDomainObjEndAPI(&vm);
19104 return ret;
19108 static int
19109 qemuDomainBlockCopyValidateMirror(virStorageSourcePtr mirror,
19110 const char *dst,
19111 bool *reuse)
19113 int desttype = virStorageSourceGetActualType(mirror);
19114 struct stat st;
19116 if (virStorageFileAccess(mirror, F_OK) < 0) {
19117 if (errno != ENOENT) {
19118 virReportSystemError(errno, "%s",
19119 _("unable to verify existence of "
19120 "block copy target"));
19121 return -1;
19124 if (*reuse || desttype == VIR_STORAGE_TYPE_BLOCK) {
19125 virReportSystemError(errno,
19126 _("missing destination file for disk %s: %s"),
19127 dst, mirror->path);
19128 return -1;
19130 } else {
19131 if (virStorageFileStat(mirror, &st) < 0) {
19132 virReportSystemError(errno,
19133 _("unable to stat block copy target '%s'"),
19134 mirror->path);
19135 return -1;
19138 if (S_ISBLK(st.st_mode)) {
19139 /* if the target is a block device, assume that we are reusing it,
19140 * so there are no attempts to create it */
19141 *reuse = true;
19142 } else {
19143 if (st.st_size && !(*reuse)) {
19144 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19145 _("external destination file for disk %s already "
19146 "exists and is not a block device: %s"),
19147 dst, mirror->path);
19148 return -1;
19151 if (desttype == VIR_STORAGE_TYPE_BLOCK) {
19152 virReportError(VIR_ERR_INVALID_ARG,
19153 _("blockdev flag requested for disk %s, but file "
19154 "'%s' is not a block device"),
19155 dst, mirror->path);
19156 return -1;
19161 return 0;
19165 /* bandwidth in bytes/s. Caller must lock vm beforehand, and not
19166 * access mirror afterwards. */
19167 static int
19168 qemuDomainBlockCopyCommon(virDomainObjPtr vm,
19169 virConnectPtr conn,
19170 const char *path,
19171 virStorageSourcePtr mirror,
19172 unsigned long long bandwidth,
19173 unsigned int granularity,
19174 unsigned long long buf_size,
19175 unsigned int flags,
19176 bool keepParentLabel)
19178 virQEMUDriverPtr driver = conn->privateData;
19179 qemuDomainObjPrivatePtr priv;
19180 char *device = NULL;
19181 virDomainDiskDefPtr disk = NULL;
19182 int ret = -1;
19183 bool need_unlink = false;
19184 virQEMUDriverConfigPtr cfg = NULL;
19185 const char *format = NULL;
19186 virErrorPtr monitor_error = NULL;
19187 bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
19188 qemuBlockJobDataPtr job = NULL;
19190 /* Preliminaries: find the disk we are editing, sanity checks */
19191 virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
19192 VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
19193 VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
19195 priv = vm->privateData;
19196 cfg = virQEMUDriverGetConfig(driver);
19198 if (virStorageSourceIsRelative(mirror)) {
19199 virReportError(VIR_ERR_INVALID_ARG, "%s",
19200 _("absolute path must be used as block copy target"));
19201 goto cleanup;
19204 if (bandwidth > LLONG_MAX) {
19205 virReportError(VIR_ERR_INVALID_ARG,
19206 _("bandwidth must be less than "
19207 "'%llu' bytes/s (%llu MiB/s)"),
19208 LLONG_MAX, LLONG_MAX >> 20);
19209 goto cleanup;
19212 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19213 goto cleanup;
19215 if (virDomainObjCheckActive(vm) < 0)
19216 goto endjob;
19218 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19219 goto endjob;
19221 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19222 goto endjob;
19224 if (qemuDomainDiskBlockJobIsActive(disk))
19225 goto endjob;
19227 if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN &&
19228 qemuDomainDefValidateDiskLunSource(mirror) < 0)
19229 goto endjob;
19231 if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
19232 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
19233 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19234 _("block copy is not supported with this QEMU binary"));
19235 goto endjob;
19237 if (!(flags & VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB) &&
19238 vm->persistent) {
19239 /* XXX if qemu ever lets us start a new domain with mirroring
19240 * already active, we can relax this; but for now, the risk of
19241 * 'managedsave' due to libvirt-guests means we can't risk
19242 * this on persistent domains. */
19243 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19244 _("domain is not transient"));
19245 goto endjob;
19248 /* clear the _SHALLOW flag if there is only one layer */
19249 if (!virStorageSourceHasBacking(disk->src))
19250 flags &= ~VIR_DOMAIN_BLOCK_COPY_SHALLOW;
19252 /* unless the user provides a pre-created file, shallow copy into a raw
19253 * file is not possible */
19254 if ((flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW) && !reuse &&
19255 mirror->format == VIR_STORAGE_FILE_RAW) {
19256 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19257 _("shallow copy of disk '%s' into a raw file "
19258 "is not possible"),
19259 disk->dst);
19260 goto endjob;
19263 /* Prepare the destination file. */
19264 /* XXX Allow non-file mirror destinations */
19265 if (!virStorageSourceIsLocalStorage(mirror)) {
19266 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
19267 _("non-file destination not supported yet"));
19268 goto endjob;
19271 if (qemuDomainStorageFileInit(driver, vm, mirror, NULL) < 0)
19272 goto endjob;
19274 if (qemuDomainBlockCopyValidateMirror(mirror, disk->dst, &reuse) < 0)
19275 goto endjob;
19277 if (!mirror->format) {
19278 if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) {
19279 mirror->format = disk->src->format;
19280 } else {
19281 /* If the user passed the REUSE_EXT flag, then either they
19282 * can also pass the RAW flag or use XML to tell us the format.
19283 * So if we get here, we assume it is safe for us to probe the
19284 * format from the file that we will be using. */
19285 mirror->format = virStorageFileProbeFormat(mirror->path, cfg->user,
19286 cfg->group);
19290 /* When copying a shareable disk we need to make sure that the disk can
19291 * be safely shared, since block copy may change the format. */
19292 if (disk->src->shared && !disk->src->readonly &&
19293 !qemuBlockStorageSourceSupportsConcurrentAccess(mirror)) {
19294 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
19295 _("can't pivot a shared disk to a storage volume not "
19296 "supporting sharing"));
19297 goto endjob;
19300 /* pre-create the image file */
19301 if (!reuse) {
19302 if (virStorageFileCreate(mirror) < 0) {
19303 virReportSystemError(errno, "%s", _("failed to create copy target"));
19304 goto endjob;
19307 need_unlink = true;
19310 if (mirror->format > 0)
19311 format = virStorageFileFormatTypeToString(mirror->format);
19313 if (virStorageSourceInitChainElement(mirror, disk->src,
19314 keepParentLabel) < 0)
19315 goto endjob;
19317 /* If reusing an external image that includes a backing file, the pivot may
19318 * result in qemu needing to open the entire backing chain, so we need to
19319 * label the full backing chain of the mirror instead of just the top image */
19320 if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT &&
19321 mirror->format >= VIR_STORAGE_FILE_BACKING &&
19322 qemuDomainDetermineDiskChain(driver, vm, disk, mirror, true) < 0)
19323 goto endjob;
19325 if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT &&
19326 virStorageSourceHasBacking(mirror)) {
19327 /* note that we don't really know whether a part of the backing chain
19328 * is shared so rolling this back is not as easy. Thus we do it only
19329 * if there's a backing chain */
19330 if (qemuDomainNamespaceSetupDisk(vm, mirror) < 0 ||
19331 qemuSetupImageChainCgroup(vm, mirror) < 0 ||
19332 qemuSecuritySetImageLabel(driver, vm, mirror, true) < 0)
19333 goto endjob;
19334 } else {
19335 if (qemuDomainDiskChainElementPrepare(driver, vm, mirror, false, true) < 0) {
19336 qemuDomainDiskChainElementRevoke(driver, vm, mirror);
19337 goto endjob;
19341 if (!(job = qemuBlockJobDiskNew(disk, QEMU_BLOCKJOB_TYPE_COPY, device)))
19342 goto endjob;
19344 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
19346 /* Actually start the mirroring */
19347 qemuDomainObjEnterMonitor(driver, vm);
19348 /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
19349 * by the user regardless of how @reuse was modified */
19350 ret = qemuMonitorDriveMirror(priv->mon, device, mirror->path, format,
19351 bandwidth, granularity, buf_size, flags);
19352 virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
19353 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19354 ret = -1;
19355 if (ret < 0) {
19356 monitor_error = virSaveLastError();
19357 qemuDomainDiskChainElementRevoke(driver, vm, mirror);
19358 goto endjob;
19361 /* Update vm in place to match changes. */
19362 qemuBlockJobStarted(job);
19363 need_unlink = false;
19364 virStorageFileDeinit(mirror);
19365 disk->mirror = mirror;
19366 mirror = NULL;
19367 disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
19369 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
19370 VIR_WARN("Unable to save status on vm %s after state change",
19371 vm->def->name);
19373 endjob:
19374 if (need_unlink && virStorageFileUnlink(mirror) < 0)
19375 VIR_WARN("%s", _("unable to remove just-created copy target"));
19376 virStorageFileDeinit(mirror);
19377 qemuDomainObjEndJob(driver, vm);
19378 if (monitor_error) {
19379 virSetError(monitor_error);
19380 virFreeError(monitor_error);
19382 qemuBlockJobStartupFinalize(job);
19384 cleanup:
19385 VIR_FREE(device);
19386 virObjectUnref(cfg);
19387 virObjectUnref(mirror);
19388 return ret;
19391 static int
19392 qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
19393 unsigned long bandwidth, unsigned int flags)
19395 virQEMUDriverPtr driver = dom->conn->privateData;
19396 virDomainObjPtr vm;
19397 int ret = -1;
19398 unsigned long long speed = bandwidth;
19399 VIR_AUTOUNREF(virStorageSourcePtr) dest = NULL;
19401 virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
19402 VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
19403 VIR_DOMAIN_BLOCK_REBASE_COPY |
19404 VIR_DOMAIN_BLOCK_REBASE_COPY_RAW |
19405 VIR_DOMAIN_BLOCK_REBASE_RELATIVE |
19406 VIR_DOMAIN_BLOCK_REBASE_COPY_DEV |
19407 VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES, -1);
19409 if (!(vm = qemuDomObjFromDomain(dom)))
19410 return -1;
19412 if (virDomainBlockRebaseEnsureACL(dom->conn, vm->def) < 0)
19413 goto cleanup;
19415 /* For normal rebase (enhanced blockpull), the common code handles
19416 * everything, including vm cleanup. */
19417 if (!(flags & VIR_DOMAIN_BLOCK_REBASE_COPY))
19418 return qemuDomainBlockPullCommon(driver, vm, path, base, bandwidth, flags);
19420 /* If we got here, we are doing a block copy rebase. */
19421 if (!(dest = virStorageSourceNew()))
19422 goto cleanup;
19423 dest->type = (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV) ?
19424 VIR_STORAGE_TYPE_BLOCK : VIR_STORAGE_TYPE_FILE;
19425 if (VIR_STRDUP(dest->path, base) < 0)
19426 goto cleanup;
19427 if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
19428 dest->format = VIR_STORAGE_FILE_RAW;
19430 /* Convert bandwidth MiB to bytes, if necessary */
19431 if (!(flags & VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES)) {
19432 if (speed > LLONG_MAX >> 20) {
19433 virReportError(VIR_ERR_OVERFLOW,
19434 _("bandwidth must be less than %llu"),
19435 LLONG_MAX >> 20);
19436 goto cleanup;
19438 speed <<= 20;
19441 /* XXX: If we are doing a shallow copy but not reusing an external
19442 * file, we should attempt to pre-create the destination with a
19443 * relative backing chain instead of qemu's default of absolute */
19444 if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE) {
19445 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
19446 _("Relative backing during copy not supported yet"));
19447 goto cleanup;
19450 /* We rely on the fact that VIR_DOMAIN_BLOCK_REBASE_SHALLOW
19451 * and VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT map to the same values
19452 * as for block copy. */
19453 flags &= (VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
19454 VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT);
19455 ret = qemuDomainBlockCopyCommon(vm, dom->conn, path, dest,
19456 speed, 0, 0, flags, true);
19457 dest = NULL;
19459 cleanup:
19460 virDomainObjEndAPI(&vm);
19461 return ret;
19465 static int
19466 qemuDomainBlockCopy(virDomainPtr dom, const char *disk, const char *destxml,
19467 virTypedParameterPtr params, int nparams,
19468 unsigned int flags)
19470 virQEMUDriverPtr driver = dom->conn->privateData;
19471 virDomainObjPtr vm;
19472 int ret = -1;
19473 unsigned long long bandwidth = 0;
19474 unsigned int granularity = 0;
19475 unsigned long long buf_size = 0;
19476 virDomainDiskDefPtr diskdef = NULL;
19477 virStorageSourcePtr dest = NULL;
19478 size_t i;
19480 virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
19481 VIR_DOMAIN_BLOCK_COPY_REUSE_EXT |
19482 VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB, -1);
19483 if (virTypedParamsValidate(params, nparams,
19484 VIR_DOMAIN_BLOCK_COPY_BANDWIDTH,
19485 VIR_TYPED_PARAM_ULLONG,
19486 VIR_DOMAIN_BLOCK_COPY_GRANULARITY,
19487 VIR_TYPED_PARAM_UINT,
19488 VIR_DOMAIN_BLOCK_COPY_BUF_SIZE,
19489 VIR_TYPED_PARAM_ULLONG,
19490 NULL) < 0)
19491 return -1;
19493 if (!(vm = qemuDomObjFromDomain(dom)))
19494 return -1;
19496 if (virDomainBlockCopyEnsureACL(dom->conn, vm->def) < 0)
19497 goto cleanup;
19499 for (i = 0; i < nparams; i++) {
19500 virTypedParameterPtr param = &params[i];
19502 /* Typed params (wisely) refused to expose unsigned long, but
19503 * back-compat demands that we stick with a maximum of
19504 * unsigned long bandwidth in MiB/s, while our value is
19505 * unsigned long long in bytes/s. Hence, we have to do
19506 * overflow detection if this is a 32-bit server handling a
19507 * 64-bit client. */
19508 if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BANDWIDTH)) {
19509 if (sizeof(unsigned long)< sizeof(bandwidth) &&
19510 param->value.ul > ULONG_MAX * (1ULL << 20)) {
19511 virReportError(VIR_ERR_OVERFLOW,
19512 _("bandwidth must be less than %llu bytes"),
19513 ULONG_MAX * (1ULL << 20));
19514 goto cleanup;
19516 bandwidth = param->value.ul;
19517 } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_GRANULARITY)) {
19518 if (param->value.ui != VIR_ROUND_UP_POWER_OF_TWO(param->value.ui)) {
19519 virReportError(VIR_ERR_INVALID_ARG, "%s",
19520 _("granularity must be power of 2"));
19521 goto cleanup;
19523 granularity = param->value.ui;
19524 } else if (STREQ(param->field, VIR_DOMAIN_BLOCK_COPY_BUF_SIZE)) {
19525 buf_size = param->value.ul;
19529 if (!(diskdef = virDomainDiskDefParse(destxml, vm->def, driver->xmlopt,
19530 VIR_DOMAIN_DEF_PARSE_INACTIVE |
19531 VIR_DOMAIN_DEF_PARSE_DISK_SOURCE)))
19532 goto cleanup;
19534 VIR_STEAL_PTR(dest, diskdef->src);
19536 ret = qemuDomainBlockCopyCommon(vm, dom->conn, disk, dest, bandwidth,
19537 granularity, buf_size, flags, false);
19539 cleanup:
19540 virDomainDiskDefFree(diskdef);
19541 virDomainObjEndAPI(&vm);
19542 return ret;
19546 static int
19547 qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
19548 unsigned int flags)
19550 virDomainObjPtr vm;
19551 virCheckFlags(VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES, -1);
19553 if (!(vm = qemuDomObjFromDomain(dom)))
19554 return -1;
19556 if (virDomainBlockPullEnsureACL(dom->conn, vm->def) < 0) {
19557 virDomainObjEndAPI(&vm);
19558 return -1;
19561 return qemuDomainBlockPullCommon(dom->conn->privateData,
19562 vm, path, NULL, bandwidth, flags);
19566 static int
19567 qemuDomainBlockCommit(virDomainPtr dom,
19568 const char *path,
19569 const char *base,
19570 const char *top,
19571 unsigned long bandwidth,
19572 unsigned int flags)
19574 virQEMUDriverPtr driver = dom->conn->privateData;
19575 virQEMUDriverConfigPtr cfg = NULL;
19576 qemuDomainObjPrivatePtr priv;
19577 virDomainObjPtr vm = NULL;
19578 char *device = NULL;
19579 int ret = -1;
19580 virDomainDiskDefPtr disk = NULL;
19581 virStorageSourcePtr topSource;
19582 unsigned int topIndex = 0;
19583 virStorageSourcePtr baseSource = NULL;
19584 unsigned int baseIndex = 0;
19585 virStorageSourcePtr top_parent = NULL;
19586 bool clean_access = false;
19587 char *topPath = NULL;
19588 char *basePath = NULL;
19589 char *backingPath = NULL;
19590 unsigned long long speed = bandwidth;
19591 qemuBlockJobDataPtr job = NULL;
19592 qemuBlockJobType jobtype = QEMU_BLOCKJOB_TYPE_COMMIT;
19593 VIR_AUTOUNREF(virStorageSourcePtr) mirror = NULL;
19595 /* XXX Add support for COMMIT_DELETE */
19596 virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
19597 VIR_DOMAIN_BLOCK_COMMIT_ACTIVE |
19598 VIR_DOMAIN_BLOCK_COMMIT_RELATIVE |
19599 VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES, -1);
19601 if (!(vm = qemuDomObjFromDomain(dom)))
19602 goto cleanup;
19603 priv = vm->privateData;
19604 cfg = virQEMUDriverGetConfig(driver);
19606 if (virDomainBlockCommitEnsureACL(dom->conn, vm->def) < 0)
19607 goto cleanup;
19609 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19610 goto cleanup;
19612 if (virDomainObjCheckActive(vm) < 0)
19613 goto endjob;
19614 /* Ensure that no one backports commit to RHEL 6.2, where cancel
19615 * behaved differently */
19616 if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_COMMIT) &&
19617 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
19618 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19619 _("online commit not supported with this QEMU binary"));
19620 goto endjob;
19623 /* Convert bandwidth MiB to bytes, if necessary */
19624 if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES)) {
19625 if (speed > LLONG_MAX >> 20) {
19626 virReportError(VIR_ERR_OVERFLOW,
19627 _("bandwidth must be less than %llu"),
19628 LLONG_MAX >> 20);
19629 goto endjob;
19631 speed <<= 20;
19634 if (!(disk = qemuDomainDiskByName(vm->def, path)))
19635 goto endjob;
19637 if (!(device = qemuAliasDiskDriveFromDisk(disk)))
19638 goto endjob;
19640 if (!disk->src->path) {
19641 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19642 _("disk %s has no source file to be committed"),
19643 disk->dst);
19644 goto endjob;
19647 if (qemuDomainDiskBlockJobIsActive(disk))
19648 goto endjob;
19650 if (!top || STREQ(top, disk->dst))
19651 topSource = disk->src;
19652 else if (virStorageFileParseChainIndex(disk->dst, top, &topIndex) < 0 ||
19653 !(topSource = virStorageFileChainLookup(disk->src, NULL,
19654 top, topIndex,
19655 &top_parent)))
19656 goto endjob;
19658 if (topSource == disk->src) {
19659 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
19660 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19661 _("active commit not supported with this QEMU binary"));
19662 goto endjob;
19664 /* XXX Should we auto-pivot when COMMIT_ACTIVE is not specified? */
19665 if (!(flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE)) {
19666 virReportError(VIR_ERR_INVALID_ARG,
19667 _("commit of '%s' active layer requires active flag"),
19668 disk->dst);
19669 goto endjob;
19672 jobtype = QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT;
19673 } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
19674 virReportError(VIR_ERR_INVALID_ARG,
19675 _("active commit requested but '%s' is not active"),
19676 topSource->path);
19677 goto endjob;
19680 if (!virStorageSourceHasBacking(topSource)) {
19681 virReportError(VIR_ERR_INVALID_ARG,
19682 _("top '%s' in chain for '%s' has no backing file"),
19683 topSource->path, path);
19684 goto endjob;
19687 if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW))
19688 baseSource = topSource->backingStore;
19689 else if (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
19690 !(baseSource = virStorageFileChainLookup(disk->src, topSource,
19691 base, baseIndex, NULL)))
19692 goto endjob;
19694 if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
19695 baseSource != topSource->backingStore) {
19696 virReportError(VIR_ERR_INVALID_ARG,
19697 _("base '%s' is not immediately below '%s' in chain "
19698 "for '%s'"),
19699 base, topSource->path, path);
19700 goto endjob;
19703 /* For an active commit, clone enough of the base to act as the mirror */
19704 if (topSource == disk->src) {
19705 if (!(mirror = virStorageSourceCopy(baseSource, false)))
19706 goto endjob;
19707 if (virStorageSourceInitChainElement(mirror,
19708 disk->src,
19709 true) < 0)
19710 goto endjob;
19713 if (flags & VIR_DOMAIN_BLOCK_COMMIT_RELATIVE &&
19714 topSource != disk->src) {
19715 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHANGE_BACKING_FILE)) {
19716 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19717 _("this qemu doesn't support relative block commit"));
19718 goto endjob;
19721 if (virStorageFileGetRelativeBackingPath(topSource, baseSource,
19722 &backingPath) < 0)
19723 goto endjob;
19725 if (!backingPath) {
19726 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
19727 _("can't keep relative backing relationship"));
19728 goto endjob;
19732 /* For the commit to succeed, we must allow qemu to open both the
19733 * 'base' image and the parent of 'top' as read/write; 'top' might
19734 * not have a parent, or might already be read-write. XXX It
19735 * would also be nice to revert 'base' to read-only, as well as
19736 * revoke access to files removed from the chain, when the commit
19737 * operation succeeds, but doing that requires tracking the
19738 * operation in XML across libvirtd restarts. */
19739 clean_access = true;
19740 if (qemuDomainDiskChainElementPrepare(driver, vm, baseSource, false, false) < 0 ||
19741 (top_parent && top_parent != disk->src &&
19742 qemuDomainDiskChainElementPrepare(driver, vm, top_parent, false, false) < 0))
19743 goto endjob;
19745 if (!(job = qemuBlockJobDiskNew(disk, jobtype, device)))
19746 goto endjob;
19748 disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
19750 /* Start the commit operation. Pass the user's original spelling,
19751 * if any, through to qemu, since qemu may behave differently
19752 * depending on whether the input was specified as relative or
19753 * absolute (that is, our absolute top_canon may do the wrong
19754 * thing if the user specified a relative name). */
19755 qemuDomainObjEnterMonitor(driver, vm);
19756 basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
19757 baseSource);
19758 topPath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
19759 topSource);
19760 if (basePath && topPath)
19761 ret = qemuMonitorBlockCommit(priv->mon, device,
19762 topPath, basePath, backingPath,
19763 speed);
19764 if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
19765 ret = -1;
19766 goto endjob;
19769 qemuBlockJobStarted(job);
19770 if (mirror) {
19771 VIR_STEAL_PTR(disk->mirror, mirror);
19772 disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
19775 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
19776 VIR_WARN("Unable to save status on vm %s after block job",
19777 vm->def->name);
19779 endjob:
19780 if (ret < 0 && clean_access) {
19781 virErrorPtr orig_err = virSaveLastError();
19782 /* Revert access to read-only, if possible. */
19783 qemuDomainDiskChainElementPrepare(driver, vm, baseSource, true, false);
19784 if (top_parent && top_parent != disk->src)
19785 qemuDomainDiskChainElementPrepare(driver, vm, top_parent, true, false);
19787 if (orig_err) {
19788 virSetError(orig_err);
19789 virFreeError(orig_err);
19792 qemuBlockJobStartupFinalize(job);
19793 qemuDomainObjEndJob(driver, vm);
19795 cleanup:
19796 VIR_FREE(topPath);
19797 VIR_FREE(basePath);
19798 VIR_FREE(backingPath);
19799 VIR_FREE(device);
19800 virObjectUnref(cfg);
19801 virDomainObjEndAPI(&vm);
19802 return ret;
19805 static int
19806 qemuDomainOpenGraphics(virDomainPtr dom,
19807 unsigned int idx,
19808 int fd,
19809 unsigned int flags)
19811 virQEMUDriverPtr driver = dom->conn->privateData;
19812 virDomainObjPtr vm = NULL;
19813 int ret = -1;
19814 qemuDomainObjPrivatePtr priv;
19815 const char *protocol;
19817 virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
19819 if (!(vm = qemuDomObjFromDomain(dom)))
19820 return -1;
19822 if (virDomainOpenGraphicsEnsureACL(dom->conn, vm->def) < 0)
19823 goto cleanup;
19825 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19826 goto cleanup;
19828 if (virDomainObjCheckActive(vm) < 0)
19829 goto endjob;
19831 priv = vm->privateData;
19833 if (idx >= vm->def->ngraphics) {
19834 virReportError(VIR_ERR_INTERNAL_ERROR,
19835 _("No graphics backend with index %d"), idx);
19836 goto endjob;
19838 switch (vm->def->graphics[idx]->type) {
19839 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
19840 protocol = "vnc";
19841 break;
19842 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
19843 protocol = "spice";
19844 break;
19845 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
19846 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
19847 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
19848 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
19849 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19850 _("Can only open VNC or SPICE graphics backends, not %s"),
19851 virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
19852 goto endjob;
19853 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
19854 default:
19855 virReportEnumRangeError(virDomainGraphicsType,
19856 vm->def->graphics[idx]->type);
19857 goto endjob;
19860 if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
19861 goto endjob;
19863 qemuDomainObjEnterMonitor(driver, vm);
19864 ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
19865 (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
19866 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19867 ret = -1;
19869 endjob:
19870 qemuDomainObjEndJob(driver, vm);
19872 cleanup:
19873 virDomainObjEndAPI(&vm);
19874 return ret;
19877 static int
19878 qemuDomainOpenGraphicsFD(virDomainPtr dom,
19879 unsigned int idx,
19880 unsigned int flags)
19882 virQEMUDriverPtr driver = dom->conn->privateData;
19883 virDomainObjPtr vm = NULL;
19884 int ret = -1;
19885 qemuDomainObjPrivatePtr priv;
19886 const char *protocol;
19887 int pair[2] = {-1, -1};
19889 virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
19891 if (!(vm = qemuDomObjFromDomain(dom)))
19892 return -1;
19894 if (virDomainOpenGraphicsFdEnsureACL(dom->conn, vm->def) < 0)
19895 goto cleanup;
19897 if (virDomainObjCheckActive(vm) < 0)
19898 goto cleanup;
19900 priv = vm->privateData;
19902 if (idx >= vm->def->ngraphics) {
19903 virReportError(VIR_ERR_INTERNAL_ERROR,
19904 _("No graphics backend with index %d"), idx);
19905 goto cleanup;
19907 switch (vm->def->graphics[idx]->type) {
19908 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
19909 protocol = "vnc";
19910 break;
19911 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
19912 protocol = "spice";
19913 break;
19914 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
19915 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
19916 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
19917 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
19918 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19919 _("Can only open VNC or SPICE graphics backends, not %s"),
19920 virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
19921 goto cleanup;
19922 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
19923 default:
19924 virReportEnumRangeError(virDomainGraphicsType,
19925 vm->def->graphics[idx]->type);
19926 goto cleanup;
19929 if (qemuSecuritySetSocketLabel(driver->securityManager, vm->def) < 0)
19930 goto cleanup;
19932 if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) < 0)
19933 goto cleanup;
19935 if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0)
19936 goto cleanup;
19938 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
19939 goto cleanup;
19940 qemuDomainObjEnterMonitor(driver, vm);
19941 ret = qemuMonitorOpenGraphics(priv->mon, protocol, pair[1], "graphicsfd",
19942 (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH));
19943 if (qemuDomainObjExitMonitor(driver, vm) < 0)
19944 ret = -1;
19945 qemuDomainObjEndJob(driver, vm);
19946 if (ret < 0)
19947 goto cleanup;
19949 ret = pair[0];
19950 pair[0] = -1;
19952 cleanup:
19953 VIR_FORCE_CLOSE(pair[0]);
19954 VIR_FORCE_CLOSE(pair[1]);
19955 virDomainObjEndAPI(&vm);
19956 return ret;
19959 typedef enum {
19960 QEMU_BLOCK_IOTUNE_SET_BYTES = 1 << 0,
19961 QEMU_BLOCK_IOTUNE_SET_IOPS = 1 << 1,
19962 QEMU_BLOCK_IOTUNE_SET_BYTES_MAX = 1 << 2,
19963 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX = 1 << 3,
19964 QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS = 1 << 4,
19965 QEMU_BLOCK_IOTUNE_SET_GROUP_NAME = 1 << 5,
19966 QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH = 1 << 6,
19967 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH = 1 << 7,
19968 } qemuBlockIoTuneSetFlags;
19971 /* If the user didn't specify bytes limits, inherit previous values;
19972 * likewise if the user didn't specify iops limits. */
19973 static int
19974 qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfoPtr newinfo,
19975 virDomainBlockIoTuneInfoPtr oldinfo,
19976 qemuBlockIoTuneSetFlags set_fields)
19978 #define SET_IOTUNE_DEFAULTS(BOOL, FIELD) \
19979 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) { \
19980 newinfo->total_##FIELD = oldinfo->total_##FIELD; \
19981 newinfo->read_##FIELD = oldinfo->read_##FIELD; \
19982 newinfo->write_##FIELD = oldinfo->write_##FIELD; \
19985 SET_IOTUNE_DEFAULTS(BYTES, bytes_sec);
19986 SET_IOTUNE_DEFAULTS(BYTES_MAX, bytes_sec_max);
19987 SET_IOTUNE_DEFAULTS(IOPS, iops_sec);
19988 SET_IOTUNE_DEFAULTS(IOPS_MAX, iops_sec_max);
19989 #undef SET_IOTUNE_DEFAULTS
19991 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))
19992 newinfo->size_iops_sec = oldinfo->size_iops_sec;
19993 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME) &&
19994 VIR_STRDUP(newinfo->group_name, oldinfo->group_name) < 0)
19995 return -1;
19997 /* The length field is handled a bit differently. If not defined/set,
19998 * QEMU will default these to 0 or 1 depending on whether something in
19999 * the same family is set or not.
20001 * Similar to other values, if nothing in the family is defined/set,
20002 * then take whatever is in the oldinfo.
20004 * To clear an existing limit, a 0 is provided; however, passing that
20005 * 0 onto QEMU if there's a family value defined/set (or defaulted)
20006 * will cause an error. So, to mimic that, if our oldinfo was set and
20007 * our newinfo is clearing, then set max_length based on whether we
20008 * have a value in the family set/defined. */
20009 #define SET_MAX_LENGTH(BOOL, FIELD) \
20010 if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL)) \
20011 newinfo->FIELD##_max_length = oldinfo->FIELD##_max_length; \
20012 else if ((set_fields & QEMU_BLOCK_IOTUNE_SET_##BOOL) && \
20013 oldinfo->FIELD##_max_length && \
20014 !newinfo->FIELD##_max_length) \
20015 newinfo->FIELD##_max_length = (newinfo->FIELD || \
20016 newinfo->FIELD##_max) ? 1 : 0;
20018 SET_MAX_LENGTH(BYTES_MAX_LENGTH, total_bytes_sec);
20019 SET_MAX_LENGTH(BYTES_MAX_LENGTH, read_bytes_sec);
20020 SET_MAX_LENGTH(BYTES_MAX_LENGTH, write_bytes_sec);
20021 SET_MAX_LENGTH(IOPS_MAX_LENGTH, total_iops_sec);
20022 SET_MAX_LENGTH(IOPS_MAX_LENGTH, read_iops_sec);
20023 SET_MAX_LENGTH(IOPS_MAX_LENGTH, write_iops_sec);
20025 #undef SET_MAX_LENGTH
20027 return 0;
20031 static int
20032 qemuDomainSetBlockIoTune(virDomainPtr dom,
20033 const char *path,
20034 virTypedParameterPtr params,
20035 int nparams,
20036 unsigned int flags)
20038 virQEMUDriverPtr driver = dom->conn->privateData;
20039 virDomainObjPtr vm = NULL;
20040 qemuDomainObjPrivatePtr priv;
20041 virDomainDefPtr def = NULL;
20042 virDomainDefPtr persistentDef = NULL;
20043 virDomainBlockIoTuneInfo info;
20044 char *drivealias = NULL;
20045 const char *qdevid = NULL;
20046 int ret = -1;
20047 size_t i;
20048 virDomainDiskDefPtr conf_disk = NULL;
20049 virDomainDiskDefPtr disk;
20050 qemuBlockIoTuneSetFlags set_fields = 0;
20051 bool supportMaxOptions = true;
20052 bool supportGroupNameOption = true;
20053 bool supportMaxLengthOptions = true;
20054 virQEMUDriverConfigPtr cfg = NULL;
20055 virObjectEventPtr event = NULL;
20056 virTypedParameterPtr eventParams = NULL;
20057 int eventNparams = 0;
20058 int eventMaxparams = 0;
20060 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20061 VIR_DOMAIN_AFFECT_CONFIG, -1);
20062 if (virTypedParamsValidate(params, nparams,
20063 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC,
20064 VIR_TYPED_PARAM_ULLONG,
20065 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC,
20066 VIR_TYPED_PARAM_ULLONG,
20067 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC,
20068 VIR_TYPED_PARAM_ULLONG,
20069 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC,
20070 VIR_TYPED_PARAM_ULLONG,
20071 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC,
20072 VIR_TYPED_PARAM_ULLONG,
20073 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC,
20074 VIR_TYPED_PARAM_ULLONG,
20075 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX,
20076 VIR_TYPED_PARAM_ULLONG,
20077 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX,
20078 VIR_TYPED_PARAM_ULLONG,
20079 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX,
20080 VIR_TYPED_PARAM_ULLONG,
20081 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX,
20082 VIR_TYPED_PARAM_ULLONG,
20083 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX,
20084 VIR_TYPED_PARAM_ULLONG,
20085 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX,
20086 VIR_TYPED_PARAM_ULLONG,
20087 VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
20088 VIR_TYPED_PARAM_ULLONG,
20089 VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
20090 VIR_TYPED_PARAM_STRING,
20091 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
20092 VIR_TYPED_PARAM_ULLONG,
20093 VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
20094 VIR_TYPED_PARAM_ULLONG,
20095 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
20096 VIR_TYPED_PARAM_ULLONG,
20097 VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
20098 VIR_TYPED_PARAM_ULLONG,
20099 VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
20100 VIR_TYPED_PARAM_ULLONG,
20101 VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
20102 VIR_TYPED_PARAM_ULLONG,
20103 NULL) < 0)
20104 return -1;
20106 memset(&info, 0, sizeof(info));
20108 if (!(vm = qemuDomObjFromDomain(dom)))
20109 return -1;
20111 if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0)
20112 goto cleanup;
20114 cfg = virQEMUDriverGetConfig(driver);
20116 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20117 goto cleanup;
20119 priv = vm->privateData;
20121 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
20122 goto endjob;
20124 if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxparams,
20125 VIR_DOMAIN_TUNABLE_BLKDEV_DISK, path) < 0)
20126 goto endjob;
20128 #define SET_IOTUNE_FIELD(FIELD, BOOL, CONST) \
20129 if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_##CONST)) { \
20130 info.FIELD = param->value.ul; \
20131 set_fields |= QEMU_BLOCK_IOTUNE_SET_##BOOL; \
20132 if (virTypedParamsAddULLong(&eventParams, &eventNparams, \
20133 &eventMaxparams, \
20134 VIR_DOMAIN_TUNABLE_BLKDEV_##CONST, \
20135 param->value.ul) < 0) \
20136 goto endjob; \
20137 continue; \
20140 for (i = 0; i < nparams; i++) {
20141 virTypedParameterPtr param = &params[i];
20143 if (param->value.ul > QEMU_BLOCK_IOTUNE_MAX) {
20144 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
20145 _("block I/O throttle limit value must"
20146 " be no more than %llu"), QEMU_BLOCK_IOTUNE_MAX);
20147 goto endjob;
20150 SET_IOTUNE_FIELD(total_bytes_sec, BYTES, TOTAL_BYTES_SEC);
20151 SET_IOTUNE_FIELD(read_bytes_sec, BYTES, READ_BYTES_SEC);
20152 SET_IOTUNE_FIELD(write_bytes_sec, BYTES, WRITE_BYTES_SEC);
20153 SET_IOTUNE_FIELD(total_iops_sec, IOPS, TOTAL_IOPS_SEC);
20154 SET_IOTUNE_FIELD(read_iops_sec, IOPS, READ_IOPS_SEC);
20155 SET_IOTUNE_FIELD(write_iops_sec, IOPS, WRITE_IOPS_SEC);
20157 SET_IOTUNE_FIELD(total_bytes_sec_max, BYTES_MAX,
20158 TOTAL_BYTES_SEC_MAX);
20159 SET_IOTUNE_FIELD(read_bytes_sec_max, BYTES_MAX,
20160 READ_BYTES_SEC_MAX);
20161 SET_IOTUNE_FIELD(write_bytes_sec_max, BYTES_MAX,
20162 WRITE_BYTES_SEC_MAX);
20163 SET_IOTUNE_FIELD(total_iops_sec_max, IOPS_MAX,
20164 TOTAL_IOPS_SEC_MAX);
20165 SET_IOTUNE_FIELD(read_iops_sec_max, IOPS_MAX,
20166 READ_IOPS_SEC_MAX);
20167 SET_IOTUNE_FIELD(write_iops_sec_max, IOPS_MAX,
20168 WRITE_IOPS_SEC_MAX);
20169 SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC);
20171 /* NB: Cannot use macro since this is a value.s not a value.ul */
20172 if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
20173 if (VIR_STRDUP(info.group_name, param->value.s) < 0)
20174 goto endjob;
20175 set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
20176 if (virTypedParamsAddString(&eventParams, &eventNparams,
20177 &eventMaxparams,
20178 VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
20179 param->value.s) < 0)
20180 goto endjob;
20181 continue;
20184 SET_IOTUNE_FIELD(total_bytes_sec_max_length, BYTES_MAX_LENGTH,
20185 TOTAL_BYTES_SEC_MAX_LENGTH);
20186 SET_IOTUNE_FIELD(read_bytes_sec_max_length, BYTES_MAX_LENGTH,
20187 READ_BYTES_SEC_MAX_LENGTH);
20188 SET_IOTUNE_FIELD(write_bytes_sec_max_length, BYTES_MAX_LENGTH,
20189 WRITE_BYTES_SEC_MAX_LENGTH);
20190 SET_IOTUNE_FIELD(total_iops_sec_max_length, IOPS_MAX_LENGTH,
20191 TOTAL_IOPS_SEC_MAX_LENGTH);
20192 SET_IOTUNE_FIELD(read_iops_sec_max_length, IOPS_MAX_LENGTH,
20193 READ_IOPS_SEC_MAX_LENGTH);
20194 SET_IOTUNE_FIELD(write_iops_sec_max_length, IOPS_MAX_LENGTH,
20195 WRITE_IOPS_SEC_MAX_LENGTH);
20198 #undef SET_IOTUNE_FIELD
20200 if ((info.total_bytes_sec && info.read_bytes_sec) ||
20201 (info.total_bytes_sec && info.write_bytes_sec)) {
20202 virReportError(VIR_ERR_INVALID_ARG, "%s",
20203 _("total and read/write of bytes_sec "
20204 "cannot be set at the same time"));
20205 goto endjob;
20208 if ((info.total_iops_sec && info.read_iops_sec) ||
20209 (info.total_iops_sec && info.write_iops_sec)) {
20210 virReportError(VIR_ERR_INVALID_ARG, "%s",
20211 _("total and read/write of iops_sec "
20212 "cannot be set at the same time"));
20213 goto endjob;
20216 if ((info.total_bytes_sec_max && info.read_bytes_sec_max) ||
20217 (info.total_bytes_sec_max && info.write_bytes_sec_max)) {
20218 virReportError(VIR_ERR_INVALID_ARG, "%s",
20219 _("total and read/write of bytes_sec_max "
20220 "cannot be set at the same time"));
20221 goto endjob;
20224 if ((info.total_iops_sec_max && info.read_iops_sec_max) ||
20225 (info.total_iops_sec_max && info.write_iops_sec_max)) {
20226 virReportError(VIR_ERR_INVALID_ARG, "%s",
20227 _("total and read/write of iops_sec_max "
20228 "cannot be set at the same time"));
20229 goto endjob;
20232 if (def) {
20233 supportMaxOptions = virQEMUCapsGet(priv->qemuCaps,
20234 QEMU_CAPS_DRIVE_IOTUNE_MAX);
20235 supportGroupNameOption = virQEMUCapsGet(priv->qemuCaps,
20236 QEMU_CAPS_DRIVE_IOTUNE_GROUP);
20237 supportMaxLengthOptions =
20238 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH);
20240 if (!supportMaxOptions &&
20241 (set_fields & (QEMU_BLOCK_IOTUNE_SET_BYTES_MAX |
20242 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX |
20243 QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))) {
20244 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20245 _("a block I/O throttling parameter is not "
20246 "supported with this QEMU binary"));
20247 goto endjob;
20250 if (!supportGroupNameOption &&
20251 (set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME)) {
20252 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20253 _("the block I/O throttling group parameter is not "
20254 "supported with this QEMU binary"));
20255 goto endjob;
20258 if (!supportMaxLengthOptions &&
20259 (set_fields & (QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH |
20260 QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH))) {
20261 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20262 _("a block I/O throttling length parameter is not "
20263 "supported with this QEMU binary"));
20264 goto endjob;
20267 if (!(disk = qemuDomainDiskByName(def, path)))
20268 goto endjob;
20270 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
20271 qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
20272 } else {
20273 if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
20274 goto endjob;
20277 if (qemuDomainSetBlockIoTuneDefaults(&info, &disk->blkdeviotune,
20278 set_fields) < 0)
20279 goto endjob;
20281 #define CHECK_MAX(val, _bool) \
20282 do { \
20283 if (info.val##_max) { \
20284 if (!info.val) { \
20285 if (QEMU_BLOCK_IOTUNE_SET_##_bool) { \
20286 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20287 _("cannot reset '%s' when " \
20288 "'%s' is set"), \
20289 #val, #val "_max"); \
20290 } else { \
20291 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20292 _("value '%s' cannot be set if " \
20293 "'%s' is not set"), \
20294 #val "_max", #val); \
20296 goto endjob; \
20298 if (info.val##_max < info.val) { \
20299 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
20300 _("value '%s' cannot be " \
20301 "smaller than '%s'"), \
20302 #val "_max", #val); \
20303 goto endjob; \
20306 } while (false)
20308 CHECK_MAX(total_bytes_sec, BYTES);
20309 CHECK_MAX(read_bytes_sec, BYTES);
20310 CHECK_MAX(write_bytes_sec, BYTES);
20311 CHECK_MAX(total_iops_sec, IOPS);
20312 CHECK_MAX(read_iops_sec, IOPS);
20313 CHECK_MAX(write_iops_sec, IOPS);
20315 #undef CHECK_MAX
20317 /* NB: Let's let QEMU decide how to handle issues with _length
20318 * via the JSON error code from the block_set_io_throttle call */
20320 qemuDomainObjEnterMonitor(driver, vm);
20321 ret = qemuMonitorSetBlockIoThrottle(priv->mon, drivealias, qdevid,
20322 &info, supportMaxOptions,
20323 set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME,
20324 supportMaxLengthOptions);
20325 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20326 ret = -1;
20327 if (ret < 0)
20328 goto endjob;
20329 ret = -1;
20331 if (virDomainDiskSetBlockIOTune(disk, &info) < 0)
20332 goto endjob;
20334 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
20335 vm, driver->caps) < 0)
20336 goto endjob;
20338 if (eventNparams) {
20339 event = virDomainEventTunableNewFromDom(dom, eventParams, eventNparams);
20340 eventNparams = 0;
20341 virObjectEventStateQueue(driver->domainEventState, event);
20345 if (persistentDef) {
20346 if (!(conf_disk = virDomainDiskByName(persistentDef, path, true))) {
20347 virReportError(VIR_ERR_INVALID_ARG,
20348 _("missing persistent configuration for disk '%s'"),
20349 path);
20350 goto endjob;
20353 if (qemuDomainSetBlockIoTuneDefaults(&info, &conf_disk->blkdeviotune,
20354 set_fields) < 0)
20355 goto endjob;
20357 if (virDomainDiskSetBlockIOTune(conf_disk, &info) < 0)
20358 goto endjob;
20360 if (virDomainSaveConfig(cfg->configDir, driver->caps,
20361 persistentDef) < 0)
20362 goto endjob;
20365 ret = 0;
20366 endjob:
20367 qemuDomainObjEndJob(driver, vm);
20369 cleanup:
20370 VIR_FREE(info.group_name);
20371 VIR_FREE(drivealias);
20372 virDomainObjEndAPI(&vm);
20373 if (eventNparams)
20374 virTypedParamsFree(eventParams, eventNparams);
20375 virObjectUnref(cfg);
20376 return ret;
20379 static int
20380 qemuDomainGetBlockIoTune(virDomainPtr dom,
20381 const char *path,
20382 virTypedParameterPtr params,
20383 int *nparams,
20384 unsigned int flags)
20386 virDomainDiskDefPtr disk;
20387 virQEMUDriverPtr driver = dom->conn->privateData;
20388 virDomainObjPtr vm = NULL;
20389 qemuDomainObjPrivatePtr priv = NULL;
20390 virDomainDefPtr def = NULL;
20391 virDomainDefPtr persistentDef = NULL;
20392 virDomainBlockIoTuneInfo reply = {0};
20393 char *drivealias = NULL;
20394 const char *qdevid = NULL;
20395 int ret = -1;
20396 int maxparams;
20398 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20399 VIR_DOMAIN_AFFECT_CONFIG |
20400 VIR_TYPED_PARAM_STRING_OKAY, -1);
20402 /* We don't return strings, and thus trivially support this flag. */
20403 flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
20405 if (!(vm = qemuDomObjFromDomain(dom)))
20406 return -1;
20408 priv = vm->privateData;
20410 if (virDomainGetBlockIoTuneEnsureACL(dom->conn, vm->def) < 0)
20411 goto cleanup;
20413 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20414 goto cleanup;
20416 /* the API check guarantees that only one of the definitions will be set */
20417 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
20418 goto endjob;
20420 if (def) {
20421 /* If the VM is running, we can check if the current VM can use
20422 * optional parameters or not. */
20423 maxparams = QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS;
20424 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX))
20425 maxparams += QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS;
20426 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_GROUP))
20427 maxparams += QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS;
20428 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH))
20429 maxparams += QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS;
20430 } else {
20431 maxparams = QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS;
20434 if (*nparams == 0) {
20435 *nparams = maxparams;
20436 ret = 0;
20437 goto endjob;
20438 } else if (*nparams < maxparams) {
20439 maxparams = *nparams;
20442 *nparams = 0;
20444 if (def) {
20445 if (!(disk = qemuDomainDiskByName(def, path)))
20446 goto endjob;
20448 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
20449 qdevid = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
20450 } else {
20451 if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
20452 goto endjob;
20454 qemuDomainObjEnterMonitor(driver, vm);
20455 ret = qemuMonitorGetBlockIoThrottle(priv->mon, drivealias, qdevid, &reply);
20456 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20457 goto endjob;
20458 if (ret < 0)
20459 goto endjob;
20462 if (persistentDef) {
20463 if (!(disk = virDomainDiskByName(persistentDef, path, true))) {
20464 virReportError(VIR_ERR_INVALID_ARG,
20465 _("disk '%s' was not found in the domain config"),
20466 path);
20467 goto endjob;
20469 reply = disk->blkdeviotune;
20471 /* Group name needs to be copied since qemuMonitorGetBlockIoThrottle
20472 * allocates it as well */
20473 if (VIR_STRDUP(reply.group_name, disk->blkdeviotune.group_name) < 0)
20474 goto endjob;
20477 #define BLOCK_IOTUNE_ASSIGN(name, var) \
20478 if (*nparams < maxparams && \
20479 virTypedParameterAssign(&params[(*nparams)++], \
20480 VIR_DOMAIN_BLOCK_IOTUNE_ ## name, \
20481 VIR_TYPED_PARAM_ULLONG, \
20482 reply.var) < 0) \
20483 goto endjob
20486 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC, total_bytes_sec);
20487 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC, read_bytes_sec);
20488 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC, write_bytes_sec);
20490 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC, total_iops_sec);
20491 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC, read_iops_sec);
20492 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC, write_iops_sec);
20494 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX, total_bytes_sec_max);
20495 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX, read_bytes_sec_max);
20496 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX, write_bytes_sec_max);
20498 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX, total_iops_sec_max);
20499 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX, read_iops_sec_max);
20500 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX, write_iops_sec_max);
20502 BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
20504 if (*nparams < maxparams) {
20505 if (virTypedParameterAssign(&params[(*nparams)++],
20506 VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
20507 VIR_TYPED_PARAM_STRING,
20508 reply.group_name) < 0)
20509 goto endjob;
20511 reply.group_name = NULL;
20514 BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
20515 BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
20516 BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
20518 BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
20519 BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
20520 BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
20521 #undef BLOCK_IOTUNE_ASSIGN
20523 ret = 0;
20525 endjob:
20526 qemuDomainObjEndJob(driver, vm);
20528 cleanup:
20529 VIR_FREE(reply.group_name);
20530 VIR_FREE(drivealias);
20531 virDomainObjEndAPI(&vm);
20532 return ret;
20535 static int
20536 qemuDomainGetDiskErrors(virDomainPtr dom,
20537 virDomainDiskErrorPtr errors,
20538 unsigned int nerrors,
20539 unsigned int flags)
20541 virQEMUDriverPtr driver = dom->conn->privateData;
20542 virDomainObjPtr vm = NULL;
20543 qemuDomainObjPrivatePtr priv;
20544 virHashTablePtr table = NULL;
20545 bool blockdev = false;
20546 int ret = -1;
20547 size_t i;
20548 int n = 0;
20550 virCheckFlags(0, -1);
20552 if (!(vm = qemuDomObjFromDomain(dom)))
20553 goto cleanup;
20555 priv = vm->privateData;
20556 blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
20558 if (virDomainGetDiskErrorsEnsureACL(dom->conn, vm->def) < 0)
20559 goto cleanup;
20561 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
20562 goto cleanup;
20564 if (virDomainObjCheckActive(vm) < 0)
20565 goto endjob;
20567 if (!errors) {
20568 ret = vm->def->ndisks;
20569 goto endjob;
20572 qemuDomainObjEnterMonitor(driver, vm);
20573 table = qemuMonitorGetBlockInfo(priv->mon);
20574 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20575 goto endjob;
20576 if (!table)
20577 goto endjob;
20579 for (i = n = 0; i < vm->def->ndisks; i++) {
20580 struct qemuDomainDiskInfo *info;
20581 virDomainDiskDefPtr disk = vm->def->disks[i];
20582 qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
20583 const char *entryname = disk->info.alias;
20585 if (blockdev)
20586 entryname = diskPriv->qomName;
20588 if ((info = virHashLookup(table, entryname)) &&
20589 info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
20590 if (n == nerrors)
20591 break;
20593 if (VIR_STRDUP(errors[n].disk, disk->dst) < 0)
20594 goto endjob;
20595 errors[n].error = info->io_status;
20596 n++;
20600 ret = n;
20602 endjob:
20603 qemuDomainObjEndJob(driver, vm);
20605 cleanup:
20606 virDomainObjEndAPI(&vm);
20607 virHashFree(table);
20608 if (ret < 0) {
20609 for (i = 0; i < n; i++)
20610 VIR_FREE(errors[i].disk);
20612 return ret;
20615 static int
20616 qemuDomainSetMetadata(virDomainPtr dom,
20617 int type,
20618 const char *metadata,
20619 const char *key,
20620 const char *uri,
20621 unsigned int flags)
20623 virQEMUDriverPtr driver = dom->conn->privateData;
20624 virDomainObjPtr vm;
20625 virQEMUDriverConfigPtr cfg = NULL;
20626 virCapsPtr caps = NULL;
20627 int ret = -1;
20629 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
20630 VIR_DOMAIN_AFFECT_CONFIG, -1);
20632 if (!(vm = qemuDomObjFromDomain(dom)))
20633 return -1;
20635 cfg = virQEMUDriverGetConfig(driver);
20637 if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0)
20638 goto cleanup;
20640 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
20641 goto cleanup;
20643 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20644 goto cleanup;
20646 ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps,
20647 driver->xmlopt, cfg->stateDir,
20648 cfg->configDir, flags);
20650 if (ret == 0) {
20651 virObjectEventPtr ev = NULL;
20652 ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
20653 virObjectEventStateQueue(driver->domainEventState, ev);
20656 qemuDomainObjEndJob(driver, vm);
20658 cleanup:
20659 virDomainObjEndAPI(&vm);
20660 virObjectUnref(caps);
20661 virObjectUnref(cfg);
20662 return ret;
20665 static char *
20666 qemuDomainGetMetadata(virDomainPtr dom,
20667 int type,
20668 const char *uri,
20669 unsigned int flags)
20671 virDomainObjPtr vm;
20672 char *ret = NULL;
20674 if (!(vm = qemuDomObjFromDomain(dom)))
20675 return NULL;
20677 if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0)
20678 goto cleanup;
20680 ret = virDomainObjGetMetadata(vm, type, uri, flags);
20682 cleanup:
20683 virDomainObjEndAPI(&vm);
20684 return ret;
20688 static int
20689 qemuDomainGetCPUStats(virDomainPtr domain,
20690 virTypedParameterPtr params,
20691 unsigned int nparams,
20692 int start_cpu,
20693 unsigned int ncpus,
20694 unsigned int flags)
20696 virDomainObjPtr vm = NULL;
20697 int ret = -1;
20698 qemuDomainObjPrivatePtr priv;
20699 virBitmapPtr guestvcpus = NULL;
20701 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
20703 if (!(vm = qemuDomObjFromDomain(domain)))
20704 return -1;
20706 priv = vm->privateData;
20708 if (virDomainGetCPUStatsEnsureACL(domain->conn, vm->def) < 0)
20709 goto cleanup;
20711 if (virDomainObjCheckActive(vm) < 0)
20712 goto cleanup;
20714 if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
20715 virReportError(VIR_ERR_OPERATION_INVALID,
20716 "%s", _("cgroup CPUACCT controller is not mounted"));
20717 goto cleanup;
20720 if (qemuDomainHasVcpuPids(vm) &&
20721 !(guestvcpus = virDomainDefGetOnlineVcpumap(vm->def)))
20722 goto cleanup;
20724 if (start_cpu == -1)
20725 ret = virCgroupGetDomainTotalCpuStats(priv->cgroup,
20726 params, nparams);
20727 else
20728 ret = virCgroupGetPercpuStats(priv->cgroup, params, nparams,
20729 start_cpu, ncpus, guestvcpus);
20730 cleanup:
20731 virBitmapFree(guestvcpus);
20732 virDomainObjEndAPI(&vm);
20733 return ret;
20736 static int
20737 qemuDomainPMSuspendForDuration(virDomainPtr dom,
20738 unsigned int target,
20739 unsigned long long duration,
20740 unsigned int flags)
20742 virQEMUDriverPtr driver = dom->conn->privateData;
20743 virDomainObjPtr vm;
20744 qemuAgentPtr agent;
20745 int ret = -1;
20747 virCheckFlags(0, -1);
20749 if (duration) {
20750 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
20751 _("Duration not supported. Use 0 for now"));
20752 return -1;
20755 if (!(target == VIR_NODE_SUSPEND_TARGET_MEM ||
20756 target == VIR_NODE_SUSPEND_TARGET_DISK ||
20757 target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
20758 virReportError(VIR_ERR_INVALID_ARG,
20759 _("Unknown suspend target: %u"),
20760 target);
20761 return -1;
20764 if (!(vm = qemuDomObjFromDomain(dom)))
20765 goto cleanup;
20767 if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0)
20768 goto cleanup;
20770 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
20771 goto cleanup;
20773 if (virDomainObjCheckActive(vm) < 0)
20774 goto endjob;
20776 if (vm->def->pm.s3 || vm->def->pm.s4) {
20777 if (vm->def->pm.s3 == VIR_TRISTATE_BOOL_NO &&
20778 (target == VIR_NODE_SUSPEND_TARGET_MEM ||
20779 target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
20780 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20781 _("S3 state is disabled for this domain"));
20782 goto endjob;
20785 if (vm->def->pm.s4 == VIR_TRISTATE_BOOL_NO &&
20786 target == VIR_NODE_SUSPEND_TARGET_DISK) {
20787 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20788 _("S4 state is disabled for this domain"));
20789 goto endjob;
20793 if (!qemuDomainAgentAvailable(vm, true))
20794 goto endjob;
20796 agent = qemuDomainObjEnterAgent(vm);
20797 ret = qemuAgentSuspend(agent, target);
20798 qemuDomainObjExitAgent(vm, agent);
20800 endjob:
20801 qemuDomainObjEndAgentJob(vm);
20803 cleanup:
20804 virDomainObjEndAPI(&vm);
20805 return ret;
20808 static int
20809 qemuDomainPMWakeup(virDomainPtr dom,
20810 unsigned int flags)
20812 virQEMUDriverPtr driver = dom->conn->privateData;
20813 virDomainObjPtr vm;
20814 int ret = -1;
20815 qemuDomainObjPrivatePtr priv;
20817 virCheckFlags(0, -1);
20819 if (!(vm = qemuDomObjFromDomain(dom)))
20820 goto cleanup;
20822 if (virDomainPMWakeupEnsureACL(dom->conn, vm->def) < 0)
20823 goto cleanup;
20825 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
20826 goto cleanup;
20828 if (virDomainObjCheckActive(vm) < 0)
20829 goto endjob;
20831 priv = vm->privateData;
20833 qemuDomainObjEnterMonitor(driver, vm);
20834 ret = qemuMonitorSystemWakeup(priv->mon);
20835 if (qemuDomainObjExitMonitor(driver, vm) < 0)
20836 ret = -1;
20838 endjob:
20839 qemuDomainObjEndJob(driver, vm);
20841 cleanup:
20842 virDomainObjEndAPI(&vm);
20843 return ret;
20846 static int
20847 qemuConnectListAllDomains(virConnectPtr conn,
20848 virDomainPtr **domains,
20849 unsigned int flags)
20851 virQEMUDriverPtr driver = conn->privateData;
20852 int ret = -1;
20854 virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
20856 if (virConnectListAllDomainsEnsureACL(conn) < 0)
20857 goto cleanup;
20859 ret = virDomainObjListExport(driver->domains, conn, domains,
20860 virConnectListAllDomainsCheckACL, flags);
20862 cleanup:
20863 return ret;
20866 static char *
20867 qemuDomainQemuAgentCommand(virDomainPtr domain,
20868 const char *cmd,
20869 int timeout,
20870 unsigned int flags)
20872 virQEMUDriverPtr driver = domain->conn->privateData;
20873 virDomainObjPtr vm;
20874 int ret = -1;
20875 char *result = NULL;
20876 qemuAgentPtr agent;
20878 virCheckFlags(0, NULL);
20880 if (!(vm = qemuDomObjFromDomain(domain)))
20881 goto cleanup;
20883 if (virDomainQemuAgentCommandEnsureACL(domain->conn, vm->def) < 0)
20884 goto cleanup;
20886 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
20887 goto cleanup;
20889 if (virDomainObjCheckActive(vm) < 0)
20890 goto endjob;
20892 if (!qemuDomainAgentAvailable(vm, true))
20893 goto endjob;
20895 qemuDomainObjTaint(driver, vm, VIR_DOMAIN_TAINT_CUSTOM_GA_COMMAND, NULL);
20897 agent = qemuDomainObjEnterAgent(vm);
20898 ret = qemuAgentArbitraryCommand(agent, cmd, &result, timeout);
20899 qemuDomainObjExitAgent(vm, agent);
20900 if (ret < 0)
20901 VIR_FREE(result);
20903 endjob:
20904 qemuDomainObjEndAgentJob(vm);
20906 cleanup:
20907 virDomainObjEndAPI(&vm);
20908 return result;
20912 static int
20913 qemuConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
20914 virDomainPtr dom,
20915 const char *event,
20916 virConnectDomainQemuMonitorEventCallback callback,
20917 void *opaque,
20918 virFreeCallback freecb,
20919 unsigned int flags)
20921 virQEMUDriverPtr driver = conn->privateData;
20922 int ret = -1;
20924 if (virConnectDomainQemuMonitorEventRegisterEnsureACL(conn) < 0)
20925 goto cleanup;
20927 if (virDomainQemuMonitorEventStateRegisterID(conn,
20928 driver->domainEventState,
20929 dom, event, callback,
20930 opaque, freecb, flags,
20931 &ret) < 0)
20932 ret = -1;
20934 cleanup:
20935 return ret;
20939 static int
20940 qemuConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
20941 int callbackID)
20943 virQEMUDriverPtr driver = conn->privateData;
20944 int ret = -1;
20946 if (virConnectDomainQemuMonitorEventDeregisterEnsureACL(conn) < 0)
20947 goto cleanup;
20949 if (virObjectEventStateDeregisterID(conn, driver->domainEventState,
20950 callbackID, true) < 0)
20951 goto cleanup;
20953 ret = 0;
20955 cleanup:
20956 return ret;
20960 static int
20961 qemuDomainFSTrim(virDomainPtr dom,
20962 const char *mountPoint,
20963 unsigned long long minimum,
20964 unsigned int flags)
20966 virQEMUDriverPtr driver = dom->conn->privateData;
20967 virDomainObjPtr vm;
20968 qemuAgentPtr agent;
20969 int ret = -1;
20971 virCheckFlags(0, -1);
20973 if (mountPoint) {
20974 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
20975 _("Specifying mount point "
20976 "is not supported for now"));
20977 return -1;
20980 if (!(vm = qemuDomObjFromDomain(dom)))
20981 goto cleanup;
20983 if (virDomainFSTrimEnsureACL(dom->conn, vm->def) < 0)
20984 goto cleanup;
20986 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
20987 goto cleanup;
20989 if (!qemuDomainAgentAvailable(vm, true))
20990 goto endjob;
20992 if (virDomainObjCheckActive(vm) < 0)
20993 goto endjob;
20995 agent = qemuDomainObjEnterAgent(vm);
20996 ret = qemuAgentFSTrim(agent, minimum);
20997 qemuDomainObjExitAgent(vm, agent);
20999 endjob:
21000 qemuDomainObjEndAgentJob(vm);
21002 cleanup:
21003 virDomainObjEndAPI(&vm);
21004 return ret;
21008 static int
21009 qemuNodeGetInfo(virConnectPtr conn,
21010 virNodeInfoPtr nodeinfo)
21012 if (virNodeGetInfoEnsureACL(conn) < 0)
21013 return -1;
21015 return virCapabilitiesGetNodeInfo(nodeinfo);
21019 static int
21020 qemuNodeGetCPUStats(virConnectPtr conn,
21021 int cpuNum,
21022 virNodeCPUStatsPtr params,
21023 int *nparams,
21024 unsigned int flags)
21026 if (virNodeGetCPUStatsEnsureACL(conn) < 0)
21027 return -1;
21029 return virHostCPUGetStats(cpuNum, params, nparams, flags);
21033 static int
21034 qemuNodeGetMemoryStats(virConnectPtr conn,
21035 int cellNum,
21036 virNodeMemoryStatsPtr params,
21037 int *nparams,
21038 unsigned int flags)
21040 if (virNodeGetMemoryStatsEnsureACL(conn) < 0)
21041 return -1;
21043 return virHostMemGetStats(cellNum, params, nparams, flags);
21047 static int
21048 qemuNodeGetCellsFreeMemory(virConnectPtr conn,
21049 unsigned long long *freeMems,
21050 int startCell,
21051 int maxCells)
21053 if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
21054 return -1;
21056 return virHostMemGetCellsFree(freeMems, startCell, maxCells);
21060 static unsigned long long
21061 qemuNodeGetFreeMemory(virConnectPtr conn)
21063 unsigned long long freeMem;
21065 if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
21066 return 0;
21068 if (virHostMemGetInfo(NULL, &freeMem) < 0)
21069 return 0;
21071 return freeMem;
21075 static int
21076 qemuNodeGetMemoryParameters(virConnectPtr conn,
21077 virTypedParameterPtr params,
21078 int *nparams,
21079 unsigned int flags)
21081 if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
21082 return -1;
21084 return virHostMemGetParameters(params, nparams, flags);
21088 static int
21089 qemuNodeSetMemoryParameters(virConnectPtr conn,
21090 virTypedParameterPtr params,
21091 int nparams,
21092 unsigned int flags)
21094 if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
21095 return -1;
21097 return virHostMemSetParameters(params, nparams, flags);
21101 static int
21102 qemuNodeGetCPUMap(virConnectPtr conn,
21103 unsigned char **cpumap,
21104 unsigned int *online,
21105 unsigned int flags)
21107 if (virNodeGetCPUMapEnsureACL(conn) < 0)
21108 return -1;
21110 return virHostCPUGetMap(cpumap, online, flags);
21114 static int
21115 qemuNodeSuspendForDuration(virConnectPtr conn,
21116 unsigned int target,
21117 unsigned long long duration,
21118 unsigned int flags)
21120 if (virNodeSuspendForDurationEnsureACL(conn) < 0)
21121 return -1;
21123 return virNodeSuspend(target, duration, flags);
21126 static int
21127 qemuConnectGetCPUModelNames(virConnectPtr conn,
21128 const char *archName,
21129 char ***models,
21130 unsigned int flags)
21132 virArch arch;
21134 virCheckFlags(0, -1);
21135 if (virConnectGetCPUModelNamesEnsureACL(conn) < 0)
21136 return -1;
21138 if (!(arch = virArchFromString(archName))) {
21139 virReportError(VIR_ERR_INVALID_ARG,
21140 _("cannot find architecture %s"),
21141 archName);
21142 return -1;
21145 return virCPUGetModels(arch, models);
21149 static char *
21150 qemuDomainGetHostname(virDomainPtr dom,
21151 unsigned int flags)
21153 virQEMUDriverPtr driver = dom->conn->privateData;
21154 virDomainObjPtr vm = NULL;
21155 qemuAgentPtr agent;
21156 char *hostname = NULL;
21158 virCheckFlags(0, NULL);
21160 if (!(vm = qemuDomObjFromDomain(dom)))
21161 return NULL;
21163 if (virDomainGetHostnameEnsureACL(dom->conn, vm->def) < 0)
21164 goto cleanup;
21166 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
21167 goto cleanup;
21169 if (virDomainObjCheckActive(vm) < 0)
21170 goto endjob;
21172 if (!qemuDomainAgentAvailable(vm, true))
21173 goto endjob;
21175 agent = qemuDomainObjEnterAgent(vm);
21176 ignore_value(qemuAgentGetHostname(agent, &hostname));
21177 qemuDomainObjExitAgent(vm, agent);
21179 endjob:
21180 qemuDomainObjEndAgentJob(vm);
21182 cleanup:
21183 virDomainObjEndAPI(&vm);
21184 return hostname;
21188 static int
21189 qemuDomainGetTime(virDomainPtr dom,
21190 long long *seconds,
21191 unsigned int *nseconds,
21192 unsigned int flags)
21194 virQEMUDriverPtr driver = dom->conn->privateData;
21195 virDomainObjPtr vm = NULL;
21196 qemuAgentPtr agent;
21197 int ret = -1;
21198 int rv;
21200 virCheckFlags(0, ret);
21202 if (!(vm = qemuDomObjFromDomain(dom)))
21203 return ret;
21205 if (virDomainGetTimeEnsureACL(dom->conn, vm->def) < 0)
21206 goto cleanup;
21208 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
21209 goto cleanup;
21211 if (virDomainObjCheckActive(vm) < 0)
21212 goto endjob;
21214 if (!qemuDomainAgentAvailable(vm, true))
21215 goto endjob;
21217 agent = qemuDomainObjEnterAgent(vm);
21218 rv = qemuAgentGetTime(agent, seconds, nseconds);
21219 qemuDomainObjExitAgent(vm, agent);
21221 if (rv < 0)
21222 goto endjob;
21224 ret = 0;
21226 endjob:
21227 qemuDomainObjEndAgentJob(vm);
21229 cleanup:
21230 virDomainObjEndAPI(&vm);
21231 return ret;
21235 static int
21236 qemuDomainSetTime(virDomainPtr dom,
21237 long long seconds,
21238 unsigned int nseconds,
21239 unsigned int flags)
21241 virQEMUDriverPtr driver = dom->conn->privateData;
21242 qemuDomainObjPrivatePtr priv;
21243 virDomainObjPtr vm;
21244 qemuAgentPtr agent;
21245 bool rtcSync = flags & VIR_DOMAIN_TIME_SYNC;
21246 int ret = -1;
21247 int rv;
21249 virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret);
21251 if (!(vm = qemuDomObjFromDomain(dom)))
21252 return ret;
21254 if (virDomainSetTimeEnsureACL(dom->conn, vm->def) < 0)
21255 goto cleanup;
21257 priv = vm->privateData;
21259 if (qemuDomainObjBeginJobWithAgent(driver, vm,
21260 QEMU_JOB_MODIFY,
21261 QEMU_AGENT_JOB_MODIFY) < 0)
21262 goto cleanup;
21264 if (virDomainObjCheckActive(vm) < 0)
21265 goto endjob;
21267 /* On x86, the rtc-reset-reinjection QMP command must be called after
21268 * setting the time to avoid trouble down the line. If the command is
21269 * not available, don't set the time at all and report an error */
21270 if (ARCH_IS_X86(vm->def->os.arch) &&
21271 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION))
21273 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
21274 _("cannot set time: qemu doesn't support "
21275 "rtc-reset-reinjection command"));
21276 goto endjob;
21279 if (!qemuDomainAgentAvailable(vm, true))
21280 goto endjob;
21282 agent = qemuDomainObjEnterAgent(vm);
21283 rv = qemuAgentSetTime(agent, seconds, nseconds, rtcSync);
21284 qemuDomainObjExitAgent(vm, agent);
21286 if (rv < 0)
21287 goto endjob;
21289 if (virDomainObjCheckActive(vm) < 0)
21290 goto endjob;
21292 /* Don't try to call rtc-reset-reinjection if it's not available */
21293 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) {
21294 qemuDomainObjEnterMonitor(driver, vm);
21295 rv = qemuMonitorRTCResetReinjection(priv->mon);
21296 if (qemuDomainObjExitMonitor(driver, vm) < 0)
21297 goto endjob;
21299 if (rv < 0)
21300 goto endjob;
21303 ret = 0;
21305 endjob:
21306 qemuDomainObjEndJobWithAgent(driver, vm);
21308 cleanup:
21309 virDomainObjEndAPI(&vm);
21310 return ret;
21314 static int
21315 qemuDomainFSFreeze(virDomainPtr dom,
21316 const char **mountpoints,
21317 unsigned int nmountpoints,
21318 unsigned int flags)
21320 virQEMUDriverPtr driver = dom->conn->privateData;
21321 virDomainObjPtr vm;
21322 int ret = -1;
21324 virCheckFlags(0, -1);
21326 if (!(vm = qemuDomObjFromDomain(dom)))
21327 goto cleanup;
21329 if (virDomainFSFreezeEnsureACL(dom->conn, vm->def) < 0)
21330 goto cleanup;
21332 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21333 goto cleanup;
21335 if (virDomainObjCheckActive(vm) < 0)
21336 goto endjob;
21338 ret = qemuDomainSnapshotFSFreeze(driver, vm, mountpoints, nmountpoints);
21340 endjob:
21341 qemuDomainObjEndAgentJob(vm);
21343 cleanup:
21344 virDomainObjEndAPI(&vm);
21345 return ret;
21349 static int
21350 qemuDomainFSThaw(virDomainPtr dom,
21351 const char **mountpoints,
21352 unsigned int nmountpoints,
21353 unsigned int flags)
21355 virQEMUDriverPtr driver = dom->conn->privateData;
21356 virDomainObjPtr vm;
21357 int ret = -1;
21359 virCheckFlags(0, -1);
21361 if (mountpoints || nmountpoints) {
21362 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
21363 _("specifying mountpoints is not supported"));
21364 return ret;
21367 if (!(vm = qemuDomObjFromDomain(dom)))
21368 goto cleanup;
21370 if (virDomainFSThawEnsureACL(dom->conn, vm->def) < 0)
21371 goto cleanup;
21373 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
21374 goto cleanup;
21376 if (virDomainObjCheckActive(vm) < 0)
21377 goto endjob;
21379 ret = qemuDomainSnapshotFSThaw(driver, vm, true);
21381 endjob:
21382 qemuDomainObjEndAgentJob(vm);
21384 cleanup:
21385 virDomainObjEndAPI(&vm);
21386 return ret;
21390 static int
21391 qemuNodeGetFreePages(virConnectPtr conn,
21392 unsigned int npages,
21393 unsigned int *pages,
21394 int startCell,
21395 unsigned int cellCount,
21396 unsigned long long *counts,
21397 unsigned int flags)
21399 virCheckFlags(0, -1);
21401 if (virNodeGetFreePagesEnsureACL(conn) < 0)
21402 return -1;
21404 return virHostMemGetFreePages(npages, pages, startCell, cellCount, counts);
21408 static char *
21409 qemuConnectGetDomainCapabilities(virConnectPtr conn,
21410 const char *emulatorbin,
21411 const char *arch_str,
21412 const char *machine,
21413 const char *virttype_str,
21414 unsigned int flags)
21416 char *ret = NULL;
21417 virQEMUDriverPtr driver = conn->privateData;
21418 virQEMUCapsPtr qemuCaps = NULL;
21419 virArch arch;
21420 virDomainVirtType virttype;
21421 virDomainCapsPtr domCaps = NULL;
21422 virQEMUDriverConfigPtr cfg = NULL;
21423 virCapsPtr caps = NULL;
21425 virCheckFlags(0, ret);
21427 if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
21428 return ret;
21430 cfg = virQEMUDriverGetConfig(driver);
21432 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
21433 goto cleanup;
21435 qemuCaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
21436 emulatorbin,
21437 arch_str,
21438 virttype_str,
21439 machine,
21440 &arch, &virttype, &machine);
21441 if (!qemuCaps)
21442 goto cleanup;
21444 if (!(domCaps = virDomainCapsNew(virQEMUCapsGetBinary(qemuCaps), machine,
21445 arch, virttype)))
21446 goto cleanup;
21448 if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps,
21449 cfg->firmwares, cfg->nfirmwares) < 0)
21450 goto cleanup;
21452 ret = virDomainCapsFormat(domCaps);
21453 cleanup:
21454 virObjectUnref(cfg);
21455 virObjectUnref(caps);
21456 virObjectUnref(domCaps);
21457 virObjectUnref(qemuCaps);
21458 return ret;
21462 static int
21463 qemuDomainGetStatsState(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
21464 virDomainObjPtr dom,
21465 virDomainStatsRecordPtr record,
21466 int *maxparams,
21467 unsigned int privflags ATTRIBUTE_UNUSED)
21469 if (virTypedParamsAddInt(&record->params,
21470 &record->nparams,
21471 maxparams,
21472 "state.state",
21473 dom->state.state) < 0)
21474 return -1;
21476 if (virTypedParamsAddInt(&record->params,
21477 &record->nparams,
21478 maxparams,
21479 "state.reason",
21480 dom->state.reason) < 0)
21481 return -1;
21483 return 0;
21487 typedef enum {
21488 QEMU_DOMAIN_STATS_HAVE_JOB = 1 << 0, /* job is entered, monitor can be
21489 accessed */
21490 QEMU_DOMAIN_STATS_BACKING = 1 << 1, /* include backing chain in
21491 block stats */
21492 } qemuDomainStatsFlags;
21495 #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB)
21498 typedef struct _virQEMUResctrlMonData virQEMUResctrlMonData;
21499 typedef virQEMUResctrlMonData *virQEMUResctrlMonDataPtr;
21500 struct _virQEMUResctrlMonData {
21501 char *name;
21502 char *vcpus;
21503 virResctrlMonitorStatsPtr *stats;
21504 size_t nstats;
21508 static void
21509 qemuDomainFreeResctrlMonData(virQEMUResctrlMonDataPtr resdata)
21511 VIR_FREE(resdata->name);
21512 VIR_FREE(resdata->vcpus);
21513 virResctrlMonitorFreeStats(resdata->stats, resdata->nstats);
21514 VIR_FREE(resdata);
21519 * qemuDomainGetResctrlMonData:
21520 * @dom: Pointer for the domain that the resctrl monitors reside in
21521 * @resdata: Pointer of virQEMUResctrlMonDataPtr pointer for receiving the
21522 * virQEMUResctrlMonDataPtr array. Caller is responsible for
21523 * freeing the array.
21524 * @nresdata: Pointer of size_t to report the size virQEMUResctrlMonDataPtr
21525 * array to caller. If *@nresdata is not 0, even if function
21526 * returns an error, the caller is also required to call
21527 * qemuDomainFreeResctrlMonData to free each element in the
21528 * *@resdata array and then the array itself.
21529 * @tag: Could be VIR_RESCTRL_MONITOR_TYPE_CACHE for getting cache statistics
21530 * from @dom cache monitors. VIR_RESCTRL_MONITOR_TYPE_MEMBW for
21531 * getting memory bandwidth statistics from memory bandwidth monitors.
21533 * Get cache or memory bandwidth statistics from @dom monitors.
21535 * Returns -1 on failure, or 0 on success.
21537 static int
21538 qemuDomainGetResctrlMonData(virDomainObjPtr dom,
21539 virQEMUResctrlMonDataPtr **resdata,
21540 size_t *nresdata,
21541 virResctrlMonitorType tag)
21543 virDomainResctrlDefPtr resctrl = NULL;
21544 virQEMUResctrlMonDataPtr res = NULL;
21545 size_t i = 0;
21546 size_t j = 0;
21548 for (i = 0; i < dom->def->nresctrls; i++) {
21549 resctrl = dom->def->resctrls[i];
21551 for (j = 0; j < resctrl->nmonitors; j++) {
21552 virDomainResctrlMonDefPtr domresmon = NULL;
21553 virResctrlMonitorPtr monitor = NULL;
21555 domresmon = resctrl->monitors[j];
21556 monitor = domresmon->instance;
21558 if (domresmon->tag != tag)
21559 continue;
21561 if (VIR_ALLOC(res) < 0)
21562 return -1;
21564 /* If virBitmapFormat successfully returns an vcpu string, then
21565 * res.vcpus is assigned with an memory space holding it,
21566 * let this newly allocated memory buffer to be freed along with
21567 * the free of 'res' */
21568 if (!(res->vcpus = virBitmapFormat(domresmon->vcpus)))
21569 goto error;
21571 if (VIR_STRDUP(res->name, virResctrlMonitorGetID(monitor)) < 0)
21572 goto error;
21574 if (virResctrlMonitorGetCacheOccupancy(monitor,
21575 &res->stats,
21576 &res->nstats) < 0)
21577 goto error;
21579 if (VIR_APPEND_ELEMENT(*resdata, *nresdata, res) < 0)
21580 goto error;
21584 return 0;
21586 error:
21587 qemuDomainFreeResctrlMonData(res);
21588 return -1;
21592 static int
21593 qemuDomainGetStatsCpuCache(virDomainObjPtr dom,
21594 virDomainStatsRecordPtr record,
21595 int *maxparams)
21597 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
21598 virQEMUResctrlMonDataPtr *resdata = NULL;
21599 size_t nresdata = 0;
21600 size_t i = 0;
21601 size_t j = 0;
21602 int ret = -1;
21604 if (!virDomainObjIsActive(dom))
21605 return 0;
21607 if (qemuDomainGetResctrlMonData(dom, &resdata, &nresdata,
21608 VIR_RESCTRL_MONITOR_TYPE_CACHE) < 0)
21609 goto cleanup;
21611 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21612 "cpu.cache.monitor.count");
21613 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21614 maxparams, param_name, nresdata) < 0)
21615 goto cleanup;
21617 for (i = 0; i < nresdata; i++) {
21618 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21619 "cpu.cache.monitor.%zu.name", i);
21620 if (virTypedParamsAddString(&record->params,
21621 &record->nparams,
21622 maxparams,
21623 param_name,
21624 resdata[i]->name) < 0)
21625 goto cleanup;
21627 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21628 "cpu.cache.monitor.%zu.vcpus", i);
21629 if (virTypedParamsAddString(&record->params, &record->nparams,
21630 maxparams, param_name,
21631 resdata[i]->vcpus) < 0)
21632 goto cleanup;
21634 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21635 "cpu.cache.monitor.%zu.bank.count", i);
21636 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21637 maxparams, param_name,
21638 resdata[i]->nstats) < 0)
21639 goto cleanup;
21641 for (j = 0; j < resdata[i]->nstats; j++) {
21642 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21643 "cpu.cache.monitor.%zu.bank.%zu.id", i, j);
21644 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21645 maxparams, param_name,
21646 resdata[i]->stats[j]->id) < 0)
21647 goto cleanup;
21649 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21650 "cpu.cache.monitor.%zu.bank.%zu.bytes", i, j);
21651 if (virTypedParamsAddUInt(&record->params, &record->nparams,
21652 maxparams, param_name,
21653 resdata[i]->stats[j]->val) < 0)
21654 goto cleanup;
21658 ret = 0;
21659 cleanup:
21660 for (i = 0; i < nresdata; i++)
21661 qemuDomainFreeResctrlMonData(resdata[i]);
21662 VIR_FREE(resdata);
21663 return ret;
21667 static int
21668 qemuDomainGetStatsCpuCgroup(virDomainObjPtr dom,
21669 virDomainStatsRecordPtr record,
21670 int *maxparams)
21672 qemuDomainObjPrivatePtr priv = dom->privateData;
21673 unsigned long long cpu_time = 0;
21674 unsigned long long user_time = 0;
21675 unsigned long long sys_time = 0;
21676 int err = 0;
21678 if (!priv->cgroup)
21679 return 0;
21681 err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time);
21682 if (!err && virTypedParamsAddULLong(&record->params,
21683 &record->nparams,
21684 maxparams,
21685 "cpu.time",
21686 cpu_time) < 0)
21687 return -1;
21689 err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time);
21690 if (!err && virTypedParamsAddULLong(&record->params,
21691 &record->nparams,
21692 maxparams,
21693 "cpu.user",
21694 user_time) < 0)
21695 return -1;
21696 if (!err && virTypedParamsAddULLong(&record->params,
21697 &record->nparams,
21698 maxparams,
21699 "cpu.system",
21700 sys_time) < 0)
21701 return -1;
21703 return 0;
21707 static int
21708 qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
21709 virDomainObjPtr dom,
21710 virDomainStatsRecordPtr record,
21711 int *maxparams,
21712 unsigned int privflags ATTRIBUTE_UNUSED)
21714 if (qemuDomainGetStatsCpuCgroup(dom, record, maxparams) < 0)
21715 return -1;
21717 if (qemuDomainGetStatsCpuCache(dom, record, maxparams) < 0)
21718 return -1;
21720 return 0;
21724 static int
21725 qemuDomainGetStatsBalloon(virQEMUDriverPtr driver,
21726 virDomainObjPtr dom,
21727 virDomainStatsRecordPtr record,
21728 int *maxparams,
21729 unsigned int privflags)
21731 virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR];
21732 int nr_stats;
21733 unsigned long long cur_balloon = 0;
21734 size_t i;
21736 if (!virDomainDefHasMemballoon(dom->def)) {
21737 cur_balloon = virDomainDefGetMemoryTotal(dom->def);
21738 } else {
21739 cur_balloon = dom->def->mem.cur_balloon;
21742 if (virTypedParamsAddULLong(&record->params,
21743 &record->nparams,
21744 maxparams,
21745 "balloon.current",
21746 cur_balloon) < 0)
21747 return -1;
21749 if (virTypedParamsAddULLong(&record->params,
21750 &record->nparams,
21751 maxparams,
21752 "balloon.maximum",
21753 virDomainDefGetMemoryTotal(dom->def)) < 0)
21754 return -1;
21756 if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
21757 return 0;
21759 nr_stats = qemuDomainMemoryStatsInternal(driver, dom, stats,
21760 VIR_DOMAIN_MEMORY_STAT_NR);
21761 if (nr_stats < 0)
21762 return 0;
21764 #define STORE_MEM_RECORD(TAG, NAME) \
21765 if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ ##TAG) \
21766 if (virTypedParamsAddULLong(&record->params, \
21767 &record->nparams, \
21768 maxparams, \
21769 "balloon." NAME, \
21770 stats[i].val) < 0) \
21771 return -1;
21773 for (i = 0; i < nr_stats; i++) {
21774 STORE_MEM_RECORD(SWAP_IN, "swap_in")
21775 STORE_MEM_RECORD(SWAP_OUT, "swap_out")
21776 STORE_MEM_RECORD(MAJOR_FAULT, "major_fault")
21777 STORE_MEM_RECORD(MINOR_FAULT, "minor_fault")
21778 STORE_MEM_RECORD(UNUSED, "unused")
21779 STORE_MEM_RECORD(AVAILABLE, "available")
21780 STORE_MEM_RECORD(RSS, "rss")
21781 STORE_MEM_RECORD(LAST_UPDATE, "last-update")
21782 STORE_MEM_RECORD(USABLE, "usable")
21783 STORE_MEM_RECORD(DISK_CACHES, "disk_caches")
21786 #undef STORE_MEM_RECORD
21788 return 0;
21792 static int
21793 qemuDomainGetStatsVcpu(virQEMUDriverPtr driver,
21794 virDomainObjPtr dom,
21795 virDomainStatsRecordPtr record,
21796 int *maxparams,
21797 unsigned int privflags)
21799 virDomainVcpuDefPtr vcpu;
21800 qemuDomainVcpuPrivatePtr vcpupriv;
21801 size_t i;
21802 int ret = -1;
21803 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
21804 virVcpuInfoPtr cpuinfo = NULL;
21805 unsigned long long *cpuwait = NULL;
21807 if (virTypedParamsAddUInt(&record->params,
21808 &record->nparams,
21809 maxparams,
21810 "vcpu.current",
21811 virDomainDefGetVcpus(dom->def)) < 0)
21812 return -1;
21814 if (virTypedParamsAddUInt(&record->params,
21815 &record->nparams,
21816 maxparams,
21817 "vcpu.maximum",
21818 virDomainDefGetVcpusMax(dom->def)) < 0)
21819 return -1;
21821 if (VIR_ALLOC_N(cpuinfo, virDomainDefGetVcpus(dom->def)) < 0 ||
21822 VIR_ALLOC_N(cpuwait, virDomainDefGetVcpus(dom->def)) < 0)
21823 goto cleanup;
21825 if (HAVE_JOB(privflags) && virDomainObjIsActive(dom) &&
21826 qemuDomainRefreshVcpuHalted(driver, dom, QEMU_ASYNC_JOB_NONE) < 0) {
21827 /* it's ok to be silent and go ahead, because halted vcpu info
21828 * wasn't here from the beginning */
21829 virResetLastError();
21832 if (qemuDomainHelperGetVcpus(dom, cpuinfo, cpuwait,
21833 virDomainDefGetVcpus(dom->def),
21834 NULL, 0) < 0) {
21835 virResetLastError();
21836 ret = 0; /* it's ok to be silent and go ahead */
21837 goto cleanup;
21840 for (i = 0; i < virDomainDefGetVcpus(dom->def); i++) {
21841 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21842 "vcpu.%u.state", cpuinfo[i].number);
21843 if (virTypedParamsAddInt(&record->params,
21844 &record->nparams,
21845 maxparams,
21846 param_name,
21847 cpuinfo[i].state) < 0)
21848 goto cleanup;
21850 /* stats below are available only if the VM is alive */
21851 if (!virDomainObjIsActive(dom))
21852 continue;
21854 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21855 "vcpu.%u.time", cpuinfo[i].number);
21856 if (virTypedParamsAddULLong(&record->params,
21857 &record->nparams,
21858 maxparams,
21859 param_name,
21860 cpuinfo[i].cpuTime) < 0)
21861 goto cleanup;
21862 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21863 "vcpu.%u.wait", cpuinfo[i].number);
21864 if (virTypedParamsAddULLong(&record->params,
21865 &record->nparams,
21866 maxparams,
21867 param_name,
21868 cpuwait[i]) < 0)
21869 goto cleanup;
21871 /* state below is extracted from the individual vcpu structs */
21872 if (!(vcpu = virDomainDefGetVcpu(dom->def, cpuinfo[i].number)))
21873 continue;
21875 vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
21877 if (vcpupriv->halted != VIR_TRISTATE_BOOL_ABSENT) {
21878 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
21879 "vcpu.%u.halted", cpuinfo[i].number);
21880 if (virTypedParamsAddBoolean(&record->params,
21881 &record->nparams,
21882 maxparams,
21883 param_name,
21884 vcpupriv->halted == VIR_TRISTATE_BOOL_YES) < 0)
21885 goto cleanup;
21889 ret = 0;
21891 cleanup:
21892 VIR_FREE(cpuinfo);
21893 VIR_FREE(cpuwait);
21894 return ret;
21897 #define QEMU_ADD_COUNT_PARAM(record, maxparams, type, count) \
21898 do { \
21899 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
21900 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \
21901 if (virTypedParamsAddUInt(&(record)->params, \
21902 &(record)->nparams, \
21903 maxparams, \
21904 param_name, \
21905 count) < 0) \
21906 goto cleanup; \
21907 } while (0)
21909 #define QEMU_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \
21910 do { \
21911 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
21912 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
21913 "%s.%zu.%s", type, num, subtype); \
21914 if (virTypedParamsAddString(&(record)->params, \
21915 &(record)->nparams, \
21916 maxparams, \
21917 param_name, \
21918 name) < 0) \
21919 goto cleanup; \
21920 } while (0)
21922 #define QEMU_ADD_NET_PARAM(record, maxparams, num, name, value) \
21923 do { \
21924 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
21925 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
21926 "net.%zu.%s", num, name); \
21927 if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
21928 &(record)->nparams, \
21929 maxparams, \
21930 param_name, \
21931 value) < 0) \
21932 return -1; \
21933 } while (0)
21935 static int
21936 qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
21937 virDomainObjPtr dom,
21938 virDomainStatsRecordPtr record,
21939 int *maxparams,
21940 unsigned int privflags ATTRIBUTE_UNUSED)
21942 size_t i;
21943 struct _virDomainInterfaceStats tmp;
21944 int ret = -1;
21946 if (!virDomainObjIsActive(dom))
21947 return 0;
21949 QEMU_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets);
21951 /* Check the path is one of the domain's network interfaces. */
21952 for (i = 0; i < dom->def->nnets; i++) {
21953 virDomainNetDefPtr net = dom->def->nets[i];
21954 virDomainNetType actualType;
21956 if (!net->ifname)
21957 continue;
21959 memset(&tmp, 0, sizeof(tmp));
21961 actualType = virDomainNetGetActualType(net);
21963 QEMU_ADD_NAME_PARAM(record, maxparams,
21964 "net", "name", i, net->ifname);
21966 if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
21967 if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) {
21968 virResetLastError();
21969 continue;
21971 } else {
21972 if (virNetDevTapInterfaceStats(net->ifname, &tmp,
21973 !virDomainNetTypeSharesHostView(net)) < 0) {
21974 virResetLastError();
21975 continue;
21979 QEMU_ADD_NET_PARAM(record, maxparams, i,
21980 "rx.bytes", tmp.rx_bytes);
21981 QEMU_ADD_NET_PARAM(record, maxparams, i,
21982 "rx.pkts", tmp.rx_packets);
21983 QEMU_ADD_NET_PARAM(record, maxparams, i,
21984 "rx.errs", tmp.rx_errs);
21985 QEMU_ADD_NET_PARAM(record, maxparams, i,
21986 "rx.drop", tmp.rx_drop);
21987 QEMU_ADD_NET_PARAM(record, maxparams, i,
21988 "tx.bytes", tmp.tx_bytes);
21989 QEMU_ADD_NET_PARAM(record, maxparams, i,
21990 "tx.pkts", tmp.tx_packets);
21991 QEMU_ADD_NET_PARAM(record, maxparams, i,
21992 "tx.errs", tmp.tx_errs);
21993 QEMU_ADD_NET_PARAM(record, maxparams, i,
21994 "tx.drop", tmp.tx_drop);
21997 ret = 0;
21998 cleanup:
21999 return ret;
22002 #undef QEMU_ADD_NET_PARAM
22004 #define QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, num, name, value) \
22005 do { \
22006 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22007 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22008 "block.%zu.%s", num, name); \
22009 if (virTypedParamsAddUInt(&(record)->params, \
22010 &(record)->nparams, \
22011 maxparams, \
22012 param_name, \
22013 value) < 0) \
22014 goto cleanup; \
22015 } while (0)
22017 /* expects a LL, but typed parameter must be ULL */
22018 #define QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, num, name, value) \
22019 do { \
22020 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22021 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22022 "block.%zu.%s", num, name); \
22023 if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
22024 &(record)->nparams, \
22025 maxparams, \
22026 param_name, \
22027 value) < 0) \
22028 goto cleanup; \
22029 } while (0)
22031 #define QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, num, name, value) \
22032 do { \
22033 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22034 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22035 "block.%zu.%s", num, name); \
22036 if (virTypedParamsAddULLong(&(record)->params, \
22037 &(record)->nparams, \
22038 maxparams, \
22039 param_name, \
22040 value) < 0) \
22041 goto cleanup; \
22042 } while (0)
22044 /* refresh information by opening images on the disk */
22045 static int
22046 qemuDomainGetStatsOneBlockFallback(virQEMUDriverPtr driver,
22047 virQEMUDriverConfigPtr cfg,
22048 virDomainObjPtr dom,
22049 virDomainStatsRecordPtr record,
22050 int *maxparams,
22051 virStorageSourcePtr src,
22052 size_t block_idx)
22054 int ret = -1;
22056 if (virStorageSourceIsEmpty(src))
22057 return 0;
22059 if (qemuStorageLimitsRefresh(driver, cfg, dom, src) < 0) {
22060 virResetLastError();
22061 return 0;
22064 if (src->allocation)
22065 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22066 "allocation", src->allocation);
22067 if (src->capacity)
22068 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22069 "capacity", src->capacity);
22070 if (src->physical)
22071 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22072 "physical", src->physical);
22073 ret = 0;
22074 cleanup:
22075 return ret;
22080 * qemuDomainGetStatsOneBlockRefreshNamed:
22081 * @src: disk source structure
22082 * @alias: disk alias
22083 * @stats: hash table containing stats for all disks
22084 * @nodedata: reply containing 'query-named-block-nodes' data
22086 * Refresh disk block stats data (qemuBlockStatsPtr) which are present only
22087 * in the reply of 'query-named-block-nodes' in cases when the data was gathered
22088 * by using query-block originally.
22090 static void
22091 qemuDomainGetStatsOneBlockRefreshNamed(virStorageSourcePtr src,
22092 const char *alias,
22093 virHashTablePtr stats,
22094 virHashTablePtr nodedata)
22096 qemuBlockStatsPtr entry;
22098 virJSONValuePtr data;
22099 unsigned long long tmp;
22101 if (!nodedata || !src->nodestorage)
22102 return;
22104 if (!(entry = virHashLookup(stats, alias)))
22105 return;
22107 if (!(data = virHashLookup(nodedata, src->nodestorage)))
22108 return;
22110 if (virJSONValueObjectGetNumberUlong(data, "write_threshold", &tmp) == 0)
22111 entry->write_threshold = tmp;
22115 static int
22116 qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
22117 virQEMUDriverConfigPtr cfg,
22118 virDomainObjPtr dom,
22119 virDomainStatsRecordPtr record,
22120 int *maxparams,
22121 const char *entryname,
22122 virStorageSourcePtr src,
22123 size_t block_idx,
22124 virHashTablePtr stats)
22126 qemuBlockStats *entry;
22127 int ret = -1;
22129 /* the VM is offline so we have to go and load the stast from the disk by
22130 * ourselves */
22131 if (!virDomainObjIsActive(dom)) {
22132 ret = qemuDomainGetStatsOneBlockFallback(driver, cfg, dom, record,
22133 maxparams, src, block_idx);
22134 goto cleanup;
22137 /* In case where qemu didn't provide the stats we stop here rather than
22138 * trying to refresh the stats from the disk. Inability to provide stats is
22139 * usually caused by blocked storage so this would make libvirtd hang */
22140 if (!stats || !entryname || !(entry = virHashLookup(stats, entryname))) {
22141 ret = 0;
22142 goto cleanup;
22145 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22146 "allocation", entry->wr_highest_offset);
22148 if (entry->capacity)
22149 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22150 "capacity", entry->capacity);
22151 if (entry->physical) {
22152 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22153 "physical", entry->physical);
22154 } else {
22155 if (qemuDomainStorageUpdatePhysical(driver, cfg, dom, src) == 0) {
22156 QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
22157 "physical", src->physical);
22158 } else {
22159 virResetLastError();
22163 ret = 0;
22164 cleanup:
22165 return ret;
22169 static int
22170 qemuDomainGetStatsBlockExportBackendStorage(const char *entryname,
22171 virHashTablePtr stats,
22172 size_t recordnr,
22173 virDomainStatsRecordPtr records,
22174 int *nrecords)
22176 qemuBlockStats *entry;
22177 int ret = -1;
22179 if (!stats || !entryname || !(entry = virHashLookup(stats, entryname))) {
22180 ret = 0;
22181 goto cleanup;
22184 if (entry->write_threshold)
22185 QEMU_ADD_BLOCK_PARAM_ULL(records, nrecords, recordnr, "threshold",
22186 entry->write_threshold);
22188 ret = 0;
22189 cleanup:
22190 return ret;
22194 static int
22195 qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
22196 virHashTablePtr stats,
22197 size_t recordnr,
22198 virDomainStatsRecordPtr records,
22199 int *nrecords)
22201 qemuBlockStats *entry;
22202 int ret = -1;
22204 /* In case where qemu didn't provide the stats we stop here rather than
22205 * trying to refresh the stats from the disk. Inability to provide stats is
22206 * usually caused by blocked storage so this would make libvirtd hang */
22207 if (!stats || !frontendname || !(entry = virHashLookup(stats, frontendname))) {
22208 ret = 0;
22209 goto cleanup;
22212 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.reqs", entry->rd_req);
22213 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.bytes", entry->rd_bytes);
22214 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "rd.times", entry->rd_total_times);
22215 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.reqs", entry->wr_req);
22216 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.bytes", entry->wr_bytes);
22217 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "wr.times", entry->wr_total_times);
22218 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "fl.reqs", entry->flush_req);
22219 QEMU_ADD_BLOCK_PARAM_LL(records, nrecords, recordnr, "fl.times", entry->flush_total_times);
22221 ret = 0;
22222 cleanup:
22223 return ret;
22227 static int
22228 qemuDomainGetStatsBlockExportHeader(virDomainDiskDefPtr disk,
22229 virStorageSourcePtr src,
22230 size_t recordnr,
22231 virDomainStatsRecordPtr records,
22232 int *nrecords)
22234 int ret = -1;
22236 QEMU_ADD_NAME_PARAM(records, nrecords, "block", "name", recordnr, disk->dst);
22238 if (virStorageSourceIsLocalStorage(src) && src->path)
22239 QEMU_ADD_NAME_PARAM(records, nrecords, "block", "path", recordnr, src->path);
22240 if (src->id)
22241 QEMU_ADD_BLOCK_PARAM_UI(records, nrecords, recordnr, "backingIndex",
22242 src->id);
22244 ret = 0;
22245 cleanup:
22246 return ret;
22250 static int
22251 qemuDomainGetStatsBlockExportDisk(virDomainDiskDefPtr disk,
22252 virHashTablePtr stats,
22253 virHashTablePtr nodestats,
22254 virDomainStatsRecordPtr records,
22255 int *nrecords,
22256 size_t *recordnr,
22257 bool visitBacking,
22258 virQEMUDriverPtr driver,
22259 virQEMUDriverConfigPtr cfg,
22260 virDomainObjPtr dom,
22261 bool blockdev)
22264 char *alias = NULL;
22265 virStorageSourcePtr n;
22266 const char *frontendalias;
22267 const char *backendalias;
22268 const char *backendstoragealias;
22269 int ret = -1;
22272 * This helps to keep logs clean from error messages on getting stats
22273 * for optional disk with nonexistent source file. We won't get any
22274 * stats for such a disk anyway in below code.
22276 if (!virDomainObjIsActive(dom) &&
22277 qemuDomainDiskIsMissingLocalOptional(disk)) {
22278 VIR_INFO("optional disk '%s' source file is missing, "
22279 "skip getting stats", disk->dst);
22281 return qemuDomainGetStatsBlockExportHeader(disk, disk->src, *recordnr,
22282 records, nrecords);
22285 for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
22286 if (blockdev) {
22287 frontendalias = QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName;
22288 backendalias = n->nodeformat;
22289 backendstoragealias = n->nodestorage;
22290 } else {
22291 /* alias may be NULL if the VM is not running */
22292 if (disk->info.alias &&
22293 !(alias = qemuDomainStorageAlias(disk->info.alias, n->id)))
22294 goto cleanup;
22296 qemuDomainGetStatsOneBlockRefreshNamed(n, alias, stats, nodestats);
22298 frontendalias = alias;
22299 backendalias = alias;
22300 backendstoragealias = alias;
22303 if (qemuDomainGetStatsBlockExportHeader(disk, n, *recordnr,
22304 records, nrecords) < 0)
22305 goto cleanup;
22307 /* The following stats make sense only for the frontend device */
22308 if (n == disk->src) {
22309 if (qemuDomainGetStatsBlockExportFrontend(frontendalias, stats, *recordnr,
22310 records, nrecords) < 0)
22311 goto cleanup;
22314 if (qemuDomainGetStatsOneBlock(driver, cfg, dom, records, nrecords,
22315 backendalias, n, *recordnr,
22316 stats) < 0)
22317 goto cleanup;
22319 if (qemuDomainGetStatsBlockExportBackendStorage(backendstoragealias,
22320 stats, *recordnr,
22321 records, nrecords) < 0)
22322 goto cleanup;
22324 VIR_FREE(alias);
22325 (*recordnr)++;
22327 if (!visitBacking)
22328 break;
22331 ret = 0;
22333 cleanup:
22334 VIR_FREE(alias);
22335 return ret;
22339 static int
22340 qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
22341 virDomainObjPtr dom,
22342 virDomainStatsRecordPtr record,
22343 int *maxparams,
22344 unsigned int privflags)
22346 size_t i;
22347 int ret = -1;
22348 int rc;
22349 virHashTablePtr stats = NULL;
22350 virHashTablePtr nodestats = NULL;
22351 virJSONValuePtr nodedata = NULL;
22352 qemuDomainObjPrivatePtr priv = dom->privateData;
22353 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
22354 bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
22355 bool fetchnodedata = virQEMUCapsGet(priv->qemuCaps,
22356 QEMU_CAPS_QUERY_NAMED_BLOCK_NODES) && !blockdev;
22357 int count_index = -1;
22358 size_t visited = 0;
22359 bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING);
22361 if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) {
22362 qemuDomainObjEnterMonitor(driver, dom);
22364 rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, visitBacking);
22366 if (rc >= 0) {
22367 if (blockdev)
22368 rc = qemuMonitorBlockStatsUpdateCapacityBlockdev(priv->mon, stats);
22369 else
22370 ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats,
22371 visitBacking));
22374 if (fetchnodedata)
22375 nodedata = qemuMonitorQueryNamedBlockNodes(priv->mon);
22377 if (qemuDomainObjExitMonitor(driver, dom) < 0)
22378 goto cleanup;
22380 /* failure to retrieve stats is fine at this point */
22381 if (rc < 0 || (fetchnodedata && !nodedata))
22382 virResetLastError();
22385 if (nodedata &&
22386 !(nodestats = qemuBlockGetNodeData(nodedata)))
22387 goto cleanup;
22389 /* When listing backing chains, it's easier to fix up the count
22390 * after the iteration than it is to iterate twice; but we still
22391 * want count listed first. */
22392 count_index = record->nparams;
22393 QEMU_ADD_COUNT_PARAM(record, maxparams, "block", 0);
22395 for (i = 0; i < dom->def->ndisks; i++) {
22396 if (qemuDomainGetStatsBlockExportDisk(dom->def->disks[i], stats, nodestats,
22397 record, maxparams, &visited,
22398 visitBacking, driver, cfg, dom,
22399 blockdev) < 0)
22400 goto cleanup;
22403 record->params[count_index].value.ui = visited;
22404 ret = 0;
22406 cleanup:
22407 virHashFree(stats);
22408 virHashFree(nodestats);
22409 virJSONValueFree(nodedata);
22410 virObjectUnref(cfg);
22411 return ret;
22414 #undef QEMU_ADD_BLOCK_PARAM_LL
22416 #undef QEMU_ADD_BLOCK_PARAM_ULL
22418 #undef QEMU_ADD_NAME_PARAM
22420 #define QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams, id, name, value) \
22421 do { \
22422 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22423 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22424 "iothread.%u.%s", id, name); \
22425 if (virTypedParamsAddUInt(&(record)->params, \
22426 &(record)->nparams, \
22427 maxparams, \
22428 param_name, \
22429 value) < 0) \
22430 goto cleanup; \
22431 } while (0)
22433 #define QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams, id, name, value) \
22434 do { \
22435 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
22436 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
22437 "iothread.%u.%s", id, name); \
22438 if (virTypedParamsAddULLong(&(record)->params, \
22439 &(record)->nparams, \
22440 maxparams, \
22441 param_name, \
22442 value) < 0) \
22443 goto cleanup; \
22444 } while (0)
22446 static int
22447 qemuDomainGetStatsIOThread(virQEMUDriverPtr driver,
22448 virDomainObjPtr dom,
22449 virDomainStatsRecordPtr record,
22450 int *maxparams,
22451 unsigned int privflags ATTRIBUTE_UNUSED)
22453 qemuDomainObjPrivatePtr priv = dom->privateData;
22454 size_t i;
22455 qemuMonitorIOThreadInfoPtr *iothreads = NULL;
22456 int niothreads;
22457 int ret = -1;
22459 if (!virDomainObjIsActive(dom))
22460 return 0;
22462 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD))
22463 return 0;
22465 if ((niothreads = qemuDomainGetIOThreadsMon(driver, dom, &iothreads)) < 0)
22466 return -1;
22468 if (niothreads == 0)
22469 return 0;
22471 QEMU_ADD_COUNT_PARAM(record, maxparams, "iothread", niothreads);
22473 for (i = 0; i < niothreads; i++) {
22474 if (iothreads[i]->poll_valid) {
22475 QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams,
22476 iothreads[i]->iothread_id,
22477 "poll-max-ns",
22478 iothreads[i]->poll_max_ns);
22479 QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
22480 iothreads[i]->iothread_id,
22481 "poll-grow",
22482 iothreads[i]->poll_grow);
22483 QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
22484 iothreads[i]->iothread_id,
22485 "poll-shrink",
22486 iothreads[i]->poll_shrink);
22490 ret = 0;
22492 cleanup:
22493 for (i = 0; i < niothreads; i++)
22494 VIR_FREE(iothreads[i]);
22495 VIR_FREE(iothreads);
22497 return ret;
22500 #undef QEMU_ADD_IOTHREAD_PARAM_UI
22502 #undef QEMU_ADD_IOTHREAD_PARAM_ULL
22504 #undef QEMU_ADD_COUNT_PARAM
22506 static int
22507 qemuDomainGetStatsPerfOneEvent(virPerfPtr perf,
22508 virPerfEventType type,
22509 virDomainStatsRecordPtr record,
22510 int *maxparams)
22512 char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
22513 uint64_t value = 0;
22515 if (virPerfReadEvent(perf, type, &value) < 0)
22516 return -1;
22518 snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "perf.%s",
22519 virPerfEventTypeToString(type));
22521 if (virTypedParamsAddULLong(&record->params,
22522 &record->nparams,
22523 maxparams,
22524 param_name,
22525 value) < 0)
22526 return -1;
22528 return 0;
22531 static int
22532 qemuDomainGetStatsPerf(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
22533 virDomainObjPtr dom,
22534 virDomainStatsRecordPtr record,
22535 int *maxparams,
22536 unsigned int privflags ATTRIBUTE_UNUSED)
22538 size_t i;
22539 qemuDomainObjPrivatePtr priv = dom->privateData;
22540 int ret = -1;
22542 for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
22543 if (!virPerfEventIsEnabled(priv->perf, i))
22544 continue;
22546 if (qemuDomainGetStatsPerfOneEvent(priv->perf, i,
22547 record, maxparams) < 0)
22548 goto cleanup;
22551 ret = 0;
22553 cleanup:
22554 return ret;
22557 typedef int
22558 (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver,
22559 virDomainObjPtr dom,
22560 virDomainStatsRecordPtr record,
22561 int *maxparams,
22562 unsigned int flags);
22564 struct qemuDomainGetStatsWorker {
22565 qemuDomainGetStatsFunc func;
22566 unsigned int stats;
22567 bool monitor;
22570 static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
22571 { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false },
22572 { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false },
22573 { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true },
22574 { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true },
22575 { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
22576 { qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
22577 { qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false },
22578 { qemuDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD, true },
22579 { NULL, 0, false }
22583 static int
22584 qemuDomainGetStatsCheckSupport(unsigned int *stats,
22585 bool enforce)
22587 unsigned int supportedstats = 0;
22588 size_t i;
22590 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++)
22591 supportedstats |= qemuDomainGetStatsWorkers[i].stats;
22593 if (*stats == 0) {
22594 *stats = supportedstats;
22595 return 0;
22598 if (enforce &&
22599 *stats & ~supportedstats) {
22600 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
22601 _("Stats types bits 0x%x are not supported by this daemon"),
22602 *stats & ~supportedstats);
22603 return -1;
22606 *stats &= supportedstats;
22607 return 0;
22611 static bool
22612 qemuDomainGetStatsNeedMonitor(unsigned int stats)
22614 size_t i;
22616 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++)
22617 if (stats & qemuDomainGetStatsWorkers[i].stats &&
22618 qemuDomainGetStatsWorkers[i].monitor)
22619 return true;
22621 return false;
22625 static int
22626 qemuDomainGetStats(virConnectPtr conn,
22627 virDomainObjPtr dom,
22628 unsigned int stats,
22629 virDomainStatsRecordPtr *record,
22630 unsigned int flags)
22632 int maxparams = 0;
22633 virDomainStatsRecordPtr tmp;
22634 size_t i;
22635 int ret = -1;
22637 if (VIR_ALLOC(tmp) < 0)
22638 goto cleanup;
22640 for (i = 0; qemuDomainGetStatsWorkers[i].func; i++) {
22641 if (stats & qemuDomainGetStatsWorkers[i].stats) {
22642 if (qemuDomainGetStatsWorkers[i].func(conn->privateData, dom, tmp,
22643 &maxparams, flags) < 0)
22644 goto cleanup;
22648 if (!(tmp->dom = virGetDomain(conn, dom->def->name,
22649 dom->def->uuid, dom->def->id)))
22650 goto cleanup;
22652 *record = tmp;
22653 tmp = NULL;
22654 ret = 0;
22656 cleanup:
22657 if (tmp) {
22658 virTypedParamsFree(tmp->params, tmp->nparams);
22659 VIR_FREE(tmp);
22662 return ret;
22666 static int
22667 qemuConnectGetAllDomainStats(virConnectPtr conn,
22668 virDomainPtr *doms,
22669 unsigned int ndoms,
22670 unsigned int stats,
22671 virDomainStatsRecordPtr **retStats,
22672 unsigned int flags)
22674 virQEMUDriverPtr driver = conn->privateData;
22675 virErrorPtr orig_err = NULL;
22676 virDomainObjPtr *vms = NULL;
22677 virDomainObjPtr vm;
22678 size_t nvms;
22679 virDomainStatsRecordPtr *tmpstats = NULL;
22680 bool enforce = !!(flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS);
22681 int nstats = 0;
22682 size_t i;
22683 int ret = -1;
22684 unsigned int privflags = 0;
22685 unsigned int domflags = 0;
22686 unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
22687 VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
22688 VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
22690 virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
22691 VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
22692 VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE |
22693 VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT |
22694 VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING |
22695 VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1);
22697 if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
22698 return -1;
22700 if (qemuDomainGetStatsCheckSupport(&stats, enforce) < 0)
22701 return -1;
22703 if (ndoms) {
22704 if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
22705 &nvms, virConnectGetAllDomainStatsCheckACL,
22706 lflags, true) < 0)
22707 return -1;
22708 } else {
22709 if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
22710 virConnectGetAllDomainStatsCheckACL,
22711 lflags) < 0)
22712 return -1;
22715 if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0)
22716 goto cleanup;
22718 if (qemuDomainGetStatsNeedMonitor(stats))
22719 privflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
22721 for (i = 0; i < nvms; i++) {
22722 virDomainStatsRecordPtr tmp = NULL;
22723 domflags = 0;
22724 vm = vms[i];
22726 virObjectLock(vm);
22728 if (HAVE_JOB(privflags)) {
22729 int rv;
22731 if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_NOWAIT)
22732 rv = qemuDomainObjBeginJobNowait(driver, vm, QEMU_JOB_QUERY);
22733 else
22734 rv = qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY);
22736 if (rv == 0)
22737 domflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
22739 /* else: without a job it's still possible to gather some data */
22741 if (flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING)
22742 domflags |= QEMU_DOMAIN_STATS_BACKING;
22743 if (qemuDomainGetStats(conn, vm, stats, &tmp, domflags) < 0) {
22744 if (HAVE_JOB(domflags) && vm)
22745 qemuDomainObjEndJob(driver, vm);
22747 virObjectUnlock(vm);
22748 goto cleanup;
22751 if (tmp)
22752 tmpstats[nstats++] = tmp;
22754 if (HAVE_JOB(domflags))
22755 qemuDomainObjEndJob(driver, vm);
22757 virObjectUnlock(vm);
22760 *retStats = tmpstats;
22761 tmpstats = NULL;
22763 ret = nstats;
22765 cleanup:
22766 virErrorPreserveLast(&orig_err);
22767 virDomainStatsRecordListFree(tmpstats);
22768 virObjectListFreeCount(vms, nvms);
22769 virErrorRestore(&orig_err);
22771 return ret;
22775 static int
22776 qemuNodeAllocPages(virConnectPtr conn,
22777 unsigned int npages,
22778 unsigned int *pageSizes,
22779 unsigned long long *pageCounts,
22780 int startCell,
22781 unsigned int cellCount,
22782 unsigned int flags)
22784 bool add = !(flags & VIR_NODE_ALLOC_PAGES_SET);
22786 virCheckFlags(VIR_NODE_ALLOC_PAGES_SET, -1);
22788 if (virNodeAllocPagesEnsureACL(conn) < 0)
22789 return -1;
22791 return virHostMemAllocPages(npages, pageSizes, pageCounts,
22792 startCell, cellCount, add);
22796 static int
22797 qemuDomainGetFSInfo(virDomainPtr dom,
22798 virDomainFSInfoPtr **info,
22799 unsigned int flags)
22801 virQEMUDriverPtr driver = dom->conn->privateData;
22802 virDomainObjPtr vm;
22803 qemuAgentPtr agent;
22804 virCapsPtr caps = NULL;
22805 virDomainDefPtr def = NULL;
22806 int ret = -1;
22808 virCheckFlags(0, ret);
22810 if (!(vm = qemuDomObjFromDomain(dom)))
22811 return ret;
22813 if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0)
22814 goto cleanup;
22816 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
22817 goto cleanup;
22819 if (virDomainObjCheckActive(vm) < 0)
22820 goto endjob;
22822 if (!qemuDomainAgentAvailable(vm, true))
22823 goto endjob;
22825 if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
22826 goto endjob;
22828 if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, false)))
22829 goto endjob;
22831 agent = qemuDomainObjEnterAgent(vm);
22832 ret = qemuAgentGetFSInfo(agent, info, def);
22833 qemuDomainObjExitAgent(vm, agent);
22835 endjob:
22836 qemuDomainObjEndAgentJob(vm);
22838 cleanup:
22839 virDomainObjEndAPI(&vm);
22840 virDomainDefFree(def);
22841 virObjectUnref(caps);
22842 return ret;
22845 static int
22846 qemuDomainInterfaceAddresses(virDomainPtr dom,
22847 virDomainInterfacePtr **ifaces,
22848 unsigned int source,
22849 unsigned int flags)
22851 virQEMUDriverPtr driver = dom->conn->privateData;
22852 virDomainObjPtr vm = NULL;
22853 qemuAgentPtr agent;
22854 int ret = -1;
22856 virCheckFlags(0, -1);
22858 if (!(vm = qemuDomObjFromDomain(dom)))
22859 goto cleanup;
22861 if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0)
22862 goto cleanup;
22864 if (virDomainObjCheckActive(vm) < 0)
22865 goto cleanup;
22867 switch (source) {
22868 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE:
22869 ret = qemuGetDHCPInterfaces(dom, vm, ifaces);
22870 break;
22872 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT:
22873 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
22874 goto cleanup;
22876 if (!qemuDomainAgentAvailable(vm, true))
22877 goto endjob;
22879 agent = qemuDomainObjEnterAgent(vm);
22880 ret = qemuAgentGetInterfaces(agent, ifaces);
22881 qemuDomainObjExitAgent(vm, agent);
22883 endjob:
22884 qemuDomainObjEndAgentJob(vm);
22886 break;
22888 case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP:
22889 ret = qemuARPGetInterfaces(vm, ifaces);
22890 break;
22892 default:
22893 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
22894 _("Unknown IP address data source %d"),
22895 source);
22896 break;
22899 cleanup:
22900 virDomainObjEndAPI(&vm);
22901 return ret;
22904 static int
22905 qemuGetDHCPInterfaces(virDomainPtr dom,
22906 virDomainObjPtr vm,
22907 virDomainInterfacePtr **ifaces)
22909 int rv = -1;
22910 int n_leases = 0;
22911 size_t i, j;
22912 size_t ifaces_count = 0;
22913 virNetworkPtr network = NULL;
22914 char macaddr[VIR_MAC_STRING_BUFLEN];
22915 virDomainInterfacePtr iface = NULL;
22916 virNetworkDHCPLeasePtr *leases = NULL;
22917 virDomainInterfacePtr *ifaces_ret = NULL;
22919 if (!dom->conn->networkDriver ||
22920 !dom->conn->networkDriver->networkGetDHCPLeases) {
22921 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
22922 _("Network driver does not support DHCP lease query"));
22923 return -1;
22926 for (i = 0; i < vm->def->nnets; i++) {
22927 if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK)
22928 continue;
22930 virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
22931 virObjectUnref(network);
22932 network = virNetworkLookupByName(dom->conn,
22933 vm->def->nets[i]->data.network.name);
22935 if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
22936 &leases, 0)) < 0)
22937 goto error;
22939 if (n_leases) {
22940 if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0)
22941 goto error;
22943 if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0)
22944 goto error;
22946 iface = ifaces_ret[ifaces_count - 1];
22947 /* Assuming each lease corresponds to a separate IP */
22948 iface->naddrs = n_leases;
22950 if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0)
22951 goto error;
22953 if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0)
22954 goto error;
22956 if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
22957 goto error;
22960 for (j = 0; j < n_leases; j++) {
22961 virNetworkDHCPLeasePtr lease = leases[j];
22962 virDomainIPAddressPtr ip_addr = &iface->addrs[j];
22964 if (VIR_STRDUP(ip_addr->addr, lease->ipaddr) < 0)
22965 goto error;
22967 ip_addr->type = lease->type;
22968 ip_addr->prefix = lease->prefix;
22971 for (j = 0; j < n_leases; j++)
22972 virNetworkDHCPLeaseFree(leases[j]);
22974 VIR_FREE(leases);
22977 VIR_STEAL_PTR(*ifaces, ifaces_ret);
22978 rv = ifaces_count;
22980 cleanup:
22981 virObjectUnref(network);
22982 if (leases) {
22983 for (i = 0; i < n_leases; i++)
22984 virNetworkDHCPLeaseFree(leases[i]);
22986 VIR_FREE(leases);
22988 return rv;
22990 error:
22991 if (ifaces_ret) {
22992 for (i = 0; i < ifaces_count; i++)
22993 virDomainInterfaceFree(ifaces_ret[i]);
22995 VIR_FREE(ifaces_ret);
22997 goto cleanup;
23001 static int
23002 qemuARPGetInterfaces(virDomainObjPtr vm,
23003 virDomainInterfacePtr **ifaces)
23005 size_t i, j;
23006 size_t ifaces_count = 0;
23007 int ret = -1;
23008 char macaddr[VIR_MAC_STRING_BUFLEN];
23009 virDomainInterfacePtr *ifaces_ret = NULL;
23010 virDomainInterfacePtr iface = NULL;
23011 virArpTablePtr table;
23013 table = virArpTableGet();
23014 if (!table)
23015 goto cleanup;
23017 for (i = 0; i < vm->def->nnets; i++) {
23018 virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
23019 for (j = 0; j < table->n; j++) {
23020 virArpTableEntry entry = table->t[j];
23022 if (STREQ(entry.mac, macaddr)) {
23023 if (VIR_ALLOC(iface) < 0)
23024 goto cleanup;
23026 if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0)
23027 goto cleanup;
23029 if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
23030 goto cleanup;
23032 if (VIR_ALLOC(iface->addrs) < 0)
23033 goto cleanup;
23034 iface->naddrs = 1;
23036 if (VIR_STRDUP(iface->addrs->addr, entry.ipaddr) < 0)
23037 goto cleanup;
23039 if (VIR_APPEND_ELEMENT(ifaces_ret, ifaces_count, iface) < 0)
23040 goto cleanup;
23045 VIR_STEAL_PTR(*ifaces, ifaces_ret);
23046 ret = ifaces_count;
23048 cleanup:
23049 virArpTableFree(table);
23050 virDomainInterfaceFree(iface);
23052 if (ifaces_ret) {
23053 for (i = 0; i < ifaces_count; i++)
23054 virDomainInterfaceFree(ifaces_ret[i]);
23056 VIR_FREE(ifaces_ret);
23058 return ret;
23062 static int
23063 qemuDomainSetUserPassword(virDomainPtr dom,
23064 const char *user,
23065 const char *password,
23066 unsigned int flags)
23068 virQEMUDriverPtr driver = dom->conn->privateData;
23069 virDomainObjPtr vm;
23070 qemuAgentPtr agent;
23071 int ret = -1;
23072 int rv;
23074 virCheckFlags(VIR_DOMAIN_PASSWORD_ENCRYPTED, -1);
23076 if (!(vm = qemuDomObjFromDomain(dom)))
23077 return ret;
23079 if (virDomainSetUserPasswordEnsureACL(dom->conn, vm->def) < 0)
23080 goto cleanup;
23082 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
23083 goto cleanup;
23085 if (virDomainObjCheckActive(vm) < 0)
23086 goto endjob;
23088 if (!qemuDomainAgentAvailable(vm, true))
23089 goto endjob;
23091 agent = qemuDomainObjEnterAgent(vm);
23092 rv = qemuAgentSetUserPassword(agent, user, password,
23093 flags & VIR_DOMAIN_PASSWORD_ENCRYPTED);
23094 qemuDomainObjExitAgent(vm, agent);
23096 if (rv < 0)
23097 goto endjob;
23099 ret = 0;
23101 endjob:
23102 qemuDomainObjEndAgentJob(vm);
23104 cleanup:
23105 virDomainObjEndAPI(&vm);
23106 return ret;
23110 static int
23111 qemuDomainRenameCallback(virDomainObjPtr vm,
23112 const char *new_name,
23113 unsigned int flags,
23114 void *opaque)
23116 virQEMUDriverPtr driver = opaque;
23117 virQEMUDriverConfigPtr cfg = NULL;
23118 virObjectEventPtr event_new = NULL;
23119 virObjectEventPtr event_old = NULL;
23120 int ret = -1;
23121 char *new_dom_name = NULL;
23122 char *old_dom_name = NULL;
23123 char *new_dom_cfg_file = NULL;
23124 char *old_dom_cfg_file = NULL;
23125 char *new_dom_autostart_link = NULL;
23126 char *old_dom_autostart_link = NULL;
23128 virCheckFlags(0, ret);
23130 if (strchr(new_name, '/')) {
23131 virReportError(VIR_ERR_XML_ERROR,
23132 _("name %s cannot contain '/'"), new_name);
23133 return -1;
23136 cfg = virQEMUDriverGetConfig(driver);
23138 if (VIR_STRDUP(new_dom_name, new_name) < 0)
23139 goto cleanup;
23141 if (!(new_dom_cfg_file = virDomainConfigFile(cfg->configDir,
23142 new_dom_name)) ||
23143 !(old_dom_cfg_file = virDomainConfigFile(cfg->configDir,
23144 vm->def->name)))
23145 goto cleanup;
23147 if (vm->autostart) {
23148 if (!(new_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
23149 new_dom_name)) ||
23150 !(old_dom_autostart_link = virDomainConfigFile(cfg->autostartDir,
23151 vm->def->name)))
23152 goto cleanup;
23154 if (symlink(new_dom_cfg_file, new_dom_autostart_link) < 0) {
23155 virReportSystemError(errno,
23156 _("Failed to create symlink '%s to '%s'"),
23157 new_dom_autostart_link, new_dom_cfg_file);
23158 goto cleanup;
23162 event_old = virDomainEventLifecycleNewFromObj(vm,
23163 VIR_DOMAIN_EVENT_UNDEFINED,
23164 VIR_DOMAIN_EVENT_UNDEFINED_RENAMED);
23166 /* Switch name in domain definition. */
23167 old_dom_name = vm->def->name;
23168 vm->def->name = new_dom_name;
23169 new_dom_name = NULL;
23171 if (virDomainSaveConfig(cfg->configDir, driver->caps, vm->def) < 0)
23172 goto rollback;
23174 if (virFileExists(old_dom_cfg_file) &&
23175 unlink(old_dom_cfg_file) < 0) {
23176 virReportSystemError(errno,
23177 _("cannot remove old domain config file %s"),
23178 old_dom_cfg_file);
23179 goto rollback;
23182 if (vm->autostart) {
23183 if (virFileIsLink(old_dom_autostart_link) &&
23184 unlink(old_dom_autostart_link) < 0) {
23185 virReportSystemError(errno,
23186 _("Failed to delete symlink '%s'"),
23187 old_dom_autostart_link);
23188 goto rollback;
23192 event_new = virDomainEventLifecycleNewFromObj(vm,
23193 VIR_DOMAIN_EVENT_DEFINED,
23194 VIR_DOMAIN_EVENT_DEFINED_RENAMED);
23195 ret = 0;
23197 cleanup:
23198 VIR_FREE(old_dom_autostart_link);
23199 VIR_FREE(new_dom_autostart_link);
23200 VIR_FREE(old_dom_cfg_file);
23201 VIR_FREE(new_dom_cfg_file);
23202 VIR_FREE(old_dom_name);
23203 VIR_FREE(new_dom_name);
23204 virObjectEventStateQueue(driver->domainEventState, event_old);
23205 virObjectEventStateQueue(driver->domainEventState, event_new);
23206 virObjectUnref(cfg);
23207 return ret;
23209 rollback:
23210 if (old_dom_name) {
23211 new_dom_name = vm->def->name;
23212 vm->def->name = old_dom_name;
23213 old_dom_name = NULL;
23216 if (virFileExists(new_dom_cfg_file))
23217 unlink(new_dom_cfg_file);
23219 if (vm->autostart &&
23220 virFileExists(new_dom_autostart_link))
23221 unlink(new_dom_autostart_link);
23223 goto cleanup;
23226 static int qemuDomainRename(virDomainPtr dom,
23227 const char *new_name,
23228 unsigned int flags)
23230 virQEMUDriverPtr driver = dom->conn->privateData;
23231 virDomainObjPtr vm = NULL;
23232 int ret = -1;
23234 virCheckFlags(0, ret);
23236 if (!(vm = qemuDomObjFromDomain(dom)))
23237 goto cleanup;
23239 if (virDomainRenameEnsureACL(dom->conn, vm->def) < 0)
23240 goto cleanup;
23242 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23243 goto cleanup;
23245 if (virDomainObjIsActive(vm)) {
23246 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23247 _("cannot rename active domain"));
23248 goto endjob;
23251 if (!vm->persistent) {
23252 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23253 _("cannot rename a transient domain"));
23254 goto endjob;
23257 if (vm->hasManagedSave) {
23258 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
23259 _("domain with a managed saved state can't be renamed"));
23260 goto endjob;
23263 if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
23264 virReportError(VIR_ERR_OPERATION_INVALID,
23265 "%s", _("domain has to be shutoff before renaming"));
23266 goto endjob;
23269 if (virDomainSnapshotObjListNum(vm->snapshots, NULL, 0) > 0) {
23270 virReportError(VIR_ERR_OPERATION_INVALID,
23271 "%s", _("cannot rename domain with snapshots"));
23272 goto endjob;
23275 if (virDomainListCheckpoints(vm->checkpoints, NULL, dom, NULL, flags) > 0) {
23276 virReportError(VIR_ERR_OPERATION_INVALID,
23277 "%s", _("cannot rename domain with checkpoints"));
23278 goto endjob;
23281 if (virDomainObjListRename(driver->domains, vm, new_name, flags,
23282 qemuDomainRenameCallback, driver) < 0)
23283 goto endjob;
23285 /* Success, domain has been renamed. */
23286 ret = 0;
23288 endjob:
23289 qemuDomainObjEndJob(driver, vm);
23291 cleanup:
23292 virDomainObjEndAPI(&vm);
23293 return ret;
23297 static int
23298 qemuDomainGetGuestVcpusParams(virTypedParameterPtr *params,
23299 unsigned int *nparams,
23300 qemuAgentCPUInfoPtr info,
23301 int ninfo)
23303 virTypedParameterPtr par = NULL;
23304 int npar = 0;
23305 int maxpar = 0;
23306 virBitmapPtr vcpus = NULL;
23307 virBitmapPtr online = NULL;
23308 virBitmapPtr offlinable = NULL;
23309 char *tmp = NULL;
23310 size_t i;
23311 int ret = -1;
23313 if (!(vcpus = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)) ||
23314 !(online = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)) ||
23315 !(offlinable = virBitmapNew(QEMU_GUEST_VCPU_MAX_ID)))
23316 goto cleanup;
23318 for (i = 0; i < ninfo; i++) {
23319 if (virBitmapSetBit(vcpus, info[i].id) < 0) {
23320 virReportError(VIR_ERR_INTERNAL_ERROR,
23321 _("vcpu id '%u' reported by guest agent is out of "
23322 "range"), info[i].id);
23323 goto cleanup;
23326 if (info[i].online)
23327 ignore_value(virBitmapSetBit(online, info[i].id));
23329 if (info[i].offlinable)
23330 ignore_value(virBitmapSetBit(offlinable, info[i].id));
23333 #define ADD_BITMAP(name) \
23334 if (!(tmp = virBitmapFormat(name))) \
23335 goto cleanup; \
23336 if (virTypedParamsAddString(&par, &npar, &maxpar, #name, tmp) < 0) \
23337 goto cleanup; \
23338 VIR_FREE(tmp)
23340 ADD_BITMAP(vcpus);
23341 ADD_BITMAP(online);
23342 ADD_BITMAP(offlinable);
23344 #undef ADD_BITMAP
23346 *params = par;
23347 *nparams = npar;
23348 par = NULL;
23349 ret = 0;
23351 cleanup:
23352 VIR_FREE(tmp);
23353 virBitmapFree(vcpus);
23354 virBitmapFree(online);
23355 virBitmapFree(offlinable);
23356 virTypedParamsFree(par, npar);
23357 return ret;
23361 static int
23362 qemuDomainGetGuestVcpus(virDomainPtr dom,
23363 virTypedParameterPtr *params,
23364 unsigned int *nparams,
23365 unsigned int flags)
23367 virQEMUDriverPtr driver = dom->conn->privateData;
23368 virDomainObjPtr vm = NULL;
23369 qemuAgentPtr agent;
23370 qemuAgentCPUInfoPtr info = NULL;
23371 int ninfo = 0;
23372 int ret = -1;
23374 virCheckFlags(0, ret);
23376 if (!(vm = qemuDomObjFromDomain(dom)))
23377 goto cleanup;
23379 if (virDomainGetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
23380 goto cleanup;
23382 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
23383 goto cleanup;
23385 if (!qemuDomainAgentAvailable(vm, true))
23386 goto endjob;
23388 agent = qemuDomainObjEnterAgent(vm);
23389 ninfo = qemuAgentGetVCPUs(agent, &info);
23390 qemuDomainObjExitAgent(vm, agent);
23392 if (ninfo < 0)
23393 goto endjob;
23395 if (qemuDomainGetGuestVcpusParams(params, nparams, info, ninfo) < 0)
23396 goto endjob;
23398 ret = 0;
23400 endjob:
23401 qemuDomainObjEndAgentJob(vm);
23403 cleanup:
23404 VIR_FREE(info);
23405 virDomainObjEndAPI(&vm);
23406 return ret;
23410 static int
23411 qemuDomainSetGuestVcpus(virDomainPtr dom,
23412 const char *cpumap,
23413 int state,
23414 unsigned int flags)
23416 virQEMUDriverPtr driver = dom->conn->privateData;
23417 virDomainObjPtr vm = NULL;
23418 virBitmapPtr map = NULL;
23419 qemuAgentCPUInfoPtr info = NULL;
23420 qemuAgentPtr agent;
23421 int ninfo = 0;
23422 size_t i;
23423 int ret = -1;
23425 virCheckFlags(0, -1);
23427 if (state != 0 && state != 1) {
23428 virReportInvalidArg(state, "%s", _("unsupported state value"));
23429 return -1;
23432 if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
23433 goto cleanup;
23435 if (!(vm = qemuDomObjFromDomain(dom)))
23436 goto cleanup;
23438 if (virDomainSetGuestVcpusEnsureACL(dom->conn, vm->def) < 0)
23439 goto cleanup;
23441 if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
23442 goto cleanup;
23444 if (!qemuDomainAgentAvailable(vm, true))
23445 goto endjob;
23447 agent = qemuDomainObjEnterAgent(vm);
23448 ninfo = qemuAgentGetVCPUs(agent, &info);
23449 qemuDomainObjExitAgent(vm, agent);
23450 agent = NULL;
23452 if (ninfo < 0)
23453 goto endjob;
23455 for (i = 0; i < ninfo; i++) {
23456 if (!virBitmapIsBitSet(map, info[i].id))
23457 continue;
23459 if (!state && !info[i].offlinable) {
23460 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
23461 _("vCPU '%u' is not offlinable"), info[i].id);
23462 goto endjob;
23465 info[i].online = !!state;
23466 info[i].modified = true;
23468 ignore_value(virBitmapClearBit(map, info[i].id));
23471 if (!virBitmapIsAllClear(map)) {
23472 char *tmp = virBitmapFormat(map);
23473 virReportError(VIR_ERR_INVALID_ARG,
23474 _("guest is missing vCPUs '%s'"), NULLSTR(tmp));
23475 VIR_FREE(tmp);
23476 goto endjob;
23479 if (!qemuDomainAgentAvailable(vm, true))
23480 goto endjob;
23482 agent = qemuDomainObjEnterAgent(vm);
23483 ret = qemuAgentSetVCPUs(agent, info, ninfo);
23484 qemuDomainObjExitAgent(vm, agent);
23486 endjob:
23487 qemuDomainObjEndAgentJob(vm);
23489 cleanup:
23490 VIR_FREE(info);
23491 virBitmapFree(map);
23492 virDomainObjEndAPI(&vm);
23493 return ret;
23497 static int
23498 qemuDomainSetVcpu(virDomainPtr dom,
23499 const char *cpumap,
23500 int state,
23501 unsigned int flags)
23503 virQEMUDriverPtr driver = dom->conn->privateData;
23504 virDomainObjPtr vm = NULL;
23505 virDomainDefPtr def = NULL;
23506 virDomainDefPtr persistentDef = NULL;
23507 virBitmapPtr map = NULL;
23508 ssize_t lastvcpu;
23509 int ret = -1;
23511 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
23512 VIR_DOMAIN_AFFECT_CONFIG, -1);
23514 if (state != 0 && state != 1) {
23515 virReportInvalidArg(state, "%s", _("unsupported state value"));
23516 return -1;
23519 if (virBitmapParse(cpumap, &map, QEMU_GUEST_VCPU_MAX_ID) < 0)
23520 goto cleanup;
23522 if ((lastvcpu = virBitmapLastSetBit(map)) < 0) {
23523 virReportError(VIR_ERR_INVALID_ARG, "%s",
23524 _("no vcpus selected for modification"));
23525 goto cleanup;
23528 if (!(vm = qemuDomObjFromDomain(dom)))
23529 goto cleanup;
23531 if (virDomainSetVcpuEnsureACL(dom->conn, vm->def, flags) < 0)
23532 goto cleanup;
23534 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23535 goto cleanup;
23537 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
23538 goto endjob;
23540 if (persistentDef) {
23541 if (lastvcpu >= virDomainDefGetVcpusMax(persistentDef)) {
23542 virReportError(VIR_ERR_INVALID_ARG,
23543 _("vcpu %zd is not present in persistent config"),
23544 lastvcpu);
23545 goto endjob;
23549 if (def) {
23550 if (lastvcpu >= virDomainDefGetVcpusMax(def)) {
23551 virReportError(VIR_ERR_INVALID_ARG,
23552 _("vcpu %zd is not present in live config"),
23553 lastvcpu);
23554 goto endjob;
23558 ret = qemuDomainSetVcpuInternal(driver, vm, def, persistentDef, map, !!state);
23560 endjob:
23561 qemuDomainObjEndJob(driver, vm);
23563 cleanup:
23564 virBitmapFree(map);
23565 virDomainObjEndAPI(&vm);
23566 return ret;
23570 static int
23571 qemuDomainSetBlockThreshold(virDomainPtr dom,
23572 const char *dev,
23573 unsigned long long threshold,
23574 unsigned int flags)
23576 virQEMUDriverPtr driver = dom->conn->privateData;
23577 qemuDomainObjPrivatePtr priv;
23578 virDomainObjPtr vm = NULL;
23579 virStorageSourcePtr src;
23580 char *nodename = NULL;
23581 int rc;
23582 int ret = -1;
23584 virCheckFlags(0, -1);
23586 if (!(vm = qemuDomObjFromDomain(dom)))
23587 goto cleanup;
23589 priv = vm->privateData;
23591 if (virDomainSetBlockThresholdEnsureACL(dom->conn, vm->def) < 0)
23592 goto cleanup;
23594 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23595 goto cleanup;
23597 if (virDomainObjCheckActive(vm) < 0)
23598 goto endjob;
23600 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCK_WRITE_THRESHOLD)) {
23601 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
23602 _("this qemu does not support setting device threshold"));
23603 goto endjob;
23606 if (!(src = qemuDomainGetStorageSourceByDevstr(dev, vm->def)))
23607 goto endjob;
23609 if (!src->nodestorage &&
23610 qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
23611 goto endjob;
23613 if (!src->nodestorage) {
23614 virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
23615 _("threshold currently can't be set for block device '%s'"),
23616 dev);
23617 goto endjob;
23620 if (VIR_STRDUP(nodename, src->nodestorage) < 0)
23621 goto endjob;
23623 qemuDomainObjEnterMonitor(driver, vm);
23624 rc = qemuMonitorSetBlockThreshold(priv->mon, nodename, threshold);
23625 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
23626 goto endjob;
23628 ret = 0;
23630 endjob:
23631 qemuDomainObjEndJob(driver, vm);
23633 cleanup:
23634 VIR_FREE(nodename);
23635 virDomainObjEndAPI(&vm);
23636 return ret;
23640 static void
23641 qemuDomainModifyLifecycleAction(virDomainDefPtr def,
23642 virDomainLifecycle type,
23643 virDomainLifecycleAction action)
23645 switch (type) {
23646 case VIR_DOMAIN_LIFECYCLE_POWEROFF:
23647 def->onPoweroff = action;
23648 break;
23649 case VIR_DOMAIN_LIFECYCLE_REBOOT:
23650 def->onReboot = action;
23651 break;
23652 case VIR_DOMAIN_LIFECYCLE_CRASH:
23653 def->onCrash = action;
23654 break;
23655 case VIR_DOMAIN_LIFECYCLE_LAST:
23656 break;
23662 static int
23663 qemuDomainSetLifecycleAction(virDomainPtr dom,
23664 unsigned int type,
23665 unsigned int action,
23666 unsigned int flags)
23668 virQEMUDriverPtr driver = dom->conn->privateData;
23669 virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
23670 qemuDomainObjPrivatePtr priv;
23671 virDomainObjPtr vm = NULL;
23672 virDomainDefPtr def = NULL;
23673 virDomainDefPtr persistentDef = NULL;
23674 int ret = -1;
23676 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
23677 VIR_DOMAIN_AFFECT_CONFIG, -1);
23679 if (!virDomainDefLifecycleActionAllowed(type, action))
23680 goto cleanup;
23682 if (!(vm = qemuDomObjFromDomain(dom)))
23683 goto cleanup;
23685 priv = vm->privateData;
23687 if (virDomainSetLifecycleActionEnsureACL(dom->conn, vm->def) < 0)
23688 goto cleanup;
23690 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
23691 goto cleanup;
23693 if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
23694 goto endjob;
23696 if (def) {
23697 if (priv->allowReboot == VIR_TRISTATE_BOOL_NO) {
23698 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
23699 _("cannot update lifecycle action because QEMU "
23700 "was started with -no-reboot option"));
23701 goto endjob;
23704 qemuDomainModifyLifecycleAction(def, type, action);
23706 if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
23707 vm, driver->caps) < 0)
23708 goto endjob;
23711 if (persistentDef) {
23712 qemuDomainModifyLifecycleAction(persistentDef, type, action);
23714 if (virDomainSaveConfig(cfg->configDir, driver->caps,
23715 persistentDef) < 0)
23716 goto endjob;
23719 ret = 0;
23721 endjob:
23722 qemuDomainObjEndJob(driver, vm);
23724 cleanup:
23725 virDomainObjEndAPI(&vm);
23726 virObjectUnref(cfg);
23727 return ret;
23731 static int
23732 qemuGetSEVInfoToParams(virQEMUCapsPtr qemuCaps,
23733 virTypedParameterPtr *params,
23734 int *nparams,
23735 unsigned int flags)
23737 int maxpar = 0;
23738 int n = 0;
23739 virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
23740 virTypedParameterPtr sevParams = NULL;
23742 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
23744 if (virTypedParamsAddString(&sevParams, &n, &maxpar,
23745 VIR_NODE_SEV_PDH, sev->pdh) < 0)
23746 return -1;
23748 if (virTypedParamsAddString(&sevParams, &n, &maxpar,
23749 VIR_NODE_SEV_CERT_CHAIN, sev->cert_chain) < 0)
23750 goto cleanup;
23752 if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
23753 VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
23754 goto cleanup;
23756 if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
23757 VIR_NODE_SEV_REDUCED_PHYS_BITS,
23758 sev->reduced_phys_bits) < 0)
23759 goto cleanup;
23761 VIR_STEAL_PTR(*params, sevParams);
23762 *nparams = n;
23763 return 0;
23765 cleanup:
23766 virTypedParamsFree(sevParams, n);
23767 return -1;
23771 static int
23772 qemuNodeGetSEVInfo(virConnectPtr conn,
23773 virTypedParameterPtr *params,
23774 int *nparams,
23775 unsigned int flags)
23777 virQEMUDriverPtr driver = conn->privateData;
23778 virQEMUCapsPtr qemucaps = NULL;
23779 int ret = -1;
23781 if (virNodeGetSevInfoEnsureACL(conn) < 0)
23782 return ret;
23784 qemucaps = virQEMUCapsCacheLookupByArch(driver->qemuCapsCache,
23785 virArchFromHost());
23786 if (!qemucaps)
23787 goto cleanup;
23789 if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
23790 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
23791 _("QEMU does not support SEV guest"));
23792 goto cleanup;
23795 if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
23796 goto cleanup;
23798 ret = 0;
23800 cleanup:
23801 virObjectUnref(qemucaps);
23803 return ret;
23807 static int
23808 qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
23809 virDomainObjPtr vm,
23810 virTypedParameterPtr *params,
23811 int *nparams,
23812 unsigned int flags)
23814 int ret = -1;
23815 char *tmp = NULL;
23816 int maxpar = 0;
23818 virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
23820 if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
23821 return -1;
23823 qemuDomainObjEnterMonitor(driver, vm);
23824 tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
23826 if (qemuDomainObjExitMonitor(driver, vm) < 0)
23827 goto endjob;
23829 if (!tmp)
23830 goto endjob;
23832 if (virTypedParamsAddString(params, nparams, &maxpar,
23833 VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
23834 tmp) < 0)
23835 goto endjob;
23837 ret = 0;
23839 endjob:
23840 VIR_FREE(tmp);
23841 qemuDomainObjEndJob(driver, vm);
23842 return ret;
23846 static int
23847 qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
23848 virTypedParameterPtr *params,
23849 int *nparams,
23850 unsigned int flags)
23852 virQEMUDriverPtr driver = domain->conn->privateData;
23853 virDomainObjPtr vm;
23854 int ret = -1;
23856 if (!(vm = qemuDomObjFromDomain(domain)))
23857 goto cleanup;
23859 if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
23860 goto cleanup;
23862 if (vm->def->sev) {
23863 if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0)
23864 goto cleanup;
23867 ret = 0;
23869 cleanup:
23870 virDomainObjEndAPI(&vm);
23871 return ret;
23874 static virHypervisorDriver qemuHypervisorDriver = {
23875 .name = QEMU_DRIVER_NAME,
23876 .connectURIProbe = qemuConnectURIProbe,
23877 .connectOpen = qemuConnectOpen, /* 0.2.0 */
23878 .connectClose = qemuConnectClose, /* 0.2.0 */
23879 .connectSupportsFeature = qemuConnectSupportsFeature, /* 0.5.0 */
23880 .connectGetType = qemuConnectGetType, /* 0.2.0 */
23881 .connectGetVersion = qemuConnectGetVersion, /* 0.2.0 */
23882 .connectGetHostname = qemuConnectGetHostname, /* 0.3.3 */
23883 .connectGetSysinfo = qemuConnectGetSysinfo, /* 0.8.8 */
23884 .connectGetMaxVcpus = qemuConnectGetMaxVcpus, /* 0.2.1 */
23885 .nodeGetInfo = qemuNodeGetInfo, /* 0.2.0 */
23886 .connectGetCapabilities = qemuConnectGetCapabilities, /* 0.2.1 */
23887 .connectListDomains = qemuConnectListDomains, /* 0.2.0 */
23888 .connectNumOfDomains = qemuConnectNumOfDomains, /* 0.2.0 */
23889 .connectListAllDomains = qemuConnectListAllDomains, /* 0.9.13 */
23890 .domainCreateXML = qemuDomainCreateXML, /* 0.2.0 */
23891 .domainLookupByID = qemuDomainLookupByID, /* 0.2.0 */
23892 .domainLookupByUUID = qemuDomainLookupByUUID, /* 0.2.0 */
23893 .domainLookupByName = qemuDomainLookupByName, /* 0.2.0 */
23894 .domainSuspend = qemuDomainSuspend, /* 0.2.0 */
23895 .domainResume = qemuDomainResume, /* 0.2.0 */
23896 .domainShutdown = qemuDomainShutdown, /* 0.2.0 */
23897 .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */
23898 .domainReboot = qemuDomainReboot, /* 0.9.3 */
23899 .domainReset = qemuDomainReset, /* 0.9.7 */
23900 .domainDestroy = qemuDomainDestroy, /* 0.2.0 */
23901 .domainDestroyFlags = qemuDomainDestroyFlags, /* 0.9.4 */
23902 .domainGetOSType = qemuDomainGetOSType, /* 0.2.2 */
23903 .domainGetMaxMemory = qemuDomainGetMaxMemory, /* 0.4.2 */
23904 .domainSetMaxMemory = qemuDomainSetMaxMemory, /* 0.4.2 */
23905 .domainSetMemory = qemuDomainSetMemory, /* 0.4.2 */
23906 .domainSetMemoryFlags = qemuDomainSetMemoryFlags, /* 0.9.0 */
23907 .domainSetMemoryParameters = qemuDomainSetMemoryParameters, /* 0.8.5 */
23908 .domainGetMemoryParameters = qemuDomainGetMemoryParameters, /* 0.8.5 */
23909 .domainSetMemoryStatsPeriod = qemuDomainSetMemoryStatsPeriod, /* 1.1.1 */
23910 .domainSetBlkioParameters = qemuDomainSetBlkioParameters, /* 0.9.0 */
23911 .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */
23912 .domainGetInfo = qemuDomainGetInfo, /* 0.2.0 */
23913 .domainGetState = qemuDomainGetState, /* 0.9.2 */
23914 .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */
23915 .domainSave = qemuDomainSave, /* 0.2.0 */
23916 .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
23917 .domainRestore = qemuDomainRestore, /* 0.2.0 */
23918 .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
23919 .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
23920 .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
23921 .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */
23922 .domainCoreDumpWithFormat = qemuDomainCoreDumpWithFormat, /* 1.2.3 */
23923 .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
23924 .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
23925 .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */
23926 .domainGetVcpusFlags = qemuDomainGetVcpusFlags, /* 0.8.5 */
23927 .domainPinVcpu = qemuDomainPinVcpu, /* 0.4.4 */
23928 .domainPinVcpuFlags = qemuDomainPinVcpuFlags, /* 0.9.3 */
23929 .domainGetVcpuPinInfo = qemuDomainGetVcpuPinInfo, /* 0.9.3 */
23930 .domainPinEmulator = qemuDomainPinEmulator, /* 0.10.0 */
23931 .domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
23932 .domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
23933 .domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
23934 .domainGetIOThreadInfo = qemuDomainGetIOThreadInfo, /* 1.2.14 */
23935 .domainPinIOThread = qemuDomainPinIOThread, /* 1.2.14 */
23936 .domainAddIOThread = qemuDomainAddIOThread, /* 1.2.15 */
23937 .domainDelIOThread = qemuDomainDelIOThread, /* 1.2.15 */
23938 .domainSetIOThreadParams = qemuDomainSetIOThreadParams, /* 4.10.0 */
23939 .domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
23940 .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
23941 .nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
23942 .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */
23943 .connectDomainXMLFromNative = qemuConnectDomainXMLFromNative, /* 0.6.4 */
23944 .connectDomainXMLToNative = qemuConnectDomainXMLToNative, /* 0.6.4 */
23945 .connectListDefinedDomains = qemuConnectListDefinedDomains, /* 0.2.0 */
23946 .connectNumOfDefinedDomains = qemuConnectNumOfDefinedDomains, /* 0.2.0 */
23947 .domainCreate = qemuDomainCreate, /* 0.2.0 */
23948 .domainCreateWithFlags = qemuDomainCreateWithFlags, /* 0.8.2 */
23949 .domainDefineXML = qemuDomainDefineXML, /* 0.2.0 */
23950 .domainDefineXMLFlags = qemuDomainDefineXMLFlags, /* 1.2.12 */
23951 .domainUndefine = qemuDomainUndefine, /* 0.2.0 */
23952 .domainUndefineFlags = qemuDomainUndefineFlags, /* 0.9.4 */
23953 .domainAttachDevice = qemuDomainAttachDevice, /* 0.4.1 */
23954 .domainAttachDeviceFlags = qemuDomainAttachDeviceFlags, /* 0.7.7 */
23955 .domainDetachDevice = qemuDomainDetachDevice, /* 0.5.0 */
23956 .domainDetachDeviceFlags = qemuDomainDetachDeviceFlags, /* 0.7.7 */
23957 .domainUpdateDeviceFlags = qemuDomainUpdateDeviceFlags, /* 0.8.0 */
23958 .domainDetachDeviceAlias = qemuDomainDetachDeviceAlias, /* 4.4.0 */
23959 .domainGetAutostart = qemuDomainGetAutostart, /* 0.2.1 */
23960 .domainSetAutostart = qemuDomainSetAutostart, /* 0.2.1 */
23961 .domainGetSchedulerType = qemuDomainGetSchedulerType, /* 0.7.0 */
23962 .domainGetSchedulerParameters = qemuDomainGetSchedulerParameters, /* 0.7.0 */
23963 .domainGetSchedulerParametersFlags = qemuDomainGetSchedulerParametersFlags, /* 0.9.2 */
23964 .domainSetSchedulerParameters = qemuDomainSetSchedulerParameters, /* 0.7.0 */
23965 .domainSetSchedulerParametersFlags = qemuDomainSetSchedulerParametersFlags, /* 0.9.2 */
23966 .domainMigratePerform = qemuDomainMigratePerform, /* 0.5.0 */
23967 .domainBlockResize = qemuDomainBlockResize, /* 0.9.8 */
23968 .domainBlockStats = qemuDomainBlockStats, /* 0.4.1 */
23969 .domainBlockStatsFlags = qemuDomainBlockStatsFlags, /* 0.9.5 */
23970 .domainInterfaceStats = qemuDomainInterfaceStats, /* 0.4.1 */
23971 .domainMemoryStats = qemuDomainMemoryStats, /* 0.7.5 */
23972 .domainBlockPeek = qemuDomainBlockPeek, /* 0.4.4 */
23973 .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */
23974 .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
23975 .nodeGetCPUStats = qemuNodeGetCPUStats, /* 0.9.3 */
23976 .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */
23977 .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */
23978 .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */
23979 .connectDomainEventRegister = qemuConnectDomainEventRegister, /* 0.5.0 */
23980 .connectDomainEventDeregister = qemuConnectDomainEventDeregister, /* 0.5.0 */
23981 .domainMigratePrepare2 = qemuDomainMigratePrepare2, /* 0.5.0 */
23982 .domainMigrateFinish2 = qemuDomainMigrateFinish2, /* 0.5.0 */
23983 .nodeDeviceDettach = qemuNodeDeviceDettach, /* 0.6.1 */
23984 .nodeDeviceDetachFlags = qemuNodeDeviceDetachFlags, /* 1.0.5 */
23985 .nodeDeviceReAttach = qemuNodeDeviceReAttach, /* 0.6.1 */
23986 .nodeDeviceReset = qemuNodeDeviceReset, /* 0.6.1 */
23987 .domainMigratePrepareTunnel = qemuDomainMigratePrepareTunnel, /* 0.7.2 */
23988 .connectIsEncrypted = qemuConnectIsEncrypted, /* 0.7.3 */
23989 .connectIsSecure = qemuConnectIsSecure, /* 0.7.3 */
23990 .domainIsActive = qemuDomainIsActive, /* 0.7.3 */
23991 .domainIsPersistent = qemuDomainIsPersistent, /* 0.7.3 */
23992 .domainIsUpdated = qemuDomainIsUpdated, /* 0.8.6 */
23993 .connectCompareCPU = qemuConnectCompareCPU, /* 0.7.5 */
23994 .connectBaselineCPU = qemuConnectBaselineCPU, /* 0.7.7 */
23995 .domainGetJobInfo = qemuDomainGetJobInfo, /* 0.7.7 */
23996 .domainGetJobStats = qemuDomainGetJobStats, /* 1.0.3 */
23997 .domainAbortJob = qemuDomainAbortJob, /* 0.7.7 */
23998 .domainMigrateGetMaxDowntime = qemuDomainMigrateGetMaxDowntime, /* 3.7.0 */
23999 .domainMigrateSetMaxDowntime = qemuDomainMigrateSetMaxDowntime, /* 0.8.0 */
24000 .domainMigrateGetCompressionCache = qemuDomainMigrateGetCompressionCache, /* 1.0.3 */
24001 .domainMigrateSetCompressionCache = qemuDomainMigrateSetCompressionCache, /* 1.0.3 */
24002 .domainMigrateSetMaxSpeed = qemuDomainMigrateSetMaxSpeed, /* 0.9.0 */
24003 .domainMigrateGetMaxSpeed = qemuDomainMigrateGetMaxSpeed, /* 0.9.5 */
24004 .connectDomainEventRegisterAny = qemuConnectDomainEventRegisterAny, /* 0.8.0 */
24005 .connectDomainEventDeregisterAny = qemuConnectDomainEventDeregisterAny, /* 0.8.0 */
24006 .domainManagedSave = qemuDomainManagedSave, /* 0.8.0 */
24007 .domainHasManagedSaveImage = qemuDomainHasManagedSaveImage, /* 0.8.0 */
24008 .domainManagedSaveRemove = qemuDomainManagedSaveRemove, /* 0.8.0 */
24009 .domainManagedSaveGetXMLDesc = qemuDomainManagedSaveGetXMLDesc, /* 3.7.0 */
24010 .domainManagedSaveDefineXML = qemuDomainManagedSaveDefineXML, /* 3.7.0 */
24011 .domainSnapshotCreateXML = qemuDomainSnapshotCreateXML, /* 0.8.0 */
24012 .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
24013 .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
24014 .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
24015 .domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
24016 .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
24017 .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
24018 .domainSnapshotListAllChildren = qemuDomainSnapshotListAllChildren, /* 0.9.13 */
24019 .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
24020 .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
24021 .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */
24022 .domainSnapshotCurrent = qemuDomainSnapshotCurrent, /* 0.8.0 */
24023 .domainSnapshotIsCurrent = qemuDomainSnapshotIsCurrent, /* 0.9.13 */
24024 .domainSnapshotHasMetadata = qemuDomainSnapshotHasMetadata, /* 0.9.13 */
24025 .domainRevertToSnapshot = qemuDomainRevertToSnapshot, /* 0.8.0 */
24026 .domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
24027 .domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
24028 .domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
24029 .domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
24030 .connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
24031 .connectDomainQemuMonitorEventDeregister = qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
24032 .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
24033 .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
24034 .domainOpenGraphicsFD = qemuDomainOpenGraphicsFD, /* 1.2.8 */
24035 .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
24036 .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
24037 .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
24038 .domainMigratePrepareTunnel3 = qemuDomainMigratePrepareTunnel3, /* 0.9.2 */
24039 .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
24040 .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
24041 .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
24042 .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
24043 .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.3 */
24044 .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.3 */
24045 .domainBlockJobAbort = qemuDomainBlockJobAbort, /* 0.9.4 */
24046 .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
24047 .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
24048 .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
24049 .domainBlockRebase = qemuDomainBlockRebase, /* 0.9.10 */
24050 .domainBlockCopy = qemuDomainBlockCopy, /* 1.2.9 */
24051 .domainBlockCommit = qemuDomainBlockCommit, /* 1.0.0 */
24052 .connectIsAlive = qemuConnectIsAlive, /* 0.9.8 */
24053 .nodeSuspendForDuration = qemuNodeSuspendForDuration, /* 0.9.8 */
24054 .domainSetBlockIoTune = qemuDomainSetBlockIoTune, /* 0.9.8 */
24055 .domainGetBlockIoTune = qemuDomainGetBlockIoTune, /* 0.9.8 */
24056 .domainSetNumaParameters = qemuDomainSetNumaParameters, /* 0.9.9 */
24057 .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
24058 .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
24059 .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
24060 .domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
24061 .domainSetMetadata = qemuDomainSetMetadata, /* 0.9.10 */
24062 .domainGetMetadata = qemuDomainGetMetadata, /* 0.9.10 */
24063 .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
24064 .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
24065 .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
24066 .nodeGetMemoryParameters = qemuNodeGetMemoryParameters, /* 0.10.2 */
24067 .nodeSetMemoryParameters = qemuNodeSetMemoryParameters, /* 0.10.2 */
24068 .nodeGetCPUMap = qemuNodeGetCPUMap, /* 1.0.0 */
24069 .domainFSTrim = qemuDomainFSTrim, /* 1.0.1 */
24070 .domainOpenChannel = qemuDomainOpenChannel, /* 1.0.2 */
24071 .domainMigrateBegin3Params = qemuDomainMigrateBegin3Params, /* 1.1.0 */
24072 .domainMigratePrepare3Params = qemuDomainMigratePrepare3Params, /* 1.1.0 */
24073 .domainMigratePrepareTunnel3Params = qemuDomainMigratePrepareTunnel3Params, /* 1.1.0 */
24074 .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.1.0 */
24075 .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.1.0 */
24076 .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.1.0 */
24077 .connectGetCPUModelNames = qemuConnectGetCPUModelNames, /* 1.1.3 */
24078 .domainFSFreeze = qemuDomainFSFreeze, /* 1.2.5 */
24079 .domainFSThaw = qemuDomainFSThaw, /* 1.2.5 */
24080 .domainGetHostname = qemuDomainGetHostname, /* 4.8.0 */
24081 .domainGetTime = qemuDomainGetTime, /* 1.2.5 */
24082 .domainSetTime = qemuDomainSetTime, /* 1.2.5 */
24083 .nodeGetFreePages = qemuNodeGetFreePages, /* 1.2.6 */
24084 .connectGetDomainCapabilities = qemuConnectGetDomainCapabilities, /* 1.2.7 */
24085 .connectGetAllDomainStats = qemuConnectGetAllDomainStats, /* 1.2.8 */
24086 .nodeAllocPages = qemuNodeAllocPages, /* 1.2.9 */
24087 .domainGetFSInfo = qemuDomainGetFSInfo, /* 1.2.11 */
24088 .domainInterfaceAddresses = qemuDomainInterfaceAddresses, /* 1.2.14 */
24089 .domainSetUserPassword = qemuDomainSetUserPassword, /* 1.2.16 */
24090 .domainRename = qemuDomainRename, /* 1.2.19 */
24091 .domainMigrateStartPostCopy = qemuDomainMigrateStartPostCopy, /* 1.3.3 */
24092 .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */
24093 .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */
24094 .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
24095 .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
24096 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
24097 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
24098 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
24099 .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
24100 .domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
24101 .domainCheckpointCreateXML = qemuDomainCheckpointCreateXML, /* 5.2.0 */
24102 .domainCheckpointGetXMLDesc = qemuDomainCheckpointGetXMLDesc, /* 5.2.0 */
24104 .domainListAllCheckpoints = qemuDomainListAllCheckpoints, /* 5.2.0 */
24105 .domainCheckpointListAllChildren = qemuDomainCheckpointListAllChildren, /* 5.2.0 */
24106 .domainCheckpointLookupByName = qemuDomainCheckpointLookupByName, /* 5.2.0 */
24107 .domainHasCurrentCheckpoint = qemuDomainHasCurrentCheckpoint, /* 5.2.0 */
24108 .domainCheckpointGetParent = qemuDomainCheckpointGetParent, /* 5.2.0 */
24109 .domainCheckpointCurrent = qemuDomainCheckpointCurrent, /* 5.2.0 */
24110 .domainCheckpointIsCurrent = qemuDomainCheckpointIsCurrent, /* 5.2.0 */
24111 .domainCheckpointHasMetadata = qemuDomainCheckpointHasMetadata, /* 5.2.0 */
24112 .domainCheckpointDelete = qemuDomainCheckpointDelete, /* 5.2.0 */
24113 .domainBackupBegin = qemuDomainBackupBegin, /* 5.2.0 */
24114 .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 5.2.0 */
24115 .domainBackupEnd = qemuDomainBackupEnd, /* 5.2.0 */
24119 static virConnectDriver qemuConnectDriver = {
24120 .localOnly = true,
24121 .uriSchemes = (const char *[]){ "qemu", NULL },
24122 .hypervisorDriver = &qemuHypervisorDriver,
24125 static virStateDriver qemuStateDriver = {
24126 .name = QEMU_DRIVER_NAME,
24127 .stateInitialize = qemuStateInitialize,
24128 .stateCleanup = qemuStateCleanup,
24129 .stateReload = qemuStateReload,
24130 .stateStop = qemuStateStop,
24133 int qemuRegister(void)
24135 if (virRegisterConnectDriver(&qemuConnectDriver,
24136 true) < 0)
24137 return -1;
24138 if (virRegisterStateDriver(&qemuStateDriver) < 0)
24139 return -1;
24140 return 0;