]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add vbox_snapshot_conf struct
authorYohan BELLEGUIC <yohan.belleguic@diateam.net>
Mon, 19 May 2014 12:47:31 +0000 (14:47 +0200)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 10 Jun 2014 14:07:36 +0000 (15:07 +0100)
This structure contains the data to be saved in the VirtualBox XML file
and can be manipulated with severals exposed functions.
The structure is created by vboxSnapshotLoadVboxFile taking the
machine XML file.
It also can rewrite the XML by using vboxSnapshotSaveVboxFile.

po/POTFILES.in
src/Makefile.am
src/vbox/vbox_snapshot_conf.c [new file with mode: 0644]
src/vbox/vbox_snapshot_conf.h [new file with mode: 0644]
tests/Makefile.am
tests/vboxsnapshotxmldata/2disks-1snap.vbox [new file with mode: 0644]
tests/vboxsnapshotxmldata/2disks-2snap.vbox [new file with mode: 0644]
tests/vboxsnapshotxmldata/2disks-3snap-brother.vbox [new file with mode: 0644]
tests/vboxsnapshotxmldata/2disks-3snap.vbox [new file with mode: 0644]
tests/vboxsnapshotxmldata/2disks-nosnap.vbox [new file with mode: 0644]
tests/vboxsnapshotxmltest.c [new file with mode: 0644]

index 2ee7225a68a4f7672486470a23e3a2c8d80a20d1..d01116bd03954e62be5e10fd3c317b61c66cb240 100644 (file)
@@ -212,6 +212,7 @@ src/util/virxml.c
 src/vbox/vbox_MSCOMGlue.c
 src/vbox/vbox_XPCOMCGlue.c
 src/vbox/vbox_driver.c
+src/vbox/vbox_snapshot_conf.c
 src/vbox/vbox_tmpl.c
 src/vmware/vmware_conf.c
 src/vmware/vmware_driver.c
index 01af16477df0c7361545c502ed2001db791d99b6..30df68f7944af5796a6c2918cdba96ce0c5ef20e 100644 (file)
@@ -663,6 +663,7 @@ VMWARE_DRIVER_SOURCES =                                             \
 VBOX_DRIVER_SOURCES =                                          \
        vbox/vbox_glue.c vbox/vbox_glue.h                       \
        vbox/vbox_driver.c vbox/vbox_driver.h                   \
+       vbox/vbox_snapshot_conf.c vbox/vbox_snapshot_conf.h \
        vbox/vbox_V2_2.c vbox/vbox_CAPI_v2_2.h                  \
        vbox/vbox_V3_0.c vbox/vbox_CAPI_v3_0.h                  \
        vbox/vbox_V3_1.c vbox/vbox_CAPI_v3_1.h                  \
