mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
qemu: snapshot: Break out redefine preparation to shared function
This commit is contained in:
parent
390c06b675
commit
670e86bfd7
@ -1099,3 +1099,153 @@ virDomainSnapshotIsExternal(virDomainSnapshotObjPtr snap)
|
|||||||
{
|
{
|
||||||
return virDomainSnapshotDefIsExternal(snap->def);
|
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 = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
|
||||||
|
int align_match = true;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -176,6 +176,13 @@ int virDomainListSnapshots(virDomainSnapshotObjListPtr snapshots,
|
|||||||
bool virDomainSnapshotDefIsExternal(virDomainSnapshotDefPtr def);
|
bool virDomainSnapshotDefIsExternal(virDomainSnapshotDefPtr def);
|
||||||
bool virDomainSnapshotIsExternal(virDomainSnapshotObjPtr snap);
|
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(virDomainSnapshotLocation)
|
||||||
VIR_ENUM_DECL(virDomainSnapshotState)
|
VIR_ENUM_DECL(virDomainSnapshotState)
|
||||||
|
|
||||||
|
@ -652,6 +652,7 @@ virDomainSnapshotLocationTypeToString;
|
|||||||
virDomainSnapshotObjListGetNames;
|
virDomainSnapshotObjListGetNames;
|
||||||
virDomainSnapshotObjListNum;
|
virDomainSnapshotObjListNum;
|
||||||
virDomainSnapshotObjListRemove;
|
virDomainSnapshotObjListRemove;
|
||||||
|
virDomainSnapshotRedefinePrep;
|
||||||
virDomainSnapshotStateTypeFromString;
|
virDomainSnapshotStateTypeFromString;
|
||||||
virDomainSnapshotStateTypeToString;
|
virDomainSnapshotStateTypeToString;
|
||||||
virDomainSnapshotUpdateRelations;
|
virDomainSnapshotUpdateRelations;
|
||||||
|
@ -12272,7 +12272,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
|||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
virDomainSnapshotObjPtr snap = NULL;
|
virDomainSnapshotObjPtr snap = NULL;
|
||||||
virDomainSnapshotPtr snapshot = NULL;
|
virDomainSnapshotPtr snapshot = NULL;
|
||||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
||||||
virDomainSnapshotDefPtr def = NULL;
|
virDomainSnapshotDefPtr def = NULL;
|
||||||
bool update_current = true;
|
bool update_current = true;
|
||||||
bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
|
bool redefine = flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
|
||||||
@ -12306,8 +12305,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
|||||||
if (redefine)
|
if (redefine)
|
||||||
parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
|
parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
|
||||||
|
|
||||||
virUUIDFormat(domain->uuid, uuidstr);
|
|
||||||
|
|
||||||
if (!(vm = qemuDomObjFromDomain(domain)))
|
if (!(vm = qemuDomObjFromDomain(domain)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -12376,133 +12373,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (redefine) {
|
if (redefine) {
|
||||||
/* Prevent circular chains */
|
if (!virDomainSnapshotRedefinePrep(domain, vm, &def, &snap,
|
||||||
if (def->parent) {
|
&update_current, flags) < 0)
|
||||||
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;
|
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;
|
|
||||||
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 {
|
} else {
|
||||||
/* Easiest way to clone inactive portion of vm->def is via
|
/* Easiest way to clone inactive portion of vm->def is via
|
||||||
* conversion in and back out of xml. */
|
* conversion in and back out of xml. */
|
||||||
|
Loading…
Reference in New Issue
Block a user