#include "network_conf.h"
#include "virterror_internal.h"
#include "domain_event.h"
+#include "storage_conf.h"
#include "uuid.h"
#include "event.h"
#include "memory.h"
}
#if VBOX_API_VERSION == 2002
+
+#define vboxIIDFromUUID(uuid, iid) nsIDFromChar((iid), (uuid))
+#define vboxIIDToUUID(uuid, iid) nsIDtoChar((uuid), (iid))
+#define vboxIIDUnalloc(iid) data->pFuncs->pfnComUnallocMem(iid)
+#define vboxIIDFree(iid) VIR_FREE(iid)
+#define vboxIIDUtf8Free(iid) VIR_FREE(iid)
+#define vboxIIDUtf16Free(iid) VIR_FREE(iid)
+#define DEBUGIID(msg, iid) DEBUGUUID(msg, iid)
+
static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
char uuidstrsrc[VIR_UUID_STRING_BUFLEN];
char uuidstrdst[VIR_UUID_STRING_BUFLEN];
typedef nsID vboxIID;
-#define vboxIIDFromUUID(uuid, iid) nsIDFromChar((iid), (uuid))
-#define vboxIIDToUUID(uuid, iid) nsIDtoChar((uuid), (iid))
-#define vboxIIDUnalloc(iid) data->pFuncs->pfnComUnallocMem(iid)
-#define vboxIIDFree(iid) VIR_FREE(iid)
-#define DEBUGIID(msg, iid) DEBUGUUID(msg, iid)
+static bool vboxIIDEqual(vboxIID *firstIID, vboxIID *secondIID) {
+ if (memcmp(firstIID, secondIID, sizeof(firstIID)) == 0)
+ return true;
+ else
+ return false;
+}
-#else /* !(VBOX_API_VERSION == 2002) */
+static void vboxIIDtoUtf8(virConnectPtr conn, vboxIID *iid, char **uuidstr) {
+ unsigned char hddUUID[VIR_UUID_BUFLEN];
-typedef PRUnichar vboxIID;
+ if (VIR_ALLOC_N(*uuidstr, VIR_UUID_STRING_BUFLEN) < 0) {
+ virReportOOMError(conn);
+ return;
+ }
+
+ vboxIIDToUUID(hddUUID, iid);
+ virUUIDFormat(hddUUID, *uuidstr);
+}
+
+static void vboxUtf8toIID(virConnectPtr conn, char *uuidstr, vboxIID **iid) {
+ unsigned char hddUUID[VIR_UUID_BUFLEN];
+
+ if (VIR_ALLOC(*iid) < 0) {
+ virReportOOMError(conn);
+ return;
+ }
+
+ virUUIDParse(uuidstr, hddUUID);
+ vboxIIDFromUUID(hddUUID, *iid);
+}
+
+#else /* !(VBOX_API_VERSION == 2002) */
#define vboxIIDFromUUID(uuid, iid)\
{\
}
#define vboxIIDFree(iid) data->pFuncs->pfnUtf16Free(iid)
+#define vboxIIDUtf8Free(iid) data->pFuncs->pfnUtf8Free(iid)
+#define vboxIIDUtf16Free(iid) data->pFuncs->pfnUtf16Free(iid)
#define vboxIIDUnalloc(iid) data->pFuncs->pfnUtf16Free(iid)
#define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16)
+typedef PRUnichar vboxIID;
+
+static bool vboxIIDEqual(vboxIID *firstIID, vboxIID *secondIID) {
+ unsigned char firstUUID[VIR_UUID_BUFLEN];
+ unsigned char secondUUID[VIR_UUID_BUFLEN];
+ char *firstIIDUtf8 = NULL;
+ char *secondIIDUtf8 = NULL;
+
+ if (!g_pVBoxGlobalData)
+ return false;
+
+ g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(firstIID, &firstIIDUtf8);
+ g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(secondIID, &secondIIDUtf8);
+
+ /* Note: we can't directly compare the utf8 strings here
+ * cause the two UUID's may have seperators as space or '-'
+ * or mixture of both and we don't want to fail here by
+ * using direct string comparison. Here virUUIDParse() takes
+ * care of these cases.
+ */
+
+ virUUIDParse(firstIIDUtf8, firstUUID);
+ virUUIDParse(secondIIDUtf8, secondUUID);
+
+ g_pVBoxGlobalData->pFuncs->pfnUtf8Free(firstIIDUtf8);
+ g_pVBoxGlobalData->pFuncs->pfnUtf8Free(secondIIDUtf8);
+
+ if (memcmp(firstUUID, secondUUID, sizeof(firstIID)) == 0)
+ return true;
+ else
+ return false;
+}
+
+static void vboxIIDtoUtf8(virConnectPtr conn, vboxIID *iid, char **uuidstr) {
+ g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(iid, uuidstr);
+ if (!(*uuidstr))
+ virReportOOMError(conn);
+}
+
+static void vboxUtf8toIID(virConnectPtr conn, char *uuidstr, vboxIID **iid) {
+ g_pVBoxGlobalData->pFuncs->pfnUtf8ToUtf16(uuidstr, iid);
+ if (!(*iid))
+ virReportOOMError(conn);
+}
+
#endif /* !(VBOX_API_VERSION == 2002) */
static virCapsPtr vboxCapsInit(void) {
return ret;
}
+/**
+ * The Storage Functions here on
+ */
+
+static virDrvOpenStatus vboxStorageOpen (virConnectPtr conn,
+ virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED) {
+ vboxGlobalData *data = conn->privateData;
+
+ if (STRNEQ(conn->driver->name, "VBOX"))
+ goto cleanup;
+
+ if ((data->pFuncs == NULL) ||
+ (data->vboxObj == NULL) ||
+ (data->vboxSession == NULL))
+ goto cleanup;
+
+ DEBUG0("vbox storage intialized");
+ /* conn->storagePrivateData = some storage specific data */
+ return VIR_DRV_OPEN_SUCCESS;
+
+cleanup:
+ return VIR_DRV_OPEN_DECLINED;
+}
+
+static int vboxStorageClose (virConnectPtr conn) {
+ DEBUG0("vbox storage unintialized");
+ conn->storagePrivateData = NULL;
+ return 0;
+}
+
+static int vboxStorageNumOfPools(virConnectPtr conn ATTRIBUTE_UNUSED) {
+
+ /** Currently only one pool supported, the default one
+ * given by ISystemProperties::defaultHardDiskFolder()
+ */
+
+ return 1;
+}
+
+static int vboxStorageListPools(virConnectPtr conn, char **const names, int nnames) {
+ int numActive = 0;
+
+ if (nnames == 1) {
+ names[numActive] = strdup("default-pool");
+ if (names[numActive] == NULL) {
+ virReportOOMError(conn);
+ } else {
+ numActive++;
+ }
+ }
+ return numActive;
+}
+
+static virStoragePoolPtr vboxStoragePoolLookupByName(virConnectPtr conn, const char *name) {
+ virStoragePoolPtr ret = NULL;
+
+ /** Current limitation of the function: since
+ * the default pool doesn't have UUID just assign
+ * one till vbox can handle pools
+ */
+ if (STREQ("default-pool", name)) {
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ const char *uuidstr = "1deff1ff-1481-464f-967f-a50fe8936cc4";
+
+ virUUIDParse(uuidstr, uuid);
+
+ ret = virGetStoragePool(conn, name, uuid);
+ }
+
+ return ret;
+}
+
+static int vboxStoragePoolNumOfVolumes(virStoragePoolPtr pool) {
+ vboxGlobalData *data = pool->conn->privateData;
+ IHardDisk **hardDisks = NULL;
+ PRUint32 hardDiskCount = 0;
+ PRUint32 hardDiskAccessible = 0;
+ nsresult rc;
+ int i;
+
+ if(data->vboxObj) {
+ rc = data->vboxObj->vtbl->GetHardDisks(data->vboxObj, &hardDiskCount, &hardDisks);
+ if (NS_SUCCEEDED(rc)) {
+ for (i = 0; i < hardDiskCount; ++i) {
+ IHardDisk *hardDisk = hardDisks[i];
+ if (hardDisk) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible)
+ hardDiskAccessible++;
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+ }
+ hardDiskCount = 0;
+ } else {
+ hardDiskCount = -1;
+ vboxError(pool->conn, VIR_ERR_INTERNAL_ERROR,"%s:%s, rc=%08x",
+ "could not get number of volumes in the pool",
+ pool->name, (unsigned)rc);
+ }
+ }
+
+ if (hardDiskAccessible)
+ return hardDiskAccessible;
+ else
+ return hardDiskCount;
+}
+
+static int vboxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int nnames) {
+ vboxGlobalData *data = pool->conn->privateData;
+ IHardDisk **hardDisks = NULL;
+ PRUint32 hardDiskCount = 0;
+ PRUint32 numActive = 0;
+ nsresult rc;
+ int i;
+
+ if(data->vboxObj) {
+ rc = data->vboxObj->vtbl->GetHardDisks(data->vboxObj, &hardDiskCount, &hardDisks);
+ if (NS_SUCCEEDED(rc)) {
+ for (i = 0; i < hardDiskCount && numActive < nnames; ++i) {
+ IHardDisk *hardDisk = hardDisks[i];
+
+ if (hardDisk) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ char *nameUtf8 = NULL;
+ PRUnichar *nameUtf16 = NULL;
+
+ hardDisk->vtbl->imedium.GetName((IMedium *)hardDisk, &nameUtf16);
+ data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8);
+
+ if (nameUtf8) {
+ DEBUG("nnames[%d]: %s", numActive, nameUtf8);
+ names[numActive] = strdup(nameUtf8);
+ if (names[numActive] == NULL) {
+ virReportOOMError(pool->conn);
+ } else {
+ numActive++;
+ }
+
+ data->pFuncs->pfnUtf8Free(nameUtf8);
+ }
+ data->pFuncs->pfnUtf16Free(nameUtf16);
+ }
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+ }
+ hardDiskCount = 0;
+ } else {
+ hardDiskCount = -1;
+ vboxError(pool->conn, VIR_ERR_INTERNAL_ERROR,"%s:%s, rc=%08x",
+ "could not get the volume list in the pool",
+ pool->name, (unsigned)rc);
+ }
+ }
+
+ if (numActive)
+ return numActive;
+ else
+ return hardDiskCount;
+}
+
+static virStorageVolPtr vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name) {
+ vboxGlobalData *data = pool->conn->privateData;
+ IHardDisk **hardDisks = NULL;
+ virStorageVolPtr ret = NULL;
+ PRUint32 hardDiskCount = 0;
+ nsresult rc;
+ int i;
+
+ if(data->vboxObj && name) {
+ rc = data->vboxObj->vtbl->GetHardDisks(data->vboxObj, &hardDiskCount, &hardDisks);
+ if (NS_SUCCEEDED(rc)) {
+ for (i = 0; i < hardDiskCount; ++i) {
+ IHardDisk *hardDisk = hardDisks[i];
+
+ if (hardDisk) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ char *nameUtf8 = NULL;
+ PRUnichar *nameUtf16 = NULL;
+
+ hardDisk->vtbl->imedium.GetName((IMedium *)hardDisk, &nameUtf16);
+
+ if (nameUtf16) {
+ data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8);
+ data->pFuncs->pfnUtf16Free(nameUtf16);
+ }
+
+ if (nameUtf8 && STREQ(nameUtf8, name)) {
+ vboxIID *hddIID = NULL;
+ char *hddIIDUtf8 = NULL;
+
+ hardDisk->vtbl->imedium.GetId((IMedium *)hardDisk, &hddIID);
+
+ if (hddIID) {
+ vboxIIDtoUtf8(pool->conn, hddIID, &hddIIDUtf8);
+ vboxIIDUnalloc(hddIID);
+ }
+
+ if (hddIIDUtf8) {
+
+ ret = virGetStorageVol(pool->conn, pool->name, name, hddIIDUtf8);
+
+ DEBUG("virStorageVolPtr: %p", ret);
+ DEBUG("Storage Volume Name: %s", name);
+ DEBUG("Storage Volume key : %s", hddIIDUtf8);
+ DEBUG("Storage Volume Pool: %s", pool->name);
+
+ vboxIIDUtf8Free(hddIIDUtf8);
+ }
+
+ data->pFuncs->pfnUtf8Free(nameUtf8);
+ break;
+ }
+
+ if (nameUtf8)
+ data->pFuncs->pfnUtf8Free(nameUtf8);
+ }
+ }
+ }
+
+ for (i = 0; i < hardDiskCount; ++i)
+ if (hardDisks[i])
+ hardDisks[i]->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisks[i]);
+ }
+ }
+
+ return ret;
+}
+
+static virStorageVolPtr vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) {
+ vboxGlobalData *data = conn->privateData;
+ vboxIID *hddIID = NULL;
+ IHardDisk *hardDisk = NULL;
+ virStorageVolPtr ret = NULL;
+ nsresult rc;
+
+#if VBOX_API_VERSION == 2002
+ if (VIR_ALLOC(hddIID) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ if(data->vboxObj && key) {
+ unsigned char hddUUID[VIR_UUID_BUFLEN];
+
+ virUUIDParse(key, hddUUID);
+ vboxIIDFromUUID(hddUUID, hddIID);
+ {
+#else /* VBOX_API_VERSION != 2002 */
+ if(data->vboxObj && key) {
+ data->pFuncs->pfnUtf8ToUtf16(key, &hddIID);
+ if (hddIID) {
+#endif /* VBOX_API_VERSION != 2002 */
+
+ rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ PRUnichar *hddNameUtf16 = NULL;
+ char *hddNameUtf8 = NULL;
+
+ hardDisk->vtbl->imedium.GetName((IMedium *)hardDisk, &hddNameUtf16);
+ data->pFuncs->pfnUtf16ToUtf8(hddNameUtf16, &hddNameUtf8);
+
+ if (hddNameUtf8) {
+ if (vboxStorageNumOfPools(conn) == 1) {
+ ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key);
+ DEBUG("Storage Volume Pool: %s", "default-pool");
+ } else {
+ /* TODO: currently only one default pool and thus
+ * nothing here, change it when pools are supported
+ */
+ }
+
+ DEBUG("Storage Volume Name: %s", key);
+ DEBUG("Storage Volume key : %s", hddNameUtf8);
+
+ data->pFuncs->pfnUtf8Free(hddNameUtf8);
+ data->pFuncs->pfnUtf16Free(hddNameUtf16);
+ }
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+ }
+ }
+
+#if VBOX_API_VERSION == 2002
+cleanup:
+#endif
+ vboxIIDFree(hddIID);
+ return ret;
+}
+
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) {
+ vboxGlobalData *data = conn->privateData;
+ PRUnichar *hddPathUtf16 = NULL;
+ IHardDisk *hardDisk = NULL;
+ virStorageVolPtr ret = NULL;
+ nsresult rc;
+
+ if(data->vboxObj && path) {
+ data->pFuncs->pfnUtf8ToUtf16(path, &hddPathUtf16);
+
+ if (hddPathUtf16) {
+ rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ PRUnichar *hddNameUtf16 = NULL;
+ char *hddNameUtf8 = NULL;
+ vboxIID *hddIID = NULL;
+ char *hddIIDUtf8 = NULL;
+
+ hardDisk->vtbl->imedium.GetName((IMedium *)hardDisk, &hddNameUtf16);
+ hardDisk->vtbl->imedium.GetId((IMedium *)hardDisk, &hddIID);
+
+ if (hddNameUtf16) {
+ data->pFuncs->pfnUtf16ToUtf8(hddNameUtf16, &hddNameUtf8);
+ data->pFuncs->pfnUtf16Free(hddNameUtf16);
+ }
+
+ if (hddIID) {
+ vboxIIDtoUtf8(conn, hddIID, &hddIIDUtf8);
+ vboxIIDUnalloc(hddIID);
+ }
+
+ if (hddIIDUtf8 && hddNameUtf8) {
+
+ /* TODO: currently only one default pool and thus
+ * the check below, change it when pools are supported
+ */
+ if (vboxStorageNumOfPools(conn) == 1)
+ ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, hddIIDUtf8);
+
+ DEBUG("Storage Volume Pool: %s", "default-pool");
+ DEBUG("Storage Volume Name: %s", hddNameUtf8);
+ DEBUG("Storage Volume key : %s", hddIIDUtf8);
+
+ }
+
+ if (hddNameUtf8)
+ data->pFuncs->pfnUtf8Free(hddNameUtf8);
+
+ if (hddIIDUtf8)
+ vboxIIDUtf8Free(hddIIDUtf8);
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+
+ data->pFuncs->pfnUtf16Free(hddPathUtf16);
+ }
+ }
+
+ return ret;
+}
+
+static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
+ const char *xml,
+ unsigned int flags ATTRIBUTE_UNUSED) {
+ vboxGlobalData *data = pool->conn->privateData;
+ virStorageVolPtr ret = NULL;
+ virStorageVolDefPtr def = NULL;
+ virStoragePoolDef poolDef;
+ nsresult rc;
+
+ /* since there is currently one default pool now
+ * and virStorageVolDefFormat() just checks it type
+ * so just assign it for now, change the behaviour
+ * when vbox supports pools.
+ */
+ memset(&poolDef, 0, sizeof(poolDef));
+ poolDef.type = VIR_STORAGE_POOL_DIR;
+
+ if ((def = virStorageVolDefParseString(pool->conn, &poolDef, xml)) == NULL)
+ goto cleanup;
+
+ if ((data->vboxObj) && def->name && def->type == VIR_STORAGE_VOL_FILE) {
+ PRUnichar *hddFormatUtf16 = NULL;
+ PRUnichar *hddNameUtf16 = NULL;
+
+ /* TODO: for now only the vmdk, vpc and vdi type harddisk
+ * variants can be created, also since there is no vdi
+ * type in enum virStorageVolFormatFileSystem {} the default
+ * will be to create vdi if nothing is specified in
+ * def->target.format
+ */
+
+ if (def->target.format == VIR_STORAGE_VOL_FILE_VMDK) {
+ data->pFuncs->pfnUtf8ToUtf16("VMDK", &hddFormatUtf16);
+ } else if (def->target.format == VIR_STORAGE_VOL_FILE_VPC) {
+ data->pFuncs->pfnUtf8ToUtf16("VHD", &hddFormatUtf16);
+ } else {
+ data->pFuncs->pfnUtf8ToUtf16("VDI", &hddFormatUtf16);
+ }
+
+ data->pFuncs->pfnUtf8ToUtf16(def->name, &hddNameUtf16);
+
+ if (hddFormatUtf16 && hddNameUtf16) {
+ IHardDisk *hardDisk = NULL;
+
+ rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ IProgress *progress = NULL;
+ PRUint64 logicalSize = def->capacity / 1024 / 1024;
+ PRUint32 variant = HardDiskVariant_Standard;
+
+ if (def->capacity == def->allocation)
+ variant = HardDiskVariant_Fixed;
+
+ rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
+ if (NS_SUCCEEDED(rc) && progress) {
+ vboxIID *hddIID = NULL;
+#if VBOX_API_VERSION == 2002
+ nsresult resultCode;
+#else
+ PRInt32 resultCode;
+#endif
+
+ progress->vtbl->WaitForCompletion(progress, -1);
+ progress->vtbl->GetResultCode(progress, &resultCode);
+
+ if (NS_SUCCEEDED(resultCode)) {
+
+ rc = hardDisk->vtbl->imedium.GetId((IMedium *)hardDisk, &hddIID);
+ if (NS_SUCCEEDED(rc)) {
+ char *hddKey = NULL;
+
+ vboxIIDtoUtf8(pool->conn, hddIID, &hddKey);
+
+ if (hddKey)
+ ret = virGetStorageVol(pool->conn, pool->name, def->name, hddKey);
+
+ vboxIIDUtf8Free(hddKey);
+ vboxIIDUnalloc(hddIID);
+ }
+ }
+
+ progress->vtbl->nsisupports.Release((nsISupports *)progress);
+ }
+
+ }
+ }
+
+ if (hddFormatUtf16)
+ data->pFuncs->pfnUtf16Free(hddFormatUtf16);
+ if (hddNameUtf16)
+ data->pFuncs->pfnUtf16Free(hddNameUtf16);
+ }
+
+cleanup:
+ virStorageVolDefFree(def);
+ return ret;
+}
+
+
+static int vboxStorageVolDelete(virStorageVolPtr vol,
+ unsigned int flags ATTRIBUTE_UNUSED) {
+ vboxGlobalData *data = vol->conn->privateData;
+ vboxIID *hddIID = NULL;
+ IHardDisk *hardDisk = NULL;
+ int ret = -1, i = 0, j = 0;
+ int deregister = 0;
+ nsresult rc;
+
+ if(data->vboxObj && vol->key) {
+
+ vboxUtf8toIID(vol->conn, vol->key, &hddIID);
+ if (hddIID) {
+
+ rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ PRUint32 machineIdsSize = 0;
+ vboxIID **machineIds = NULL;
+
+ hardDisk->vtbl->imedium.GetMachineIds((IMedium *)hardDisk, &machineIdsSize, &machineIds);
+
+ for (i = 0; i < machineIdsSize; i++) {
+ IMachine *machine = NULL;
+
+ rc = data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, machineIds[i]);
+ if (NS_SUCCEEDED(rc)) {
+
+ rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddAttachSize = 0;
+ IHardDiskAttachment **hddAttachments = NULL;
+
+ machine->vtbl->GetHardDiskAttachments(machine, &hddAttachSize, &hddAttachments);
+ for (j = 0; j < hddAttachSize; j++) {
+ IHardDiskAttachment *hddAttachment = hddAttachments[j];
+
+ if (hddAttachment) {
+ IHardDisk *hdd = NULL;
+
+ rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd);
+ if (NS_SUCCEEDED(rc) && hdd) {
+ vboxIID *iid = NULL;
+
+ hdd->vtbl->imedium.GetId((IMedium *)hdd, &iid);
+ if (iid) {
+
+ DEBUGIID("HardDisk (to delete) UUID", hddIID);
+ DEBUGIID("HardDisk (currently processing) UUID", iid);
+
+ if (vboxIIDEqual(hddIID, iid)) {
+ PRUnichar *controller = NULL;
+ PRInt32 port = 0;
+ PRInt32 device = 0;
+
+ DEBUGIID("Found HardDisk to delete, UUID", hddIID);
+
+ hddAttachment->vtbl->GetController(hddAttachment, &controller);
+ hddAttachment->vtbl->GetPort(hddAttachment, &port);
+ hddAttachment->vtbl->GetDevice(hddAttachment, &device);
+
+ rc = machine->vtbl->DetachHardDisk(machine, controller, port, device);
+ if (NS_SUCCEEDED(rc)) {
+ rc = machine->vtbl->SaveSettings(machine);
+ DEBUG0("saving machine settings");
+ }
+
+ if (NS_SUCCEEDED(rc)) {
+ deregister++;
+ DEBUG("deregistering hdd:%d", deregister);
+ }
+
+ if (controller)
+ data->pFuncs->pfnUtf16Free(controller);
+ }
+ vboxIIDUnalloc(iid);
+ }
+ hdd->vtbl->imedium.nsisupports.Release((nsISupports *)hdd);
+ }
+ hddAttachment->vtbl->nsisupports.Release((nsISupports *)hddAttachment);
+ }
+ }
+ machine->vtbl->nsisupports.Release((nsISupports *)machine);
+ }
+ data->vboxSession->vtbl->Close(data->vboxSession);
+ }
+ }
+
+ for (i = 0; i < machineIdsSize; i++)
+ if (machineIds[i])
+ vboxIIDUnalloc(machineIds[i]);
+
+ if (machineIdsSize == 0 || machineIdsSize == deregister) {
+ IProgress *progress = NULL;
+
+ rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress);
+
+ if (NS_SUCCEEDED(rc) && progress) {
+ progress->vtbl->WaitForCompletion(progress, -1);
+ progress->vtbl->nsisupports.Release((nsISupports *)progress);
+ DEBUGIID("HardDisk deleted, UUID", hddIID);
+ ret = 0;
+ }
+ }
+
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+
+ vboxIIDUtf16Free(hddIID);
+ }
+ }
+
+ return ret;
+}
+
+static int vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) {
+ vboxGlobalData *data = vol->conn->privateData;
+ IHardDisk *hardDisk = NULL;
+ vboxIID *hddIID = NULL;
+ int ret = -1;
+ nsresult rc;
+
+ if(data->vboxObj && vol->key && info) {
+
+ vboxUtf8toIID(vol->conn, vol->key, &hddIID);
+ if (hddIID) {
+
+ rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ PRUint32 hddType;
+ PRUint64 hddLogicalSize;
+ PRUint64 hddActualSize;
+
+ hardDisk->vtbl->GetType(hardDisk, &hddType);
+ if (hddType == HardDiskType_Writethrough)
+ info->type = VIR_STORAGE_VOL_BLOCK;
+ else
+ info->type = VIR_STORAGE_VOL_FILE;
+
+ hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
+ info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
+
+ hardDisk->vtbl->imedium.GetSize((IMedium *)hardDisk, &hddActualSize);
+ info->allocation = hddActualSize;
+
+ ret = 0;
+
+ DEBUG("Storage Volume Name: %s", vol->name);
+ DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File");
+ DEBUG("Storage Volume Capacity: %llu", info->capacity);
+ DEBUG("Storage Volume Allocation: %llu", info->allocation);
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+
+ vboxIIDUtf16Free(hddIID);
+ }
+ }
+
+ return ret;
+}
+
+static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags ATTRIBUTE_UNUSED) {
+ vboxGlobalData *data = vol->conn->privateData;
+ IHardDisk *hardDisk = NULL;
+ vboxIID *hddIID = NULL;
+ char *ret = NULL;
+ virStoragePoolDef pool;
+ virStorageVolDef def;
+ int defOk = 0;
+ nsresult rc;
+
+ memset(&pool, 0, sizeof(pool));
+ memset(&def, 0, sizeof(def));
+
+ if(data->vboxObj && vol->key) {
+
+ vboxUtf8toIID(vol->conn, vol->key, &hddIID);
+ if (hddIID) {
+
+ rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ rc = hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) {
+ PRUnichar *hddFormatUtf16 = NULL;
+ PRUint64 hddLogicalSize;
+ PRUint64 hddActualSize;
+ PRUint32 hddType;
+
+ /* since there is currently one default pool now
+ * and virStorageVolDefFormat() just checks it type
+ * so just assign it for now, change the behaviour
+ * when vbox supports pools.
+ */
+ pool.type = VIR_STORAGE_POOL_DIR;
+
+ rc = hardDisk->vtbl->GetType(hardDisk, &hddType);
+ if (NS_SUCCEEDED(rc)) {
+ if (hddType == HardDiskType_Writethrough)
+ def.type = VIR_STORAGE_VOL_BLOCK;
+ else
+ def.type = VIR_STORAGE_VOL_FILE;
+ defOk = 1;
+ } else {
+ defOk = 0;
+ }
+
+ rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
+ if (NS_SUCCEEDED(rc) && defOk)
+ def.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
+ else
+ defOk = 0;
+
+ rc = hardDisk->vtbl->imedium.GetSize((IMedium *)hardDisk, &hddActualSize);
+ if (NS_SUCCEEDED(rc) && defOk)
+ def.allocation = hddActualSize;
+ else
+ defOk = 0;
+
+ def.name = strdup(vol->name);
+ if (!(def.name && defOk))
+ defOk = 0;
+
+ def.key = strdup(vol->key);
+ if (!(def.key && defOk))
+ defOk = 0;
+
+ rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16);
+ if (NS_SUCCEEDED(rc) && defOk) {
+ char *hddFormatUtf8 = NULL;
+
+ data->pFuncs->pfnUtf16ToUtf8(hddFormatUtf16, &hddFormatUtf8);
+ if (hddFormatUtf8) {
+
+ DEBUG("Storage Volume Format: %s", hddFormatUtf8);
+
+ if (STRCASEEQ("vmdk", hddFormatUtf8))
+ def.target.format = VIR_STORAGE_VOL_FILE_VMDK;
+ else if (STRCASEEQ("vhd", hddFormatUtf8))
+ def.target.format = VIR_STORAGE_VOL_FILE_VPC;
+ else
+ def.target.format = VIR_STORAGE_VOL_FILE_RAW;
+
+ /* TODO: need to add vdi to enum virStorageVolFormatFileSystem {}
+ * and then add it here
+ */
+
+ data->pFuncs->pfnUtf8Free(hddFormatUtf8);
+ }
+
+ data->pFuncs->pfnUtf16Free(hddFormatUtf16);
+ } else {
+ defOk = 0;
+ }
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+
+ vboxIIDUtf16Free(hddIID);
+ }
+ }
+
+ if (defOk)
+ ret = virStorageVolDefFormat(vol->conn, &pool, &def);
+
+ return ret;
+}
+
+static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
+ vboxGlobalData *data = vol->conn->privateData;
+ IHardDisk *hardDisk = NULL;
+ vboxIID *hddIID = NULL;
+ char *ret = NULL;
+ nsresult rc;
+
+ if(data->vboxObj && vol->key) {
+
+ vboxUtf8toIID(vol->conn, vol->key, &hddIID);
+ if (hddIID) {
+
+ rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID, &hardDisk);
+ if (NS_SUCCEEDED(rc)) {
+ PRUint32 hddstate;
+
+ hardDisk->vtbl->imedium.GetState((IMedium *)hardDisk, &hddstate);
+ if (hddstate != MediaState_Inaccessible) {
+ PRUnichar *hddLocationUtf16 = NULL;
+ char *hddLocationUtf8 = NULL;
+
+ hardDisk->vtbl->imedium.GetLocation((IMedium *)hardDisk, &hddLocationUtf16);
+
+ data->pFuncs->pfnUtf16ToUtf8(hddLocationUtf16, &hddLocationUtf8);
+ if (hddLocationUtf8) {
+
+ ret = strdup(hddLocationUtf8);
+ if (!ret)
+ virReportOOMError(vol->conn);
+
+ DEBUG("Storage Volume Name: %s", vol->name);
+ DEBUG("Storage Volume Path: %s", hddLocationUtf8);
+ DEBUG("Storage Volume Pool: %s", vol->pool);
+
+ data->pFuncs->pfnUtf8Free(hddLocationUtf8);
+ }
+
+ data->pFuncs->pfnUtf16Free(hddLocationUtf16);
+ }
+
+ hardDisk->vtbl->imedium.nsisupports.Release((nsISupports *)hardDisk);
+ }
+
+ vboxIIDUtf16Free(hddIID);
+ }
+ }
+
+ return ret;
+}
/**
* Function Tables
.networkGetAutostart = NULL,
.networkSetAutostart = NULL
};
+
+virStorageDriver NAME(StorageDriver) = {
+ .name = "VBOX",
+ .open = vboxStorageOpen,
+ .close = vboxStorageClose,
+ .numOfPools = vboxStorageNumOfPools,
+ .listPools = vboxStorageListPools,
+ .numOfDefinedPools = NULL,
+ .listDefinedPools = NULL,
+ .findPoolSources = NULL,
+ .poolLookupByName = vboxStoragePoolLookupByName,
+ .poolLookupByUUID = NULL,
+ .poolLookupByVolume = NULL,
+ .poolCreateXML = NULL,
+ .poolDefineXML = NULL,
+ .poolBuild = NULL,
+ .poolUndefine = NULL,
+ .poolCreate = NULL,
+ .poolDestroy = NULL,
+ .poolDelete = NULL,
+ .poolRefresh = NULL,
+ .poolGetInfo = NULL,
+ .poolGetXMLDesc = NULL,
+ .poolGetAutostart = NULL,
+ .poolSetAutostart = NULL,
+ .poolNumOfVolumes = vboxStoragePoolNumOfVolumes,
+ .poolListVolumes = vboxStoragePoolListVolumes,
+
+ .volLookupByName = vboxStorageVolLookupByName,
+ .volLookupByKey = vboxStorageVolLookupByKey,
+ .volLookupByPath = vboxStorageVolLookupByPath,
+ .volCreateXML = vboxStorageVolCreateXML,
+ .volCreateXMLFrom = NULL,
+ .volDelete = vboxStorageVolDelete,
+ .volGetInfo = vboxStorageVolGetInfo,
+ .volGetXMLDesc = vboxStorageVolGetXMLDesc,
+ .volGetPath = vboxStorageVolGetPath,
+};