diff --git a/src/vbox/vbox_snapshot_conf.c b/src/vbox/vbox_snapshot_conf.c
new file mode 100644 (file)
index 0000000..4909665
--- /dev/null
@@ -0,0 +1,1537 @@
+/*
+ * Copyright 2014, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "vbox_snapshot_conf.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virlog.h"
+#include "virstring.h"
+#include "virxml.h"
+
+#include <libxml/xpathInternals.h>
+
+#define VIR_FROM_THIS                   VIR_FROM_VBOX
+VIR_LOG_INIT("vbox.vbox_snapshot_conf");
+
+static virVBoxSnapshotConfHardDiskPtr
+virVBoxSnapshotConfCreateVBoxSnapshotConfHardDiskPtr(xmlNodePtr diskNode,
+                                                     xmlXPathContextPtr xPathContext,
+                                                     const char *machineLocation)
+{
+    virVBoxSnapshotConfHardDiskPtr hardDisk = NULL;
+    xmlNodePtr *nodes = NULL;
+    char *uuid = NULL;
+    char **searchTabResult = NULL;
+    int resultSize = 0;
+    size_t i = 0;
+    int result = -1;
+    char *location = NULL;
+    char *tmp = NULL;
+    int n = 0;
+    if (VIR_ALLOC(hardDisk) < 0)
+        goto cleanup;
+
+    xPathContext->node = diskNode;
+
+    n = virXPathNodeSet("./vbox:HardDisk", xPathContext, &nodes);
+    if (n < 0)
+        goto cleanup;
+
+    if (n && VIR_ALLOC_N(hardDisk->children, n) < 0)
+        goto cleanup;
+    hardDisk->nchildren = n;
+    for (i = 0; i < hardDisk->nchildren; i++) {
+        hardDisk->children[i] = virVBoxSnapshotConfCreateVBoxSnapshotConfHardDiskPtr(nodes[i], xPathContext, machineLocation);
+        if (hardDisk->children[i] == NULL)
+            goto cleanup;
+        hardDisk->children[i]->parent = hardDisk;
+    }
+    uuid = virXMLPropString(diskNode, "uuid");
+    /*we use virStringSearch because the uuid is between brackets*/
+    resultSize = virStringSearch(uuid,
+                                 VBOX_UUID_REGEX,
+                                 1,
+                                 &searchTabResult);
+    if (resultSize != 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <HardDisk> 'uuid' attribute"));
+        goto cleanup;
+    }
+    if (VIR_STRDUP(hardDisk->uuid, searchTabResult[0]) < 0)
+        goto cleanup;
+
+    location = virXMLPropString(diskNode, "location");
+    if (location == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <HardDisk> 'location' attribute"));
+        goto cleanup;
+    }
+    if (location[0] != '/') {
+        /*The location is a relative path, so we must change it into an absolute one. */
+        if (virAsprintf(&tmp, "%s%s", machineLocation, location) < 0)
+            goto cleanup;
+        if (VIR_STRDUP(hardDisk->location, tmp) < 0)
+            goto cleanup;
+    } else {
+        if (VIR_STRDUP(hardDisk->location, location) < 0)
+            goto cleanup;
+    }
+    hardDisk->format = virXMLPropString(diskNode, "format");
+    if (hardDisk->format == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <HardDisk> 'format' attribute"));
+        goto cleanup;
+    }
+    hardDisk->type = virXMLPropString(diskNode, "type");
+    result = 0;
+
+ cleanup:
+    VIR_FREE(uuid);
+    VIR_FREE(nodes);
+    VIR_FREE(location);
+    VIR_FREE(tmp);
+    virStringFreeList(searchTabResult);
+    if (result < 0) {
+        virVboxSnapshotConfHardDiskFree(hardDisk);
+        hardDisk = NULL;
+    }
+    return hardDisk;
+}
+
+static virVBoxSnapshotConfMediaRegistryPtr
+virVBoxSnapshotConfRetrieveMediaRegistry(xmlNodePtr mediaRegistryNode,
+                                         xmlXPathContextPtr xPathContext,
+                                         const char *machineLocation)
+{
+    virVBoxSnapshotConfMediaRegistryPtr mediaRegistry = NULL;
+    xmlNodePtr hardDisksNode = NULL;
+    xmlNodePtr *nodes = NULL;
+    size_t i = 0;
+    int result = -1;
+    int n = 0;
+
+    if (VIR_ALLOC(mediaRegistry) < 0)
+        goto cleanup;
+
+    xPathContext->node = mediaRegistryNode;
+    hardDisksNode = virXPathNode("./vbox:HardDisks", xPathContext);
+
+    xPathContext->node = hardDisksNode;
+    n = virXPathNodeSet("./vbox:HardDisk", xPathContext, &nodes);
+    if (n < 0)
+        goto cleanup;
+    if (n && VIR_ALLOC_N(mediaRegistry->disks, n) < 0)
+        goto cleanup;
+    mediaRegistry->ndisks = n;
+    for (i = 0; i < mediaRegistry->ndisks; i++) {
+        mediaRegistry->disks[i] = virVBoxSnapshotConfCreateVBoxSnapshotConfHardDiskPtr(nodes[i],
+                                                                   xPathContext,
+                                                                   machineLocation);
+        if (mediaRegistry->disks[i] == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Cannot create a vboxSnapshotXmlHardDisk"));
+            goto cleanup;
+        }
+    }
+    n = 0;
+    VIR_FREE(nodes);
+
+    xPathContext->node = mediaRegistryNode;
+    n = virXPathNodeSet("./*[not(self::vbox:HardDisks)]",
+                                                 xPathContext, &nodes);
+    if (n < 0)
+        goto cleanup;
+    if (n && VIR_ALLOC_N(mediaRegistry->otherMedia, n) < 0)
+        goto cleanup;
+    mediaRegistry->notherMedia = n;
+    for (i = 0; i < mediaRegistry->notherMedia; i++) {
+        mediaRegistry->otherMedia[i] = virXMLNodeToString(mediaRegistryNode->doc,
+                                                          nodes[i]);
+    }
+
+    result = 0;
+
+ cleanup:
+    if (result < 0) {
+        virVBoxSnapshotConfMediaRegistryFree(mediaRegistry);
+        mediaRegistry = NULL;
+    }
+    VIR_FREE(nodes);
+    return mediaRegistry;
+}
+
+static virVBoxSnapshotConfSnapshotPtr
+virVBoxSnapshotConfRetrieveSnapshot(xmlNodePtr snapshotNode,
+                                    xmlXPathContextPtr xPathContext)
+{
+    virVBoxSnapshotConfSnapshotPtr snapshot = NULL;
+    xmlNodePtr hardwareNode = NULL;
+    xmlNodePtr descriptionNode = NULL;
+    xmlNodePtr storageControllerNode = NULL;
+    xmlNodePtr snapshotsNode = NULL;
+    xmlNodePtr *nodes = NULL;
+    char *uuid = NULL;
+    char **searchTabResult = NULL;
+    int resultSize = 0;
+    size_t i = 0;
+    int result = -1;
+    int n = 0;
+
+    if (VIR_ALLOC(snapshot) < 0)
+        goto cleanup;
+
+    uuid = virXMLPropString(snapshotNode, "uuid");
+    /*we use virStringSearch because the uuid is between brackets*/
+    resultSize = virStringSearch(uuid,
+                                 VBOX_UUID_REGEX,
+                                 1,
+                                 &searchTabResult);
+    if (resultSize != 1) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Snapshot> 'uuid' attribute"));
+        goto cleanup;
+    }
+    if (VIR_STRDUP(snapshot->uuid, searchTabResult[0]) < 0)
+        goto cleanup;
+
+    snapshot->name = virXMLPropString(snapshotNode, "name");
+    if (snapshot->name == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Snapshot> 'name' attribute"));
+        goto cleanup;
+    }
+    snapshot->timeStamp = virXMLPropString(snapshotNode, "timeStamp");
+    if (snapshot->timeStamp == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Snapshot> 'timeStamp' attribute"));
+        goto cleanup;
+    }
+
+    xPathContext->node = snapshotNode;
+    descriptionNode = virXPathNode("./vbox:Description", xPathContext);
+    if (descriptionNode != NULL) {
+        snapshot->description = virXMLNodeToString(descriptionNode->doc, descriptionNode);
+    }
+
+    hardwareNode = virXPathNode("./vbox:Hardware", xPathContext);
+    if (hardwareNode == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Snapshot> <Hardware> node"));
+        goto cleanup;
+    }
+    snapshot->hardware = virXMLNodeToString(snapshotNode->doc, hardwareNode);
+
+    storageControllerNode = virXPathNode("./vbox:StorageControllers", xPathContext);
+    if (storageControllerNode == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Snapshot> <StorageControllers> node"));
+        goto cleanup;
+    }
+    snapshot->storageController = virXMLNodeToString(snapshotNode->doc,
+                                                     storageControllerNode);
+
+    snapshotsNode = virXPathNode("./vbox:Snapshots", xPathContext);
+
+    if (snapshotsNode != NULL) {
+        xPathContext->node = snapshotsNode;
+        n = virXPathNodeSet("./vbox:Snapshot", xPathContext, &nodes);
+        if (n < 0)
+            goto cleanup;
+        if (n && VIR_ALLOC_N(snapshot->children, n) < 0)
+            goto cleanup;
+        snapshot->nchildren = n;
+        for (i = 0; i <  snapshot->nchildren; i++) {
+            snapshot->children[i] = virVBoxSnapshotConfRetrieveSnapshot(nodes[i], xPathContext);
+            if (snapshot->children[i] == NULL) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Cannot create a vboxSnapshotXmlSnapshotPtr"));
+                goto cleanup;
+            }
+            snapshot->children[i]->parent = snapshot;
+        }
+    }
+
+    result = 0;
+
+ cleanup:
+    if (result < 0) {
+        virVBoxSnapshotConfSnapshotFree(snapshot);
+        snapshot = NULL;
+    }
+    VIR_FREE(nodes);
+    VIR_FREE(uuid);
+    virStringFreeList(searchTabResult);
+    return snapshot;
+}
+
+virVBoxSnapshotConfSnapshotPtr
+virVBoxSnapshotConfSnapshotByName(virVBoxSnapshotConfSnapshotPtr snapshot,
+                                  const char *snapshotName)
+{
+    size_t i = 0;
+    virVBoxSnapshotConfSnapshotPtr ret = NULL;
+    if (STREQ(snapshot->name, snapshotName))
+        return snapshot;
+    for (i = 0; i < snapshot->nchildren; i++) {
+        ret = virVBoxSnapshotConfSnapshotByName(snapshot->children[i], snapshotName);
+        if (ret != NULL)
+            return ret;
+    }
+    return ret;
+}
+
+static virVBoxSnapshotConfHardDiskPtr
+virVBoxSnapshotConfHardDiskById(virVBoxSnapshotConfHardDiskPtr disk,
+                                const char *parentHardDiskId)
+{
+    size_t i = 0;
+    virVBoxSnapshotConfHardDiskPtr ret = NULL;
+    if (STREQ(disk->uuid, parentHardDiskId))
+        return disk;
+    for (i = 0; i < disk->nchildren; i++) {
+        ret = virVBoxSnapshotConfHardDiskById(disk->children[i], parentHardDiskId);
+        if (ret != NULL)
+            return ret;
+    }
+    return ret;
+}
+
+static virVBoxSnapshotConfHardDiskPtr
+virVBoxSnapshotConfHardDiskByLocation(virVBoxSnapshotConfHardDiskPtr disk,
+                                      const char *parentLocation)
+{
+    size_t i = 0;
+    virVBoxSnapshotConfHardDiskPtr ret = NULL;
+    if (STREQ(disk->location, parentLocation))
+        return disk;
+    for (i = 0; i < disk->nchildren; i++) {
+        ret = virVBoxSnapshotConfHardDiskByLocation(disk->children[i], parentLocation);
+        if (ret != NULL)
+            return ret;
+    }
+    return ret;
+}
+
+static xmlNodePtr
+virVBoxSnapshotConfCreateHardDiskNode(virVBoxSnapshotConfHardDiskPtr hardDisk)
+{
+    int result = -1;
+    size_t i = 0;
+    char *uuid = NULL;
+    xmlNodePtr ret = xmlNewNode(NULL, BAD_CAST "HardDisk");
+    if (virAsprintf(&uuid, "{%s}", hardDisk->uuid) < 0)
+        goto cleanup;
+
+    if (xmlNewProp(ret, BAD_CAST "uuid", BAD_CAST uuid) == NULL)
+        goto cleanup;
+    if (xmlNewProp(ret, BAD_CAST "location", BAD_CAST hardDisk->location) == NULL)
+        goto cleanup;
+    if (xmlNewProp(ret, BAD_CAST "format", BAD_CAST hardDisk->format) == NULL)
+        goto cleanup;
+    if (hardDisk->type != NULL && xmlNewProp(ret, BAD_CAST "type", BAD_CAST hardDisk->type) == NULL)
+        goto cleanup;
+
+    for (i = 0; i < hardDisk->nchildren; i++) {
+        xmlNodePtr child = virVBoxSnapshotConfCreateHardDiskNode(hardDisk->children[i]);
+        if (child != NULL)
+            xmlAddChild(ret, child);
+    }
+
+    result = 0;
+ cleanup:
+    if (result < 0) {
+        xmlUnlinkNode(ret);
+        xmlFreeNode(ret);
+    }
+    VIR_FREE(uuid);
+    return ret;
+}
+
+static int
+virVBoxSnapshotConfSerializeSnapshot(xmlNodePtr node,
+                                     virVBoxSnapshotConfSnapshotPtr snapshot)
+{
+    int result = -1;
+    size_t i = 0;
+    xmlNodePtr descriptionNode = NULL;
+    xmlNodePtr snapshotsNode = NULL;
+    xmlNodePtr hardwareNode = NULL;
+    xmlNodePtr storageControllerNode = NULL;
+    xmlParserErrors parseError = XML_ERR_OK;
+    char *uuid = NULL;
+    char *timeStamp = NULL;
+
+    char **firstRegex = NULL;
+    int firstRegexResult = 0;
+    char **secondRegex = NULL;
+    int secondRegexResult = 0;
+
+    if (virAsprintf(&uuid, "{%s}", snapshot->uuid) < 0)
+        goto cleanup;
+
+    if (xmlNewProp(node, BAD_CAST "uuid", BAD_CAST uuid) == NULL)
+        goto cleanup;
+    if (xmlNewProp(node, BAD_CAST "name", BAD_CAST snapshot->name) == NULL)
+        goto cleanup;
+
+    /* We change the date format from "yyyy-MM-dd hh:mm:ss.msec+timeZone"
+     * to "yyyy-MM-ddThh:mm:ssZ"*/
+    firstRegexResult = virStringSearch(snapshot->timeStamp,
+                                       "([0-9]{4}-[0-9]{2}-[0-9]{2})",
+                                       1,
+                                       &firstRegex);
+    secondRegexResult = virStringSearch(snapshot->timeStamp,
+                                        "([0-9]{2}:[0-9]{2}:[0-9]{2})",
+                                        1,
+                                        &secondRegex);
+    if (firstRegexResult < 1)
+        goto cleanup;
+    if (secondRegexResult < 1)
+        goto cleanup;
+    if (virAsprintf(&timeStamp, "%sT%sZ", firstRegex[0], secondRegex[0]) < 0)
+        goto cleanup;
+
+    if (xmlNewProp(node, BAD_CAST "timeStamp", BAD_CAST timeStamp) == NULL)
+        goto cleanup;
+
+    /*node description*/
+    if (snapshot->description != NULL) {
+        descriptionNode = xmlNewNode(NULL, BAD_CAST "Description");
+        xmlNodeSetContent(descriptionNode, BAD_CAST snapshot->description);
+        xmlAddChild(node, descriptionNode);
+    }
+    /*hardware*/
+    parseError = xmlParseInNodeContext(node,
+                                       snapshot->hardware,
+                                       (int)strlen(snapshot->hardware),
+                                       0,
+                                       &hardwareNode);
+    if (parseError != XML_ERR_OK) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to add the snapshot hardware"));
+        goto cleanup;
+    }
+    xmlAddChild(node, hardwareNode);
+
+    /*storageController*/
+    if (xmlParseInNodeContext(node, snapshot->storageController,
+                              (int)strlen(snapshot->storageController),
+                              0,
+                              &storageControllerNode) != XML_ERR_OK) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to add the snapshot storageController"));
+        goto cleanup;
+    }
+    xmlAddChild(node, storageControllerNode);
+
+    if (snapshot->nchildren > 0) {
+        snapshotsNode = xmlNewNode(NULL, BAD_CAST "Snapshots");
+        xmlAddChild(node, snapshotsNode);
+        for (i = 0; i < snapshot->nchildren; i++) {
+            xmlNodePtr child = xmlNewNode(NULL, BAD_CAST "Snapshot");
+            xmlAddChild(snapshotsNode, child);
+            if (virVBoxSnapshotConfSerializeSnapshot(child, snapshot->children[i]) < 0) {
+                goto cleanup;
+            }
+        }
+    }
+    result = 0;
+
+ cleanup:
+    if (result < 0) {
+        xmlFreeNode(descriptionNode);
+        xmlUnlinkNode(snapshotsNode);
+        xmlFreeNode(snapshotsNode);
+    }
+    virStringFreeList(firstRegex);
+    virStringFreeList(secondRegex);
+    VIR_FREE(uuid);
+    VIR_FREE(timeStamp);
+    return result;
+}
+
+static size_t
+virVBoxSnapshotConfAllChildren(virVBoxSnapshotConfHardDiskPtr disk,
+                               virVBoxSnapshotConfHardDiskPtr **list)
+{
+    size_t returnSize = 0;
+    size_t tempSize = 0;
+    virVBoxSnapshotConfHardDiskPtr *ret = NULL;
+    virVBoxSnapshotConfHardDiskPtr *tempList = NULL;
+    size_t i = 0;
+    size_t j = 0;
+    if (VIR_ALLOC_N(ret, 0) < 0)
+        return 0;
+
+    for (i = 0; i < disk->nchildren; i++) {
+        tempSize = virVBoxSnapshotConfAllChildren(disk->children[i], &tempList);
+        if (VIR_EXPAND_N(ret, returnSize, tempSize) < 0)
+            return 0;
+
+        for (j = 0; j < tempSize; j++) {
+            ret[returnSize - tempSize + j] = tempList[j];
+        }
+    }
+    if (VIR_EXPAND_N(ret, returnSize, 1) < 0)
+        return 0;
+
+    ret[returnSize - 1] = disk;
+    *list = ret;
+    return returnSize;
+}
+
+void
+virVboxSnapshotConfHardDiskFree(virVBoxSnapshotConfHardDiskPtr disk)
+{
+    size_t i = 0;
+
+    if (!disk)
+        return;
+
+    VIR_FREE(disk->uuid);
+    VIR_FREE(disk->location);
+    VIR_FREE(disk->format);
+    VIR_FREE(disk->type);
+    for (i = 0; i < disk->nchildren; i++)
+        virVboxSnapshotConfHardDiskFree(disk->children[i]);
+    VIR_FREE(disk->children);
+    VIR_FREE(disk);
+}
+
+
+void
+virVBoxSnapshotConfMediaRegistryFree(virVBoxSnapshotConfMediaRegistryPtr mediaRegistry)
+{
+    size_t i = 0;
+
+    if (!mediaRegistry)
+        return;
+
+    for (i = 0; i < mediaRegistry->ndisks; i++)
+        virVboxSnapshotConfHardDiskFree(mediaRegistry->disks[i]);
+    VIR_FREE(mediaRegistry->disks);
+    for (i = 0; i < mediaRegistry->notherMedia; i++)
+        VIR_FREE(mediaRegistry->otherMedia[i]);
+    VIR_FREE(mediaRegistry->otherMedia);
+    VIR_FREE(mediaRegistry);
+}
+
+void
+virVBoxSnapshotConfSnapshotFree(virVBoxSnapshotConfSnapshotPtr snapshot)
+{
+    size_t i = 0;
+
+    if (!snapshot)
+        return;
+
+    VIR_FREE(snapshot->uuid);
+    VIR_FREE(snapshot->name);
+    VIR_FREE(snapshot->timeStamp);
+    VIR_FREE(snapshot->description);
+    VIR_FREE(snapshot->hardware);
+    VIR_FREE(snapshot->storageController);
+    for (i = 0; i < snapshot->nchildren; i++)
+        virVBoxSnapshotConfSnapshotFree(snapshot->children[i]);
+    VIR_FREE(snapshot->children);
+    VIR_FREE(snapshot);
+}
+
+void
+virVBoxSnapshotConfMachineFree(virVBoxSnapshotConfMachinePtr machine)
+{
+    if (!machine)
+        return;
+
+    VIR_FREE(machine->uuid);
+    VIR_FREE(machine->name);
+    VIR_FREE(machine->currentSnapshot);
+    VIR_FREE(machine->snapshotFolder);
+    VIR_FREE(machine->lastStateChange);
+    virVBoxSnapshotConfMediaRegistryFree(machine->mediaRegistry);
+    VIR_FREE(machine->hardware);
+    VIR_FREE(machine->extraData);
+    virVBoxSnapshotConfSnapshotFree(machine->snapshot);
+    VIR_FREE(machine->storageController);
+    VIR_FREE(machine);
+}
+
+/*
+ *vboxSnapshotLoadVboxFile: Create a vboxSnapshotXmlMachinePtr from a VirtualBoxl xml file.
+ *return an initialized vboxSnapshotXmlMachinePtr on success
+ *return NULL on failure
+ *filePath must not be NULL.
+ */
+virVBoxSnapshotConfMachinePtr
+virVBoxSnapshotConfLoadVboxFile(const char *filePath,
+                                const char *machineLocation)
+{
+    int ret = -1;
+    virVBoxSnapshotConfMachinePtr machineDescription = NULL;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr machineNode = NULL;
+    xmlNodePtr cur = NULL;
+    xmlXPathContextPtr xPathContext = NULL;
+    char *currentStateModifiedString = NULL;
+
+    char **searchResultTab = NULL;
+    ssize_t searchResultSize = 0;
+    char *currentSnapshotAttribute = NULL;
+
+    if (filePath == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Filepath is Null"));
+        goto cleanup;
+    }
+
+    if (VIR_ALLOC(machineDescription) < 0)
+        goto cleanup;
+
+    xml = virXMLParse(filePath, NULL, NULL);
+    if (xml == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to parse the xml"));
+        goto cleanup;
+    }
+    if (!(xPathContext = xmlXPathNewContext(xml))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    if (xmlXPathRegisterNs(xPathContext,
+                           BAD_CAST "vbox",
+                           BAD_CAST "http://www.innotek.de/VirtualBox-settings") < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Failed to register xml namespace "
+                         "'http://www.innotek.de/VirtualBox-settings'"));
+        goto cleanup;
+    }
+
+    /*Retrieve MachineNode*/
+    cur = xmlDocGetRootElement(xml);
+    xPathContext->node = cur;
+    machineNode = virXPathNode("./vbox:Machine", xPathContext);
+    if (machineNode == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <VirtualBox> <Machine> node"));
+        goto cleanup;
+    }
+
+    machineDescription->uuid = virXMLPropString(machineNode, "uuid");
+    if (machineDescription->uuid == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> 'uuid' attribute"));
+        goto cleanup;
+    }
+    machineDescription->name = virXMLPropString(machineNode, "name");
+    if (machineDescription->name == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> 'name' attribute"));
+        goto cleanup;
+    }
+
+    currentSnapshotAttribute = virXMLPropString(machineNode, "currentSnapshot");
+    if (currentSnapshotAttribute != NULL) {
+        /*we use virStringSearch because the uuid is between brackets*/
+        searchResultSize = virStringSearch(currentSnapshotAttribute,
+                                           VBOX_UUID_REGEX,
+                                           1,
+                                           &searchResultTab);
+        if (searchResultSize != 1) {
+            virReportError(VIR_ERR_XML_ERROR, "%s"
+                           , _("Cannot parse <Machine> 'currentSnapshot' attribute"));
+            goto cleanup;
+        }
+        if (VIR_STRDUP(machineDescription->currentSnapshot, searchResultTab[0]) < 0)
+            goto cleanup;
+    }
+
+    machineDescription->snapshotFolder = virXMLPropString(machineNode, "snapshotFolder");
+    if (machineDescription->snapshotFolder == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> 'snapshotFolder' attribute"));
+        goto cleanup;
+    }
+
+    currentStateModifiedString = virXMLPropString(machineNode, "currentStateModified");
+    if (currentStateModifiedString != NULL && STREQ(currentStateModifiedString, "true")) {
+        machineDescription->currentStateModified = 1;
+    } else {
+        machineDescription->currentStateModified = 0;
+    }
+    machineDescription->lastStateChange = virXMLPropString(machineNode, "lastStateChange");
+    if (machineDescription->lastStateChange == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> 'lastStateChange' attribute"));
+        goto cleanup;
+    }
+
+    xPathContext->node = machineNode;
+    cur = virXPathNode("./vbox:Hardware", xPathContext);
+    if (cur == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> <Hardware> node"));
+        goto cleanup;
+    }
+    machineDescription->hardware = virXMLNodeToString(xml, cur);
+
+    cur = virXPathNode("./vbox:ExtraData", xPathContext);
+    if (cur)
+        machineDescription->extraData = virXMLNodeToString(xml, cur);
+
+    cur = virXPathNode("./vbox:StorageControllers", xPathContext);
+    if (cur == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> <StorageControllers> node"));
+        goto cleanup;
+    }
+    machineDescription->storageController = virXMLNodeToString(xml, cur);
+
+    /*retrieve mediaRegistry*/
+    cur = virXPathNode("./vbox:MediaRegistry", xPathContext);
+    if (cur == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s"
+                       , _("Cannot parse <Machine> <MediaRegistry> node"));
+        goto cleanup;
+    }
+    machineDescription->mediaRegistry = virVBoxSnapshotConfRetrieveMediaRegistry(cur, xPathContext, machineLocation);
+    if (machineDescription->mediaRegistry == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       ("Unable to create media registry"));
+        goto cleanup;
+    }
+
+    /*retrieve snapshot*/
+    xPathContext->node = machineNode;
+    cur = virXPathNode("./vbox:Snapshot", xPathContext);
+    if (cur != NULL) {
+        machineDescription->snapshot = virVBoxSnapshotConfRetrieveSnapshot(cur, xPathContext);
+        if (!machineDescription->snapshot)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    xmlXPathFreeContext(xPathContext);
+    xmlFreeDoc(xml);
+
+    VIR_FREE(currentStateModifiedString);
+    VIR_FREE(currentSnapshotAttribute);
+    virStringFreeList(searchResultTab);
+    if (ret < 0) {
+        virVBoxSnapshotConfMachineFree(machineDescription);
+        machineDescription = NULL;
+    }
+    return machineDescription;
+}
+
+/*
+ *addSnapshotToXmlMachine: Add a vboxSnapshotXmlSnapshotPtr to a vboxSnapshotXmlMachinePtr.
+ *If 'snapshotParentName' is not NULL, the snapshot whose name is 'snapshotParentName'
+ *becomes the snapshot parent.
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfAddSnapshotToXmlMachine(virVBoxSnapshotConfSnapshotPtr snapshot,
+                                           virVBoxSnapshotConfMachinePtr machine,
+                                           const char *snapshotParentName)
+{
+    int ret = -1;
+    virVBoxSnapshotConfSnapshotPtr parentSnapshot = NULL;
+
+    if (snapshot == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Snapshot is Null"));
+        goto cleanup;
+    }
+    if (machine == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Machine is Null"));
+        goto cleanup;
+    }
+
+    /*If parent is NULL and the machine has no snapshot yet,
+     *it means that the added snapshot is the first snapshot*/
+    if (snapshotParentName == NULL) {
+        if (machine->snapshot != NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Unable to add this snapshot, there is already a snapshot "
+                             "linked to the machine"));
+            goto cleanup;
+        }
+        machine->snapshot = snapshot;
+        ret = 0;
+        goto cleanup;
+    } else {
+        if (machine->snapshot == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("The machine has no snapshot and it should have it"));
+            goto cleanup;
+        }
+        parentSnapshot = virVBoxSnapshotConfSnapshotByName(machine->snapshot, snapshotParentName);
+        if (parentSnapshot == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unable to find the snapshot %s"), snapshotParentName);
+            goto cleanup;
+        }
+        if (VIR_EXPAND_N(parentSnapshot->children, parentSnapshot->nchildren, 1) < 0)
+            goto cleanup;
+
+        parentSnapshot->children[parentSnapshot->nchildren - 1] = snapshot;
+        ret = 0;
+    }
+
+ cleanup:
+    return ret;
+}
+
+/*
+ *addHardDisksToMediaRegistry: Add a vboxSnapshotXmlHardDiskPtr to the registry as a
+ *child of the disk whose uuid is 'parentHardDiskId'.
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfAddHardDiskToMediaRegistry(virVBoxSnapshotConfHardDiskPtr hardDisk,
+                                              virVBoxSnapshotConfMediaRegistryPtr mediaRegistry,
+                                              const char *parentHardDiskId)
+{
+    int ret = -1;
+    size_t i = 0;
+    virVBoxSnapshotConfHardDiskPtr parentDisk = NULL;
+    if (hardDisk == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Hard disk is null"));
+        goto cleanup;
+    }
+    if (mediaRegistry == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Media Registry is null"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < mediaRegistry->ndisks; i++) {
+        parentDisk = virVBoxSnapshotConfHardDiskById(mediaRegistry->disks[i], parentHardDiskId);
+        if (parentDisk != NULL)
+            break;
+    }
+    if (parentDisk == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Unable to get the parent disk"));
+        goto cleanup;
+    }
+    /*Hard disk found*/
+    if (VIR_EXPAND_N(parentDisk->children, parentDisk->nchildren, 1) < 0)
+        goto cleanup;
+
+    parentDisk->children[parentDisk->nchildren - 1] = hardDisk;
+    if (hardDisk->parent == NULL) {
+        hardDisk->parent = parentDisk;
+    }
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+/*
+ *removeSnapshot: Remove the vboxSnapshotXmlSnapshotPtr whose name is 'snapshotName'
+ *from a vboxSnapshotXmlMachinePtr.
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfRemoveSnapshot(virVBoxSnapshotConfMachinePtr machine,
+                                  const char *snapshotName)
+{
+    int ret = -1;
+    size_t i = 0;
+    virVBoxSnapshotConfSnapshotPtr snapshot = NULL;
+    virVBoxSnapshotConfSnapshotPtr parentSnapshot = NULL;
+    if (machine == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("machine is null"));
+        goto cleanup;
+    }
+    if (snapshotName == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("snapshotName is null"));
+        goto cleanup;
+    }
+    if (machine->snapshot == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("the machine has no snapshot"));
+        goto cleanup;
+    }
+    snapshot = virVBoxSnapshotConfSnapshotByName(machine->snapshot, snapshotName);
+    if (snapshot == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to find the snapshot with name %s"), snapshotName);
+        goto cleanup;
+    }
+    if (snapshot->nchildren > 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("This snapshot has children, "
+                         "please delete theses snapshots before"));
+        goto cleanup;
+    }
+
+    if (snapshot->parent == NULL) {
+        if (machine->snapshot != snapshot) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("You are trying to remove a snapshot which does not exists"));
+            goto cleanup;
+        }
+        machine->snapshot = NULL;
+        virVBoxSnapshotConfSnapshotFree(snapshot);
+        ret = 0;
+        goto cleanup;
+    }
+    parentSnapshot = snapshot->parent;
+
+    snapshot->parent = NULL;
+    while (i < parentSnapshot->nchildren && parentSnapshot->children[i] != snapshot) {
+        ++i;
+    }
+    if (VIR_DELETE_ELEMENT(parentSnapshot->children, i, parentSnapshot->nchildren) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+/*
+ *removeHardDisk: Remove the vboxSnapshotXmlHardDiskPtr whose uuid is 'uuid' from a
+ *vboxSnapshotXmlMediaRegistryPtr. The hard disk must not have any children.
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfRemoveHardDisk(virVBoxSnapshotConfMediaRegistryPtr mediaRegistry,
+                                  const char *uuid)
+{
+    int ret = -1;
+    size_t i = 0;
+    virVBoxSnapshotConfHardDiskPtr hardDisk = NULL;
+    virVBoxSnapshotConfHardDiskPtr parentHardDisk = NULL;
+    if (mediaRegistry == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Media registry is null"));
+        goto cleanup;
+    }
+    if (uuid == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Uuid is null"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < mediaRegistry->ndisks; i++) {
+        hardDisk = virVBoxSnapshotConfHardDiskById(mediaRegistry->disks[i], uuid);
+        if (hardDisk != NULL)
+            break;
+    }
+    if (hardDisk == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to find the hard disk with uuid %s"), uuid);
+        goto cleanup;
+    }
+    if (hardDisk->parent == NULL) {
+        //it means that the hard disk is in 'root'
+        for (i = 0; i < mediaRegistry->ndisks; i++) {
+            if (hardDisk == mediaRegistry->disks[i])
+                break;
+        }
+        if (VIR_DELETE_ELEMENT(mediaRegistry->disks, i, mediaRegistry->ndisks) < 0)
+            goto cleanup;
+        ret = 0;
+        goto cleanup;
+    }
+
+    parentHardDisk = hardDisk->parent;
+    i = 0;
+    while (i < parentHardDisk->nchildren && parentHardDisk->children[i] != hardDisk) {
+        ++i;
+    }
+    hardDisk->parent = NULL;
+    if (VIR_DELETE_ELEMENT(parentHardDisk->children, i, parentHardDisk->nchildren) < 0)
+        goto cleanup;
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+/*vboxSnapshotSaveVboxFile: Create a VirtualBox XML file from a vboxSnapshotXmlMachinePtr.
+ *The file is saved at 'filePath'.
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfSaveVboxFile(virVBoxSnapshotConfMachinePtr machine,
+                                const char *filePath)
+{
+    int ret = -1;
+    size_t i = 0;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr mediaRegistryNode = NULL;
+    xmlNodePtr snapshotNode = NULL;
+    xmlNodePtr machineNode = NULL;
+    xmlNodePtr hardDisksNode = NULL;
+    xmlNodePtr cur = NULL;
+    xmlParserErrors parseError = XML_ERR_OK;
+    char *currentSnapshot = NULL;
+    char *timeStamp = NULL;
+
+    char **firstRegex = NULL;
+    int firstRegexResult = 0;
+    char **secondRegex = NULL;
+    int secondRegexResult = 0;
+
+    if (machine == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Machine is null"));
+        goto cleanup;
+    }
+    if (filePath == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Filepath is null"));
+        goto cleanup;
+    }
+    xml = xmlNewDoc(BAD_CAST "1.0");
+    if (!xml) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    cur = xmlNewNode(NULL, BAD_CAST "VirtualBox");
+    if (!cur) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (!xmlNewProp(cur, BAD_CAST "version", BAD_CAST "1.12-linux")) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+    if (xmlNewProp(cur,
+                   BAD_CAST "xmlns",
+                   BAD_CAST "http://www.innotek.de/VirtualBox-settings") == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+
+    xmlDocSetRootElement(xml, cur);
+
+    cur = xmlNewDocComment(xml,
+                           BAD_CAST "WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE\n"
+                           "OVERWRITTEN AND LOST.\n"
+                           "Changes to this xml configuration should be made using Virtualbox\n"
+                           "or other application using the libvirt API");
+    if (!cur) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (!xmlAddPrevSibling(xmlDocGetRootElement(xml), cur)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlAddPrevSibling"));
+        goto cleanup;
+    }
+
+    machineNode = xmlNewNode(NULL, BAD_CAST "Machine");
+    if (!machineNode) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (!xmlNewProp(machineNode, BAD_CAST "uuid", BAD_CAST machine->uuid)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+    if (!xmlNewProp(machineNode, BAD_CAST "name", BAD_CAST machine->name)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+
+    if (machine->currentSnapshot != NULL) {
+        if (virAsprintf(&currentSnapshot, "{%s}", machine->currentSnapshot) < 0)
+            goto cleanup;
+        if (!xmlNewProp(machineNode, BAD_CAST "currentSnapshot", BAD_CAST currentSnapshot)) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Error in xmlNewProp"));
+            goto cleanup;
+        }
+    }
+    if (!xmlNewProp(machineNode, BAD_CAST "snapshotFolder", BAD_CAST machine->snapshotFolder)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+    if (!xmlNewProp(machineNode, BAD_CAST "currentStateModified",
+               BAD_CAST(machine->currentStateModified == 0 ? "false" : "true"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+    if (!xmlNewProp(machineNode, BAD_CAST "OSType", BAD_CAST "Other")) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+
+    firstRegexResult = virStringSearch(machine->lastStateChange,
+                                       "([0-9]{4}-[0-9]{2}-[0-9]{2})",
+                                       1,
+                                       &firstRegex);
+    secondRegexResult = virStringSearch(machine->lastStateChange,
+                                        "([0-9]{2}:[0-9]{2}:[0-9]{2})",
+                                        1,
+                                        &secondRegex);
+    if (firstRegexResult < 1)
+        goto cleanup;
+    if (secondRegexResult < 1)
+        goto cleanup;
+
+    if (virAsprintf(&timeStamp, "%sT%sZ", firstRegex[0], secondRegex[0]) < 0)
+        goto cleanup;
+    if (!xmlNewProp(machineNode, BAD_CAST "lastStateChange", BAD_CAST timeStamp)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Error in xmlNewProp"));
+        goto cleanup;
+    }
+    xmlAddChild(xmlDocGetRootElement(xml), machineNode);
+
+    mediaRegistryNode = xmlNewNode(NULL, BAD_CAST "MediaRegistry");
+    if (!mediaRegistryNode) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    xmlAddChild(machineNode, mediaRegistryNode);
+    for (i = 0; i < machine->mediaRegistry->notherMedia; i++) {
+        parseError = xmlParseInNodeContext(mediaRegistryNode,
+                              machine->mediaRegistry->otherMedia[i],
+                              (int)strlen(machine->mediaRegistry->otherMedia[i]),
+                              0,
+                              &cur);
+        if (parseError != XML_ERR_OK) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Unable to add media registry other media"));
+            goto cleanup;
+        }
+        xmlAddChild(mediaRegistryNode, cur);
+    }
+    hardDisksNode = xmlNewNode(NULL, BAD_CAST "HardDisks");
+    if (!hardDisksNode) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    for (i = 0; i < machine->mediaRegistry->ndisks; i++) {
+        xmlNodePtr child = virVBoxSnapshotConfCreateHardDiskNode(machine->mediaRegistry->disks[i]);
+        if (child != NULL)
+            xmlAddChild(hardDisksNode, child);
+    }
+    xmlAddChild(mediaRegistryNode, hardDisksNode);
+
+    parseError = xmlParseInNodeContext(machineNode,
+                                       machine->hardware,
+                                       (int)strlen(machine->hardware),
+                                       0,
+                                       &cur);
+    if (parseError != XML_ERR_OK) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to add hardware machine"));
+        goto cleanup;
+    }
+    xmlAddChild(machineNode, cur);
+
+    if (machine->extraData != NULL) {
+        parseError = xmlParseInNodeContext(xmlDocGetRootElement(xml),
+                                           machine->extraData,
+                                           (int)strlen(machine->extraData),
+                                           0,
+                                           &cur);
+        if (parseError != XML_ERR_OK) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Unable to add extra data"));
+            goto cleanup;
+        }
+        xmlAddChild(machineNode, cur);
+    }
+
+    parseError = xmlParseInNodeContext(machineNode,
+                                       machine->storageController,
+                                       (int)strlen(machine->storageController),
+                                       0,
+                                       &cur);
+    if (parseError != XML_ERR_OK) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to add storage controller"));
+        goto cleanup;
+    }
+    xmlAddChild(machineNode, cur);
+
+    if (machine->snapshot != NULL) {
+        snapshotNode = xmlNewNode(NULL, BAD_CAST "Snapshot");
+        xmlAddChild(machineNode, snapshotNode);
+        if (virVBoxSnapshotConfSerializeSnapshot(snapshotNode, machine->snapshot) < 0) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Failed to serialize snapshot"));
+            goto cleanup;
+        }
+    }
+
+    if (xmlSaveFormatFileEnc(filePath, xml, "ISO-8859-1", -1) < 0) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to save the xml"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(currentSnapshot);
+    VIR_FREE(timeStamp);
+
+    xmlUnlinkNode(hardDisksNode);
+    xmlFreeNode(hardDisksNode);
+
+    xmlUnlinkNode(mediaRegistryNode);
+    xmlFreeNode(mediaRegistryNode);
+
+    xmlUnlinkNode(snapshotNode);
+    xmlFreeNode(snapshotNode);
+
+    xmlUnlinkNode(cur);
+    xmlFreeNode(cur);
+
+    xmlUnlinkNode(machineNode);
+    xmlFreeNode(machineNode);
+
+    xmlFreeDoc(xml);
+
+    virStringFreeList(firstRegex);
+    virStringFreeList(secondRegex);
+    return ret;
+}
+
+/*
+ *isCurrentSnapshot: Return 1 if 'snapshotName' corresponds to the
+ *vboxSnapshotXmlMachinePtr's current snapshot, return 0 otherwise.
+ */
+int
+virVBoxSnapshotConfIsCurrentSnapshot(virVBoxSnapshotConfMachinePtr machine,
+                                     const char *snapshotName)
+{
+    virVBoxSnapshotConfSnapshotPtr snapshot = NULL;
+    if (machine == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Machine is null"));
+        goto cleanup;
+    }
+    if (snapshotName == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("snapshotName is null"));
+        goto cleanup;
+    }
+    snapshot = virVBoxSnapshotConfSnapshotByName(machine->snapshot, snapshotName);
+    return STREQ(snapshot->uuid, machine->currentSnapshot);
+
+ cleanup:
+    return 0;
+}
+
+/*
+ *getRWDisksPathsFromLibvirtXML: Parse a libvirt XML snapshot file, allocates and
+ *fills a list of read-write disk paths.
+ *return array length on success, -1 on failure.
+ */
+int
+virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(const char *filePath,
+                                                 char ***rwDisksPath)
+{
+    int result = -1;
+    size_t i = 0;
+    char **ret;
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr xPathContext = NULL;
+    xmlNodePtr *nodes = NULL;
+    int nodeSize = 0;
+    *rwDisksPath = NULL;
+    if (filePath == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("filePath is null"));
+        goto cleanup;
+    }
+    xml = virXMLParse(filePath, NULL, NULL);
+    if (xml == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to parse the xml"));
+        goto cleanup;
+    }
+    if (!(xPathContext = xmlXPathNewContext(xml))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    xPathContext->node = xmlDocGetRootElement(xml);
+    nodeSize = virXPathNodeSet("/domainsnapshot/disks/disk", xPathContext, &nodes);
+
+    if (VIR_ALLOC_N(ret, nodeSize) < 0)
+        goto cleanup;
+
+    for (i = 0; i < nodeSize; i++) {
+        xmlNodePtr node = nodes[i];
+        xPathContext->node = node;
+        xmlNodePtr sourceNode = virXPathNode("./source", xPathContext);
+        if (sourceNode) {
+            ret[i] = virXMLPropString(sourceNode, "file");
+        }
+    }
+    result = 0;
+
+ cleanup:
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(xPathContext);
+    if (result < 0) {
+        for (i = 0; i < nodeSize; i++)
+            VIR_FREE(ret[i]);
+        VIR_FREE(ret);
+        nodeSize = -1;
+    } else {
+        *rwDisksPath = ret;
+    }
+    return nodeSize;
+}
+
+/*
+ *getRODisksPathsFromLibvirtXML: *Parse a libvirt XML snapshot file, allocates and fills
+ *a list of read-only disk paths (the parents of the read-write disks).
+ *return array length on success, -1 on failure.
+ */
+int
+virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(const char *filePath,
+                                                 char ***roDisksPath)
+{
+    int result = -1;
+    size_t i = 0;
+    char **ret;
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr xPathContext = NULL;
+    xmlNodePtr *nodes = NULL;
+    int nodeSize = 0;
+    if (filePath == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("filePath is null"));
+        goto cleanup;
+    }
+    xml = virXMLParse(filePath, NULL, NULL);
+    if (xml == NULL) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Unable to parse the xml"));
+        goto cleanup;
+    }
+    if (!(xPathContext = xmlXPathNewContext(xml))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    xPathContext->node = xmlDocGetRootElement(xml);
+    nodeSize = virXPathNodeSet("/domainsnapshot/domain/devices/disk",
+                               xPathContext,
+                               &nodes);
+    if (VIR_ALLOC_N(ret, nodeSize) < 0)
+        goto cleanup;
+
+    for (i = 0; i < nodeSize; i++) {
+        xmlNodePtr node = nodes[i];
+        xPathContext->node = node;
+        xmlNodePtr sourceNode = virXPathNode("./source", xPathContext);
+        if (sourceNode) {
+            ret[i] = virXMLPropString(sourceNode, "file");
+        }
+    }
+    result = 0;
+
+ cleanup:
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(xPathContext);
+    if (result < 0) {
+        virStringFreeList(ret);
+        nodeSize = -1;
+    }
+    *roDisksPath = ret;
+    return nodeSize;
+}
+
+/*
+ *hardDiskUuidByLocation: Return the uuid of the hard disk whose location is 'location'
+ *return a valid uuid, or NULL on failure
+ */
+const char *
+virVBoxSnapshotConfHardDiskUuidByLocation(virVBoxSnapshotConfMachinePtr machine,
+                                          const char *location)
+{
+    size_t i = 0;
+    virVBoxSnapshotConfHardDiskPtr hardDisk = NULL;
+    for (i = 0; i < machine->mediaRegistry->ndisks; i++) {
+        hardDisk = virVBoxSnapshotConfHardDiskByLocation(machine->mediaRegistry->disks[i], location);
+        if (hardDisk != NULL)
+            break;
+    }
+    if (hardDisk == NULL)
+        return NULL;
+    return hardDisk->uuid;
+}
+
+/*Retreive the whole ancestry of the vboxSnapshotXmlHardDiskPtr whose location is
+ *'location', and store them in a newly allocated list of vboxSnapshotXmlHardDiskPtr.
+ *This list begins with the requested disk, and ends with the farthest ancestor.
+ *return array length on success, -1 on failure.*/
+
+size_t
+virVBoxSnapshotConfDiskListToOpen(virVBoxSnapshotConfMachinePtr machine,
+                                  virVBoxSnapshotConfHardDiskPtr **hardDiskToOpen,
+                                  const char *location)
+{
+    size_t i = 0;
+    size_t returnSize = 0;
+    virVBoxSnapshotConfHardDiskPtr *ret = NULL;
+    virVBoxSnapshotConfHardDiskPtr hardDisk = NULL;
+    for (i = 0; i < machine->mediaRegistry->ndisks; i++) {
+        hardDisk = virVBoxSnapshotConfHardDiskByLocation(machine->mediaRegistry->disks[i], location);
+        if (hardDisk != NULL)
+            break;
+    }
+    if (hardDisk == NULL)
+        return 0;
+    if (VIR_ALLOC_N(ret, 1) < 0)
+        return 0;
+
+    returnSize = 1;
+    ret[returnSize - 1] = hardDisk;
+
+    while (hardDisk->parent != NULL) {
+        if (VIR_EXPAND_N(ret, returnSize, 1) < 0)
+            return 0;
+        ret[returnSize - 1] = hardDisk->parent;
+        hardDisk = hardDisk->parent;
+    }
+    *hardDiskToOpen = ret;
+    return returnSize;
+}
+
+/*
+ *removeFakeDisks: Remove all fake disks from the machine's mediaRegistry
+ *return 0 on success
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfRemoveFakeDisks(virVBoxSnapshotConfMachinePtr machine)
+{
+    int ret = -1;
+    size_t i = 0;
+    size_t j = 0;
+    size_t tempSize = 0;
+    size_t diskSize = 0;
+    virVBoxSnapshotConfHardDiskPtr *tempList = NULL;
+    virVBoxSnapshotConfHardDiskPtr *diskList = NULL;
+    if (VIR_ALLOC_N(diskList, 0) < 0)
+        return ret;
+
+    for (i = 0; i < machine->mediaRegistry->ndisks; i++) {
+        tempSize = virVBoxSnapshotConfAllChildren(machine->mediaRegistry->disks[i], &tempList);
+        if (VIR_EXPAND_N(diskList, diskSize, tempSize) < 0)
+            return ret;
+        for (j = 0; j < tempSize; j++) {
+            diskList[diskSize - tempSize + j] = tempList[j];
+        }
+    }
+    for (i = 0; i < diskSize; i++) {
+        if (strstr(diskList[i]->location, "fake") != NULL) {
+            if (virVBoxSnapshotConfRemoveHardDisk(machine->mediaRegistry, diskList[i]->uuid) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Unable to remove hard disk %s from media registry"),
+                               diskList[i]->location);
+                return ret;
+            }
+        }
+    }
+    ret = 0;
+    return ret;
+}
+
+/*
+ *diskIsInMediaRegistry: Check if the media registry contains the disk whose location is 'location'.
+ *return 0 if the disk is not in the media registry
+ *return 1 if the disk is in the media registry
+ *return -1 on failure
+ */
+int
+virVBoxSnapshotConfDiskIsInMediaRegistry(virVBoxSnapshotConfMachinePtr machine,
+                                         const char *location)
+{
+    int ret = -1;
+    size_t i = 0;
+    size_t j = 0;
+    size_t tempSize = 0;
+    size_t diskSize = 0;
+    virVBoxSnapshotConfHardDiskPtr *tempList = NULL;
+    virVBoxSnapshotConfHardDiskPtr *diskList = NULL;
+    if (VIR_ALLOC_N(diskList, 0) < 0)
+        return ret;
+
+    for (i = 0; i < machine->mediaRegistry->ndisks; i++) {
+        tempSize = virVBoxSnapshotConfAllChildren(machine->mediaRegistry->disks[i], &tempList);
+        if (VIR_EXPAND_N(diskList, diskSize, tempSize) < 0)
+            return ret;
+        for (j = 0; j < tempSize; j++) {
+            diskList[diskSize - tempSize + j] = tempList[j];
+        }
+    }
+    for (i = 0; i < diskSize; i++) {
+        if (STREQ(diskList[i]->location, location)) {
+            ret = 1;
+            return ret;
+        }
+    }
+    ret = 0;
+    return ret;
+}
+
+/*
+ *hardDisksPtrByLocation: Return a vboxSnapshotXmlHardDiskPtr whose location is 'location'
+ */
+virVBoxSnapshotConfHardDiskPtr
+virVBoxSnapshotConfHardDiskPtrByLocation(virVBoxSnapshotConfMachinePtr machine,
+                                         const char *location)
+{
+    int it = 0;
+    virVBoxSnapshotConfHardDiskPtr disk = NULL;
+    for (it = 0; it < machine->mediaRegistry->ndisks; it++) {
+        disk = virVBoxSnapshotConfHardDiskByLocation(machine->mediaRegistry->disks[it], location);
+        if (disk != NULL)
+            break;
+    }
+    return disk;
+}
diff --git a/src/vbox/vbox_snapshot_conf.h b/src/vbox/vbox_snapshot_conf.h
new file mode 100644 (file)
index 0000000..3864b30
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef VBOX_SNAPSHOT_CONF_H
+# define VBOX_SNAPSHOT_CONF_H
+
+# include "internal.h"
+
+# define VBOX_UUID_REGEX "([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})"
+
+/*Stores VirtualBox xml hard disk information
+A hard disk can have a parent and children*/
+typedef struct _virVBoxSnapshotConfHardDisk virVBoxSnapshotConfHardDisk;
+typedef virVBoxSnapshotConfHardDisk *virVBoxSnapshotConfHardDiskPtr;
+struct _virVBoxSnapshotConfHardDisk {
+    virVBoxSnapshotConfHardDiskPtr parent;
+    char *uuid;
+    char *location;
+    char *format;
+    char *type;
+    size_t nchildren;
+    virVBoxSnapshotConfHardDiskPtr *children;
+};
+
+/*Stores Virtualbox xml media registry information
+We separate disks from other media to manipulate them*/
+typedef struct _virVBoxSnapshotConfMediaRegistry virVBoxSnapshotConfMediaRegistry;
+typedef virVBoxSnapshotConfMediaRegistry *virVBoxSnapshotConfMediaRegistryPtr;
+struct _virVBoxSnapshotConfMediaRegistry {
+    size_t ndisks;
+    virVBoxSnapshotConfHardDiskPtr *disks;
+    size_t notherMedia;
+    char **otherMedia;
+};
+
+/*Stores VirtualBox xml snapshot information
+A snapshot can have a parent and children*/
+typedef struct _virVBoxSnapshotConfSnapshot virVBoxSnapshotConfSnapshot;
+typedef virVBoxSnapshotConfSnapshot *virVBoxSnapshotConfSnapshotPtr;
+struct _virVBoxSnapshotConfSnapshot {
+    virVBoxSnapshotConfSnapshotPtr parent;
+    char *uuid;
+    char *name;
+    char *timeStamp;
+    char *description;
+    char *hardware;
+    char *storageController;
+    size_t nchildren;
+    virVBoxSnapshotConfSnapshotPtr *children;
+};
+
+/*Stores VirtualBox xml Machine information*/
+typedef struct _virVBoxSnapshotConfMachine virVBoxSnapshotConfMachine;
+typedef virVBoxSnapshotConfMachine *virVBoxSnapshotConfMachinePtr;
+struct _virVBoxSnapshotConfMachine {
+    char *uuid;
+    char *name;
+    char *currentSnapshot;
+    char *snapshotFolder;
+    int currentStateModified;
+    char *lastStateChange;
+    virVBoxSnapshotConfMediaRegistryPtr mediaRegistry;
+    char *hardware;
+    char *extraData;
+    virVBoxSnapshotConfSnapshotPtr snapshot;
+    char *storageController;
+};
+
+void
+virVboxSnapshotConfHardDiskFree(virVBoxSnapshotConfHardDiskPtr disk);
+void
+virVBoxSnapshotConfMediaRegistryFree(virVBoxSnapshotConfMediaRegistryPtr mediaRegistry);
+void
+virVBoxSnapshotConfSnapshotFree(virVBoxSnapshotConfSnapshotPtr snapshot);
+void
+virVBoxSnapshotConfMachineFree(virVBoxSnapshotConfMachinePtr machine);
+
+virVBoxSnapshotConfMachinePtr
+virVBoxSnapshotConfLoadVboxFile(const char *filePath,
+                                const char *machineLocation);
+int
+virVBoxSnapshotConfAddSnapshotToXmlMachine(virVBoxSnapshotConfSnapshotPtr snapshot,
+                                           virVBoxSnapshotConfMachinePtr machine,
+                                           const char *snapshotParentName);
+int
+virVBoxSnapshotConfAddHardDiskToMediaRegistry(virVBoxSnapshotConfHardDiskPtr hardDisk,
+                                              virVBoxSnapshotConfMediaRegistryPtr mediaRegistry,
+                                              const char *parentHardDiskId);
+int
+virVBoxSnapshotConfRemoveSnapshot(virVBoxSnapshotConfMachinePtr machine,
+                                  const char *snapshotName);
+int
+virVBoxSnapshotConfRemoveHardDisk(virVBoxSnapshotConfMediaRegistryPtr mediaRegistry,
+                                  const char *uuid);
+int
+virVBoxSnapshotConfSaveVboxFile(virVBoxSnapshotConfMachinePtr machine,
+                                const char *filePath);
+int
+virVBoxSnapshotConfIsCurrentSnapshot(virVBoxSnapshotConfMachinePtr machine,
+                                     const char *snapshotName);
+int
+virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(const char *filePath,
+                                                 char ***realReadWriteDisksPath);
+int
+virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(const char *filePath,
+                                                 char ***realReadOnlyDisksPath);
+const char *
+virVBoxSnapshotConfHardDiskUuidByLocation(virVBoxSnapshotConfMachinePtr machine,
+                                          const char *location);
+size_t
+virVBoxSnapshotConfDiskListToOpen(virVBoxSnapshotConfMachinePtr machine,
+                                  virVBoxSnapshotConfHardDiskPtr **hardDiskToOpen,
+                                  const char *location);
+int
+virVBoxSnapshotConfRemoveFakeDisks(virVBoxSnapshotConfMachinePtr machine);
+int
+virVBoxSnapshotConfDiskIsInMediaRegistry(virVBoxSnapshotConfMachinePtr machine,
+                                         const char *location);
+virVBoxSnapshotConfHardDiskPtr
+virVBoxSnapshotConfHardDiskPtrByLocation(virVBoxSnapshotConfMachinePtr machine,
+                                         const char *location);
+virVBoxSnapshotConfSnapshotPtr
+virVBoxSnapshotConfSnapshotByName(virVBoxSnapshotConfSnapshotPtr snapshot,
+                                  const char *snapshotName);
+
+#endif /*VBOX_SNAPSHOT_CONF_H*/
index 9f4dff34a480612b27c265d0621261b937802a63..c99906158b11efcb7f49cbc1e4c765aee3df8c7d 100644 (file)
@@ -125,6 +125,7 @@ EXTRA_DIST =                \
        sysinfodata \
        test-lib.sh     \
        vircaps2xmldata \
