snapshot: implement snapshot children listing in qemu

Not too hard to wire up.  The trickiest part is realizing that
listing children of a snapshot cannot use SNAPSHOT_LIST_ROOTS,
and that we overloaded that bit to also mean SNAPSHOT_LIST_DESCENDANTS;
we use that bit to decide which iteration to use, but don't want
the existing counting/listing functions to see that bit.

* src/conf/domain_conf.h (virDomainSnapshotObjListNumFrom)
(virDomainSnapshotObjListGetNamesFrom): New prototypes.
* src/conf/domain_conf.c (virDomainSnapshotObjListNumFrom)
(virDomainSnapshotObjListGetNamesFrom): New functions.
* src/libvirt_private.syms (domain_conf.h): Export them.
* src/qemu/qemu_driver.c (qemuDomainSnapshotNumChildren)
(qemuDomainSnapshotListChildrenNames): New functions.
This commit is contained in:
Eric Blake 2011-09-29 12:42:36 -06:00
parent db536236f4
commit 5907403716
4 changed files with 147 additions and 0 deletions

View File

@ -12180,6 +12180,37 @@ cleanup:
return -1; return -1;
} }
int virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
virDomainSnapshotObjListPtr snapshots,
char **const names, int maxnames,
unsigned int flags)
{
struct virDomainSnapshotNameData data = { 0, 0, maxnames, names, 0 };
int i;
data.flags = flags & ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
virDomainSnapshotForEachDescendant(snapshots, snapshot,
virDomainSnapshotObjListCopyNames,
&data);
else
virDomainSnapshotForEachChild(snapshots, snapshot,
virDomainSnapshotObjListCopyNames, &data);
if (data.oom) {
virReportOOMError();
goto cleanup;
}
return data.numnames;
cleanup:
for (i = 0; i < data.numnames; i++)
VIR_FREE(data.names[i]);
return -1;
}
struct virDomainSnapshotNumData { struct virDomainSnapshotNumData {
int count; int count;
unsigned int flags; unsigned int flags;
@ -12207,6 +12238,26 @@ int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
return data.count; return data.count;
} }
int
virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
virDomainSnapshotObjListPtr snapshots,
unsigned int flags)
{
struct virDomainSnapshotNumData data = { 0, 0 };
data.flags = flags & ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
virDomainSnapshotForEachDescendant(snapshots, snapshot,
virDomainSnapshotObjListCount,
&data);
else
virDomainSnapshotForEachChild(snapshots, snapshot,
virDomainSnapshotObjListCount, &data);
return data.count;
}
virDomainSnapshotObjPtr virDomainSnapshotObjPtr
virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots, virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots,
const char *name) const char *name)

View File

@ -1499,6 +1499,13 @@ int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
unsigned int flags); unsigned int flags);
int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots, int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
unsigned int flags); unsigned int flags);
int virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
virDomainSnapshotObjListPtr snapshots,
char **const names, int maxnames,
unsigned int flags);
int virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
virDomainSnapshotObjListPtr snapshots,
unsigned int flags);
virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots, virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots,
const char *name); const char *name);
void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,

View File

@ -415,7 +415,9 @@ virDomainSnapshotForEachChild;
virDomainSnapshotForEachDescendant; virDomainSnapshotForEachDescendant;
virDomainSnapshotHasChildren; virDomainSnapshotHasChildren;
virDomainSnapshotObjListGetNames; virDomainSnapshotObjListGetNames;
virDomainSnapshotObjListGetNamesFrom;
virDomainSnapshotObjListNum; virDomainSnapshotObjListNum;
virDomainSnapshotObjListNumFrom;
virDomainSnapshotObjListRemove; virDomainSnapshotObjListRemove;
virDomainSnapshotStateTypeFromString; virDomainSnapshotStateTypeFromString;
virDomainSnapshotStateTypeToString; virDomainSnapshotStateTypeToString;

View File

@ -9446,6 +9446,91 @@ cleanup:
return n; return n;
} }
static int
qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
char **names,
int nameslen,
unsigned int flags)
{
struct qemud_driver *driver = snapshot->domain->conn->privateData;
virDomainObjPtr vm = NULL;
virDomainSnapshotObjPtr snap = NULL;
int n = -1;
virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1);
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(snapshot->domain->uuid, uuidstr);
qemuReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
if (!snap) {
qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
_("no domain snapshot with matching name '%s'"),
snapshot->name);
goto cleanup;
}
n = virDomainSnapshotObjListGetNamesFrom(snap, &vm->snapshots,
names, nameslen, flags);
cleanup:
if (vm)
virDomainObjUnlock(vm);
qemuDriverUnlock(driver);
return n;
}
static int
qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
unsigned int flags)
{
struct qemud_driver *driver = snapshot->domain->conn->privateData;
virDomainObjPtr vm = NULL;
virDomainSnapshotObjPtr snap = NULL;
int n = -1;
virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1);
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, snapshot->domain->uuid);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(snapshot->domain->uuid, uuidstr);
qemuReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
snap = virDomainSnapshotFindByName(&vm->snapshots, snapshot->name);
if (!snap) {
qemuReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
_("no domain snapshot with matching name '%s'"),
snapshot->name);
goto cleanup;
}
/* All qemu snapshots have libvirt metadata, so
* VIR_DOMAIN_SNAPSHOT_LIST_METADATA makes no difference to our
* answer. */
n = virDomainSnapshotObjListNumFrom(snap, &vm->snapshots, flags);
cleanup:
if (vm)
virDomainObjUnlock(vm);
qemuDriverUnlock(driver);
return n;
}
static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain, static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain,
const char *name, const char *name,
unsigned int flags) unsigned int flags)
@ -10568,6 +10653,8 @@ static virDriver qemuDriver = {
.domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */ .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */
.domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */ .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */
.domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */ .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */
.domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */
.domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */
.domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */ .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */
.domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */ .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */
.domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */ .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */