---
src/vbox/vbox_common.c | 712 ++++++++++++++++++++++++++++++++++++++
src/vbox/vbox_tmpl.c | 756 ++++++-----------------------------------
src/vbox/vbox_uniformed_api.h | 22 +-
3 files changed, 843 insertions(+), 647 deletions(-)
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index 8f3fe03..36260de 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -77,6 +77,8 @@ VIR_LOG_INIT("vbox.vbox_common");
#define VBOX_UTF16_TO_UTF8(arg1, arg2) gVBoxAPI.UPFN.Utf16ToUtf8(data->pFuncs, arg1,
arg2)
#define VBOX_UTF8_TO_UTF16(arg1, arg2) gVBoxAPI.UPFN.Utf8ToUtf16(data->pFuncs, arg1,
arg2)
+#define VBOX_ADDREF(arg) gVBoxAPI.nsUISupports.AddRef((void *)(arg))
+
#define VBOX_RELEASE(arg) \
do { \
if (arg) { \
@@ -5369,3 +5371,713 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
virDomainSnapshotDefFree(def);
return ret;
}
+
+static int
+vboxDomainSnapshotGetAll(virDomainPtr dom,
+ IMachine *machine,
+ ISnapshot ***snapshots)
+{
+ vboxIIDUnion empty;
+ ISnapshot **list = NULL;
+ PRUint32 count;
+ nsresult rc;
+ unsigned int next;
+ unsigned int top;
+
+ VBOX_IID_INITIALIZE(&empty);
+ rc = gVBoxAPI.UIMachine.GetSnapshotCount(machine, &count);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get snapshot count for domain %s"),
+ dom->name);
+ goto error;
+ }
+
+ if (count == 0)
+ goto out;
+
+ if (VIR_ALLOC_N(list, count) < 0)
+ goto error;
+
+ rc = gVBoxAPI.UIMachine.FindSnapshot(machine, &empty, list);
+ if (NS_FAILED(rc) || !list[0]) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get root snapshot for domain %s"),
+ dom->name);
+ goto error;
+ }
+
+ /* BFS walk through snapshot tree */
+ top = 1;
+ for (next = 0; next < count; next++) {
+ vboxArray children = VBOX_ARRAY_INITIALIZER;
+ size_t i;
+
+ if (!list[next]) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected number of snapshots < %u"),
count);
+ goto error;
+ }
+
+ rc = gVBoxAPI.UArray.vboxArrayGet(&children, list[next],
+
gVBoxAPI.UArray.handleSnapshotGetChildren(list[next]));
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("could not get children
snapshots"));
+ goto error;
+ }
+ for (i = 0; i < children.count; i++) {
+ ISnapshot *child = children.items[i];
+ if (!child)
+ continue;
+ if (top == count) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected number of snapshots > %u"),
count);
+ gVBoxAPI.UArray.vboxArrayRelease(&children);
+ goto error;
+ }
+ VBOX_ADDREF(child);
+ list[top++] = child;
+ }
+ gVBoxAPI.UArray.vboxArrayRelease(&children);
+ }
+
+ out:
+ *snapshots = list;
+ return count;
+
+ error:
+ if (list) {
+ for (next = 0; next < count; next++)
+ VBOX_RELEASE(list[next]);
+ }
+ VIR_FREE(list);
+
+ return -1;
+}
+
+static ISnapshot *
+vboxDomainSnapshotGet(vboxGlobalData *data,
+ virDomainPtr dom,
+ IMachine *machine,
+ const char *name)
+{
+ ISnapshot **snapshots = NULL;
+ ISnapshot *snapshot = NULL;
+ nsresult rc;
+ int count = 0;
+ size_t i;
+
+ if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0)
+ goto cleanup;
+
+ for (i = 0; i < count; i++) {
+ PRUnichar *nameUtf16;
+ char *nameUtf8;
+
+ rc = gVBoxAPI.UISnapshot.GetName(snapshots[i], &nameUtf16);
+ if (NS_FAILED(rc) || !nameUtf16) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("could not get snapshot name"));
+ goto cleanup;
+ }
+ VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
+ VBOX_UTF16_FREE(nameUtf16);
+ if (STREQ(name, nameUtf8))
+ snapshot = snapshots[i];
+ VBOX_UTF8_FREE(nameUtf8);
+
+ if (snapshot)
+ break;
+ }
+
+ if (!snapshot) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("domain %s has no snapshots with name %s"),
+ dom->name, name);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (count > 0) {
+ for (i = 0; i < count; i++) {
+ if (snapshots[i] != snapshot)
+ VBOX_RELEASE(snapshots[i]);
+ }
+ }
+ VIR_FREE(snapshots);
+ return snapshot;
+}
+
+static
+int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
+ virDomainSnapshotPtr snapshot)
+{
+ virDomainPtr dom = snapshot->domain;
+ VBOX_OBJECT_CHECK(dom->conn, int, -1);
+ vboxIIDUnion domiid;
+ IMachine *machine = NULL;
+ ISnapshot *snap = NULL;
+ IMachine *snapMachine = NULL;
+ vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
+ PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
+ PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
+ int diskCount = 0;
+ nsresult rc;
+ vboxIIDUnion snapIid;
+ char *snapshotUuidStr = NULL;
+ size_t i = 0;
+
+ if (!gVBoxAPI.vboxSnapshotRedefine)
+ VIR_WARN("This function may not work in current version");
+
+ VBOX_IID_INITIALIZE(&snapIid);
+ if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) <
0)
+ goto cleanup;
+
+ if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
+ goto cleanup;
+
+ rc = gVBoxAPI.UISnapshot.GetId(snap, &snapIid);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get snapshot id"));
+ goto cleanup;
+ }
+
+ gVBoxAPI.UIID.vboxIIDToUtf8(data, &snapIid, &snapshotUuidStr);
+ vboxIIDUnalloc(&snapIid);
+ rc = gVBoxAPI.UISnapshot.GetMachine(snap, &snapMachine);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("could not get machine"));
+ goto cleanup;
+ }
+ def->ndisks = 0;
+ rc = gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, snapMachine,
+
gVBoxAPI.UArray.handleMachineGetMediumAttachments(snapMachine));
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("no medium attachments"));
+ goto cleanup;
+ }
+ /* get the number of attachments */
+ for (i = 0; i < mediumAttachments.count; i++) {
+ IMediumAttachment *imediumattach = mediumAttachments.items[i];
+ if (imediumattach) {
+ IMedium *medium = NULL;
+
+ rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium"));
+ goto cleanup;
+ }
+ if (medium) {
+ def->ndisks++;
+ VBOX_RELEASE(medium);
+ }
+ }
+ }
+ /* Allocate mem, if fails return error */
+ if (VIR_ALLOC_N(def->disks, def->ndisks) < 0)
+ goto cleanup;
+ for (i = 0; i < def->ndisks; i++) {
+ if (VIR_ALLOC(def->disks[i].src) < 0)
+ goto cleanup;
+ }
+
+ if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
+ goto cleanup;
+
+ /* get the attachment details here */
+ for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks;
i++) {
+ IStorageController *storageController = NULL;
+ PRUnichar *storageControllerName = NULL;
+ PRUint32 deviceType = DeviceType_Null;
+ PRUint32 storageBus = StorageBus_Null;
+ IMedium *disk = NULL;
+ PRUnichar *childLocUtf16 = NULL;
+ char *childLocUtf8 = NULL;
+ PRUint32 deviceInst = 0;
+ PRInt32 devicePort = 0;
+ PRInt32 deviceSlot = 0;
+ vboxArray children = VBOX_ARRAY_INITIALIZER;
+ vboxArray snapshotIids = VBOX_ARRAY_INITIALIZER;
+ IMediumAttachment *imediumattach = mediumAttachments.items[i];
+ void *handle;
+ size_t j = 0;
+ size_t k = 0;
+ if (!imediumattach)
+ continue;
+ rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium"));
+ goto cleanup;
+ }
+ if (!disk)
+ continue;
+ rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach,
&storageControllerName);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get controller"));
+ goto cleanup;
+ }
+ if (!storageControllerName) {
+ VBOX_RELEASE(disk);
+ continue;
+ }
+ handle = gVBoxAPI.UArray.handleMediumGetChildren(disk);
+ rc = gVBoxAPI.UArray.vboxArrayGet(&children, disk, handle);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get children disk"));
+ goto cleanup;
+ }
+ handle = gVBoxAPI.UArray.handleMediumGetSnapshotIds(disk);
+ rc = gVBoxAPI.UArray.vboxArrayGetWithIIDArg(&snapshotIids, disk,
+ handle, &domiid);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get snapshot ids"));
+ goto cleanup;
+ }
+ for (j = 0; j < children.count; ++j) {
+ IMedium *child = children.items[j];
+ for (k = 0; k < snapshotIids.count; ++k) {
+ PRUnichar *diskSnapId = snapshotIids.items[k];
+ char *diskSnapIdStr = NULL;
+ VBOX_UTF16_TO_UTF8(diskSnapId, &diskSnapIdStr);
+ if (STREQ(diskSnapIdStr, snapshotUuidStr)) {
+ rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
+
storageControllerName,
+
&storageController);
+ VBOX_UTF16_FREE(storageControllerName);
+ if (!storageController) {
+ VBOX_RELEASE(child);
+ break;
+ }
+ rc = gVBoxAPI.UIMedium.GetLocation(child, &childLocUtf16);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get disk location"));
+ goto cleanup;
+ }
+ VBOX_UTF16_TO_UTF8(childLocUtf16, &childLocUtf8);
+ VBOX_UTF16_FREE(childLocUtf16);
+ if (VIR_STRDUP(def->disks[diskCount].src->path, childLocUtf8)
< 0) {
+ VBOX_RELEASE(child);
+ VBOX_RELEASE(storageController);
+ goto cleanup;
+ }
+ VBOX_UTF8_FREE(childLocUtf8);
+
+ rc = gVBoxAPI.UIStorageController.GetBus(storageController,
&storageBus);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get storage controller
bus"));
+ goto cleanup;
+ }
+ rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach,
&deviceType);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachment
type"));
+ goto cleanup;
+ }
+ rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach,
&devicePort);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachment
type"));
+ goto cleanup;
+ }
+ rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach,
&deviceSlot);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachment
device"));
+ goto cleanup;
+ }
+ def->disks[diskCount].src->type = VIR_STORAGE_TYPE_FILE;
+ def->disks[diskCount].name = vboxGenerateMediumName(storageBus,
+ deviceInst,
+ devicePort,
+ deviceSlot,
+ maxPortPerInst,
+ maxSlotPerPort);
+ }
+ VBOX_UTF8_FREE(diskSnapIdStr);
+ }
+ }
+ VBOX_RELEASE(storageController);
+ VBOX_RELEASE(disk);
+ diskCount++;
+ }
+ gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments);
+
+ ret = 0;
+ cleanup:
+ if (ret < 0) {
+ for (i = 0; i < def->ndisks; i++) {
+ VIR_FREE(def->disks[i].src);
+ }
+ VIR_FREE(def->disks);
+ def->ndisks = 0;
+ }
+ VBOX_RELEASE(snap);
+ return ret;
+}
+
+static
+int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
+ virDomainSnapshotDefPtr def)
+{
+ virDomainPtr dom = snapshot->domain;
+ VBOX_OBJECT_CHECK(dom->conn, int, -1);
+ vboxIIDUnion domiid;
+ ISnapshot *snap = NULL;
+ IMachine *machine = NULL;
+ IMachine *snapMachine = NULL;
+ IStorageController *storageController = NULL;
+ IMedium *disk = NULL;
+ nsresult rc;
+ vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
+ size_t i = 0;
+ PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
+ PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
+ int diskCount = 0;
+
+ if (!gVBoxAPI.vboxSnapshotRedefine)
+ VIR_WARN("This function may not work in current version");
+
+ if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) <
0)
+ goto cleanup;
+
+ if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
+ goto cleanup;
+
+ rc = gVBoxAPI.UISnapshot.GetMachine(snap, &snapMachine);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get machine"));
+ goto cleanup;
+ }
+ /*
+ * Get READ ONLY disks
+ * In the snapshot metadata, these are the disks written inside the <domain>
node
+ */
+ rc = gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, snapMachine,
+
gVBoxAPI.UArray.handleMachineGetMediumAttachments(snapMachine));
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachments"));
+ goto cleanup;
+ }
+ /* get the number of attachments */
+ for (i = 0; i < mediumAttachments.count; i++) {
+ IMediumAttachment *imediumattach = mediumAttachments.items[i];
+ if (imediumattach) {
+ IMedium *medium = NULL;
+
+ rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium"));
+ goto cleanup;
+ }
+ if (medium) {
+ def->dom->ndisks++;
+ VBOX_RELEASE(medium);
+ }
+ }
+ }
+
+ /* Allocate mem, if fails return error */
+ if (VIR_ALLOC_N(def->dom->disks, def->dom->ndisks) >= 0) {
+ for (i = 0; i < def->dom->ndisks; i++) {
+ virDomainDiskDefPtr diskDef = virDomainDiskDefNew();
+ if (!diskDef)
+ goto cleanup;
+ def->dom->disks[i] = diskDef;
+ }
+ } else {
+ goto cleanup;
+ }
+
+ if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
+ goto cleanup;
+
+ /* get the attachment details here */
+ for (i = 0; i < mediumAttachments.count && diskCount <
def->dom->ndisks; i++) {
+ PRUnichar *storageControllerName = NULL;
+ PRUint32 deviceType = DeviceType_Null;
+ PRUint32 storageBus = StorageBus_Null;
+ PRBool readOnly = PR_FALSE;
+ PRUnichar *mediumLocUtf16 = NULL;
+ char *mediumLocUtf8 = NULL;
+ PRUint32 deviceInst = 0;
+ PRInt32 devicePort = 0;
+ PRInt32 deviceSlot = 0;
+ IMediumAttachment *imediumattach = mediumAttachments.items[i];
+ if (!imediumattach)
+ continue;
+ rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium"));
+ goto cleanup;
+ }
+ if (!disk)
+ continue;
+ rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach,
&storageControllerName);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get storage controller name"));
+ goto cleanup;
+ }
+ if (!storageControllerName)
+ continue;
+ rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
+ storageControllerName,
+ &storageController);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get storage controller"));
+ goto cleanup;
+ }
+ VBOX_UTF16_FREE(storageControllerName);
+ if (!storageController)
+ continue;
+ rc = gVBoxAPI.UIMedium.GetLocation(disk, &mediumLocUtf16);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get disk location"));
+ goto cleanup;
+ }
+ VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
+ VBOX_UTF16_FREE(mediumLocUtf16);
+ if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8)
< 0)
+ goto cleanup;
+
+ VBOX_UTF8_FREE(mediumLocUtf8);
+
+ rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get storage controller bus"));
+ goto cleanup;
+ }
+ if (storageBus == StorageBus_IDE) {
+ def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE;
+ } else if (storageBus == StorageBus_SATA) {
+ def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA;
+ } else if (storageBus == StorageBus_SCSI) {
+ def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+ } else if (storageBus == StorageBus_Floppy) {
+ def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC;
+ }
+
+ rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachment type"));
+ goto cleanup;
+ }
+ if (deviceType == DeviceType_HardDisk)
+ def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+ else if (deviceType == DeviceType_Floppy)
+ def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
+ else if (deviceType == DeviceType_DVD)
+ def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+
+ rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get medium attachment port"));
+ goto cleanup;
+ }
+ rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get device"));
+ goto cleanup;
+ }
+ rc = gVBoxAPI.UIMedium.GetReadOnly(disk, &readOnly);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot get read only attribute"));
+ goto cleanup;
+ }
+ if (readOnly == PR_TRUE)
+ def->dom->disks[diskCount]->src->readonly = true;
+ def->dom->disks[diskCount]->src->type = VIR_STORAGE_TYPE_FILE;
+ def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
+ deviceInst,
+ devicePort,
+ deviceSlot,
+ maxPortPerInst,
+ maxSlotPerPort);
+ if (!def->dom->disks[diskCount]->dst) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not generate medium name for the disk "
+ "at: controller instance:%u, port:%d, slot:%d"),
+ deviceInst, devicePort, deviceSlot);
+ ret = -1;
+ goto cleanup;
+ }
+ diskCount ++;
+ }
+ /* cleanup on error */
+
+ ret = 0;
+ cleanup:
+ if (ret < 0) {
+ for (i = 0; i < def->dom->ndisks; i++)
+ virDomainDiskDefFree(def->dom->disks[i]);
+ VIR_FREE(def->dom->disks);
+ def->dom->ndisks = 0;
+ }
+ VBOX_RELEASE(disk);
+ VBOX_RELEASE(storageController);
+ gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments);
+ VBOX_RELEASE(snap);
+ return ret;
+}
+
+char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ virDomainPtr dom = snapshot->domain;
+ VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
+ vboxIIDUnion domiid;
+ IMachine *machine = NULL;
+ ISnapshot *snap = NULL;
+ ISnapshot *parent = NULL;
+ nsresult rc;
+ virDomainSnapshotDefPtr def = NULL;
+ PRUnichar *str16;
+ char *str8;
+ PRInt64 timestamp;
+ PRBool online = PR_FALSE;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virCheckFlags(0, NULL);
+
+ if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) <
0)
+ goto cleanup;
+
+ if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
+ goto cleanup;
+
+ if (VIR_ALLOC(def) < 0 || VIR_ALLOC(def->dom) < 0)
+ goto cleanup;
+ if (VIR_STRDUP(def->name, snapshot->name) < 0)
+ goto cleanup;
+
+ if (gVBoxAPI.vboxSnapshotRedefine) {
+ /* Register def->dom properties for them to be saved inside the snapshot XMl
+ * Otherwise, there is a problem while parsing the xml
+ */
+ PRUint32 memorySize = 0;
+ PRUint32 CPUCount = 0;
+
+ def->dom->virtType = VIR_DOMAIN_VIRT_VBOX;
+ def->dom->id = dom->id;
+ memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
+ if (VIR_STRDUP(def->dom->name, dom->name) < 0)
+ goto cleanup;
+ gVBoxAPI.UIMachine.GetMemorySize(machine, &memorySize);
+ def->dom->mem.cur_balloon = memorySize * 1024;
+ /* Currently setting memory and maxMemory as same, cause
+ * the notation here seems to be inconsistent while
+ * reading and while dumping xml
+ */
+ def->dom->mem.max_balloon = memorySize * 1024;
+ if (VIR_STRDUP(def->dom->os.type, "hvm") < 0)
+ goto cleanup;
+ def->dom->os.arch = virArchFromHost();
+ gVBoxAPI.UIMachine.GetCPUCount(machine, &CPUCount);
+ def->dom->maxvcpus = def->dom->vcpus = CPUCount;
+ if (vboxSnapshotGetReadWriteDisks(def, snapshot) < 0) {
+ VIR_DEBUG("Could not get read write disks for snapshot");
+ }
+
+ if (vboxSnapshotGetReadOnlyDisks(snapshot, def) < 0) {
+ VIR_DEBUG("Could not get Readonly disks for snapshot");
+ }
+ }
+
+ rc = gVBoxAPI.UISnapshot.GetDescription(snap, &str16);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get description of snapshot %s"),
+ snapshot->name);
+ goto cleanup;
+ }
+ if (str16) {
+ VBOX_UTF16_TO_UTF8(str16, &str8);
+ VBOX_UTF16_FREE(str16);
+ if (VIR_STRDUP(def->description, str8) < 0) {
+ VBOX_UTF8_FREE(str8);
+ goto cleanup;
+ }
+ VBOX_UTF8_FREE(str8);
+ }
+
+ rc = gVBoxAPI.UISnapshot.GetTimeStamp(snap, ×tamp);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get creation time of snapshot %s"),
+ snapshot->name);
+ goto cleanup;
+ }
+ /* timestamp is in milliseconds while creationTime in seconds */
+ def->creationTime = timestamp / 1000;
+
+ rc = gVBoxAPI.UISnapshot.GetParent(snap, &parent);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get parent of snapshot %s"),
+ snapshot->name);
+ goto cleanup;
+ }
+ if (parent) {
+ rc = gVBoxAPI.UISnapshot.GetName(parent, &str16);
+ if (NS_FAILED(rc) || !str16) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get name of parent of snapshot %s"),
+ snapshot->name);
+ goto cleanup;
+ }
+ VBOX_UTF16_TO_UTF8(str16, &str8);
+ VBOX_UTF16_FREE(str16);
+ if (VIR_STRDUP(def->parent, str8) < 0) {
+ VBOX_UTF8_FREE(str8);
+ goto cleanup;
+ }
+ VBOX_UTF8_FREE(str8);
+ }
+
+ rc = gVBoxAPI.UISnapshot.GetOnline(snap, &online);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get online state of snapshot %s"),
+ snapshot->name);
+ goto cleanup;
+ }
+ if (online)
+ def->state = VIR_DOMAIN_RUNNING;
+ else
+ def->state = VIR_DOMAIN_SHUTOFF;
+
+ virUUIDFormat(dom->uuid, uuidstr);
+ memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
+ ret = virDomainSnapshotDefFormat(uuidstr, def, flags, 0);
+
+ cleanup:
+ virDomainSnapshotDefFree(def);
+ VBOX_RELEASE(parent);
+ VBOX_RELEASE(snap);
+ VBOX_RELEASE(machine);
+ vboxIIDUnalloc(&domiid);
+ return ret;
+}
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 2218baf..4b5f993 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -676,70 +676,6 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu,
#endif /* !(VBOX_API_VERSION == 2002000) */
/**
- * function to generate the name for medium,
- * for e.g: hda, sda, etc
- *
- * @returns null terminated string with device name or NULL
- * for failures
- * @param conn Input Connection Pointer
- * @param storageBus Input storage bus type
- * @param deviceInst Input device instance number
- * @param devicePort Input port number
- * @param deviceSlot Input slot number
- * @param aMaxPortPerInst Input array of max port per device instance
- * @param aMaxSlotPerPort Input array of max slot per device port
- *
- */
-/* This functions is used for 4.2 and later only since vboxDomainGetXMLDesc
- * is rewritten. */
-#if VBOX_API_VERSION >= 4002000
-static char *vboxGenerateMediumName(PRUint32 storageBus,
- PRInt32 deviceInst,
- PRInt32 devicePort,
- PRInt32 deviceSlot,
- PRUint32 *aMaxPortPerInst,
- PRUint32 *aMaxSlotPerPort)
-{
- const char *prefix = NULL;
- char *name = NULL;
- int total = 0;
- PRUint32 maxPortPerInst = 0;
- PRUint32 maxSlotPerPort = 0;
-
- if (!aMaxPortPerInst ||
- !aMaxSlotPerPort)
- return NULL;
-
- if ((storageBus < StorageBus_IDE) ||
- (storageBus > StorageBus_Floppy))
- return NULL;
-
- maxPortPerInst = aMaxPortPerInst[storageBus];
- maxSlotPerPort = aMaxSlotPerPort[storageBus];
- total = (deviceInst * maxPortPerInst * maxSlotPerPort)
- + (devicePort * maxSlotPerPort)
- + deviceSlot;
-
- if (storageBus == StorageBus_IDE) {
- prefix = "hd";
- } else if ((storageBus == StorageBus_SATA) ||
- (storageBus == StorageBus_SCSI)) {
- prefix = "sd";
- } else if (storageBus == StorageBus_Floppy) {
- prefix = "fd";
- }
-
- name = virIndexToDiskName(total, prefix);
-
- VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, "
- "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u",
- NULLSTR(name), total, storageBus, deviceInst, devicePort,
- deviceSlot, maxPortPerInst, maxSlotPerPort);
- return name;
-}
-#endif /* VBOX_API_VERSION >= 4002000 */
-
-/**
* function to get the StorageBus, Port number
* and Device number for the given devicename
* e.g: hda has StorageBus = IDE, port = 0,
@@ -802,7 +738,6 @@ static bool vboxGetDeviceDetails(const char *deviceName,
return true;
}
-# endif /* VBOX_API_VERSION < 4000000 */
/**
* function to get the values for max port per
@@ -815,9 +750,8 @@ static bool vboxGetDeviceDetails(const char *deviceName,
*
*/
-/* This function would not be used in 4.0 and 4.1 since
- * vboxDomainGetXMLDesc is written*/
-# if VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000
+/* This function would not be used in 4.1 and later since
+ * vboxDomainSnapshotGetXMLDesc is written*/
static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox,
PRUint32 *maxPortPerInst,
PRUint32 *maxSlotPerPort)
@@ -862,7 +796,7 @@ static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox,
return true;
}
-# endif /* VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000 */
+# endif /* VBOX_API_VERSION < 4000000 */
/**
* Converts Utf-16 string to int
@@ -1588,583 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data,
return snapshot;
}
-#if VBOX_API_VERSION >=4002000
-static
-int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
- virDomainSnapshotPtr snapshot)
-{
- virDomainPtr dom = snapshot->domain;
- VBOX_OBJECT_CHECK(dom->conn, int, -1);
- vboxIID domiid = VBOX_IID_INITIALIZER;
- IMachine *machine = NULL;
- ISnapshot *snap = NULL;
- IMachine *snapMachine = NULL;
- vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
- PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
- PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
- int diskCount = 0;
- nsresult rc;
- vboxIID snapIid = VBOX_IID_INITIALIZER;
- char *snapshotUuidStr = NULL;
- size_t i = 0;
-
- vboxIIDFromUUID(&domiid, dom->uuid);
- rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("no domain with matching UUID"));
- goto cleanup;
- }
- if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
- goto cleanup;
-
- rc = snap->vtbl->GetId(snap, &snapIid.value);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not get snapshot id"));
- goto cleanup;
- }
-
- VBOX_UTF16_TO_UTF8(snapIid.value, &snapshotUuidStr);
- rc = snap->vtbl->GetMachine(snap, &snapMachine);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("could not get machine"));
- goto cleanup;
- }
- def->ndisks = 0;
- rc = vboxArrayGet(&mediumAttachments, snapMachine,
snapMachine->vtbl->GetMediumAttachments);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("no medium attachments"));
- goto cleanup;
- }
- /* get the number of attachments */
- for (i = 0; i < mediumAttachments.count; i++) {
- IMediumAttachment *imediumattach = mediumAttachments.items[i];
- if (imediumattach) {
- IMedium *medium = NULL;
-
- rc = imediumattach->vtbl->GetMedium(imediumattach, &medium);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium"));
- goto cleanup;
- }
- if (medium) {
- def->ndisks++;
- VBOX_RELEASE(medium);
- }
- }
- }
- /* Allocate mem, if fails return error */
- if (VIR_ALLOC_N(def->disks, def->ndisks) < 0)
- goto cleanup;
- for (i = 0; i < def->ndisks; i++) {
- if (VIR_ALLOC(def->disks[i].src) < 0)
- goto cleanup;
- }
-
- if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
- goto cleanup;
-
- /* get the attachment details here */
- for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks;
i++) {
- IStorageController *storageController = NULL;
- PRUnichar *storageControllerName = NULL;
- PRUint32 deviceType = DeviceType_Null;
- PRUint32 storageBus = StorageBus_Null;
- IMedium *disk = NULL;
- PRUnichar *childLocUtf16 = NULL;
- char *childLocUtf8 = NULL;
- PRUint32 deviceInst = 0;
- PRInt32 devicePort = 0;
- PRInt32 deviceSlot = 0;
- vboxArray children = VBOX_ARRAY_INITIALIZER;
- vboxArray snapshotIids = VBOX_ARRAY_INITIALIZER;
- IMediumAttachment *imediumattach = mediumAttachments.items[i];
- size_t j = 0;
- size_t k = 0;
- if (!imediumattach)
- continue;
- rc = imediumattach->vtbl->GetMedium(imediumattach, &disk);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium"));
- goto cleanup;
- }
- if (!disk)
- continue;
- rc = imediumattach->vtbl->GetController(imediumattach,
&storageControllerName);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get controller"));
- goto cleanup;
- }
- if (!storageControllerName) {
- VBOX_RELEASE(disk);
- continue;
- }
- rc = vboxArrayGet(&children, disk, disk->vtbl->GetChildren);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get children disk"));
- goto cleanup;
- }
- rc = vboxArrayGetWithPtrArg(&snapshotIids, disk,
disk->vtbl->GetSnapshotIds, domiid.value);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get snapshot ids"));
- goto cleanup;
- }
- for (j = 0; j < children.count; ++j) {
- IMedium *child = children.items[j];
- for (k = 0; k < snapshotIids.count; ++k) {
- PRUnichar *diskSnapId = snapshotIids.items[k];
- char *diskSnapIdStr = NULL;
- VBOX_UTF16_TO_UTF8(diskSnapId, &diskSnapIdStr);
- if (STREQ(diskSnapIdStr, snapshotUuidStr)) {
- rc = machine->vtbl->GetStorageControllerByName(machine,
- storageControllerName,
- &storageController);
- VBOX_UTF16_FREE(storageControllerName);
- if (!storageController) {
- VBOX_RELEASE(child);
- break;
- }
- rc = child->vtbl->GetLocation(child, &childLocUtf16);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get disk location"));
- goto cleanup;
- }
- VBOX_UTF16_TO_UTF8(childLocUtf16, &childLocUtf8);
- VBOX_UTF16_FREE(childLocUtf16);
- if (VIR_STRDUP(def->disks[diskCount].src->path, childLocUtf8)
< 0) {
- VBOX_RELEASE(child);
- VBOX_RELEASE(storageController);
- goto cleanup;
- }
- VBOX_UTF8_FREE(childLocUtf8);
-
- rc = storageController->vtbl->GetBus(storageController,
&storageBus);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get storage controller
bus"));
- goto cleanup;
- }
- rc = imediumattach->vtbl->GetType(imediumattach,
&deviceType);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachment
type"));
- goto cleanup;
- }
- rc = imediumattach->vtbl->GetPort(imediumattach,
&devicePort);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachment
type"));
- goto cleanup;
- }
- rc = imediumattach->vtbl->GetDevice(imediumattach,
&deviceSlot);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachment
device"));
- goto cleanup;
- }
- def->disks[diskCount].src->type = VIR_STORAGE_TYPE_FILE;
- def->disks[diskCount].name = vboxGenerateMediumName(storageBus,
- deviceInst,
- devicePort,
- deviceSlot,
- maxPortPerInst,
- maxSlotPerPort);
- }
- VBOX_UTF8_FREE(diskSnapIdStr);
- }
- }
- VBOX_RELEASE(storageController);
- VBOX_RELEASE(disk);
- diskCount++;
- }
- vboxArrayRelease(&mediumAttachments);
-
- ret = 0;
- cleanup:
- if (ret < 0) {
- for (i = 0; i < def->ndisks; i++) {
- VIR_FREE(def->disks[i].src);
- }
- VIR_FREE(def->disks);
- def->ndisks = 0;
- }
- VBOX_RELEASE(snap);
- return ret;
-}
-
-static
-int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
- virDomainSnapshotDefPtr def)
-{
- virDomainPtr dom = snapshot->domain;
- VBOX_OBJECT_CHECK(dom->conn, int, -1);
- vboxIID domiid = VBOX_IID_INITIALIZER;
- ISnapshot *snap = NULL;
- IMachine *machine = NULL;
- IMachine *snapMachine = NULL;
- IStorageController *storageController = NULL;
- IMedium *disk = NULL;
- nsresult rc;
- vboxIIDFromUUID(&domiid, dom->uuid);
- vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
- size_t i = 0;
- PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
- PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
- int diskCount = 0;
-
- rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_NO_DOMAIN, "%s",
- _("no domain with matching UUID"));
- goto cleanup;
- }
-
- if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
- goto cleanup;
-
- rc = snap->vtbl->GetMachine(snap, &snapMachine);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get machine"));
- goto cleanup;
- }
- /*
- * Get READ ONLY disks
- * In the snapshot metadata, these are the disks written inside the <domain>
node
- */
- rc = vboxArrayGet(&mediumAttachments, snapMachine,
snapMachine->vtbl->GetMediumAttachments);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachments"));
- goto cleanup;
- }
- /* get the number of attachments */
- for (i = 0; i < mediumAttachments.count; i++) {
- IMediumAttachment *imediumattach = mediumAttachments.items[i];
- if (imediumattach) {
- IMedium *medium = NULL;
-
- rc = imediumattach->vtbl->GetMedium(imediumattach, &medium);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium"));
- goto cleanup;
- }
- if (medium) {
- def->dom->ndisks++;
- VBOX_RELEASE(medium);
- }
- }
- }
-
- /* Allocate mem, if fails return error */
- if (VIR_ALLOC_N(def->dom->disks, def->dom->ndisks) >= 0) {
- for (i = 0; i < def->dom->ndisks; i++) {
- virDomainDiskDefPtr diskDef = virDomainDiskDefNew();
- if (!diskDef)
- goto cleanup;
- def->dom->disks[i] = diskDef;
- }
- } else {
- goto cleanup;
- }
-
- if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
- goto cleanup;
-
- /* get the attachment details here */
- for (i = 0; i < mediumAttachments.count && diskCount <
def->dom->ndisks; i++) {
- PRUnichar *storageControllerName = NULL;
- PRUint32 deviceType = DeviceType_Null;
- PRUint32 storageBus = StorageBus_Null;
- PRBool readOnly = PR_FALSE;
- PRUnichar *mediumLocUtf16 = NULL;
- char *mediumLocUtf8 = NULL;
- PRUint32 deviceInst = 0;
- PRInt32 devicePort = 0;
- PRInt32 deviceSlot = 0;
- IMediumAttachment *imediumattach = mediumAttachments.items[i];
- if (!imediumattach)
- continue;
- rc = imediumattach->vtbl->GetMedium(imediumattach, &disk);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium"));
- goto cleanup;
- }
- if (!disk)
- continue;
- rc = imediumattach->vtbl->GetController(imediumattach,
&storageControllerName);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get storage controller name"));
- goto cleanup;
- }
- if (!storageControllerName)
- continue;
- rc = machine->vtbl->GetStorageControllerByName(machine,
- storageControllerName,
- &storageController);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get storage controller"));
- goto cleanup;
- }
- VBOX_UTF16_FREE(storageControllerName);
- if (!storageController)
- continue;
- rc = disk->vtbl->GetLocation(disk, &mediumLocUtf16);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get disk location"));
- goto cleanup;
- }
- VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
- VBOX_UTF16_FREE(mediumLocUtf16);
- if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8)
< 0)
- goto cleanup;
-
- VBOX_UTF8_FREE(mediumLocUtf8);
-
- rc = storageController->vtbl->GetBus(storageController, &storageBus);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get storage controller bus"));
- goto cleanup;
- }
- if (storageBus == StorageBus_IDE) {
- def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE;
- } else if (storageBus == StorageBus_SATA) {
- def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA;
- } else if (storageBus == StorageBus_SCSI) {
- def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI;
- } else if (storageBus == StorageBus_Floppy) {
- def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC;
- }
-
- rc = imediumattach->vtbl->GetType(imediumattach, &deviceType);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachment type"));
- goto cleanup;
- }
- if (deviceType == DeviceType_HardDisk)
- def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
- else if (deviceType == DeviceType_Floppy)
- def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
- else if (deviceType == DeviceType_DVD)
- def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-
- rc = imediumattach->vtbl->GetPort(imediumattach, &devicePort);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get medium attachment port"));
- goto cleanup;
- }
- rc = imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get device"));
- goto cleanup;
- }
- rc = disk->vtbl->GetReadOnly(disk, &readOnly);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get read only attribute"));
- goto cleanup;
- }
- if (readOnly == PR_TRUE)
- def->dom->disks[diskCount]->src->readonly = true;
- def->dom->disks[diskCount]->src->type = VIR_STORAGE_TYPE_FILE;
- def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
- deviceInst,
- devicePort,
- deviceSlot,
- maxPortPerInst,
- maxSlotPerPort);
- if (!def->dom->disks[diskCount]->dst) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not generate medium name for the disk "
- "at: controller instance:%u, port:%d, slot:%d"),
- deviceInst, devicePort, deviceSlot);
- ret = -1;
- goto cleanup;
- }
- diskCount ++;
- }
- /* cleanup on error */
-
- ret = 0;
- cleanup:
- if (ret < 0) {
- for (i = 0; i < def->dom->ndisks; i++)
- virDomainDiskDefFree(def->dom->disks[i]);
- VIR_FREE(def->dom->disks);
- def->dom->ndisks = 0;
- }
- VBOX_RELEASE(disk);
- VBOX_RELEASE(storageController);
- vboxArrayRelease(&mediumAttachments);
- VBOX_RELEASE(snap);
- return ret;
-}
-#endif
-
-static char *
-vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
- unsigned int flags)
-{
- virDomainPtr dom = snapshot->domain;
- VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
- vboxIID domiid = VBOX_IID_INITIALIZER;
- IMachine *machine = NULL;
- ISnapshot *snap = NULL;
- ISnapshot *parent = NULL;
- nsresult rc;
- virDomainSnapshotDefPtr def = NULL;
- PRUnichar *str16;
- char *str8;
- PRInt64 timestamp;
- PRBool online = PR_FALSE;
- char uuidstr[VIR_UUID_STRING_BUFLEN];
-#if VBOX_API_VERSION >=4002000
- PRUint32 memorySize = 0;
- PRUint32 CPUCount = 0;
-#endif
-
- virCheckFlags(0, NULL);
-
- vboxIIDFromUUID(&domiid, dom->uuid);
- rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_NO_DOMAIN, "%s",
- _("no domain with matching UUID"));
- goto cleanup;
- }
-
- if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
- goto cleanup;
-
- if (VIR_ALLOC(def) < 0 || VIR_ALLOC(def->dom) < 0)
- goto cleanup;
- if (VIR_STRDUP(def->name, snapshot->name) < 0)
- goto cleanup;
-
-#if VBOX_API_VERSION >=4002000
- /* Register def->dom properties for them to be saved inside the snapshot XMl
- * Otherwise, there is a problem while parsing the xml
- */
- def->dom->virtType = VIR_DOMAIN_VIRT_VBOX;
- def->dom->id = dom->id;
- memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
- if (VIR_STRDUP(def->dom->name, dom->name) < 0)
- goto cleanup;
- machine->vtbl->GetMemorySize(machine, &memorySize);
- def->dom->mem.cur_balloon = memorySize * 1024;
- /* Currently setting memory and maxMemory as same, cause
- * the notation here seems to be inconsistent while
- * reading and while dumping xml
- */
- def->dom->mem.max_balloon = memorySize * 1024;
- if (VIR_STRDUP(def->dom->os.type, "hvm") < 0)
- goto cleanup;
- def->dom->os.arch = virArchFromHost();
- machine->vtbl->GetCPUCount(machine, &CPUCount);
- def->dom->maxvcpus = def->dom->vcpus = CPUCount;
- if (vboxSnapshotGetReadWriteDisks(def, snapshot) < 0) {
- VIR_DEBUG("Could not get read write disks for snapshot");
- }
-
- if (vboxSnapshotGetReadOnlyDisks(snapshot, def) < 0) {
- VIR_DEBUG("Could not get Readonly disks for snapshot");
- }
-#endif /* VBOX_API_VERSION >= 4002000 */
-
- rc = snap->vtbl->GetDescription(snap, &str16);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not get description of snapshot %s"),
- snapshot->name);
- goto cleanup;
- }
- if (str16) {
- VBOX_UTF16_TO_UTF8(str16, &str8);
- VBOX_UTF16_FREE(str16);
- if (VIR_STRDUP(def->description, str8) < 0) {
- VBOX_UTF8_FREE(str8);
- goto cleanup;
- }
- VBOX_UTF8_FREE(str8);
- }
-
- rc = snap->vtbl->GetTimeStamp(snap, ×tamp);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not get creation time of snapshot %s"),
- snapshot->name);
- goto cleanup;
- }
- /* timestamp is in milliseconds while creationTime in seconds */
- def->creationTime = timestamp / 1000;
-
- rc = snap->vtbl->GetParent(snap, &parent);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not get parent of snapshot %s"),
- snapshot->name);
- goto cleanup;
- }
- if (parent) {
- rc = parent->vtbl->GetName(parent, &str16);
- if (NS_FAILED(rc) || !str16) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not get name of parent of snapshot %s"),
- snapshot->name);
- goto cleanup;
- }
- VBOX_UTF16_TO_UTF8(str16, &str8);
- VBOX_UTF16_FREE(str16);
- if (VIR_STRDUP(def->parent, str8) < 0) {
- VBOX_UTF8_FREE(str8);
- goto cleanup;
- }
- VBOX_UTF8_FREE(str8);
- }
-
- rc = snap->vtbl->GetOnline(snap, &online);
- if (NS_FAILED(rc)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("could not get online state of snapshot %s"),
- snapshot->name);
- goto cleanup;
- }
- if (online)
- def->state = VIR_DOMAIN_RUNNING;
- else
- def->state = VIR_DOMAIN_SHUTOFF;
-
- virUUIDFormat(dom->uuid, uuidstr);
- memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
- ret = virDomainSnapshotDefFormat(uuidstr, def, flags, 0);
-
- cleanup:
- virDomainSnapshotDefFree(def);
- VBOX_RELEASE(parent);
- VBOX_RELEASE(snap);
- VBOX_RELEASE(machine);
- vboxIIDUnalloc(&domiid);
- return ret;
-}
-
static int
vboxDomainSnapshotNum(virDomainPtr dom,
unsigned int flags)
@@ -6708,6 +6065,12 @@ _vboxIIDToUtf8(vboxGlobalData *data ATTRIBUTE_UNUSED,
#endif /* !(VBOX_API_VERSION == 2002000) */
}
+static nsresult
+_vboxArrayGetWithIIDArg(vboxArray *array, void *self, void *getter, vboxIIDUnion *iidu)
+{
+ return vboxArrayGetWithPtrArg(array, self, getter, IID_MEMBER(value));
+}
+
static void* _handleGetMachines(IVirtualBox *vboxObj)
{
return vboxObj->vtbl->GetMachines;
@@ -6732,11 +6095,36 @@ static void* _handleMachineGetSharedFolders(IMachine *machine)
return machine->vtbl->GetSharedFolders;
}
+static void* _handleSnapshotGetChildren(ISnapshot *snapshot)
+{
+ return snapshot->vtbl->GetChildren;
+}
+
+static void* _handleMediumGetChildren(IMedium *medium ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION < 3001000
+ vboxUnsupported();
+ return 0;
+#else /* VBOX_API_VERSION >= 3001000 */
+ return medium->vtbl->GetChildren;
+#endif /* VBOX_API_VERSION >= 3001000 */
+}
+
+static void* _handleMediumGetSnapshotIds(IMedium *medium)
+{
+ return medium->vtbl->GetSnapshotIds;
+}
+
static nsresult _nsisupportsRelease(nsISupports *nsi)
{
return nsi->vtbl->Release(nsi);
}
+static nsresult _nsisupportsAddRef(nsISupports *nsi)
+{
+ return nsi->vtbl->AddRef(nsi);
+}
+
static nsresult
_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16)
{
@@ -6989,6 +6377,16 @@ _machineUnregister(IMachine *machine ATTRIBUTE_UNUSED,
}
static nsresult
+_machineFindSnapshot(IMachine *machine, vboxIIDUnion *iidu, ISnapshot **snapshot)
+{
+#if VBOX_API_VERSION < 4000000
+ return machine->vtbl->GetSnapshot(machine, IID_MEMBER(value), snapshot);
+#else /* VBOX_API_VERSION >= 4000000 */
+ return machine->vtbl->FindSnapshot(machine, IID_MEMBER(value), snapshot);
+#endif /* VBOX_API_VERSION >= 4000000 */
+}
+
+static nsresult
_machineGetAccessible(IMachine *machine, PRBool *isAccessible)
{
return machine->vtbl->GetAccessible(machine, isAccessible);
@@ -7218,6 +6616,12 @@ _machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar
*value)
}
static nsresult
+_machineGetSnapshotCount(IMachine *machine, PRUint32 *snapshotCount)
+{
+ return machine->vtbl->GetSnapshotCount(machine, snapshotCount);
+}
+
+static nsresult
_machineSaveSettings(IMachine *machine)
{
return machine->vtbl->SaveSettings(machine);
@@ -8155,6 +7559,48 @@ _sharedFolderGetWritable(ISharedFolder *sharedFolder, PRBool
*writable)
return sharedFolder->vtbl->GetWritable(sharedFolder, writable);
}
+static nsresult
+_snapshotGetName(ISnapshot *snapshot, PRUnichar **name)
+{
+ return snapshot->vtbl->GetName(snapshot, name);
+}
+
+static nsresult
+_snapshotGetId(ISnapshot *snapshot, vboxIIDUnion *iidu)
+{
+ return snapshot->vtbl->GetId(snapshot, &IID_MEMBER(value));
+}
+
+static nsresult
+_snapshotGetMachine(ISnapshot *snapshot, IMachine **machine)
+{
+ return snapshot->vtbl->GetMachine(snapshot, machine);
+}
+
+static nsresult
+_snapshotGetDescription(ISnapshot *snapshot, PRUnichar **description)
+{
+ return snapshot->vtbl->GetDescription(snapshot, description);
+}
+
+static nsresult
+_snapshotGetTimeStamp(ISnapshot *snapshot, PRInt64 *timeStamp)
+{
+ return snapshot->vtbl->GetTimeStamp(snapshot, timeStamp);
+}
+
+static nsresult
+_snapshotGetParent(ISnapshot *snapshot, ISnapshot **parent)
+{
+ return snapshot->vtbl->GetParent(snapshot, parent);
+}
+
+static nsresult
+_snapshotGetOnline(ISnapshot *snapshot, PRBool *online)
+{
+ return snapshot->vtbl->GetOnline(snapshot, online);
+}
+
static bool _machineStateOnline(PRUint32 state)
{
return ((state >= MachineState_FirstOnline) &&
@@ -8212,15 +7658,20 @@ static vboxUniformedIID _UIID = {
static vboxUniformedArray _UArray = {
.vboxArrayGet = vboxArrayGet,
+ .vboxArrayGetWithIIDArg = _vboxArrayGetWithIIDArg,
.vboxArrayRelease = vboxArrayRelease,
.handleGetMachines = _handleGetMachines,
.handleUSBGetDeviceFilters = _handleUSBGetDeviceFilters,
.handleMachineGetMediumAttachments = _handleMachineGetMediumAttachments,
.handleMachineGetSharedFolders = _handleMachineGetSharedFolders,
+ .handleSnapshotGetChildren = _handleSnapshotGetChildren,
+ .handleMediumGetChildren = _handleMediumGetChildren,
+ .handleMediumGetSnapshotIds = _handleMediumGetSnapshotIds,
};
static vboxUniformednsISupports _nsUISupports = {
.Release = _nsisupportsRelease,
+ .AddRef = _nsisupportsAddRef,
};
static vboxUniformedIVirtualBox _UIVirtualBox = {
@@ -8243,6 +7694,7 @@ static vboxUniformedIMachine _UIMachine = {
.RemoveSharedFolder = _machineRemoveSharedFolder,
.LaunchVMProcess = _machineLaunchVMProcess,
.Unregister = _machineUnregister,
+ .FindSnapshot = _machineFindSnapshot,
.GetAccessible = _machineGetAccessible,
.GetState = _machineGetState,
.GetName = _machineGetName,
@@ -8275,6 +7727,7 @@ static vboxUniformedIMachine _UIMachine = {
.SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled,
.GetExtraData = _machineGetExtraData,
.SetExtraData = _machineSetExtraData,
+ .GetSnapshotCount = _machineGetSnapshotCount,
.SaveSettings = _machineSaveSettings,
};
@@ -8432,6 +7885,16 @@ static vboxUniformedISharedFolder _UISharedFolder = {
.GetWritable = _sharedFolderGetWritable,
};
+static vboxUniformedISnapshot _UISnapshot = {
+ .GetName = _snapshotGetName,
+ .GetId = _snapshotGetId,
+ .GetMachine = _snapshotGetMachine,
+ .GetDescription = _snapshotGetDescription,
+ .GetTimeStamp = _snapshotGetTimeStamp,
+ .GetParent = _snapshotGetParent,
+ .GetOnline = _snapshotGetOnline,
+};
+
static uniformedMachineStateChecker _machineStateChecker = {
.Online = _machineStateOnline,
.Inactive = _machineStateInactive,
@@ -8481,6 +7944,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->UIMediumAttachment = _UIMediumAttachment;
pVBoxAPI->UIStorageController = _UIStorageController;
pVBoxAPI->UISharedFolder = _UISharedFolder;
+ pVBoxAPI->UISnapshot = _UISnapshot;
pVBoxAPI->machineStateChecker = _machineStateChecker;
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h
index 8357df5..6b04b57 100644
--- a/src/vbox/vbox_uniformed_api.h
+++ b/src/vbox/vbox_uniformed_api.h
@@ -166,17 +166,22 @@ typedef struct {
/* Functions for vboxArray */
typedef struct {
nsresult (*vboxArrayGet)(vboxArray *array, void *self, void *getter);
+ nsresult (*vboxArrayGetWithIIDArg)(vboxArray *array, void *self, void *getter,
vboxIIDUnion *iidu);
void (*vboxArrayRelease)(vboxArray *array);
/* Generate function pointers for vboxArrayGet */
void* (*handleGetMachines)(IVirtualBox *vboxObj);
void* (*handleUSBGetDeviceFilters)(IUSBCommon *USBCommon);
void* (*handleMachineGetMediumAttachments)(IMachine *machine);
void* (*handleMachineGetSharedFolders)(IMachine *machine);
+ void* (*handleSnapshotGetChildren)(ISnapshot *snapshot);
+ void* (*handleMediumGetChildren)(IMedium *medium);
+ void* (*handleMediumGetSnapshotIds)(IMedium *medium);
} vboxUniformedArray;
/* Functions for nsISupports */
typedef struct {
nsresult (*Release)(nsISupports *nsi);
+ nsresult (*AddRef)(nsISupports *nsi);
} vboxUniformednsISupports;
/* Functions for IVirtualBox */
@@ -211,6 +216,7 @@ typedef struct {
IProgress **progress);
nsresult (*Unregister)(IMachine *machine, PRUint32 cleanupMode,
PRUint32 *aMediaSize, IMedium ***aMedia);
+ nsresult (*FindSnapshot)(IMachine *machine, vboxIIDUnion *iidu, ISnapshot
**snapshot);
nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible);
nsresult (*GetState)(IMachine *machine, PRUint32 *state);
nsresult (*GetName)(IMachine *machine, PRUnichar **name);
@@ -243,6 +249,7 @@ typedef struct {
nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool
accelerate2DVideoEnabled);
nsresult (*GetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar **value);
nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value);
+ nsresult (*GetSnapshotCount)(IMachine *machine, PRUint32 *snapshotCount);
nsresult (*SaveSettings)(IMachine *machine);
} vboxUniformedIMachine;
@@ -427,6 +434,17 @@ typedef struct {
nsresult (*GetWritable)(ISharedFolder *sharedFolder, PRBool *writable);
} vboxUniformedISharedFolder;
+/* Functions for ISnapshot */
+typedef struct {
+ nsresult (*GetName)(ISnapshot *snapshot, PRUnichar **name);
+ nsresult (*GetId)(ISnapshot *snapshot, vboxIIDUnion *iidu);
+ nsresult (*GetMachine)(ISnapshot *snapshot, IMachine **machine);
+ nsresult (*GetDescription)(ISnapshot *snapshot, PRUnichar **description);
+ nsresult (*GetTimeStamp)(ISnapshot *snapshot, PRInt64 *timeStamp);
+ nsresult (*GetParent)(ISnapshot *snapshot, ISnapshot **parent);
+ nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online);
+} vboxUniformedISnapshot;
+
typedef struct {
bool (*Online)(PRUint32 state);
bool (*Inactive)(PRUint32 state);
@@ -477,6 +495,7 @@ typedef struct {
vboxUniformedIMediumAttachment UIMediumAttachment;
vboxUniformedIStorageController UIStorageController;
vboxUniformedISharedFolder UISharedFolder;
+ vboxUniformedISnapshot UISnapshot;
uniformedMachineStateChecker machineStateChecker;
/* vbox API features */
bool domainEventCallbacks;
@@ -556,7 +575,8 @@ virDomainSnapshotPtr
vboxDomainSnapshotCreateXML(virDomainPtr dom,
const char *xmlDesc,
unsigned int flags);
-
+char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
/* Version specified functions for installing uniformed API */
void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
--
1.7.9.5