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. --- src/conf/domain_conf.c | 51 +++++++++++++++++++++++++++ src/conf/domain_conf.h | 7 ++++ src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1871974..40b3589 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12132,6 +12132,37 @@ cleanup: 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 { int count; unsigned int flags; @@ -12159,6 +12190,26 @@ int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots, 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 virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots, const char *name) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4126d58..1d490d0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1488,6 +1488,13 @@ int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots, unsigned int flags); int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots, 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, const char *name); void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6505eae..3c7e44d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -419,7 +419,9 @@ virDomainSnapshotForEachChild; virDomainSnapshotForEachDescendant; virDomainSnapshotHasChildren; virDomainSnapshotObjListGetNames; +virDomainSnapshotObjListGetNamesFrom; virDomainSnapshotObjListNum; +virDomainSnapshotObjListNumFrom; virDomainSnapshotObjListRemove; virDomainSnapshotStateTypeFromString; virDomainSnapshotStateTypeToString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b459b73..eccb48d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9448,6 +9448,91 @@ cleanup: 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, const char *name, unsigned int flags) @@ -10538,6 +10623,8 @@ static virDriver qemuDriver = { .domainSnapshotGetXMLDesc = qemuDomainSnapshotGetXMLDesc, /* 0.8.0 */ .domainSnapshotNum = qemuDomainSnapshotNum, /* 0.8.0 */ .domainSnapshotListNames = qemuDomainSnapshotListNames, /* 0.8.0 */ + .domainSnapshotNumChildren = qemuDomainSnapshotNumChildren, /* 0.9.7 */ + .domainSnapshotListChildrenNames = qemuDomainSnapshotListChildrenNames, /* 0.9.7 */ .domainSnapshotLookupByName = qemuDomainSnapshotLookupByName, /* 0.8.0 */ .domainHasCurrentSnapshot = qemuDomainHasCurrentSnapshot, /* 0.8.0 */ .domainSnapshotGetParent = qemuDomainSnapshotGetParent, /* 0.9.7 */ -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list