mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-30 13:37:17 +00:00
list: add virDomainListAllSnapshots API
There was an inherent race between virDomainSnapshotNum() and virDomainSnapshotListNames(), where an additional snapshot could be created in the meantime, or where a snapshot could be deleted before converting the name back to a virDomainSnapshotPtr. It was also an awkward name: the function operates on domains, not domain snapshots. virDomainSnapshotListChildrenNames() suffered from the same inherent race, although its naming was nicer. This patch makes things nicer by grabbing a snapshot list atomically, in the format most useful to the user. * include/libvirt/libvirt.h.in (virDomainListAllSnapshots) (virDomainSnapshotListAllChildren): New declarations. * src/libvirt.c (virDomainSnapshotListNames) (virDomainSnapshotListChildrenNames): Add cross-references. (virDomainListAllSnapshots, virDomainSnapshotListAllChildren): New functions. * src/libvirt_public.syms (LIBVIRT_0.9.13): Export them. * src/driver.h (virDrvDomainListAllSnapshots) (virDrvDomainSnapshotListAllChildren): New callbacks. * python/generator.py (skip_function): Prepare for later hand-written versions.
This commit is contained in:
parent
35ae18f3c6
commit
37bb0447bb
@ -3390,7 +3390,8 @@ char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
|
|||||||
*
|
*
|
||||||
* Flags valid for virDomainSnapshotNum(),
|
* Flags valid for virDomainSnapshotNum(),
|
||||||
* virDomainSnapshotListNames(), virDomainSnapshotNumChildren(), and
|
* virDomainSnapshotListNames(), virDomainSnapshotNumChildren(), and
|
||||||
* virDomainSnapshotListChildrenNames(). Note that the interpretation
|
* virDomainSnapshotListChildrenNames(), virDomainListAllSnapshots(),
|
||||||
|
* and virDomainSnapshotListAllChildren(). Note that the interpretation
|
||||||
* of flag (1<<0) depends on which function it is passed to; but serves
|
* of flag (1<<0) depends on which function it is passed to; but serves
|
||||||
* to toggle the per-call default of whether the listing is shallow or
|
* to toggle the per-call default of whether the listing is shallow or
|
||||||
* recursive. Remaining bits come in groups; if all bits from a group are
|
* recursive. Remaining bits come in groups; if all bits from a group are
|
||||||
@ -3423,6 +3424,11 @@ int virDomainSnapshotNum(virDomainPtr domain, unsigned int flags);
|
|||||||
int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
|
int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
/* Get all snapshot objects for this domain */
|
||||||
|
int virDomainListAllSnapshots(virDomainPtr domain,
|
||||||
|
virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/* Return the number of child snapshots for this snapshot */
|
/* Return the number of child snapshots for this snapshot */
|
||||||
int virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
|
int virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
@ -3432,6 +3438,11 @@ int virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
|
|||||||
char **names, int nameslen,
|
char **names, int nameslen,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
/* Get all snapshot object children for this snapshot */
|
||||||
|
int virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
|
||||||
|
virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/* Get a handle to a named snapshot */
|
/* Get a handle to a named snapshot */
|
||||||
virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
|
virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
@ -454,6 +454,8 @@ skip_function = (
|
|||||||
'virSaveLastError', # We have our own python error wrapper
|
'virSaveLastError', # We have our own python error wrapper
|
||||||
'virFreeError', # Only needed if we use virSaveLastError
|
'virFreeError', # Only needed if we use virSaveLastError
|
||||||
'virConnectListAllDomains', #overridden in virConnect.py
|
'virConnectListAllDomains', #overridden in virConnect.py
|
||||||
|
'virDomainListAllSnapshots', # overridden in virDomain.py
|
||||||
|
'virDomainSnapshotListAllChildren', # overridden in virDomainSnapshot.py
|
||||||
|
|
||||||
'virStreamRecvAll', # Pure python libvirt-override-virStream.py
|
'virStreamRecvAll', # Pure python libvirt-override-virStream.py
|
||||||
'virStreamSendAll', # Pure python libvirt-override-virStream.py
|
'virStreamSendAll', # Pure python libvirt-override-virStream.py
|
||||||
|
12
src/driver.h
12
src/driver.h
@ -627,6 +627,11 @@ typedef int
|
|||||||
int nameslen,
|
int nameslen,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*virDrvDomainListAllSnapshots)(virDomainPtr domain,
|
||||||
|
virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef int
|
typedef int
|
||||||
(*virDrvDomainSnapshotNumChildren)(virDomainSnapshotPtr snapshot,
|
(*virDrvDomainSnapshotNumChildren)(virDomainSnapshotPtr snapshot,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
@ -637,6 +642,11 @@ typedef int
|
|||||||
int nameslen,
|
int nameslen,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*virDrvDomainSnapshotListAllChildren)(virDomainSnapshotPtr snapshot,
|
||||||
|
virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef virDomainSnapshotPtr
|
typedef virDomainSnapshotPtr
|
||||||
(*virDrvDomainSnapshotLookupByName)(virDomainPtr domain,
|
(*virDrvDomainSnapshotLookupByName)(virDomainPtr domain,
|
||||||
const char *name,
|
const char *name,
|
||||||
@ -993,8 +1003,10 @@ struct _virDriver {
|
|||||||
virDrvDomainSnapshotGetXMLDesc domainSnapshotGetXMLDesc;
|
virDrvDomainSnapshotGetXMLDesc domainSnapshotGetXMLDesc;
|
||||||
virDrvDomainSnapshotNum domainSnapshotNum;
|
virDrvDomainSnapshotNum domainSnapshotNum;
|
||||||
virDrvDomainSnapshotListNames domainSnapshotListNames;
|
virDrvDomainSnapshotListNames domainSnapshotListNames;
|
||||||
|
virDrvDomainListAllSnapshots domainListAllSnapshots;
|
||||||
virDrvDomainSnapshotNumChildren domainSnapshotNumChildren;
|
virDrvDomainSnapshotNumChildren domainSnapshotNumChildren;
|
||||||
virDrvDomainSnapshotListChildrenNames domainSnapshotListChildrenNames;
|
virDrvDomainSnapshotListChildrenNames domainSnapshotListChildrenNames;
|
||||||
|
virDrvDomainSnapshotListAllChildren domainSnapshotListAllChildren;
|
||||||
virDrvDomainSnapshotLookupByName domainSnapshotLookupByName;
|
virDrvDomainSnapshotLookupByName domainSnapshotLookupByName;
|
||||||
virDrvDomainHasCurrentSnapshot domainHasCurrentSnapshot;
|
virDrvDomainHasCurrentSnapshot domainHasCurrentSnapshot;
|
||||||
virDrvDomainSnapshotGetParent domainSnapshotGetParent;
|
virDrvDomainSnapshotGetParent domainSnapshotGetParent;
|
||||||
|
177
src/libvirt.c
177
src/libvirt.c
@ -17123,9 +17123,8 @@ error:
|
|||||||
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
||||||
*
|
*
|
||||||
* Collect the list of domain snapshots for the given domain, and store
|
* Collect the list of domain snapshots for the given domain, and store
|
||||||
* their names in @names. Caller is responsible for freeing each member
|
* their names in @names. The value to use for @nameslen can be determined
|
||||||
* of the array. The value to use for @nameslen can be determined by
|
* by virDomainSnapshotNum() with the same @flags.
|
||||||
* virDomainSnapshotNum() with the same @flags.
|
|
||||||
*
|
*
|
||||||
* By default, this command covers all snapshots; it is also possible to
|
* By default, this command covers all snapshots; it is also possible to
|
||||||
* limit things to just snapshots with no parents, when @flags includes
|
* limit things to just snapshots with no parents, when @flags includes
|
||||||
@ -17149,14 +17148,17 @@ error:
|
|||||||
* whether they have metadata that would prevent the removal of the last
|
* whether they have metadata that would prevent the removal of the last
|
||||||
* reference to a domain.
|
* reference to a domain.
|
||||||
*
|
*
|
||||||
* Returns the number of domain snapshots found or -1 in case of error.
|
|
||||||
* Note that this command is inherently racy: another connection can
|
* Note that this command is inherently racy: another connection can
|
||||||
* define a new snapshot between a call to virDomainSnapshotNum() and
|
* define a new snapshot between a call to virDomainSnapshotNum() and
|
||||||
* this call. You are only guaranteed that all currently defined
|
* this call. You are only guaranteed that all currently defined
|
||||||
* snapshots were listed if the return is less than @nameslen. Likewise,
|
* snapshots were listed if the return is less than @nameslen. Likewise,
|
||||||
* you should be prepared for virDomainSnapshotLookupByName() to fail when
|
* you should be prepared for virDomainSnapshotLookupByName() to fail when
|
||||||
* converting a name from this call into a snapshot object, if another
|
* converting a name from this call into a snapshot object, if another
|
||||||
* connection deletes the snapshot in the meantime.
|
* connection deletes the snapshot in the meantime. For more control over
|
||||||
|
* the results, see virDomainListAllSnapshots().
|
||||||
|
*
|
||||||
|
* Returns the number of domain snapshots found or -1 in case of error.
|
||||||
|
* The caller is responsible for freeing each member of the array.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
|
virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
|
||||||
@ -17194,6 +17196,81 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virDomainListAllSnapshots:
|
||||||
|
* @domain: a domain object
|
||||||
|
* @snaps: pointer to variable to store the array containing snapshot objects,
|
||||||
|
* or NULL if the list is not required (just returns number of
|
||||||
|
* snapshots)
|
||||||
|
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
||||||
|
*
|
||||||
|
* Collect the list of domain snapshots for the given domain, and allocate
|
||||||
|
* an array to store those objects. This API solves the race inherent in
|
||||||
|
* virDomainSnapshotListNames().
|
||||||
|
*
|
||||||
|
* By default, this command covers all snapshots; it is also possible to
|
||||||
|
* limit things to just snapshots with no parents, when @flags includes
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_ROOTS. Additional filters are provided in
|
||||||
|
* groups, where each group contains bits that describe mutually exclusive
|
||||||
|
* attributes of a snapshot, and where all bits within a group describe
|
||||||
|
* all possible snapshots. Some hypervisors might reject explicit bits
|
||||||
|
* from a group where the hypervisor cannot make a distinction. For a
|
||||||
|
* group supported by a given hypervisor, the behavior when no bits of a
|
||||||
|
* group are set is identical to the behavior when all bits in that group
|
||||||
|
* are set. When setting bits from more than one group, it is possible to
|
||||||
|
* select an impossible combination, in that case a hypervisor may return
|
||||||
|
* either 0 or an error.
|
||||||
|
*
|
||||||
|
* The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
|
||||||
|
* have no further children (a leaf snapshot).
|
||||||
|
*
|
||||||
|
* The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
|
||||||
|
* whether they have metadata that would prevent the removal of the last
|
||||||
|
* reference to a domain.
|
||||||
|
*
|
||||||
|
* Returns the number of domain snapshots found or -1 and sets @snaps to
|
||||||
|
* NULL in case of error. On success, the array stored into @snaps is
|
||||||
|
* guaranteed to have an extra allocated element set to NULL but not included
|
||||||
|
* in the return count, to make iteration easier. The caller is responsible
|
||||||
|
* for calling virDomainSnapshotFree() on each array element, then calling
|
||||||
|
* free() on @snaps.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virConnectPtr conn;
|
||||||
|
|
||||||
|
VIR_DOMAIN_DEBUG(domain, "snaps=%p, flags=%x", snaps, flags);
|
||||||
|
|
||||||
|
virResetLastError();
|
||||||
|
|
||||||
|
if (snaps)
|
||||||
|
*snaps = NULL;
|
||||||
|
|
||||||
|
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = domain->conn;
|
||||||
|
|
||||||
|
if (conn->driver->domainListAllSnapshots) {
|
||||||
|
int ret = conn->driver->domainListAllSnapshots(domain, snaps, flags);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||||
|
error:
|
||||||
|
virDispatchError(conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainSnapshotNumChildren:
|
* virDomainSnapshotNumChildren:
|
||||||
* @snapshot: a domain snapshot object
|
* @snapshot: a domain snapshot object
|
||||||
@ -17263,9 +17340,9 @@ error:
|
|||||||
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
||||||
*
|
*
|
||||||
* Collect the list of domain snapshots that are children of the given
|
* Collect the list of domain snapshots that are children of the given
|
||||||
* snapshot, and store their names in @names. Caller is responsible for
|
* snapshot, and store their names in @names. The value to use for
|
||||||
* freeing each member of the array. The value to use for @nameslen can
|
* @nameslen can be determined by virDomainSnapshotNumChildren() with
|
||||||
* be determined by virDomainSnapshotNumChildren() with the same @flags.
|
* the same @flags.
|
||||||
*
|
*
|
||||||
* By default, this command covers only direct children; it is also possible
|
* By default, this command covers only direct children; it is also possible
|
||||||
* to expand things to cover all descendants, when @flags includes
|
* to expand things to cover all descendants, when @flags includes
|
||||||
@ -17296,7 +17373,11 @@ error:
|
|||||||
* snapshots were listed if the return is less than @nameslen. Likewise,
|
* snapshots were listed if the return is less than @nameslen. Likewise,
|
||||||
* you should be prepared for virDomainSnapshotLookupByName() to fail when
|
* you should be prepared for virDomainSnapshotLookupByName() to fail when
|
||||||
* converting a name from this call into a snapshot object, if another
|
* converting a name from this call into a snapshot object, if another
|
||||||
* connection deletes the snapshot in the meantime.
|
* connection deletes the snapshot in the meantime. For more control over
|
||||||
|
* the results, see virDomainSnapshotListAllChildren().
|
||||||
|
*
|
||||||
|
* Returns the number of domain snapshots found or -1 in case of error.
|
||||||
|
* The caller is responsible for freeing each member of the array.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
|
virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
|
||||||
@ -17338,6 +17419,84 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virDomainSnapshotListAllChildren:
|
||||||
|
* @snapshot: a domain snapshot object
|
||||||
|
* @snaps: pointer to variable to store the array containing snapshot objects,
|
||||||
|
* or NULL if the list is not required (just returns number of
|
||||||
|
* snapshots)
|
||||||
|
* @flags: bitwise-OR of supported virDomainSnapshotListFlags
|
||||||
|
*
|
||||||
|
* Collect the list of domain snapshots that are children of the given
|
||||||
|
* snapshot, and allocate an array to store those objects. This API solves
|
||||||
|
* the race inherent in virDomainSnapshotListChildrenNames().
|
||||||
|
*
|
||||||
|
* By default, this command covers only direct children; it is also possible
|
||||||
|
* to expand things to cover all descendants, when @flags includes
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS. Also, some filters are provided in
|
||||||
|
* groups, where each group contains bits that describe mutually exclusive
|
||||||
|
* attributes of a snapshot, and where all bits within a group describe
|
||||||
|
* all possible snapshots. Some hypervisors might reject explicit bits
|
||||||
|
* from a group where the hypervisor cannot make a distinction. For a
|
||||||
|
* group supported by a given hypervisor, the behavior when no bits of a
|
||||||
|
* group are set is identical to the behavior when all bits in that group
|
||||||
|
* are set. When setting bits from more than one group, it is possible to
|
||||||
|
* select an impossible combination, in that case a hypervisor may return
|
||||||
|
* either 0 or an error.
|
||||||
|
*
|
||||||
|
* The first group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_LEAVES and
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, to filter based on snapshots that
|
||||||
|
* have no further children (a leaf snapshot).
|
||||||
|
*
|
||||||
|
* The next group of @flags is VIR_DOMAIN_SNAPSHOT_LIST_METADATA and
|
||||||
|
* VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, for filtering snapshots based on
|
||||||
|
* whether they have metadata that would prevent the removal of the last
|
||||||
|
* reference to a domain.
|
||||||
|
*
|
||||||
|
* Returns the number of domain snapshots found or -1 and sets @snaps to
|
||||||
|
* NULL in case of error. On success, the array stored into @snaps is
|
||||||
|
* guaranteed to have an extra allocated element set to NULL but not included
|
||||||
|
* in the return count, to make iteration easier. The caller is responsible
|
||||||
|
* for calling virDomainSnapshotFree() on each array element, then calling
|
||||||
|
* free() on @snaps.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
|
||||||
|
virDomainSnapshotPtr **snaps,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virConnectPtr conn;
|
||||||
|
|
||||||
|
VIR_DEBUG("snapshot=%p, snaps=%p, flags=%x", snapshot, snaps, flags);
|
||||||
|
|
||||||
|
virResetLastError();
|
||||||
|
|
||||||
|
if (snaps)
|
||||||
|
*snaps = NULL;
|
||||||
|
|
||||||
|
if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
|
||||||
|
virLibDomainSnapshotError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
|
||||||
|
__FUNCTION__);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = snapshot->domain->conn;
|
||||||
|
|
||||||
|
if (conn->driver->domainSnapshotListAllChildren) {
|
||||||
|
int ret = conn->driver->domainSnapshotListAllChildren(snapshot, snaps,
|
||||||
|
flags);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
|
||||||
|
error:
|
||||||
|
virDispatchError(conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainSnapshotLookupByName:
|
* virDomainSnapshotLookupByName:
|
||||||
* @domain: a domain object
|
* @domain: a domain object
|
||||||
|
@ -537,8 +537,10 @@ LIBVIRT_0.9.11 {
|
|||||||
LIBVIRT_0.9.13 {
|
LIBVIRT_0.9.13 {
|
||||||
global:
|
global:
|
||||||
virConnectListAllDomains;
|
virConnectListAllDomains;
|
||||||
|
virDomainListAllSnapshots;
|
||||||
virDomainSnapshotHasMetadata;
|
virDomainSnapshotHasMetadata;
|
||||||
virDomainSnapshotIsCurrent;
|
virDomainSnapshotIsCurrent;
|
||||||
|
virDomainSnapshotListAllChildren;
|
||||||
virDomainSnapshotRef;
|
virDomainSnapshotRef;
|
||||||
} LIBVIRT_0.9.11;
|
} LIBVIRT_0.9.11;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user