[libvirt] [PATCH 1/2] vz: add domain snapshots functionality
Maxim Nestratov
mnestratov at virtuozzo.com
Wed May 18 15:07:40 UTC 2016
02.05.2016 12:33, Nikolay Shirokovskiy пишет:
> This solution does not keep snapshots cache because vz sdk lacks good support
> for snapshot related events.
>
> Libvirt and vz sdk has different approach to snapshot ids. vz sdk always
> auto generate them while libvirt has ability to specify id by user.
> Thus I have no other choice rather than simply ignore ids set by user
> or generated by libvirt.
>
> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
> ---
> src/libvirt_private.syms | 2 +
> src/vz/vz_driver.c | 535 +++++++++++++++++++++++++++++++++++++++++++++++
> src/vz/vz_sdk.c | 216 +++++++++++++++++++
> src/vz/vz_sdk.h | 5 +
> src/vz/vz_utils.h | 1 +
> 5 files changed, 759 insertions(+)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 0de35ef..81b9b1d 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -808,7 +808,9 @@ virDomainSnapshotForEachDescendant;
> virDomainSnapshotIsExternal;
> virDomainSnapshotLocationTypeFromString;
> virDomainSnapshotLocationTypeToString;
> +virDomainSnapshotObjListFree;
> virDomainSnapshotObjListGetNames;
> +virDomainSnapshotObjListNew;
> virDomainSnapshotObjListNum;
> virDomainSnapshotObjListRemove;
> virDomainSnapshotRedefinePrep;
> diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
> index 1497b72..03d3e53 100644
> --- a/src/vz/vz_driver.c
> +++ b/src/vz/vz_driver.c
> @@ -1581,6 +1581,525 @@ static int vzDomainSetMemory(virDomainPtr domain, unsigned long memory)
> return vzDomainSetMemoryFlagsImpl(domain, memory, 0, false);
> }
>
> +static virDomainSnapshotObjPtr
> +vzSnapObjFromName(virDomainSnapshotObjListPtr snapshots, const char *name)
> +{
> + virDomainSnapshotObjPtr snap = NULL;
> + snap = virDomainSnapshotFindByName(snapshots, name);
> + if (!snap)
> + virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
> + _("no domain snapshot with matching name '%s'"), name);
> +
> + return snap;
> +}
> +
> +static virDomainSnapshotObjPtr
> +vzSnapObjFromSnapshot(virDomainSnapshotObjListPtr snapshots,
> + virDomainSnapshotPtr snapshot)
> +{
> + return vzSnapObjFromName(snapshots, snapshot->name);
> +}
> +
> +static int
> +vzCurrentSnapshotIterator(void *payload,
> + const void *name ATTRIBUTE_UNUSED,
> + void *data)
> +{
> + virDomainSnapshotObjPtr snapshot = payload;
> + virDomainSnapshotObjPtr *current = data;
> +
> + if (snapshot->def->current)
> + *current = snapshot;
> +
> + return 0;
> +}
> +
> +static virDomainSnapshotObjPtr
> +vzFindCurrentSnapshot(virDomainSnapshotObjListPtr snapshots)
> +{
> + virDomainSnapshotObjPtr current = NULL;
> +
> + virDomainSnapshotForEach(snapshots, vzCurrentSnapshotIterator, ¤t);
> + return current;
> +}
> +
> +static int
> +vzDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + n = virDomainSnapshotObjListNum(snapshots, NULL, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static int
> +vzDomainSnapshotListNames(virDomainPtr domain,
> + char **names,
> + int nameslen,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + n = virDomainSnapshotObjListGetNames(snapshots, NULL, names, nameslen, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static int
> +vzDomainListAllSnapshots(virDomainPtr domain,
> + virDomainSnapshotPtr **snaps,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + n = virDomainListSnapshots(snapshots, NULL, domain, snaps, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static char *
> +vzDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + char *xml = NULL;
> + virDomainSnapshotObjPtr snap;
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + vzConnPtr privconn = snapshot->domain->conn->privateData;
> +
> + virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return NULL;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + virUUIDFormat(snapshot->domain->uuid, uuidstr);
> +
> + xml = virDomainSnapshotDefFormat(uuidstr, snap->def, privconn->driver->caps,
> + virDomainDefFormatConvertXMLFlags(flags),
> + 0);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return xml;
> +}
> +
> +static int
> +vzDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + n = virDomainSnapshotObjListNum(snapshots, snap, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static int
> +vzDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
> + char **names,
> + int nameslen,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + n = virDomainSnapshotObjListGetNames(snapshots, snap, names, nameslen, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static int
> +vzDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot,
> + virDomainSnapshotPtr **snaps,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int n = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
> + VIR_DOMAIN_SNAPSHOT_FILTERS_ALL, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + n = virDomainListSnapshots(snapshots, snap, snapshot->domain, snaps, flags);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return n;
> +}
> +
> +static virDomainSnapshotPtr
> +vzDomainSnapshotLookupByName(virDomainPtr domain,
> + const char *name,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotPtr snapshot = NULL;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> +
> + virCheckFlags(0, NULL);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return NULL;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromName(snapshots, name)))
> + goto cleanup;
> +
> + snapshot = virGetDomainSnapshot(domain, snap->def->name);
> +
> + cleanup:
> + virObjectUnlock(dom);
> + virDomainSnapshotObjListFree(snapshots);
> +
> + return snapshot;
> +}
> +
> +static int
> +vzDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + int ret = -1;
> +
> + virCheckFlags(0, -1);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + ret = vzFindCurrentSnapshot(snapshots) != NULL;
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return ret;
> +}
> +
> +static virDomainSnapshotPtr
> +vzDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotPtr parent = NULL;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> +
> + virCheckFlags(0, NULL);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return NULL;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + if (!snap->def->parent) {
> + virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
> + _("snapshot '%s' does not have a parent"),
> + snap->def->name);
> + goto cleanup;
> + }
> +
> + parent = virGetDomainSnapshot(snapshot->domain, snap->def->parent);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return parent;
> +}
> +
> +static virDomainSnapshotPtr
> +vzDomainSnapshotCurrent(virDomainPtr domain, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + virDomainSnapshotPtr snapshot = NULL;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + virDomainSnapshotObjPtr current;
> +
> + virCheckFlags(0, NULL);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return NULL;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(current = vzFindCurrentSnapshot(snapshots))) {
> + virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s",
> + _("the domain does not have a current snapshot"));
> + goto cleanup;
> + }
> +
> + snapshot = virGetDomainSnapshot(domain, current->def->name);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return snapshot;
> +}
> +
> +static int
> +vzDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + int ret = -1;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + virDomainSnapshotObjPtr current;
> +
> + virCheckFlags(0, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + current = vzFindCurrentSnapshot(snapshots);
> + ret = current && STREQ(snapshot->name, current->def->name);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> +
> + return ret;
> +}
> +
> +static int
> +vzDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
> + unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + int ret = -1;
> + virDomainSnapshotObjPtr snap;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> +
> + virCheckFlags(0, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(snap = vzSnapObjFromSnapshot(snapshots, snapshot)))
> + goto cleanup;
> +
> + ret = 1;
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> + return ret;
> +}
> +
> +static virDomainSnapshotPtr
> +vzDomainSnapshotCreateXML(virDomainPtr domain,
> + const char *xmlDesc,
> + unsigned int flags)
> +{
> + virDomainSnapshotDefPtr def = NULL;
> + virDomainSnapshotPtr snapshot = NULL;
> + virDomainObjPtr dom;
> + vzConnPtr privconn = domain->conn->privateData;
> + vzDriverPtr driver = privconn->driver;
> + unsigned int parse_flags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + virDomainSnapshotObjPtr current;
> +
> + virCheckFlags(0, NULL);
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + return NULL;
> +
> + if (!(def = virDomainSnapshotDefParseString(xmlDesc, driver->caps,
> + driver->xmlopt, parse_flags)))
> + goto cleanup;
> +
> + if (def->ndisks > 0) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("configuring disks is not supported for vz snapshots"));
> + goto cleanup;
> + }
> +
> + if (def->memory) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("configuring memory location is not supported"));
> + goto cleanup;
> + }
> +
> + /* snaphot name is ignored, it will be set to auto generated by sdk uuid */
> + if (prlsdkCreateSnapshot(dom, def->description) < 0)
> + goto cleanup;
> +
> + if (!(snapshots = prlsdkLoadSnapshots(dom)))
> + goto cleanup;
> +
> + if (!(current = vzFindCurrentSnapshot(snapshots))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("can't find created snapshot"));
> + goto cleanup;
> + }
> +
> + /* hopefully new current snapshot is newly created one */
> + snapshot = virGetDomainSnapshot(domain, current->def->name);
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + virObjectUnlock(dom);
> + virDomainSnapshotDefFree(def);
> +
> + return snapshot;
> +}
> +
> +static int
> +vzDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + int ret = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + ret = prlsdkDeleteSnapshot(dom, snapshot->name,
> + flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN);
> +
> + virObjectUnlock(dom);
> +
> + return ret;
> +}
> +
> +static int
> +vzDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags)
> +{
> + virDomainObjPtr dom;
> + int ret = -1;
> +
> + virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, -1);
> +
> + if (!(dom = vzDomObjFromDomain(snapshot->domain)))
> + return -1;
> +
> + ret = prlsdkSwitchToSnapshot(dom, snapshot->name,
> + flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED);
> +
> + virObjectUnlock(dom);
> +
> + return ret;
> +}
> +
> static virHypervisorDriver vzHypervisorDriver = {
> .name = "vz",
> .connectOpen = vzConnectOpen, /* 0.10.0 */
> @@ -1648,6 +2167,22 @@ static virHypervisorDriver vzHypervisorDriver = {
> .connectUnregisterCloseCallback = vzConnectUnregisterCloseCallback, /* 1.3.2 */
> .domainSetMemoryFlags = vzDomainSetMemoryFlags, /* 1.3.4 */
> .domainSetMemory = vzDomainSetMemory, /* 1.3.4 */
> + .domainSnapshotNum = vzDomainSnapshotNum, /* 1.3.5 */
> + .domainSnapshotListNames = vzDomainSnapshotListNames, /* 1.3.5 */
> + .domainListAllSnapshots = vzDomainListAllSnapshots, /* 1.3.5 */
> + .domainSnapshotGetXMLDesc = vzDomainSnapshotGetXMLDesc, /* 1.3.5 */
> + .domainSnapshotNumChildren = vzDomainSnapshotNumChildren, /* 1.3.5 */
> + .domainSnapshotListChildrenNames = vzDomainSnapshotListChildrenNames, /* 1.3.5 */
> + .domainSnapshotListAllChildren = vzDomainSnapshotListAllChildren, /* 1.3.5 */
> + .domainSnapshotLookupByName = vzDomainSnapshotLookupByName, /* 1.3.5 */
> + .domainHasCurrentSnapshot = vzDomainHasCurrentSnapshot, /* 1.3.5 */
> + .domainSnapshotGetParent = vzDomainSnapshotGetParent, /* 1.3.5 */
> + .domainSnapshotCurrent = vzDomainSnapshotCurrent, /* 1.3.5 */
> + .domainSnapshotIsCurrent = vzDomainSnapshotIsCurrent, /* 1.3.5 */
> + .domainSnapshotHasMetadata = vzDomainSnapshotHasMetadata, /* 1.3.5 */
> + .domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */
> + .domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
> + .domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */
> };
>
> static virConnectDriver vzConnectDriver = {
> diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
> index 8cc8430..23b9277 100644
> --- a/src/vz/vz_sdk.c
> +++ b/src/vz/vz_sdk.c
> @@ -4267,3 +4267,219 @@ int prlsdkSetMemsize(virDomainObjPtr dom, unsigned int memsize)
> error:
> return -1;
> }
> +
> +static long long
> +prlsdkParseDateTime(const char *str)
> +{
> + struct tm tm;
> + const char *tmp;
> +
> + tmp = strptime(str, "%Y-%m-%d %H:%M:%S", &tm);
> + if (!tmp || *tmp != '\0') {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("unexpected DateTime format: '%s'"), str);
> + return -1;
> + }
> +
> + return mktime(&tm);
> +}
> +
> +static virDomainSnapshotObjListPtr
> +prlsdkParseSnapshotTree(const char *treexml)
> +{
> + virDomainSnapshotObjListPtr ret = NULL;
> + xmlDocPtr xml = NULL;
> + xmlXPathContextPtr ctxt = NULL;
> + xmlNodePtr root;
> + xmlNodePtr *nodes = NULL;
> + virDomainSnapshotDefPtr def = NULL;
> + virDomainSnapshotObjPtr snapshot;
> + virDomainSnapshotObjPtr current = NULL;
> + virDomainSnapshotObjListPtr snapshots = NULL;
> + char *xmlstr = NULL;
> + int n;
> + size_t i;
> +
> + if (!(snapshots = virDomainSnapshotObjListNew()))
> + return NULL;
> +
> + if (*treexml == '\0')
> + return snapshots;
> +
> + if (!(xml = virXMLParse(NULL, treexml, _("(snapshot_tree)"))))
> + goto cleanup;
> +
> + root = xmlDocGetRootElement(xml);
> + if (!xmlStrEqual(root->name, BAD_CAST "ParallelsSavedStates")) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("unexpected root element: '%s'"), root->name);
> + goto cleanup;
> + }
> +
> + ctxt = xmlXPathNewContext(xml);
> + if (ctxt == NULL) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + ctxt->node = root;
> +
> + if ((n = virXPathNodeSet("//SavedStateItem", ctxt, &nodes)) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("cannot extract snapshot nodes"));
> + goto cleanup;
> + }
> +
> + for (i = 0; i < n; i++) {
> + if (nodes[i]->parent == root)
> + continue;
> +
> + if (VIR_ALLOC(def) < 0)
> + goto cleanup;
> +
> + ctxt->node = nodes[i];
> +
> + def->name = virXPathString("string(./@guid)", ctxt);
> + if (!def->name) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("missing 'guid' attribute"));
> + goto cleanup;
> + }
> +
> + def->parent = virXPathString("string(../@guid)", ctxt);
> +
> + xmlstr = virXPathString("string(./DateTime)", ctxt);
> + if (!xmlstr) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("missing 'DateTime' element"));
> + goto cleanup;
> + }
> + if ((def->creationTime = prlsdkParseDateTime(xmlstr)) < 0)
> + goto cleanup;
> + VIR_FREE(xmlstr);
> +
> + def->description = virXPathString("string(./Description)", ctxt);
> +
> + def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
> + xmlstr = virXPathString("string(../@state)", ctxt);
There is a typo here, should be "string(./@state)".
Otherwise you will show the state of parent's snapshot and not the one
you are parsing.
> + if (!xmlstr) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("missing 'state' attribute"));
> + goto cleanup;
> + } else if (STREQ(xmlstr, "poweron")) {
> + def->state = VIR_DOMAIN_RUNNING;
> + def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
> + } else if (STREQ(xmlstr, "pause")) {
> + def->state = VIR_DOMAIN_PAUSED;
> + def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL;
> + } else if (STREQ(xmlstr, "suspend")) {
> + def->state = VIR_DOMAIN_SHUTOFF;
> + } else if (STREQ(xmlstr, "poweroff")) {
> + def->state = VIR_DOMAIN_SHUTOFF;
> + } else {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("unexpected snapshot state: %s"), xmlstr);
> + }
> + VIR_FREE(xmlstr);
> +
> + xmlstr = virXPathString("string(./@current)", ctxt);
> + def->current = xmlstr && STREQ("yes", xmlstr);
> + VIR_FREE(xmlstr);
> +
> + if (!(snapshot = virDomainSnapshotAssignDef(snapshots, def)))
> + goto cleanup;
> + def = NULL;
> +
> + if (snapshot->def->current) {
> + if (current) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("too many current snapshots"));
> + goto cleanup;
> + }
> + current = snapshot;
> + }
> + }
> +
> + if (virDomainSnapshotUpdateRelations(snapshots) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("snapshots have inconsistent relations"));
> + goto cleanup;
> + }
> +
> + ret = snapshots;
> + snapshots = NULL;
> +
> + cleanup:
> + virDomainSnapshotObjListFree(snapshots);
> + VIR_FREE(nodes);
> + VIR_FREE(xmlstr);
> + xmlXPathFreeContext(ctxt);
> + xmlFreeDoc(xml);
> + VIR_FREE(def);
> +
> + return ret;
> +}
> +
> +virDomainSnapshotObjListPtr
> +prlsdkLoadSnapshots(virDomainObjPtr dom)
> +{
> + virDomainSnapshotObjListPtr ret = NULL;
> + PRL_HANDLE job;
> + PRL_HANDLE result = PRL_INVALID_HANDLE;
> + vzDomObjPtr privdom = dom->privateData;
> + char *treexml = NULL;
> +
> + job = PrlVm_GetSnapshotsTreeEx(privdom->sdkdom, PGST_WITHOUT_SCREENSHOTS);
> + if (PRL_FAILED(getJobResult(job, &result)))
> + goto cleanup;
> +
> + if (!(treexml = prlsdkGetStringParamVar(PrlResult_GetParamAsString, result)))
> + goto cleanup;
> +
> + ret = prlsdkParseSnapshotTree(treexml);
> + cleanup:
> +
> + PrlHandle_Free(result);
> + VIR_FREE(treexml);
> + return ret;
> +}
> +
> +int prlsdkCreateSnapshot(virDomainObjPtr dom, const char *description)
> +{
> + vzDomObjPtr privdom = dom->privateData;
> + PRL_HANDLE job;
> +
> + job = PrlVm_CreateSnapshot(privdom->sdkdom, "",
> + description ? : "");
> + if (PRL_FAILED(waitJob(job)))
> + return -1;
> +
> + return 0;
> +}
> +
> +int prlsdkDeleteSnapshot(virDomainObjPtr dom, const char *uuid, bool children)
> +{
> + vzDomObjPtr privdom = dom->privateData;
> + PRL_HANDLE job;
> +
> + job = PrlVm_DeleteSnapshot(privdom->sdkdom, uuid, children);
> + if (PRL_FAILED(waitJob(job)))
> + return -1;
> +
> + return 0;
> +}
> +
> +int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused)
> +{
> + vzDomObjPtr privdom = dom->privateData;
> + PRL_HANDLE job;
> + PRL_UINT32 flags = 0;
> +
> + if (paused)
> + flags |= PSSF_SKIP_RESUME;
> +
> + job = PrlVm_SwitchToSnapshotEx(privdom->sdkdom, uuid, flags);
> + if (PRL_FAILED(waitJob(job)))
> + return -1;
> +
> + return 0;
> +}
> diff --git a/src/vz/vz_sdk.h b/src/vz/vz_sdk.h
> index e562f98..47ff5b9 100644
> --- a/src/vz/vz_sdk.h
> +++ b/src/vz/vz_sdk.h
> @@ -82,3 +82,8 @@ void
> prlsdkDomObjFreePrivate(void *p);
> /* memsize is in MiB */
> int prlsdkSetMemsize(virDomainObjPtr dom, unsigned int memsize);
> +
> +virDomainSnapshotObjListPtr prlsdkLoadSnapshots(virDomainObjPtr dom);
> +int prlsdkCreateSnapshot(virDomainObjPtr dom, const char *description);
> +int prlsdkDeleteSnapshot(virDomainObjPtr dom, const char *uuid, bool children);
> +int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused);
> diff --git a/src/vz/vz_utils.h b/src/vz/vz_utils.h
> index ee843d8..ba4d3c5 100644
> --- a/src/vz/vz_utils.h
> +++ b/src/vz/vz_utils.h
> @@ -27,6 +27,7 @@
>
> # include "driver.h"
> # include "conf/domain_conf.h"
> +# include "conf/snapshot_conf.h"
> # include "conf/virdomainobjlist.h"
> # include "conf/domain_event.h"
> # include "virthread.h"
More information about the libvir-list
mailing list