mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Snapshot internal methods.
Signed-off-by: Chris Lalancette <clalance@redhat.com>
This commit is contained in:
parent
2f992d4be4
commit
9b55a52b4f
@ -28,6 +28,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "virterror_internal.h"
|
#include "virterror_internal.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "macvtap.h"
|
#include "macvtap.h"
|
||||||
#include "nwfilter_conf.h"
|
#include "nwfilter_conf.h"
|
||||||
|
#include "ignore-value.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||||
|
|
||||||
@ -744,6 +746,8 @@ static void virDomainObjFree(virDomainObjPtr dom)
|
|||||||
|
|
||||||
virMutexDestroy(&dom->lock);
|
virMutexDestroy(&dom->lock);
|
||||||
|
|
||||||
|
virDomainSnapshotObjListDeinit(&dom->snapshots);
|
||||||
|
|
||||||
VIR_FREE(dom);
|
VIR_FREE(dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,6 +800,8 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps)
|
|||||||
domain->state = VIR_DOMAIN_SHUTOFF;
|
domain->state = VIR_DOMAIN_SHUTOFF;
|
||||||
domain->refs = 1;
|
domain->refs = 1;
|
||||||
|
|
||||||
|
virDomainSnapshotObjListInit(&domain->snapshots);
|
||||||
|
|
||||||
VIR_DEBUG("obj=%p", domain);
|
VIR_DEBUG("obj=%p", domain);
|
||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
@ -6558,4 +6564,363 @@ cleanup:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Snapshot Def functions */
|
||||||
|
void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def)
|
||||||
|
{
|
||||||
|
if (!def)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VIR_FREE(def->name);
|
||||||
|
VIR_FREE(def->description);
|
||||||
|
VIR_FREE(def->parent);
|
||||||
|
VIR_FREE(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr,
|
||||||
|
int newSnapshot)
|
||||||
|
{
|
||||||
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
|
xmlNodePtr root;
|
||||||
|
virDomainSnapshotDefPtr def = NULL;
|
||||||
|
virDomainSnapshotDefPtr ret = NULL;
|
||||||
|
char *creation = NULL, *state = NULL;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
xml = virXMLParse(NULL, xmlStr, "domainsnapshot.xml");
|
||||||
|
if (!xml) {
|
||||||
|
virDomainReportError(VIR_ERR_XML_ERROR,
|
||||||
|
"%s",_("failed to parse snapshot xml document"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("missing root element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xmlStrEqual(root->name, BAD_CAST "domainsnapshot")) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("incorrect root element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt = xmlXPathNewContext(xml);
|
||||||
|
if (ctxt == NULL) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC(def) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt->node = root;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
def->name = virXPathString("string(./name)", ctxt);
|
||||||
|
if (def->name == NULL)
|
||||||
|
ignore_value(virAsprintf(&def->name, "%ld", tv.tv_sec));
|
||||||
|
|
||||||
|
if (def->name == NULL) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
def->description = virXPathString("string(./description)", ctxt);
|
||||||
|
|
||||||
|
if (!newSnapshot) {
|
||||||
|
if (virXPathLong("string(./creationTime)", ctxt,
|
||||||
|
&def->creationTime) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("missing creationTime from existing snapshot"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
def->parent = virXPathString("string(./parent/name)", ctxt);
|
||||||
|
|
||||||
|
state = virXPathString("string(./state)", ctxt);
|
||||||
|
if (state == NULL) {
|
||||||
|
/* there was no state in an existing snapshot; this
|
||||||
|
* should never happen
|
||||||
|
*/
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("missing state from existing snapshot"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
def->state = virDomainStateTypeFromString(state);
|
||||||
|
if (def->state < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid state '%s' in domain snapshot XML"),
|
||||||
|
state);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virXPathLong("string(./active)", ctxt, &def->active) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Could not find 'active' element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
def->creationTime = tv.tv_sec;
|
||||||
|
|
||||||
|
ret = def;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(creation);
|
||||||
|
VIR_FREE(state);
|
||||||
|
xmlXPathFreeContext(ctxt);
|
||||||
|
if (ret == NULL)
|
||||||
|
virDomainSnapshotDefFree(def);
|
||||||
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *virDomainSnapshotDefFormat(char *domain_uuid,
|
||||||
|
virDomainSnapshotDefPtr def,
|
||||||
|
int internal)
|
||||||
|
{
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
virBufferAddLit(&buf, "<domainsnapshot>\n");
|
||||||
|
virBufferVSprintf(&buf, " <name>%s</name>\n", def->name);
|
||||||
|
if (def->description)
|
||||||
|
virBufferVSprintf(&buf, " <description>%s</description>\n",
|
||||||
|
def->description);
|
||||||
|
virBufferVSprintf(&buf, " <state>%s</state>\n",
|
||||||
|
virDomainStateTypeToString(def->state));
|
||||||
|
if (def->parent) {
|
||||||
|
virBufferAddLit(&buf, " <parent>\n");
|
||||||
|
virBufferVSprintf(&buf, " <name>%s</name>\n", def->parent);
|
||||||
|
virBufferAddLit(&buf, " </parent>\n");
|
||||||
|
}
|
||||||
|
virBufferVSprintf(&buf, " <creationTime>%ld</creationTime>\n",
|
||||||
|
def->creationTime);
|
||||||
|
virBufferAddLit(&buf, " <domain>\n");
|
||||||
|
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", domain_uuid);
|
||||||
|
virBufferAddLit(&buf, " </domain>\n");
|
||||||
|
if (internal)
|
||||||
|
virBufferVSprintf(&buf, " <active>%ld</active>\n", def->active);
|
||||||
|
virBufferAddLit(&buf, "</domainsnapshot>\n");
|
||||||
|
|
||||||
|
if (virBufferError(&buf)) {
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virBufferContentAndReset(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Snapshot Obj functions */
|
||||||
|
static virDomainSnapshotObjPtr virDomainSnapshotObjNew(void)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr snapshot;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(snapshot) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot->refs = 1;
|
||||||
|
|
||||||
|
VIR_DEBUG("obj=%p", snapshot);
|
||||||
|
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virDomainSnapshotObjFree(virDomainSnapshotObjPtr snapshot)
|
||||||
|
{
|
||||||
|
if (!snapshot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VIR_DEBUG("obj=%p", snapshot);
|
||||||
|
|
||||||
|
virDomainSnapshotDefFree(snapshot->def);
|
||||||
|
}
|
||||||
|
|
||||||
|
int virDomainSnapshotObjUnref(virDomainSnapshotObjPtr snapshot)
|
||||||
|
{
|
||||||
|
snapshot->refs--;
|
||||||
|
VIR_DEBUG("obj=%p refs=%d", snapshot, snapshot->refs);
|
||||||
|
if (snapshot->refs == 0) {
|
||||||
|
virDomainSnapshotObjFree(snapshot);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return snapshot->refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
virDomainSnapshotObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
const virDomainSnapshotDefPtr def)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr snap;
|
||||||
|
|
||||||
|
if (virHashLookup(snapshots->objs, def->name) != NULL) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unexpected domain snapshot %s already exists"),
|
||||||
|
def->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(snap = virDomainSnapshotObjNew()))
|
||||||
|
return NULL;
|
||||||
|
snap->def = def;
|
||||||
|
|
||||||
|
if (virHashAddEntry(snapshots->objs, snap->def->name, snap) < 0) {
|
||||||
|
VIR_FREE(snap);
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return snap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Snapshot Obj List functions */
|
||||||
|
int virDomainSnapshotObjListInit(virDomainSnapshotObjListPtr snapshots)
|
||||||
|
{
|
||||||
|
snapshots->objs = virHashCreate(50);
|
||||||
|
if (!snapshots->objs) {
|
||||||
|
virReportOOMError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virDomainSnapshotObjListDeallocator(void *payload,
|
||||||
|
const char *name ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr obj = payload;
|
||||||
|
|
||||||
|
virDomainSnapshotObjUnref(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virDomainSnapshotObjListDeinit(virDomainSnapshotObjListPtr snapshots)
|
||||||
|
{
|
||||||
|
if (snapshots->objs)
|
||||||
|
virHashFree(snapshots->objs, virDomainSnapshotObjListDeallocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct virDomainSnapshotNameData {
|
||||||
|
int oom;
|
||||||
|
int numnames;
|
||||||
|
int maxnames;
|
||||||
|
char **const names;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virDomainSnapshotObjListCopyNames(void *payload,
|
||||||
|
const char *name ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr obj = payload;
|
||||||
|
struct virDomainSnapshotNameData *data = opaque;
|
||||||
|
|
||||||
|
if (data->oom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data->numnames < data->maxnames) {
|
||||||
|
if (!(data->names[data->numnames] = strdup(obj->def->name)))
|
||||||
|
data->oom = 1;
|
||||||
|
else
|
||||||
|
data->numnames++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
char **const names, int maxnames)
|
||||||
|
{
|
||||||
|
struct virDomainSnapshotNameData data = { 0, 0, maxnames, names };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
virHashForEach(snapshots->objs, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virDomainSnapshotObjListCount(void *payload ATTRIBUTE_UNUSED,
|
||||||
|
const char *name ATTRIBUTE_UNUSED,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
int *count = data;
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
virHashForEach(snapshots->objs, virDomainSnapshotObjListCount, &count);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virDomainSnapshotObjListSearchName(const void *payload,
|
||||||
|
const char *name ATTRIBUTE_UNUSED,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr obj = (virDomainSnapshotObjPtr)payload;
|
||||||
|
int want = 0;
|
||||||
|
|
||||||
|
if (STREQ(obj->def->name, (const char *)data))
|
||||||
|
want = 1;
|
||||||
|
|
||||||
|
return want;
|
||||||
|
}
|
||||||
|
|
||||||
|
virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return virHashSearch(snapshots->objs, virDomainSnapshotObjListSearchName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
virDomainSnapshotObjPtr snapshot)
|
||||||
|
{
|
||||||
|
virHashRemoveEntry(snapshots->objs, snapshot->def->name,
|
||||||
|
virDomainSnapshotObjListDeallocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct snapshot_has_children {
|
||||||
|
char *name;
|
||||||
|
int number;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virDomainSnapshotCountChildren(void *payload,
|
||||||
|
const char *name ATTRIBUTE_UNUSED,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
virDomainSnapshotObjPtr obj = payload;
|
||||||
|
struct snapshot_has_children *curr = data;
|
||||||
|
|
||||||
|
if (obj->def->parent && STREQ(obj->def->parent, curr->name))
|
||||||
|
curr->number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int virDomainSnapshotHasChildren(virDomainSnapshotObjPtr snap,
|
||||||
|
virDomainSnapshotObjListPtr snapshots)
|
||||||
|
{
|
||||||
|
struct snapshot_has_children children;
|
||||||
|
|
||||||
|
children.name = snap->def->name;
|
||||||
|
children.number = 0;
|
||||||
|
virHashForEach(snapshots->objs, virDomainSnapshotCountChildren, &children);
|
||||||
|
|
||||||
|
return children.number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! PROXY */
|
#endif /* ! PROXY */
|
||||||
|
@ -741,6 +741,58 @@ struct _virDomainClockDef {
|
|||||||
|
|
||||||
# define VIR_DOMAIN_CPUMASK_LEN 1024
|
# define VIR_DOMAIN_CPUMASK_LEN 1024
|
||||||
|
|
||||||
|
|
||||||
|
/* Snapshot state */
|
||||||
|
typedef struct _virDomainSnapshotDef virDomainSnapshotDef;
|
||||||
|
typedef virDomainSnapshotDef *virDomainSnapshotDefPtr;
|
||||||
|
struct _virDomainSnapshotDef {
|
||||||
|
char *name;
|
||||||
|
char *description;
|
||||||
|
char *parent;
|
||||||
|
time_t creationTime;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
long active;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainSnapshotObj virDomainSnapshotObj;
|
||||||
|
typedef virDomainSnapshotObj *virDomainSnapshotObjPtr;
|
||||||
|
struct _virDomainSnapshotObj {
|
||||||
|
int refs;
|
||||||
|
|
||||||
|
virDomainSnapshotDefPtr def;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainSnapshotObjList virDomainSnapshotObjList;
|
||||||
|
typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;
|
||||||
|
struct _virDomainSnapshotObjList {
|
||||||
|
/* name string -> virDomainSnapshotObj mapping
|
||||||
|
* for O(1), lockless lookup-by-name */
|
||||||
|
virHashTable *objs;
|
||||||
|
};
|
||||||
|
|
||||||
|
virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr,
|
||||||
|
int newSnapshot);
|
||||||
|
void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def);
|
||||||
|
char *virDomainSnapshotDefFormat(char *domain_uuid,
|
||||||
|
virDomainSnapshotDefPtr def,
|
||||||
|
int internal);
|
||||||
|
virDomainSnapshotObjPtr virDomainSnapshotAssignDef(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
const virDomainSnapshotDefPtr def);
|
||||||
|
|
||||||
|
int virDomainSnapshotObjListInit(virDomainSnapshotObjListPtr objs);
|
||||||
|
void virDomainSnapshotObjListDeinit(virDomainSnapshotObjListPtr objs);
|
||||||
|
int virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
char **const names, int maxnames);
|
||||||
|
int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots);
|
||||||
|
virDomainSnapshotObjPtr virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots,
|
||||||
|
const char *name);
|
||||||
|
void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,
|
||||||
|
virDomainSnapshotObjPtr snapshot);
|
||||||
|
int virDomainSnapshotObjUnref(virDomainSnapshotObjPtr snapshot);
|
||||||
|
int virDomainSnapshotHasChildren(virDomainSnapshotObjPtr snap,
|
||||||
|
virDomainSnapshotObjListPtr snapshots);
|
||||||
|
|
||||||
/* Guest VM main configuration */
|
/* Guest VM main configuration */
|
||||||
typedef struct _virDomainDef virDomainDef;
|
typedef struct _virDomainDef virDomainDef;
|
||||||
typedef virDomainDef *virDomainDefPtr;
|
typedef virDomainDef *virDomainDefPtr;
|
||||||
@ -828,6 +880,9 @@ struct _virDomainObj {
|
|||||||
virDomainDefPtr def; /* The current definition */
|
virDomainDefPtr def; /* The current definition */
|
||||||
virDomainDefPtr newDef; /* New definition to activate at shutdown */
|
virDomainDefPtr newDef; /* New definition to activate at shutdown */
|
||||||
|
|
||||||
|
virDomainSnapshotObjList snapshots;
|
||||||
|
virDomainSnapshotObjPtr current_snapshot;
|
||||||
|
|
||||||
void *privateData;
|
void *privateData;
|
||||||
void (*privateDataFreeFunc)(void *);
|
void (*privateDataFreeFunc)(void *);
|
||||||
};
|
};
|
||||||
|
@ -206,6 +206,16 @@ virDomainTimerTickpolicyTypeToString;
|
|||||||
virDomainTimerTickpolicyTypeFromString;
|
virDomainTimerTickpolicyTypeFromString;
|
||||||
virDomainTimerModeTypeToString;
|
virDomainTimerModeTypeToString;
|
||||||
virDomainTimerModeTypeFromString;
|
virDomainTimerModeTypeFromString;
|
||||||
|
virDomainSnapshotObjListGetNames;
|
||||||
|
virDomainSnapshotObjListNum;
|
||||||
|
virDomainSnapshotFindByName;
|
||||||
|
virDomainSnapshotObjListAdd;
|
||||||
|
virDomainSnapshotObjListRemove;
|
||||||
|
virDomainSnapshotHasChildren;
|
||||||
|
virDomainSnapshotObjUnref;
|
||||||
|
virDomainSnapshotDefParseString;
|
||||||
|
virDomainSnapshotDefFormat;
|
||||||
|
virDomainSnapshotAssignDef;
|
||||||
|
|
||||||
|
|
||||||
# domain_event.h
|
# domain_event.h
|
||||||
|
Loading…
Reference in New Issue
Block a user