mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 14:15:28 +00:00
vz: add domain snapshots functionality
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@virtuozzo.com> Signed-off-by: Maxim Nestratov <mnestratov@virtuozzo.com>
This commit is contained in:
parent
027986f5bf
commit
abc85b2cab
@ -809,7 +809,9 @@ virDomainSnapshotForEachDescendant;
|
||||
virDomainSnapshotIsExternal;
|
||||
virDomainSnapshotLocationTypeFromString;
|
||||
virDomainSnapshotLocationTypeToString;
|
||||
virDomainSnapshotObjListFree;
|
||||
virDomainSnapshotObjListGetNames;
|
||||
virDomainSnapshotObjListNew;
|
||||
virDomainSnapshotObjListNum;
|
||||
virDomainSnapshotObjListRemove;
|
||||
virDomainSnapshotRedefinePrep;
|
||||
|
@ -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 = {
|
||||
|
216
src/vz/vz_sdk.c
216
src/vz/vz_sdk.c
@ -4274,3 +4274,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);
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user