If the <path> in target element is not given, libvirt will put the
new volume in ~/.VirtualBox by default.
---
src/vbox/vbox_common.h | 10 ++++
src/vbox/vbox_storage.c | 110 +++++++++++++++++++++++++++++++++++++++
src/vbox/vbox_tmpl.c | 114 ++++++-----------------------------------
src/vbox/vbox_uniformed_api.h | 11 ++++
4 files changed, 147 insertions(+), 98 deletions(-)
diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h
index 9af3129..d318921 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 1878139..1e6ca67 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 c6f027e..7c14c0d 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 39d5d98..d0403ad 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);
--
1.7.9.5