提交 0cd409cd 编写于 作者: T Taowei Luo 提交者: Michal Privoznik

vbox: Rewrite vboxStorageVolCreateXML

If the <path> in target element is not given, libvirt will put the
new volume in ~/.VirtualBox by default.
上级 382e655d
......@@ -290,6 +290,16 @@ enum MediaState
MediaState_Deleting = 6
};
enum HardDiskVariant
{
HardDiskVariant_Standard = 0,
HardDiskVariant_VmdkSplit2G = 0x01,
HardDiskVariant_VmdkStreamOptimized = 0x04,
HardDiskVariant_VmdkESX = 0x08,
HardDiskVariant_Fixed = 0x10000,
HardDiskVariant_Diff = 0x20000
};
# define VBOX_E_OBJECT_NOT_FOUND 0x80BB0001
# define VBOX_E_INVALID_VM_STATE 0x80BB0002
# define VBOX_E_VM_ERROR 0x80BB0003
......
......@@ -26,6 +26,7 @@
#include "domain_event.h"
#include "virlog.h"
#include "virstring.h"
#include "storage_conf.h"
#include "vbox_common.h"
#include "vbox_uniformed_api.h"
......@@ -420,3 +421,112 @@ virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const char *path
VBOX_UTF16_FREE(hddPathUtf16);
return ret;
}
virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
const char *xml, unsigned int flags)
{
vboxGlobalData *data = pool->conn->privateData;
virStorageVolDefPtr def = NULL;
PRUnichar *hddFormatUtf16 = NULL;
PRUnichar *hddNameUtf16 = NULL;
virStoragePoolDef poolDef;
nsresult rc;
vboxIIDUnion hddIID;
unsigned char uuid[VIR_UUID_BUFLEN];
char key[VIR_UUID_STRING_BUFLEN] = "";
IHardDisk *hardDisk = NULL;
IProgress *progress = NULL;
PRUint64 logicalSize = 0;
PRUint32 variant = HardDiskVariant_Standard;
resultCodeUnion resultCode;
virStorageVolPtr ret = NULL;
if (!data->vboxObj) {
return ret;
}
virCheckFlags(0, NULL);
/* 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(&poolDef, xml)) == NULL)
goto cleanup;
if (!def->name ||
(def->type != VIR_STORAGE_VOL_FILE))
goto cleanup;
/* For now only the vmdk, vpc and vdi type harddisk
* variants can be created. For historical reason, we default to vdi */
if (def->target.format == VIR_STORAGE_FILE_VMDK) {
VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
} else if (def->target.format == VIR_STORAGE_FILE_VPC) {
VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
} else {
VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
}
/* If target.path isn't given, use default path ~/.VirtualBox/image_name */
if (def->target.path == NULL &&
virAsprintf(&def->target.path, "%s/.VirtualBox/%s", virGetUserDirectory(), def->name) < 0)
goto cleanup;
VBOX_UTF8_TO_UTF16(def->target.path, &hddNameUtf16);
if (!hddFormatUtf16 || !hddNameUtf16)
goto cleanup;
rc = gVBoxAPI.UIVirtualBox.CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
if (NS_FAILED(rc)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not create harddisk, rc=%08x"),
(unsigned)rc);
goto cleanup;
}
logicalSize = VIR_DIV_UP(def->target.capacity, 1024 * 1024);
if (def->target.capacity == def->target.allocation)
variant = HardDiskVariant_Fixed;
rc = gVBoxAPI.UIHardDisk.CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
if (NS_FAILED(rc) || !progress) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not create base storage, rc=%08x"),
(unsigned)rc);
goto cleanup;
}
gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode);
if (RC_FAILED(resultCode)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not create base storage, rc=%08x"),
(unsigned)resultCode.uResultCode);
goto cleanup;
}
VBOX_IID_INITIALIZE(&hddIID);
rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
if (NS_FAILED(rc))
goto cleanup;
vboxIIDToUUID(&hddIID, uuid);
virUUIDFormat(uuid, key);
ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
NULL, NULL);
cleanup:
vboxIIDUnalloc(&hddIID);
VBOX_RELEASE(progress);
VBOX_UTF16_FREE(hddFormatUtf16);
VBOX_UTF16_FREE(hddNameUtf16);
virStorageVolDefFree(def);
return ret;
}
......@@ -2034,104 +2034,6 @@ _registerDomainEvent(virHypervisorDriverPtr driver)
* The Storage Functions here on
*/
static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
const char *xml,
unsigned int flags)
{
VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL);
virStorageVolDefPtr def = NULL;
PRUnichar *hddFormatUtf16 = NULL;
PRUnichar *hddNameUtf16 = NULL;
virStoragePoolDef poolDef;
nsresult rc;
virCheckFlags(0, NULL);
/* 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(&poolDef, xml)) == NULL)
goto cleanup;
if (!def->name ||
(def->type != VIR_STORAGE_VOL_FILE))
goto cleanup;
/* For now only the vmdk, vpc and vdi type harddisk
* variants can be created. For historical reason, we default to vdi */
if (def->target.format == VIR_STORAGE_FILE_VMDK) {
VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
} else if (def->target.format == VIR_STORAGE_FILE_VPC) {
VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
} else {
VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
}
VBOX_UTF8_TO_UTF16(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 = VIR_DIV_UP(def->target.capacity,
1024 * 1024);
PRUint32 variant = HardDiskVariant_Standard;
if (def->target.capacity == def->target.allocation)
variant = HardDiskVariant_Fixed;
#if VBOX_API_VERSION < 4003000
rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
#else
rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress);
#endif
if (NS_SUCCEEDED(rc) && progress) {
#if VBOX_API_VERSION == 2002000
nsresult resultCode;
#else
PRInt32 resultCode;
#endif
progress->vtbl->WaitForCompletion(progress, -1);
progress->vtbl->GetResultCode(progress, &resultCode);
if (NS_SUCCEEDED(resultCode)) {
vboxIID hddIID = VBOX_IID_INITIALIZER;
unsigned char uuid[VIR_UUID_BUFLEN];
char key[VIR_UUID_STRING_BUFLEN] = "";
rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
if (NS_SUCCEEDED(rc)) {
vboxIIDToUUID(&hddIID, uuid);
virUUIDFormat(uuid, key);
ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
NULL, NULL);
}
vboxIIDUnalloc(&hddIID);
}
VBOX_RELEASE(progress);
}
}
}
VBOX_UTF16_FREE(hddFormatUtf16);
VBOX_UTF16_FREE(hddNameUtf16);
cleanup:
virStorageVolDefFree(def);
return ret;
}
static int vboxStorageVolDelete(virStorageVolPtr vol,
unsigned int flags)
{
......@@ -5123,6 +5025,17 @@ _dhcpServerStop(IDHCPServer *dhcpServer)
return dhcpServer->vtbl->Stop(dhcpServer);
}
static nsresult
_hardDiskCreateBaseStorage(IHardDisk *hardDisk, PRUint64 logicalSize,
PRUint32 variant, IProgress **progress)
{
#if VBOX_API_VERSION < 4003000
return hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, progress);
#else
return hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, progress);
#endif
}
static bool _machineStateOnline(PRUint32 state)
{
return ((state >= MachineState_FirstOnline) &&
......@@ -5464,6 +5377,10 @@ static vboxUniformedIDHCPServer _UIDHCPServer = {
.Stop = _dhcpServerStop,
};
static vboxUniformedIHardDisk _UIHardDisk = {
.CreateBaseStorage = _hardDiskCreateBaseStorage,
};
static uniformedMachineStateChecker _machineStateChecker = {
.Online = _machineStateOnline,
.Inactive = _machineStateInactive,
......@@ -5520,6 +5437,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->UIHost = _UIHost;
pVBoxAPI->UIHNInterface = _UIHNInterface;
pVBoxAPI->UIDHCPServer = _UIDHCPServer;
pVBoxAPI->UIHardDisk = _UIHardDisk;
pVBoxAPI->machineStateChecker = _machineStateChecker;
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
......
......@@ -517,6 +517,14 @@ typedef struct {
nsresult (*Stop)(IDHCPServer *dhcpServer);
} vboxUniformedIDHCPServer;
/* Functions for IHardDisk, in vbox3.1 and later, it will call the
* corresponding functions in IMedium as IHardDisk does't exist in
* these versions. */
typedef struct {
nsresult (*CreateBaseStorage)(IHardDisk *hardDisk, PRUint64 logicalSize,
PRUint32 variant, IProgress **progress);
} vboxUniformedIHardDisk;
typedef struct {
bool (*Online)(PRUint32 state);
bool (*Inactive)(PRUint32 state);
......@@ -574,6 +582,7 @@ typedef struct {
vboxUniformedIHost UIHost;
vboxUniformedIHNInterface UIHNInterface;
vboxUniformedIDHCPServer UIDHCPServer;
vboxUniformedIHardDisk UIHardDisk;
uniformedMachineStateChecker machineStateChecker;
/* vbox API features */
bool domainEventCallbacks;
......@@ -602,6 +611,8 @@ int vboxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int n
virStorageVolPtr vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name);
virStorageVolPtr vboxStorageVolLookupByKey(virConnectPtr conn, const char *key);
virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const char *path);
virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
const char *xml, unsigned int flags);
/* Version specified functions for installing uniformed API */
void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册