[libvirt] [PATCH v3 6/8] qemu: snapshot: Break out redefine preparation to shared function

Cole Robinson crobinso at redhat.com
Wed Sep 25 19:15:37 UTC 2013


---
 src/conf/snapshot_conf.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/snapshot_conf.h |   7 +++
 src/libvirt_private.syms |   1 +
 src/qemu/qemu_driver.c   | 131 +----------------------------------------
 4 files changed, 160 insertions(+), 129 deletions(-)

diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index 207a8fe..1fcc4cb 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -1099,3 +1099,153 @@ virDomainSnapshotIsExternal(virDomainSnapshotObjPtr snap)
 {
     return virDomainSnapshotDefIsExternal(snap->def);
 }
+
+int
+virDomainSnapshotRedefinePrep(virDomainPtr domain,
+                              virDomainObjPtr vm,
+                              virDomainSnapshotDefPtr *defptr,
+                              virDomainSnapshotObjPtr *snap,
+                              bool *update_current,
+                              unsigned int flags)
+{
+    virDomainSnapshotDefPtr def = *defptr;
+    int ret = -1;
+    int align_location;
+    int align_match;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    virDomainSnapshotObjPtr other;
+
+    virUUIDFormat(domain->uuid, uuidstr);
+
+    /* Prevent circular chains */
+    if (def->parent) {
+        if (STREQ(def->name, def->parent)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("cannot set snapshot %s as its own parent"),
+                           def->name);
+            goto cleanup;
+        }
+        other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
+        if (!other) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("parent %s for snapshot %s not found"),
+                           def->parent, def->name);
+            goto cleanup;
+        }
+        while (other->def->parent) {
+            if (STREQ(other->def->parent, def->name)) {
+                virReportError(VIR_ERR_INVALID_ARG,
+                               _("parent %s would create cycle to %s"),
+                               other->def->name, def->name);
+                goto cleanup;
+            }
+            other = virDomainSnapshotFindByName(vm->snapshots,
+                                                other->def->parent);
+            if (!other) {
+                VIR_WARN("snapshots are inconsistent for %s",
+                         vm->def->name);
+                break;
+            }
+        }
+    }
+
+    /* Check that any replacement is compatible */
+    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) &&
+        def->state != VIR_DOMAIN_DISK_SNAPSHOT) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("disk-only flag for snapshot %s requires "
+                         "disk-snapshot state"),
+                       def->name);
+        goto cleanup;
+
+    }
+
+    if (def->dom &&
+        memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("definition for snapshot %s must use uuid %s"),
+                       def->name, uuidstr);
+        goto cleanup;
+    }
+
+    other = virDomainSnapshotFindByName(vm->snapshots, def->name);
+    if (other) {
+        if ((other->def->state == VIR_DOMAIN_RUNNING ||
+             other->def->state == VIR_DOMAIN_PAUSED) !=
+            (def->state == VIR_DOMAIN_RUNNING ||
+             def->state == VIR_DOMAIN_PAUSED)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("cannot change between online and offline "
+                             "snapshot state in snapshot %s"),
+                           def->name);
+            goto cleanup;
+        }
+
+        if ((other->def->state == VIR_DOMAIN_DISK_SNAPSHOT) !=
+            (def->state == VIR_DOMAIN_DISK_SNAPSHOT)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("cannot change between disk snapshot and "
+                             "system checkpoint in snapshot %s"),
+                           def->name);
+            goto cleanup;
+        }
+
+        if (other->def->dom) {
+            if (def->dom) {
+                if (!virDomainDefCheckABIStability(other->def->dom,
+                                                   def->dom))
+                    goto cleanup;
+            } else {
+                /* Transfer the domain def */
+                def->dom = other->def->dom;
+                other->def->dom = NULL;
+            }
+        }
+
+        if (def->dom) {
+            if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
+                virDomainSnapshotDefIsExternal(def)) {
+                align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
+                align_match = false;
+            }
+
+            if (virDomainSnapshotAlignDisks(def, align_location,
+                                            align_match) < 0) {
+                /* revert stealing of the snapshot domain definition */
+                if (def->dom && !other->def->dom) {
+                    other->def->dom = def->dom;
+                    def->dom = NULL;
+                }
+                goto cleanup;
+            }
+        }
+
+        if (other == vm->current_snapshot) {
+            *update_current = true;
+            vm->current_snapshot = NULL;
+        }
+
+        /* Drop and rebuild the parent relationship, but keep all
+         * child relations by reusing snap.  */
+        virDomainSnapshotDropParent(other);
+        virDomainSnapshotDefFree(other->def);
+        other->def = def;
+        *defptr = NULL;
+        *snap = other;
+    } else {
+        if (def->dom) {
+            if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
+                def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
+                align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
+                align_match = false;
+            }
+            if (virDomainSnapshotAlignDisks(def, align_location,
+                                            align_match) < 0)
+                goto cleanup;
+        }
+    }
+
+    ret = 0;
+cleanup:
+    return ret;
+}
diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h
index 0b8d18a..e8f8179 100644
--- a/src/conf/snapshot_conf.h
+++ b/src/conf/snapshot_conf.h
@@ -176,6 +176,13 @@ int virDomainListSnapshots(virDomainSnapshotObjListPtr snapshots,
 bool virDomainSnapshotDefIsExternal(virDomainSnapshotDefPtr def);
 bool virDomainSnapshotIsExternal(virDomainSnapshotObjPtr snap);
 
+int virDomainSnapshotRedefinePrep(virDomainPtr domain,
+                                  virDomainObjPtr vm,
+                                  virDomainSnapshotDefPtr *def,
+                                  virDomainSnapshotObjPtr *snap,
+                                  bool *update_current,
+                                  unsigned int flags);
+
 VIR_ENUM_DECL(virDomainSnapshotLocation)
 VIR_ENUM_DECL(virDomainSnapshotState)
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 48e4b04..e999c25 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -652,6 +652,7 @@ virDomainSnapshotLocationTypeToString;
 virDomainSnapshotObjListGetNames;
 virDomainSnapshotObjListNum;
 virDomainSnapshotObjListRemove;
+virDomainSnapshotRedefinePrep;
 virDomainSnapshotStateTypeFromString;
 virDomainSnapshotStateTypeToString;
 virDomainSnapshotUpdateRelations;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0dc975b..2ebcb35 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12270,7 +12270,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
     char *xml = NULL;
     virDomainSnapshotObjPtr snap = NULL;
     virDomainSnapshotPtr snapshot = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
     virDomainSnapshotDefPtr def = NULL;
     bool update_current = true;
     bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
@@ -12304,8 +12303,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
     if (redefine)
         parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
 
-    virUUIDFormat(domain->uuid, uuidstr);
-
     if (!(vm = qemuDomObjFromDomain(domain)))
         goto cleanup;
 
@@ -12374,133 +12371,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
     }
 
     if (redefine) {
-        /* Prevent circular chains */
-        if (def->parent) {
-            if (STREQ(def->name, def->parent)) {
-                virReportError(VIR_ERR_INVALID_ARG,
-                               _("cannot set snapshot %s as its own parent"),
-                               def->name);
-                goto cleanup;
-            }
-            other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
-            if (!other) {
-                virReportError(VIR_ERR_INVALID_ARG,
-                               _("parent %s for snapshot %s not found"),
-                               def->parent, def->name);
-                goto cleanup;
-            }
-            while (other->def->parent) {
-                if (STREQ(other->def->parent, def->name)) {
-                    virReportError(VIR_ERR_INVALID_ARG,
-                                   _("parent %s would create cycle to %s"),
-                                   other->def->name, def->name);
-                    goto cleanup;
-                }
-                other = virDomainSnapshotFindByName(vm->snapshots,
-                                                    other->def->parent);
-                if (!other) {
-                    VIR_WARN("snapshots are inconsistent for %s",
-                             vm->def->name);
-                    break;
-                }
-            }
-        }
-
-        /* Check that any replacement is compatible */
-        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) &&
-            def->state != VIR_DOMAIN_DISK_SNAPSHOT) {
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("disk-only flag for snapshot %s requires "
-                             "disk-snapshot state"),
-                           def->name);
-            goto cleanup;
-
-        }
-
-        if (def->dom &&
-            memcmp(def->dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) {
-            virReportError(VIR_ERR_INVALID_ARG,
-                           _("definition for snapshot %s must use uuid %s"),
-                           def->name, uuidstr);
+        if (!virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
+                                           &update_current, flags) < 0)
             goto cleanup;
-        }
-
-        other = virDomainSnapshotFindByName(vm->snapshots, def->name);
-        if (other) {
-            if ((other->def->state == VIR_DOMAIN_RUNNING ||
-                 other->def->state == VIR_DOMAIN_PAUSED) !=
-                (def->state == VIR_DOMAIN_RUNNING ||
-                 def->state == VIR_DOMAIN_PAUSED)) {
-                virReportError(VIR_ERR_INVALID_ARG,
-                               _("cannot change between online and offline "
-                                 "snapshot state in snapshot %s"),
-                               def->name);
-                goto cleanup;
-            }
-
-            if ((other->def->state == VIR_DOMAIN_DISK_SNAPSHOT) !=
-                (def->state == VIR_DOMAIN_DISK_SNAPSHOT)) {
-                virReportError(VIR_ERR_INVALID_ARG,
-                               _("cannot change between disk snapshot and "
-                                 "system checkpoint in snapshot %s"),
-                               def->name);
-                goto cleanup;
-            }
-
-            if (other->def->dom) {
-                if (def->dom) {
-                    if (!virDomainDefCheckABIStability(other->def->dom,
-                                                       def->dom))
-                        goto cleanup;
-                } else {
-                    /* Transfer the domain def */
-                    def->dom = other->def->dom;
-                    other->def->dom = NULL;
-                }
-            }
-
-            if (def->dom) {
-                if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
-                    virDomainSnapshotDefIsExternal(def)) {
-                    align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
-                    align_match = false;
-                }
-
-                if (virDomainSnapshotAlignDisks(def, align_location,
-                                                align_match) < 0) {
-                    /* revert stealing of the snapshot domain definition */
-                    if (def->dom && !other->def->dom) {
-                        other->def->dom = def->dom;
-                        def->dom = NULL;
-                    }
-                    goto cleanup;
-                }
-            }
-
-            if (other == vm->current_snapshot) {
-                update_current = true;
-                vm->current_snapshot = NULL;
-            }
-
-            /* Drop and rebuild the parent relationship, but keep all
-             * child relations by reusing snap.  */
-            virDomainSnapshotDropParent(other);
-            virDomainSnapshotDefFree(other->def);
-            other->def = def;
-            def = NULL;
-            snap = other;
-        } else {
-            if (def->dom) {
-                if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
-                    def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
-                    align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
-                    align_match = false;
-                }
-                if (virDomainSnapshotAlignDisks(def, align_location,
-                                                align_match) < 0)
-                    goto cleanup;
-            }
-        }
     } else {
         /* Easiest way to clone inactive portion of vm->def is via
          * conversion in and back out of xml.  */
-- 
1.8.3.1




More information about the libvir-list mailing list