mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 22:25:25 +00:00
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:
parent
0cf672fa91
commit
6b50bbea00
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user