VBox add Storage Volume support

* src/vbox/vbox_driver.c src/vbox/vbox_tmpl.c: adds the driver for
  storage volumes
This commit is contained in:
Pritesh Kothari 2009-09-04 16:28:52 +02:00 committed by Daniel Veillard
parent 0cf672fa91
commit 6b50bbea00
2 changed files with 933 additions and 7 deletions

View File

@ -41,8 +41,10 @@
extern virDriver vbox22Driver;
extern virNetworkDriver vbox22NetworkDriver;
extern virStorageDriver vbox22StorageDriver;
extern virDriver vbox30Driver;
extern virNetworkDriver vbox30NetworkDriver;
extern virStorageDriver vbox30StorageDriver;
static virDriver vboxDriverDummy;
@ -55,6 +57,7 @@ static virDriver vboxDriverDummy;
int vboxRegister(void) {
virDriverPtr driver;
virNetworkDriverPtr networkDriver;
virStorageDriverPtr storageDriver;
uint32_t uVersion;
/*
@ -65,6 +68,7 @@ int vboxRegister(void) {
*/
driver = &vboxDriverDummy;
networkDriver = &vbox22NetworkDriver;
storageDriver = &vbox22StorageDriver;
/* Init the glue and get the API version. */
if (VBoxCGlueInit() == 0) {
@ -83,10 +87,12 @@ int vboxRegister(void) {
DEBUG0("VirtualBox API version: 2.2");
driver = &vbox22Driver;
networkDriver = &vbox22NetworkDriver;
storageDriver = &vbox22StorageDriver;
} else if (uVersion >= 2002051 && uVersion < 3000051) {
DEBUG0("VirtualBox API version: 3.0");
driver = &vbox30Driver;
networkDriver = &vbox30NetworkDriver;
storageDriver = &vbox30StorageDriver;
} else {
DEBUG0("Unsupport VirtualBox API version");
}
@ -99,6 +105,8 @@ int vboxRegister(void) {
return -1;
if (virRegisterNetworkDriver(networkDriver) < 0)
return -1;
if (virRegisterStorageDriver(storageDriver) < 0)
return -1;
return 0;
}

View File

@ -44,6 +44,7 @@
#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"
@ -159,6 +160,15 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
}
#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];
@ -241,16 +251,39 @@ static void nsIDFromChar(nsID *iid, const unsigned char *uuid) {
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;
}
static void vboxIIDtoUtf8(virConnectPtr conn, vboxIID *iid, char **uuidstr) {
unsigned char hddUUID[VIR_UUID_BUFLEN];
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) */
typedef PRUnichar vboxIID;
#define vboxIIDFromUUID(uuid, iid)\
{\
char vboxIIDUtf8[VIR_UUID_STRING_BUFLEN];\
@ -268,9 +301,56 @@ typedef PRUnichar vboxIID;
}
#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) {
@ -5475,6 +5555,806 @@ cleanup:
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
@ -5576,3 +6456,41 @@ virNetworkDriver NAME(NetworkDriver) = {
.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,
};