mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 12:35:17 +00:00
vbox: Rewrite vboxDomainSnapshotGetXMLDesc
This commit is contained in:
parent
677ecdc070
commit
72c23d65c1
@ -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) { \
|
||||
@ -5357,3 +5359,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;
|
||||
}
|
||||
|
@ -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
|
||||
@ -803,7 +739,6 @@ static bool vboxGetDeviceDetails(const char *deviceName,
|
||||
|
||||
return true;
|
||||
}
|
||||
# endif /* VBOX_API_VERSION < 4000000 */
|
||||
|
||||
/**
|
||||
* function to get the values for max port per
|
||||
@ -816,9 +751,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)
|
||||
@ -863,7 +797,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
|
||||
@ -1589,583 +1523,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)
|
||||
@ -6709,6 +6066,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;
|
||||
@ -6733,11 +6096,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,
|
||||
#endif /* VBOX_API_VERSION >= 4000000 */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -7218,6 +6616,12 @@ _machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value)
|
||||
return machine->vtbl->SetExtraData(machine, key, value);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
_machineGetSnapshotCount(IMachine *machine, PRUint32 *snapshotCount)
|
||||
{
|
||||
return machine->vtbl->GetSnapshotCount(machine, snapshotCount);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
_machineSaveSettings(IMachine *machine)
|
||||
{
|
||||
@ -8156,6 +7560,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) &&
|
||||
@ -8213,15 +7659,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 = {
|
||||
@ -8244,6 +7695,7 @@ static vboxUniformedIMachine _UIMachine = {
|
||||
.RemoveSharedFolder = _machineRemoveSharedFolder,
|
||||
.LaunchVMProcess = _machineLaunchVMProcess,
|
||||
.Unregister = _machineUnregister,
|
||||
.FindSnapshot = _machineFindSnapshot,
|
||||
.GetAccessible = _machineGetAccessible,
|
||||
.GetState = _machineGetState,
|
||||
.GetName = _machineGetName,
|
||||
@ -8276,6 +7728,7 @@ static vboxUniformedIMachine _UIMachine = {
|
||||
.SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled,
|
||||
.GetExtraData = _machineGetExtraData,
|
||||
.SetExtraData = _machineSetExtraData,
|
||||
.GetSnapshotCount = _machineGetSnapshotCount,
|
||||
.SaveSettings = _machineSaveSettings,
|
||||
};
|
||||
|
||||
@ -8433,6 +7886,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,
|
||||
@ -8482,6 +7945,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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user