+       vboxsnapshotxmldata \
        virsh-uriprecedence \
        virfiledata \
        virpcitestdata \
@@ -236,6 +237,10 @@ if WITH_ESX
 test_programs += esxutilstest
 endif WITH_ESX
 
+if WITH_VBOX
+test_programs += vboxsnapshotxmltest
+endif WITH_VBOX
+
 if WITH_VMX
 test_programs += vmx2xmltest xml2vmxtest
 endif WITH_VMX
@@ -619,6 +624,16 @@ else ! WITH_ESX
 EXTRA_DIST += esxutilstest.c
 endif ! WITH_ESX
 
+if WITH_VBOX
+vboxsnapshotxmltest_SOURCES = \
+       vboxsnapshotxmltest.c \
+       testutils.c testutils.h
+vbox_LDADDS = ../src/libvirt_driver_vbox_impl.la
+vboxsnapshotxmltest_LDADD = $(LDADDS) $(vbox_LDADDS)
+else ! WITH_VBOX
+EXTRA_DIST += vboxsnapshotxmltest.c
+endif ! WITH_VBOX
+
 if WITH_VMX
 vmx2xmltest_SOURCES = \
        vmx2xmltest.c \
diff --git a/tests/vboxsnapshotxmldata/2disks-1snap.vbox b/tests/vboxsnapshotxmldata/2disks-1snap.vbox
new file mode 100644 (file)
index 0000000..f80c5af
--- /dev/null
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+OVERWRITTEN AND LOST.
+Changes to this xml configuration should be made using Virtualbox
+or other application using the libvirt API-->
+<VirtualBox version="1.12-linux" xmlns="http://www.innotek.de/VirtualBox-settings">
+  <Machine uuid="{74864f52-a7b7-4172-a7a5-54b6f3e9cd21}" name="74864f52-a7b7-4172-a7a5-54b6f3e9cd21" currentSnapshot="{364c7314-b2d9-4fcf-b786-47b987449ef7}" snapshotFolder="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots" currentStateModified="false" OSType="Other" lastStateChange="2014-05-15T11:49:46Z">
+    <MediaRegistry>
+      <DVDImages/>
+      <FloppyImages/>
+      <HardDisks>
+        <HardDisk uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk1.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{a28723b5-8093-4548-bf87-e5fa4136f0a3}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-0.vdi" format="VDI"/>
+        </HardDisk>
+        <HardDisk uuid="{f113fdf8-9750-4557-a8be-87fd02319071}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk2.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{e1ff7f14-e6e5-40ac-8e05-8381a8ee5be9}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-1.vdi" format="VDI"/>
+        </HardDisk>
+      </HardDisks>
+    </MediaRegistry>
+    <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+    <ExtraData>
+      <ExtraDataItem name="FRONTEND/Type" value="vrdp"/>
+    </ExtraData>
+    <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{a28723b5-8093-4548-bf87-e5fa4136f0a3}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{e1ff7f14-e6e5-40ac-8e05-8381a8ee5be9}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+    <Snapshot uuid="{364c7314-b2d9-4fcf-b786-47b987449ef7}" name="15052014-115228" timeStamp="2014-05-15T09:52:29Z">
+      <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+      <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{f113fdf8-9750-4557-a8be-87fd02319071}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+    </Snapshot>
+  </Machine>
+</VirtualBox>
diff --git a/tests/vboxsnapshotxmldata/2disks-2snap.vbox b/tests/vboxsnapshotxmldata/2disks-2snap.vbox
new file mode 100644 (file)
index 0000000..8277937
--- /dev/null
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+OVERWRITTEN AND LOST.
+Changes to this xml configuration should be made using Virtualbox
+or other application using the libvirt API-->
+<VirtualBox version="1.12-linux" xmlns="http://www.innotek.de/VirtualBox-settings">
+  <Machine uuid="{74864f52-a7b7-4172-a7a5-54b6f3e9cd21}" name="74864f52-a7b7-4172-a7a5-54b6f3e9cd21" currentSnapshot="{94afa063-9281-4e15-b586-a5e1fc5e17bf}" snapshotFolder="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots" currentStateModified="false" OSType="Other" lastStateChange="2014-05-15T11:49:46Z">
+    <MediaRegistry>
+      <DVDImages/>
+      <FloppyImages/>
+      <HardDisks>
+        <HardDisk uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk1.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{de551924-a484-4f88-9897-c3c4986b8f75}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{de551924-a484-4f88-9897-c3c4986b8f75}.vdi" format="VDI">
+            <HardDisk uuid="{df6194b0-7eec-4b3c-a838-8323dd9075eb}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-0.vdi" format="VDI"/>
+          </HardDisk>
+        </HardDisk>
+        <HardDisk uuid="{f113fdf8-9750-4557-a8be-87fd02319071}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk2.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{72638d05-918a-43e8-9994-dcc9a3e2f2fe}.vdi" format="VDI">
+            <HardDisk uuid="{43fc566a-4c66-426b-9b43-3568fe653efd}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-1.vdi" format="VDI"/>
+          </HardDisk>
+        </HardDisk>
+      </HardDisks>
+    </MediaRegistry>
+    <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+    <ExtraData>
+      <ExtraDataItem name="FRONTEND/Type" value="vrdp"/>
+    </ExtraData>
+    <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{df6194b0-7eec-4b3c-a838-8323dd9075eb}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{43fc566a-4c66-426b-9b43-3568fe653efd}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+    <Snapshot uuid="{364c7314-b2d9-4fcf-b786-47b987449ef7}" name="15052014-115228" timeStamp="2014-05-15T09:52:29Z">
+      <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+      <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{f113fdf8-9750-4557-a8be-87fd02319071}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+      <Snapshots>
+        <Snapshot uuid="{94afa063-9281-4e15-b586-a5e1fc5e17bf}" name="15052014-115248" timeStamp="2014-05-15T09:52:49Z">
+          <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+          <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{de551924-a484-4f88-9897-c3c4986b8f75}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+        </Snapshot>
+      </Snapshots>
+    </Snapshot>
+  </Machine>
+</VirtualBox>
diff --git a/tests/vboxsnapshotxmldata/2disks-3snap-brother.vbox b/tests/vboxsnapshotxmldata/2disks-3snap-brother.vbox
new file mode 100644 (file)
index 0000000..b5472f9
--- /dev/null
@@ -0,0 +1,786 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+OVERWRITTEN AND LOST.
+Changes to this xml configuration should be made using Virtualbox
+or other application using the libvirt API-->
+<VirtualBox version="1.12-linux" xmlns="http://www.innotek.de/VirtualBox-settings">
+  <Machine uuid="{74864f52-a7b7-4172-a7a5-54b6f3e9cd21}" name="74864f52-a7b7-4172-a7a5-54b6f3e9cd21" currentSnapshot="{5d8b609b-f5af-4025-8aca-220480fa6394}" snapshotFolder="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots" currentStateModified="false" OSType="Other" lastStateChange="2014-05-15T11:49:46Z">
+    <MediaRegistry>
+      <DVDImages/>
+      <FloppyImages/>
+      <HardDisks>
+        <HardDisk uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk1.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{de551924-a484-4f88-9897-c3c4986b8f75}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{de551924-a484-4f88-9897-c3c4986b8f75}.vdi" format="VDI">
+            <HardDisk uuid="{55c4d273-380b-43c6-b394-b2636051cfc7}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{55c4d273-380b-43c6-b394-b2636051cfc7}.vdi" format="VDI"/>
+            <HardDisk uuid="{bf3ea5d4-fcb3-4cfe-b289-9d605fc94c3b}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{bf3ea5d4-fcb3-4cfe-b289-9d605fc94c3b}.vdi" format="VDI">
+              <HardDisk uuid="{f79158b5-258d-4afa-a0ad-2e7c113da30c}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{f79158b5-258d-4afa-a0ad-2e7c113da30c}.vdi" format="VDI"/>
+            </HardDisk>
+          </HardDisk>
+        </HardDisk>
+        <HardDisk uuid="{f113fdf8-9750-4557-a8be-87fd02319071}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk2.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{72638d05-918a-43e8-9994-dcc9a3e2f2fe}.vdi" format="VDI">
+            <HardDisk uuid="{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}.vdi" format="VDI"/>
+            <HardDisk uuid="{18394ad4-fad9-4cb7-9de9-7477a93aab08}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{18394ad4-fad9-4cb7-9de9-7477a93aab08}.vdi" format="VDI">
+              <HardDisk uuid="{71030c24-a668-41c6-be9c-7704d39e2618}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{71030c24-a668-41c6-be9c-7704d39e2618}.vdi" format="VDI"/>
+            </HardDisk>
+          </HardDisk>
+        </HardDisk>
+      </HardDisks>
+    </MediaRegistry>
+    <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" authTimeout="5000" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+    <ExtraData>
+      <ExtraDataItem name="FRONTEND/Type" value="vrdp"/>
+    </ExtraData>
+    <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{f79158b5-258d-4afa-a0ad-2e7c113da30c}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{71030c24-a668-41c6-be9c-7704d39e2618}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+    <Snapshot uuid="{364c7314-b2d9-4fcf-b786-47b987449ef7}" name="15052014-115228" timeStamp="2014-05-15T09:52:29Z">
+      <Hardware version="2">
+        <CPU count="1" hotplug="false">
+          <HardwareVirtEx enabled="true"/>
+          <HardwareVirtExNestedPaging enabled="true"/>
+          <HardwareVirtExVPID enabled="true"/>
+          <HardwareVirtExUX enabled="true"/>
+          <PAE enabled="false"/>
+          <LongMode enabled="true"/>
+          <HardwareVirtExLargePages enabled="false"/>
+          <HardwareVirtForce enabled="false"/>
+        </CPU>
+        <Memory RAMSize="192" PageFusion="false"/>
+        <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+        <HPET enabled="false"/>
+        <Chipset type="PIIX3"/>
+        <Boot>
+          <Order position="1" device="HardDisk"/>
+          <Order position="2" device="None"/>
+          <Order position="3" device="None"/>
+          <Order position="4" device="None"/>
+        </Boot>
+        <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+        <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+        <RemoteDisplay enabled="true" authType="Null" authTimeout="5000" allowMultiConnection="true">
+          <VRDEProperties>
+            <Property name="TCP/Ports" value="5900"/>
+          </VRDEProperties>
+        </RemoteDisplay>
+        <BIOS>
+          <ACPI enabled="true"/>
+          <IOAPIC enabled="true"/>
+          <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+          <BootMenu mode="MessageAndMenu"/>
+          <TimeOffset value="0"/>
+          <PXEDebug enabled="false"/>
+        </BIOS>
+        <USB>
+          <Controllers/>
+          <DeviceFilters/>
+        </USB>
+        <Network>
+          <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+              <InternalNetwork name="intnet"/>
+              <NATNetwork name="NatNetwork"/>
+            </DisabledModes>
+            <BridgedInterface name="hns0000000v"/>
+          </Adapter>
+          <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+          <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+            <DisabledModes>
+              <NAT>
+                <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+              </NAT>
+            </DisabledModes>
+          </Adapter>
+        </Network>
+        <UART>
+          <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+          <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        </UART>
+        <LPT>
+          <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+          <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+        </LPT>
+        <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+        <RTC localOrUTC="local"/>
+        <SharedFolders/>
+        <Clipboard mode="Disabled"/>
+        <DragAndDrop mode="Disabled"/>
+        <IO>
+          <IoCache enabled="true" size="5"/>
+          <BandwidthGroups/>
+        </IO>
+        <HostPci>
+          <Devices/>
+        </HostPci>
+        <EmulatedUSB>
+          <CardReader enabled="false"/>
+        </EmulatedUSB>
+        <Guest memoryBalloonSize="0"/>
+        <GuestProperties/>
+      </Hardware>
+      <StorageControllers>
+        <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+          <AttachedDevice type="HardDisk" port="0" device="0">
+            <Image uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}"/>
+          </AttachedDevice>
+          <AttachedDevice type="HardDisk" port="0" device="1">
+            <Image uuid="{f113fdf8-9750-4557-a8be-87fd02319071}"/>
+          </AttachedDevice>
+        </StorageController>
+        <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+        <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+        <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+      </StorageControllers>
+      <Snapshots>
+        <Snapshot uuid="{94afa063-9281-4e15-b586-a5e1fc5e17bf}" name="15052014-115248" timeStamp="2014-05-15T09:52:49Z">
+          <Hardware version="2">
+            <CPU count="1" hotplug="false">
+              <HardwareVirtEx enabled="true"/>
+              <HardwareVirtExNestedPaging enabled="true"/>
+              <HardwareVirtExVPID enabled="true"/>
+              <HardwareVirtExUX enabled="true"/>
+              <PAE enabled="false"/>
+              <LongMode enabled="true"/>
+              <HardwareVirtExLargePages enabled="false"/>
+              <HardwareVirtForce enabled="false"/>
+            </CPU>
+            <Memory RAMSize="192" PageFusion="false"/>
+            <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+            <HPET enabled="false"/>
+            <Chipset type="PIIX3"/>
+            <Boot>
+              <Order position="1" device="HardDisk"/>
+              <Order position="2" device="None"/>
+              <Order position="3" device="None"/>
+              <Order position="4" device="None"/>
+            </Boot>
+            <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+            <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+            <RemoteDisplay enabled="true" authType="Null" authTimeout="5000" allowMultiConnection="true">
+              <VRDEProperties>
+                <Property name="TCP/Ports" value="5900"/>
+              </VRDEProperties>
+            </RemoteDisplay>
+            <BIOS>
+              <ACPI enabled="true"/>
+              <IOAPIC enabled="true"/>
+              <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+              <BootMenu mode="MessageAndMenu"/>
+              <TimeOffset value="0"/>
+              <PXEDebug enabled="false"/>
+            </BIOS>
+            <USB>
+              <Controllers/>
+              <DeviceFilters/>
+            </USB>
+            <Network>
+              <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                  <InternalNetwork name="intnet"/>
+                  <NATNetwork name="NatNetwork"/>
+                </DisabledModes>
+                <BridgedInterface name="hns0000000v"/>
+              </Adapter>
+              <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+              <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+                <DisabledModes>
+                  <NAT>
+                    <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                    <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                  </NAT>
+                </DisabledModes>
+              </Adapter>
+            </Network>
+            <UART>
+              <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+              <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+            </UART>
+            <LPT>
+              <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+              <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+            </LPT>
+            <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+            <RTC localOrUTC="local"/>
+            <SharedFolders/>
+            <Clipboard mode="Disabled"/>
+            <DragAndDrop mode="Disabled"/>
+            <IO>
+              <IoCache enabled="true" size="5"/>
+              <BandwidthGroups/>
+            </IO>
+            <HostPci>
+              <Devices/>
+            </HostPci>
+            <EmulatedUSB>
+              <CardReader enabled="false"/>
+            </EmulatedUSB>
+            <Guest memoryBalloonSize="0"/>
+            <GuestProperties/>
+          </Hardware>
+          <StorageControllers>
+            <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+              <AttachedDevice type="HardDisk" port="0" device="0">
+                <Image uuid="{de551924-a484-4f88-9897-c3c4986b8f75}"/>
+              </AttachedDevice>
+              <AttachedDevice type="HardDisk" port="0" device="1">
+                <Image uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}"/>
+              </AttachedDevice>
+            </StorageController>
+            <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+            <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+            <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+          </StorageControllers>
+          <Snapshots>
+            <Snapshot uuid="{574d0edf-0f9d-47ef-82e3-1b6d2d54a537}" name="15052014-115306" timeStamp="2014-05-15T09:53:06Z">
+              <Hardware version="2">
+                <CPU count="1" hotplug="false">
+                  <HardwareVirtEx enabled="true"/>
+                  <HardwareVirtExNestedPaging enabled="true"/>
+                  <HardwareVirtExVPID enabled="true"/>
+                  <HardwareVirtExUX enabled="true"/>
+                  <PAE enabled="false"/>
+                  <LongMode enabled="true"/>
+                  <HardwareVirtExLargePages enabled="false"/>
+                  <HardwareVirtForce enabled="false"/>
+                </CPU>
+                <Memory RAMSize="192" PageFusion="false"/>
+                <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+                <HPET enabled="false"/>
+                <Chipset type="PIIX3"/>
+                <Boot>
+                  <Order position="1" device="HardDisk"/>
+                  <Order position="2" device="None"/>
+                  <Order position="3" device="None"/>
+                  <Order position="4" device="None"/>
+                </Boot>
+                <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+                <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+                <RemoteDisplay enabled="true" authType="Null" authTimeout="5000" allowMultiConnection="true">
+                  <VRDEProperties>
+                    <Property name="TCP/Ports" value="5900"/>
+                  </VRDEProperties>
+                </RemoteDisplay>
+                <BIOS>
+                  <ACPI enabled="true"/>
+                  <IOAPIC enabled="true"/>
+                  <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+                  <BootMenu mode="MessageAndMenu"/>
+                  <TimeOffset value="0"/>
+                  <PXEDebug enabled="false"/>
+                </BIOS>
+                <USB>
+                  <Controllers/>
+                  <DeviceFilters/>
+                </USB>
+                <Network>
+                  <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                      <InternalNetwork name="intnet"/>
+                      <NATNetwork name="NatNetwork"/>
+                    </DisabledModes>
+                    <BridgedInterface name="hns0000000v"/>
+                  </Adapter>
+                  <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                  <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+                    <DisabledModes>
+                      <NAT>
+                        <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+                        <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+                      </NAT>
+                    </DisabledModes>
+                  </Adapter>
+                </Network>
+                <UART>
+                  <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+                  <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+                </UART>
+                <LPT>
+                  <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+                  <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+                </LPT>
+                <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+                <RTC localOrUTC="local"/>
+                <SharedFolders/>
+                <Clipboard mode="Disabled"/>
+                <DragAndDrop mode="Disabled"/>
+                <IO>
+                  <IoCache enabled="true" size="5"/>
+                  <BandwidthGroups/>
+                </IO>
+                <HostPci>
+                  <Devices/>
+                </HostPci>
+                <EmulatedUSB>
+                  <CardReader enabled="false"/>
+                </EmulatedUSB>
+                <Guest memoryBalloonSize="0"/>
+                <GuestProperties/>
+              </Hardware>
+              <StorageControllers>
+                <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+                  <AttachedDevice type="HardDisk" port="0" device="0">
+                    <Image uuid="{55c4d273-380b-43c6-b394-b2636051cfc7}"/>
+                  </AttachedDevice>
+                  <AttachedDevice type="HardDisk" port="0" device="1">
+                    <Image uuid="{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}"/>
+                  </AttachedDevice>
+                </StorageController>
+                <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+                <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+                <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+              </StorageControllers>
+            </Snapshot>
+            <Snapshot uuid="{5d8b609b-f5af-4025-8aca-220480fa6394}" name="15052014-115334" timeStamp="2014-05-15T09:53:35Z">
+              <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" authTimeout="5000" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+              <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{bf3ea5d4-fcb3-4cfe-b289-9d605fc94c3b}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{18394ad4-fad9-4cb7-9de9-7477a93aab08}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+            </Snapshot>
+          </Snapshots>
+        </Snapshot>
+      </Snapshots>
+    </Snapshot>
+  </Machine>
+</VirtualBox>
diff --git a/tests/vboxsnapshotxmldata/2disks-3snap.vbox b/tests/vboxsnapshotxmldata/2disks-3snap.vbox
new file mode 100644 (file)
index 0000000..2fb6fe7
--- /dev/null
@@ -0,0 +1,636 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+OVERWRITTEN AND LOST.
+Changes to this xml configuration should be made using Virtualbox
+or other application using the libvirt API-->
+<VirtualBox version="1.12-linux" xmlns="http://www.innotek.de/VirtualBox-settings">
+  <Machine uuid="{74864f52-a7b7-4172-a7a5-54b6f3e9cd21}" name="74864f52-a7b7-4172-a7a5-54b6f3e9cd21" currentSnapshot="{574d0edf-0f9d-47ef-82e3-1b6d2d54a537}" snapshotFolder="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots" currentStateModified="false" OSType="Other" lastStateChange="2014-05-15T11:49:46Z">
+    <MediaRegistry>
+      <DVDImages/>
+      <FloppyImages/>
+      <HardDisks>
+        <HardDisk uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk1.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{de551924-a484-4f88-9897-c3c4986b8f75}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{de551924-a484-4f88-9897-c3c4986b8f75}.vdi" format="VDI">
+            <HardDisk uuid="{bf3ea5d4-fcb3-4cfe-b289-9d605fc94c3b}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{bf3ea5d4-fcb3-4cfe-b289-9d605fc94c3b}.vdi" format="VDI"/>
+            <HardDisk uuid="{55c4d273-380b-43c6-b394-b2636051cfc7}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{55c4d273-380b-43c6-b394-b2636051cfc7}.vdi" format="VDI">
+              <HardDisk uuid="{64c31740-9498-4c90-866b-650819686ef5}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-0.vdi" format="VDI"/>
+            </HardDisk>
+          </HardDisk>
+        </HardDisk>
+        <HardDisk uuid="{f113fdf8-9750-4557-a8be-87fd02319071}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk2.vdi" format="VDI" type="Normal">
+          <HardDisk uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{72638d05-918a-43e8-9994-dcc9a3e2f2fe}.vdi" format="VDI">
+            <HardDisk uuid="{18394ad4-fad9-4cb7-9de9-7477a93aab08}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{18394ad4-fad9-4cb7-9de9-7477a93aab08}.vdi" format="VDI"/>
+            <HardDisk uuid="{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots/{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}.vdi" format="VDI">
+              <HardDisk uuid="{ec8ccae3-adc5-4bfd-b381-5a5eca357699}" location="/root/VirtualBox VMs/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/fakedisk-1.vdi" format="VDI"/>
+            </HardDisk>
+          </HardDisk>
+        </HardDisk>
+      </HardDisks>
+    </MediaRegistry>
+    <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+    <ExtraData>
+      <ExtraDataItem name="FRONTEND/Type" value="vrdp"/>
+    </ExtraData>
+    <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{64c31740-9498-4c90-866b-650819686ef5}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{ec8ccae3-adc5-4bfd-b381-5a5eca357699}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+    <Snapshot uuid="{364c7314-b2d9-4fcf-b786-47b987449ef7}" name="15052014-115228" timeStamp="2014-05-15T09:52:29Z">
+      <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+      <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{f113fdf8-9750-4557-a8be-87fd02319071}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+      <Snapshots>
+        <Snapshot uuid="{94afa063-9281-4e15-b586-a5e1fc5e17bf}" name="15052014-115248" timeStamp="2014-05-15T09:52:49Z">
+          <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+          <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{de551924-a484-4f88-9897-c3c4986b8f75}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{72638d05-918a-43e8-9994-dcc9a3e2f2fe}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+          <Snapshots>
+            <Snapshot uuid="{574d0edf-0f9d-47ef-82e3-1b6d2d54a537}" name="15052014-115306" timeStamp="2014-05-15T09:53:06Z">
+              <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+              <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{55c4d273-380b-43c6-b394-b2636051cfc7}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{f9f1a347-e9b0-4ba3-bf5d-cfbccccf8c27}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+            </Snapshot>
+          </Snapshots>
+        </Snapshot>
+      </Snapshots>
+    </Snapshot>
+  </Machine>
+</VirtualBox>
diff --git a/tests/vboxsnapshotxmldata/2disks-nosnap.vbox b/tests/vboxsnapshotxmldata/2disks-nosnap.vbox
new file mode 100644 (file)
index 0000000..7037503
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+OVERWRITTEN AND LOST.
+Changes to this xml configuration should be made using Virtualbox
+or other application using the libvirt API-->
+<VirtualBox version="1.12-linux" xmlns="http://www.innotek.de/VirtualBox-settings">
+  <Machine uuid="{74864f52-a7b7-4172-a7a5-54b6f3e9cd21}" name="74864f52-a7b7-4172-a7a5-54b6f3e9cd21" snapshotFolder="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/Snapshots" currentStateModified="false" OSType="Other" lastStateChange="2014-05-15T11:49:46Z">
+    <MediaRegistry>
+      <DVDImages/>
+      <FloppyImages/>
+      <HardDisks>
+        <HardDisk uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk1.vdi" format="VDI" type="Normal"/>
+        <HardDisk uuid="{f113fdf8-9750-4557-a8be-87fd02319071}" location="/home/libvirt/vbox/74864f52-a7b7-4172-a7a5-54b6f3e9cd21/libvirtTest-disk2.vdi" format="VDI" type="Normal"/>
+      </HardDisks>
+    </MediaRegistry>
+    <Hardware version="2">
+      <CPU count="1" hotplug="false">
+        <HardwareVirtEx enabled="true"/>
+        <HardwareVirtExNestedPaging enabled="true"/>
+        <HardwareVirtExVPID enabled="true"/>
+        <HardwareVirtExUX enabled="true"/>
+        <PAE enabled="false"/>
+        <LongMode enabled="true"/>
+        <HardwareVirtExLargePages enabled="false"/>
+        <HardwareVirtForce enabled="false"/>
+      </CPU>
+      <Memory RAMSize="192" PageFusion="false"/>
+      <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
+      <HPET enabled="false"/>
+      <Chipset type="PIIX3"/>
+      <Boot>
+        <Order position="1" device="HardDisk"/>
+        <Order position="2" device="None"/>
+        <Order position="3" device="None"/>
+        <Order position="4" device="None"/>
+      </Boot>
+      <Display VRAMSize="8" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
+      <VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
+      <RemoteDisplay enabled="true" authType="Null" allowMultiConnection="true">
+        <VRDEProperties>
+          <Property name="TCP/Ports" value="5900"/>
+        </VRDEProperties>
+      </RemoteDisplay>
+      <BIOS>
+        <ACPI enabled="true"/>
+        <IOAPIC enabled="true"/>
+        <Logo fadeIn="true" fadeOut="true" displayTime="0"/>
+        <BootMenu mode="MessageAndMenu"/>
+        <TimeOffset value="0"/>
+        <PXEDebug enabled="false"/>
+      </BIOS>
+      <USB>
+        <Controllers/>
+        <DeviceFilters/>
+      </USB>
+      <Network>
+        <Adapter slot="0" enabled="true" MACAddress="0800272A589D" cable="true" speed="0" type="82540EM">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+            <InternalNetwork name="intnet"/>
+            <NATNetwork name="NatNetwork"/>
+          </DisabledModes>
+          <BridgedInterface name="hns0000000v"/>
+        </Adapter>
+        <Adapter slot="1" enabled="false" MACAddress="0800276B5197" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="2" enabled="false" MACAddress="080027A346C9" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="3" enabled="false" MACAddress="08002749A665" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="4" enabled="false" MACAddress="0800273246C6" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="5" enabled="false" MACAddress="080027B0B358" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="6" enabled="false" MACAddress="080027BF23E5" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+        <Adapter slot="7" enabled="false" MACAddress="080027BEE078" cable="true" speed="0" type="Am79C973">
+          <DisabledModes>
+            <NAT>
+              <DNS pass-domain="true" use-proxy="false" use-host-resolver="false"/>
+              <Alias logging="false" proxy-only="false" use-same-ports="false"/>
+            </NAT>
+          </DisabledModes>
+        </Adapter>
+      </Network>
+      <UART>
+        <Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+        <Port slot="1" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
+      </UART>
+      <LPT>
+        <Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
+        <Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
+      </LPT>
+      <AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
+      <RTC localOrUTC="local"/>
+      <SharedFolders/>
+      <Clipboard mode="Disabled"/>
+      <DragAndDrop mode="Disabled"/>
+      <IO>
+        <IoCache enabled="true" size="5"/>
+        <BandwidthGroups/>
+      </IO>
+      <HostPci>
+        <Devices/>
+      </HostPci>
+      <EmulatedUSB>
+        <CardReader enabled="false"/>
+      </EmulatedUSB>
+      <Guest memoryBalloonSize="0"/>
+      <GuestProperties/>
+    </Hardware>
+    <ExtraData>
+      <ExtraDataItem name="FRONTEND/Type" value="vrdp"/>
+    </ExtraData>
+    <StorageControllers>
+      <StorageController name="IDE Controller" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
+        <AttachedDevice type="HardDisk" port="0" device="0">
+          <Image uuid="{105122e9-f6d2-42c1-9c11-c01699c79517}"/>
+        </AttachedDevice>
+        <AttachedDevice type="HardDisk" port="0" device="1">
+          <Image uuid="{f113fdf8-9750-4557-a8be-87fd02319071}"/>
+        </AttachedDevice>
+      </StorageController>
+      <StorageController name="SATA Controller" type="AHCI" PortCount="30" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3"/>
+      <StorageController name="SCSI Controller" type="LsiLogic" PortCount="16" useHostIOCache="false" Bootable="true"/>
+      <StorageController name="Floppy Controller" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true"/>
+    </StorageControllers>
+  </Machine>
+</VirtualBox>
diff --git a/tests/vboxsnapshotxmltest.c b/tests/vboxsnapshotxmltest.c
new file mode 100644 (file)
index 0000000..7795688
--- /dev/null
@@ -0,0 +1,161 @@
+#include <config.h>
+
+#include "testutils.h"
+
+#ifdef WITH_VBOX
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <regex.h>
+# include "vbox/vbox_snapshot_conf.h"
+
+# define VIR_FROM_THIS VIR_FROM_NONE
+
+static const char *testSnapshotXMLVariableLineRegexStr =
+        "lastStateChange=[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z";
+
+regex_t *testSnapshotXMLVariableLineRegex = NULL;
+
+static char *
+testFilterXML(char *xml)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char **xmlLines = NULL;
+    char **xmlLine;
+    char *ret = NULL;
+
+    if (!(xmlLines = virStringSplit(xml, "\n", 0))) {
+        VIR_FREE(xml);
+        goto cleanup;
+    }
+    VIR_FREE(xml);
+
+    for (xmlLine = xmlLines; *xmlLine; xmlLine++) {
+        if (regexec(testSnapshotXMLVariableLineRegex,
+                    *xmlLine, 0, NULL, 0) == 0)
+            continue;
+
+        virBufferStrcat(&buf, *xmlLine, "\n", NULL);
+    }
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    ret = virBufferContentAndReset(&buf);
+
+ cleanup:
+   virBufferFreeAndReset(&buf);
+   virStringFreeList(xmlLines);
+   return ret;
+}
+
+static int
+testCompareXMLtoXMLFiles(const char *xml)
+{
+    char *xmlData = NULL;
+    char *actual = NULL;
+    char *pathResult = NULL;
+    int ret = -1;
+    virVBoxSnapshotConfMachinePtr machine = NULL;
+    if (virAsprintf(&pathResult, "%s/vboxsnapshotxmldata/testResult.vbox",
+                    abs_srcdir) < 0)
+        return -1;
+
+    if (virtTestLoadFile(xml, &xmlData) < 0)
+        goto fail;
+
+    if (!(machine = virVBoxSnapshotConfLoadVboxFile(xml, (char*)"")))
+        goto fail;
+
+    if (virVBoxSnapshotConfSaveVboxFile(machine, pathResult) < 0)
+        goto fail;
+
+    if (virtTestLoadFile(pathResult, &actual) < 0)
+        goto fail;
+
+    if (unlink(pathResult) < 0)
+        goto fail;
+
+    if (!(actual = testFilterXML(actual)))
+        goto fail;
+    if (!(xmlData = testFilterXML(xmlData)))
+        goto fail;
+
+    if (STRNEQ(actual, xmlData)) {
+        virtTestDifference(stderr, xmlData, actual);
+        goto fail;
+    }
+
+    ret = 0;
+
+ fail:
+    VIR_FREE(xmlData);
+    VIR_FREE(actual);
+    virVBoxSnapshotConfMachineFree(machine);
+    VIR_FREE(pathResult);
+
+    return ret;
+}
+
+static int
+testCompareXMLToXMLHelper(const void *data)
+{
+    int result = -1;
+    char *xml = NULL;
+
+    if (virAsprintf(&xml, "%s/vboxsnapshotxmldata/%s.vbox",
+                    abs_srcdir, (const char*)data) < 0)
+        return -1;
+
+    result = testCompareXMLtoXMLFiles(xml);
+
+    VIR_FREE(xml);
+    return result;
+}
+
+static int
+mymain(void)
+{
+    int ret = 0;
+    if (VIR_ALLOC(testSnapshotXMLVariableLineRegex) < 0)
+        goto cleanup;
+
+    if (regcomp(testSnapshotXMLVariableLineRegex,
+                testSnapshotXMLVariableLineRegexStr,
+                REG_EXTENDED | REG_NOSUB) != 0) {
+        ret = -1;
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "failed to compile test regex");
+        goto cleanup;
+    }
+
+# define DO_TEST(name)                                       \
+    if (virtTestRun("VBox Snapshot XML-2-XML " name,        \
+                    testCompareXMLToXMLHelper, (name)) < 0) \
+        ret = -1
+
+    DO_TEST("2disks-nosnap");
+    DO_TEST("2disks-1snap");
+    DO_TEST("2disks-2snap");
+    DO_TEST("2disks-3snap");
+    DO_TEST("2disks-3snap-brother");
+
+ cleanup:
+    if (testSnapshotXMLVariableLineRegex)
+        regfree(testSnapshotXMLVariableLineRegex);
+    VIR_FREE(testSnapshotXMLVariableLineRegex);
+    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
+
+#else
+
+int main(void)
+{
+    return EXIT_AM_SKIP;
+}
+
+#endif /*WITH_VBOX*/