[libvirt] [RFC PATCH REBASE 07/10] qemu: backup: add qemuDomainBackupCreateXML implementation

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Fri May 5 06:22:28 UTC 2017


Supported options

- backup to file or block device
- specify format of backup
---
 src/conf/backup_conf.c   |  32 ++++++++++++++
 src/conf/backup_conf.h   |   5 +++
 src/libvirt_private.syms |   1 +
 src/qemu/qemu_driver.c   | 112 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c
index a5bd995..49f1370 100644
--- a/src/conf/backup_conf.c
+++ b/src/conf/backup_conf.c
@@ -265,3 +265,35 @@ virDomainBackupDefFree(virDomainBackupDefPtr def)
 
     VIR_FREE(def);
 }
+
+
+int
+virDomainBackupDefResolveDisks(virDomainBackupDefPtr def,
+                               virDomainDefPtr vmdef)
+{
+    int ret = -1;
+    size_t i, j;
+
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainBackupDiskDefPtr disk = &def->disks[i];
+
+        for (j = 0; j < i; j++) {
+            if (STREQ(def->disks[j].name, disk->name)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("disk '%s' specified twice"), disk->name);
+                goto cleanup;
+            }
+        }
+
+        if (!(disk->vmdisk = virDomainDiskByName(vmdef, disk->name, false))) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("no disk named '%s'"), disk->name);
+            goto cleanup;
+        }
+    }
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
diff --git a/src/conf/backup_conf.h b/src/conf/backup_conf.h
index 6f689e3..ae7411e 100644
--- a/src/conf/backup_conf.h
+++ b/src/conf/backup_conf.h
@@ -33,6 +33,7 @@ typedef virDomainBackupDiskDef *virDomainBackupDiskDefPtr;
 struct _virDomainBackupDiskDef {
     char *name;     /* name matching the <target dev='...' of the domain */
     virStorageSourcePtr target;
+    virDomainDiskDefPtr vmdisk;
 };
 
 /* Stores the complete backup metadata */
@@ -62,4 +63,8 @@ virDomainBackupDefParseNode(xmlDocPtr xml,
 void
 virDomainBackupDefFree(virDomainBackupDefPtr def);
 
+int
+virDomainBackupDefResolveDisks(virDomainBackupDefPtr def,
+                               virDomainDefPtr vmdef);
+
 #endif /* __BACKUP_CONF_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e2ffc91..e788b3c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -46,6 +46,7 @@ virAccessPermStorageVolTypeToString;
 virDomainBackupDefFree;
 virDomainBackupDefParseNode;
 virDomainBackupDefParseString;
+virDomainBackupDefResolveDisks;
 
 
 # conf/capabilities.h
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a5c664e..91bad28 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20449,6 +20449,115 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
 }
 
 
+static virDomainBackupPtr
+qemuDomainBackupCreateXML(virDomainPtr domain,
+                          const char *xmlDesc,
+                          unsigned int flags)
+{
+    virQEMUDriverPtr driver = domain->conn->privateData;
+    qemuDomainObjPrivatePtr priv;
+    virDomainBackupDefPtr def = NULL;
+    virDomainBackupPtr backup = NULL;
+    virDomainBackupPtr ret = NULL;
+    virJSONValuePtr actions = NULL;
+    virDomainObjPtr vm = NULL;
+    char *path = NULL, *device = NULL;
+    bool job = false;
+    int rc;
+    size_t i;
+
+    virCheckFlags(0, NULL);
+
+    if (!(vm = qemuDomObjFromDomain(domain)))
+        goto cleanup;
+
+    if (virDomainBackupCreateXMLEnsureACL(domain->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (!(def = virDomainBackupDefParseString(xmlDesc, NULL, NULL, 0)))
+        goto cleanup;
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+    job = true;
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       "%s", _("backing up inactive domains is not supported"));
+        goto cleanup;
+    }
+
+    if (virDomainBackupDefResolveDisks(def, vm->def) < 0)
+        goto cleanup;
+
+    if (!(actions = virJSONValueNewArray()))
+        goto cleanup;
+
+    for (i = 0; i < def->ndisks; i++) {
+        virStorageSourcePtr target = def->disks[i].target;
+        virDomainDiskDefPtr disk = def->disks[i].vmdisk;
+        const char *format_str = NULL;
+
+        if (target->type != VIR_STORAGE_TYPE_FILE &&
+            target->type != VIR_STORAGE_TYPE_BLOCK) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("disk '%s' backup type '%s' is not supported"),
+                           def->disks[i].name,
+                           virStorageTypeToString(target->type));
+            goto cleanup;
+        }
+
+        if (qemuDomainDiskBlockJobIsActive(disk))
+            goto cleanup;
+
+        if (qemuGetDriveSourceString(target, NULL, &path) < 0)
+            goto cleanup;
+
+        if (!(device = qemuAliasFromDisk(disk)))
+            goto cleanup;
+
+        if (target->format)
+            format_str = virStorageFileFormatTypeToString(target->format);
+
+        if (qemuMonitorDriveBackup(actions, device, path, NULL, format_str, 0,
+                                   false) < 0)
+            goto cleanup;
+
+        VIR_FREE(path);
+        VIR_FREE(device);
+    }
+
+    priv = vm->privateData;
+    if (!(backup = virGetDomainBackup(domain, def->name)))
+        goto cleanup;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    rc = qemuMonitorTransaction(priv->mon, actions);
+    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+        goto cleanup;
+
+    ret = backup;
+    backup = NULL;
+
+    for (i = 0; i < def->ndisks; i++)
+        QEMU_DOMAIN_DISK_PRIVATE(def->disks->vmdisk)->blockjob = true;
+
+ cleanup:
+    if (job)
+        qemuDomainObjEndJob(driver, vm);
+
+    VIR_FREE(path);
+    VIR_FREE(device);
+
+    virDomainBackupDefFree(def);
+    virJSONValueFree(actions);
+    virDomainObjEndAPI(&vm);
+    virObjectUnref(backup);
+
+    return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectOpen = qemuConnectOpen, /* 0.2.0 */
@@ -20663,7 +20772,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */
     .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */
     .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
-    .domainSetBlockThreshold = qemuDomainSetBlockThreshold /* 3.2.0 */
+    .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
+    .domainBackupCreateXML = qemuDomainBackupCreateXML, /* 3.4.0 */
 };
 
 
-- 
1.8.3.1




More information about the libvir-list mailing list