mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
snapshot: Split out virDomainSnapshotRedefineValidate helper
Pull out the portion of virDomainSnapshotRefinePrep() that deals with definition sanity into a separate helper routine that can be reused with bulk redefine, leaving behind only the code specific to loop checking and in-place updates that are only needed in single-definition handling. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
44a9b872e8
commit
1e90fa89d1
@ -426,6 +426,87 @@ virDomainSnapshotDefParseString(const char *xmlStr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Perform sanity checking on a redefined snapshot definition. If
|
||||||
|
* @other is non-NULL, this may include swapping def->dom from other
|
||||||
|
* into def. */
|
||||||
|
static int
|
||||||
|
virDomainSnapshotRedefineValidate(virDomainSnapshotDefPtr def,
|
||||||
|
const unsigned char *domain_uuid,
|
||||||
|
virDomainSnapshotObjPtr other,
|
||||||
|
virDomainXMLOptionPtr xmlopt,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
|
||||||
|
bool align_match = true;
|
||||||
|
bool external = def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT ||
|
||||||
|
virDomainSnapshotDefIsExternal(def);
|
||||||
|
|
||||||
|
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) && !external) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("disk-only flag for snapshot %s requires "
|
||||||
|
"disk-snapshot state"),
|
||||||
|
def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (def->dom && memcmp(def->dom->uuid, domain_uuid, VIR_UUID_BUFLEN)) {
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
|
||||||
|
virUUIDFormat(domain_uuid, uuidstr);
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("definition for snapshot %s must use uuid %s"),
|
||||||
|
def->name, uuidstr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other) {
|
||||||
|
if ((other->def->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
|
||||||
|
other->def->state == VIR_DOMAIN_SNAPSHOT_PAUSED) !=
|
||||||
|
(def->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
|
||||||
|
def->state == VIR_DOMAIN_SNAPSHOT_PAUSED)) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("cannot change between online and offline "
|
||||||
|
"snapshot state in snapshot %s"),
|
||||||
|
def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((other->def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT) !=
|
||||||
|
(def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT)) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("cannot change between disk only and "
|
||||||
|
"full system in snapshot %s"),
|
||||||
|
def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other->def->dom) {
|
||||||
|
if (def->dom) {
|
||||||
|
if (!virDomainDefCheckABIStability(other->def->dom,
|
||||||
|
def->dom, xmlopt))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
/* Transfer the domain def */
|
||||||
|
def->dom = other->def->dom;
|
||||||
|
other->def->dom = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->dom) {
|
||||||
|
if (external) {
|
||||||
|
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
|
||||||
|
align_match = false;
|
||||||
|
}
|
||||||
|
if (virDomainSnapshotAlignDisks(def, align_location,
|
||||||
|
align_match) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainSnapshotDefAssignExternalNames:
|
* virDomainSnapshotDefAssignExternalNames:
|
||||||
* @def: snapshot def object
|
* @def: snapshot def object
|
||||||
@ -1322,12 +1403,8 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
|
|||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
virDomainSnapshotDefPtr def = *defptr;
|
virDomainSnapshotDefPtr def = *defptr;
|
||||||
int ret = -1;
|
|
||||||
int align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
|
|
||||||
bool align_match = true;
|
|
||||||
virDomainSnapshotObjPtr other;
|
virDomainSnapshotObjPtr other;
|
||||||
bool external = def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT ||
|
bool check_if_stolen;
|
||||||
virDomainSnapshotDefIsExternal(def);
|
|
||||||
|
|
||||||
/* Prevent circular chains */
|
/* Prevent circular chains */
|
||||||
if (def->parent) {
|
if (def->parent) {
|
||||||
@ -1335,21 +1412,21 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
|
|||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("cannot set snapshot %s as its own parent"),
|
_("cannot set snapshot %s as its own parent"),
|
||||||
def->name);
|
def->name);
|
||||||
goto cleanup;
|
return -1;
|
||||||
}
|
}
|
||||||
other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
|
other = virDomainSnapshotFindByName(vm->snapshots, def->parent);
|
||||||
if (!other) {
|
if (!other) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("parent %s for snapshot %s not found"),
|
_("parent %s for snapshot %s not found"),
|
||||||
def->parent, def->name);
|
def->parent, def->name);
|
||||||
goto cleanup;
|
return -1;
|
||||||
}
|
}
|
||||||
while (other->def->parent) {
|
while (other->def->parent) {
|
||||||
if (STREQ(other->def->parent, def->name)) {
|
if (STREQ(other->def->parent, def->name)) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("parent %s would create cycle to %s"),
|
_("parent %s would create cycle to %s"),
|
||||||
other->def->name, def->name);
|
other->def->name, def->name);
|
||||||
goto cleanup;
|
return -1;
|
||||||
}
|
}
|
||||||
other = virDomainSnapshotFindByName(vm->snapshots,
|
other = virDomainSnapshotFindByName(vm->snapshots,
|
||||||
other->def->parent);
|
other->def->parent);
|
||||||
@ -1361,77 +1438,18 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that any replacement is compatible */
|
|
||||||
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) && !external) {
|
|
||||||
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)) {
|
|
||||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
||||||
|
|
||||||
virUUIDFormat(domain->uuid, uuidstr);
|
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
|
||||||
_("definition for snapshot %s must use uuid %s"),
|
|
||||||
def->name, uuidstr);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
other = virDomainSnapshotFindByName(vm->snapshots, def->name);
|
other = virDomainSnapshotFindByName(vm->snapshots, def->name);
|
||||||
if (other) {
|
check_if_stolen = other && other->def->dom;
|
||||||
if ((other->def->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
|
if (virDomainSnapshotRedefineValidate(def, domain->uuid, other, xmlopt,
|
||||||
other->def->state == VIR_DOMAIN_SNAPSHOT_PAUSED) !=
|
flags) < 0) {
|
||||||
(def->state == VIR_DOMAIN_SNAPSHOT_RUNNING ||
|
/* revert any stealing of the snapshot domain definition */
|
||||||
def->state == VIR_DOMAIN_SNAPSHOT_PAUSED)) {
|
if (check_if_stolen && def->dom && !other->def->dom) {
|
||||||
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_SNAPSHOT_DISK_SNAPSHOT) !=
|
|
||||||
(def->state == VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT)) {
|
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
|
||||||
_("cannot change between disk only and "
|
|
||||||
"full system in snapshot %s"),
|
|
||||||
def->name);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other->def->dom) {
|
|
||||||
if (def->dom) {
|
|
||||||
if (!virDomainDefCheckABIStability(other->def->dom,
|
|
||||||
def->dom, xmlopt))
|
|
||||||
goto cleanup;
|
|
||||||
} else {
|
|
||||||
/* Transfer the domain def */
|
|
||||||
def->dom = other->def->dom;
|
|
||||||
other->def->dom = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def->dom) {
|
|
||||||
if (external) {
|
|
||||||
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;
|
other->def->dom = def->dom;
|
||||||
def->dom = NULL;
|
def->dom = NULL;
|
||||||
}
|
}
|
||||||
goto cleanup;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
if (other) {
|
||||||
|
|
||||||
if (other == vm->current_snapshot) {
|
if (other == vm->current_snapshot) {
|
||||||
*update_current = true;
|
*update_current = true;
|
||||||
vm->current_snapshot = NULL;
|
vm->current_snapshot = NULL;
|
||||||
@ -1444,19 +1462,7 @@ virDomainSnapshotRedefinePrep(virDomainPtr domain,
|
|||||||
other->def = def;
|
other->def = def;
|
||||||
*defptr = NULL;
|
*defptr = NULL;
|
||||||
*snap = other;
|
*snap = other;
|
||||||
} else {
|
|
||||||
if (def->dom) {
|
|
||||||
if (external) {
|
|
||||||
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
|
|
||||||
align_match = false;
|
|
||||||
}
|
|
||||||
if (virDomainSnapshotAlignDisks(def, align_location,
|
|
||||||
align_match) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
return 0;
|
||||||
cleanup:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user