mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-23 04:55:18 +00:00
vbox: Rewrite vboxStorageVolCreateXML
If the <path> in target element is not given, libvirt will put the new volume in ~/.VirtualBox by default.
This commit is contained in:
parent
382e655d16
commit
0cd409cdb3
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user