[libvirt] [PATCH 13/20] vbox: Rewrite vboxStorageVolCreateXML

Taowei uaedante at gmail.com
Wed Aug 20 12:46:27 UTC 2014


If the <path> in target is not given, the volume will be put in
~/.VirtualBox by default.
---
 src/vbox/vbox_common.c        |  105 +++++++++++++++++++++++++++++++++++++
 src/vbox/vbox_common.h        |   10 ++++
 src/vbox/vbox_tmpl.c          |  114 ++++++-----------------------------------
 src/vbox/vbox_uniformed_api.h |   11 ++++
 4 files changed, 142 insertions(+), 98 deletions(-)

diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index f1ec7f4..75e41fb 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -36,6 +36,7 @@
 #include "fdstream.h"
 #include "configmake.h"
 #include "network_conf.h"
+#include "storage_conf.h"
 
 #include "vbox_common.h"
 #include "vbox_uniformed_api.h"
@@ -8650,6 +8651,110 @@ virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const char *path
     return ret;
 }
 
+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;
+    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;
+
+    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;
+}
+
 /**
  * Function Tables
  */
diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h
index 71592c9..ce3a5d1 100644
--- a/src/vbox/vbox_common.h
+++ b/src/vbox/vbox_common.h
@@ -289,6 +289,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_tmpl.c b/src/vbox/vbox_tmpl.c
index 5aa1677..6bb12ef 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -2022,104 +2022,6 @@ _registerDomainEvent(virDriverPtr 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)
 {
@@ -5109,6 +5011,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) &&
@@ -5450,6 +5363,10 @@ static vboxUniformedIDHCPServer _UIDHCPServer = {
     .Stop = _dhcpServerStop,
 };
 
+static vboxUniformedIHardDisk _UIHardDisk = {
+    .CreateBaseStorage = _hardDiskCreateBaseStorage,
+};
+
 static uniformedMachineStateChecker _machineStateChecker = {
     .Online = _machineStateOnline,
     .Inactive = _machineStateInactive,
@@ -5506,6 +5423,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 8a2a96b..781c312 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




More information about the libvir-list mailing list