With this, it is possible to update the path to a disk backing
image on either the save or restore action, without having to
binary edit the XML embedded in the state file.
* src/qemu/qemu_driver.c (qemuDomainSaveInternal)
(qemuDomainSaveImageOpen): Add parameter.
(qemuDomainSaveFlags, qemuDomainManagedSave)
(qemuDomainRestoreFlags, qemuDomainObjRestore): Update callers.
---
v2: new patch
Tested via:
virsh start dom
virsh dumpxml dom > dom.xml
ln /path/to/disk /path/to/disk2
ln /path/to/disk /path/to/disk3
edit dom.xml to change /path/to/disk to /path/to/disk2
virsh save dom dom.save --xml dom.xml
check that xml embedded in binary dom.save did change
cp dom.xml dom.xml2
edit dom.xml to change /path/to/disk2 to /path/to/disk3
edit dom.xml2 to break abi, such as removing entire cdrom <disk> element
virsh restore dom.save --xml dom.xml2 => properly failed
virsh restore dom.save --xml dom.xml
virsh dumpxml dom - validate that /path/to/disk3 is in use
Which means it is now possible to do:
virsh dumpxml dom > dom.xml
virsh save dom dom.save
use qemu-img to create new qcow2 files with backing file of the original images
alter dom.xml to reflect the new file names
virsh restore dom.save --xml dom.xml
to externally manage disk snapshots causing changed file names.
Not quite where I wanted to be with snapshot support, but certainly
a step in the right direction!
src/qemu/qemu_driver.c | 56 +++++++++++++++++++++++++++++++++--------------
1 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 73d2938..d1fa06f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2113,7 +2113,7 @@ qemuCompressProgramName(int compress)
static int
qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
virDomainObjPtr vm, const char *path,
- int compressed, bool bypass_cache)
+ int compressed, bool bypass_cache, const char *xmlin)
{
char *xml = NULL;
struct qemud_save_header header;
@@ -2160,7 +2160,22 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr
dom,
}
/* Get XML for the domain */
- xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+ if (xmlin) {
+ virDomainDefPtr def = NULL;
+
+ if (!(def = virDomainDefParseString(driver->caps, xmlin,
+ QEMU_EXPECTED_VIRT_TYPES,
+ VIR_DOMAIN_XML_INACTIVE))) {
+ goto endjob;
+ }
+ if (!virDomainDefCheckABIStability(vm->def, def)) {
+ virDomainDefFree(def);
+ goto endjob;
+ }
+ xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
+ } else {
+ xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+ }
if (!xml) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to get domain xml"));
@@ -2381,11 +2396,6 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char
*dxml,
virDomainObjPtr vm = NULL;
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE, -1);
- if (dxml) {
- qemuReportError(VIR_ERR_INVALID_ARG, "%s",
- _("xml modification unsupported"));
- return -1;
- }
qemuDriverLock(driver);
@@ -2423,7 +2433,8 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char
*dxml,
}
ret = qemuDomainSaveInternal(driver, dom, vm, path, compressed,
- (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0);
+ (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
+ dxml);
vm = NULL;
cleanup:
@@ -2487,7 +2498,8 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags)
compressed = QEMUD_SAVE_FORMAT_RAW;
ret = qemuDomainSaveInternal(driver, dom, vm, name, compressed,
- (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0);
+ (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
+ NULL);
vm = NULL;
cleanup:
@@ -3616,7 +3628,8 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
const char *path,
virDomainDefPtr *ret_def,
struct qemud_save_header *ret_header,
- bool bypass_cache, virFileDirectFdPtr *directFd)
+ bool bypass_cache, virFileDirectFdPtr *directFd,
+ const char *xmlin)
{
int fd;
struct qemud_save_header header;
@@ -3700,6 +3713,20 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
QEMU_EXPECTED_VIRT_TYPES,
VIR_DOMAIN_XML_INACTIVE)))
goto error;
+ if (xmlin) {
+ virDomainDefPtr def2 = NULL;
+
+ if (!(def2 = virDomainDefParseString(driver->caps, xmlin,
+ QEMU_EXPECTED_VIRT_TYPES,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto error;
+ if (!virDomainDefCheckABIStability(def, def2)) {
+ virDomainDefFree(def2);
+ goto error;
+ }
+ virDomainDefFree(def);
+ def = def2;
+ }
VIR_FREE(xml);
@@ -3834,17 +3861,12 @@ qemuDomainRestoreFlags(virConnectPtr conn,
virFileDirectFdPtr directFd = NULL;
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE, -1);
- if (dxml) {
- qemuReportError(VIR_ERR_INVALID_ARG, "%s",
- _("xml modification unsupported"));
- return -1;
- }
qemuDriverLock(driver);
fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
(flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
- &directFd);
+ &directFd, dxml);
if (fd < 0)
goto cleanup;
@@ -3904,7 +3926,7 @@ qemuDomainObjRestore(virConnectPtr conn,
virFileDirectFdPtr directFd = NULL;
fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
- bypass_cache, &directFd);
+ bypass_cache, &directFd, NULL);
if (fd < 0)
goto cleanup;
--
1.7.4.4