diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 9af3129d67e012a045efa880c5eab305eeeecf53..d31892182064f3cf439f93193d22dc730b29eb61 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -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 diff --git a/src/vbox/vbox_storage.c b/src/vbox/vbox_storage.c index 1878139e163f6fbeb426a0ea515566584059dd4b..1e6ca674ba18f0eaf37518be0ca75b7d7540cd25 100644 --- a/src/vbox/vbox_storage.c +++ b/src/vbox/vbox_storage.c @@ -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; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c6f027ef3754e5b5e75720c1203a846a41c5f513..7c14c0d46d6d6320b33fa6c98bc9bbd560da222b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -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 diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 39d5d98ead0e165e6e620d7e9ceabd8a925ca7ca..d0403ad6d6be3e3109cf9acda890ac5af288a53e 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -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);