<html>
<head>
</head>
<body class='hmmessage'><div dir='ltr'>


<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Tahoma
}
--></style>
<div dir="ltr">


Patch to add API to upload Volume contents using ESX driver. As stream driver is not supported for ESX, I have used libcurl to transfer the volume, second, using flags here to pass <br>file descriptor of the source file.<br> <br>diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c<br>index 9b64891..0519efc 100644<br>--- a/src/esx/esx_storage_driver.c<br>+++ b/src/esx/esx_storage_driver.c<br>@@ -1643,6 +1643,94 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)<br>     return 1;<br> }<br> <br>+/**<br>+ * esxStorageVolumeUpload<br>+ *<br>+ * Upload file contents to a given volume. <br>+ * Method uses libcurl to POST the contents to ESX server.<br>+ * flags is used to pass file descriptor of the <br>+ * source file to be read.<br>+ */<br>+static int<br>+esxStorageVolumeUpload(virStorageVolPtr volume,<br>+                       virStreamPtr stream,<br>+                       unsigned long long offset,<br>+                       unsigned long long length,<br>+                       unsigned int flags)<br>+{<br>+    esxPrivate *priv = volume->conn->privateData;<br>+    int err = -1;<br>+    char *escapedDatastoreName = NULL;<br>+    char *url = NULL;<br>+    virBuffer buffer = VIR_BUFFER_INITIALIZER;<br>+    int fd = (int)flags;<br>+<br>+    /**<br>+     * Use CURL module to transfer the file to ESX. <br>+     * Use flags to pass the file handle.<br>+     */<br>+    const char *unescapedDatastoreName = virStorageVolGetPoolName(volume);<br>+    const char *volumeName = virStorageVolGetName(volume);<br>+<br>+    if (!unescapedDatastoreName) {<br>+        goto cleanup;<br>+    }<br>+<br>+    if (volume->conn != stream->conn) {<br>+        virReportInvalidArg(conn,<br>+                _("conn in %s must match stream connection."),<br>+                __FUNCTION__);<br>+        goto cleanup;<br>+    }<br>+   <br>+    virBufferAsprintf(&buffer, "%s://%s:%d/folder/", <br>+            priv->parsedUri->transport,<br>+            volume->conn->uri->server, volume->conn->uri->port);<br>+<br>+    escapedDatastoreName = esxUtil_EscapeDatastoreItem(unescapedDatastoreName);<br>+<br>+    if (escapedDatastoreName == NULL) {<br>+        goto cleanup;<br>+    }<br>+<br>+    /* Prepare URL to upload file */<br>+    virBufferAdd(&buffer, volumeName, strlen(volumeName));<br>+    virBufferAddLit(&buffer, "?dcPath=");<br>+    virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);<br>+    virBufferAddLit(&buffer, "&dsName=");<br>+    virBufferURIEncodeString(&buffer, escapedDatastoreName);<br>+<br>+    if (virBufferError(&buffer)) {<br>+        virReportOOMError();<br>+        goto cleanup;<br>+    }<br>+<br>+    url = virBufferContentAndReset(&buffer);<br>+<br>+    if (esxVI_EnsureSession(priv->primary) < 0) {<br>+        return -1;<br>+    }   <br>+<br>+    /* Upload file */<br>+    if (esxVI_CURL_UploadFile(priv->primary->curl, url, <br>+                              fd, offset, length) < 0) {<br>+        goto cleanup;<br>+    }<br>+<br>+    err = 0;<br>+<br>+  cleanup:<br>+<br>+    if (url == NULL) {<br>+        virBufferFreeAndReset(&buffer);<br>+    }<br>+<br>+    VIR_FREE(escapedDatastoreName);<br>+    VIR_FREE(url);<br>+<br>+    return err;<br>+<br>+}<br> <br> <br> static virStorageDriver esxStorageDriver = {<br>@@ -1673,6 +1761,7 @@ static virStorageDriver esxStorageDriver = {<br>     .volGetInfo = esxStorageVolumeGetInfo, /* 0.8.4 */<br>     .volGetXMLDesc = esxStorageVolumeGetXMLDesc, /* 0.8.4 */<br>     .volGetPath = esxStorageVolumeGetPath, /* 0.8.4 */<br>+    .volUpload = esxStorageVolumeUpload, /* 0.9.x */<br>     .poolIsActive = esxStoragePoolIsActive, /* 0.8.2 */<br>     .poolIsPersistent = esxStoragePoolIsPersistent, /* 0.8.2 */<br> };<br>diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c<br>index 5b5ab69..831ae36 100644<br>--- a/src/esx/esx_vi.c<br>+++ b/src/esx/esx_vi.c<br>@@ -425,7 +425,67 @@ esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content)<br>     return 0;<br> }<br> <br>+static size_t<br>+esxVI_CURL_read_callback(void *ptr, size_t size, size_t nmemb, void *stream)<br>+{<br>+    size_t retcode = read((int) stream, ptr, size*nmemb);<br>+<br>+    VIR_DEBUG("Read bytes: %d", retcode);<br>+<br>+    return retcode;<br>+}<br>+<br>+int <br>+esxVI_CURL_UploadFile(esxVI_CURL *curl, <br>+                      const char *url, <br>+                      int fd, <br>+                      unsigned long long offset,<br>+                      unsigned long long length)<br>+{                      <br>+    int error = -1;<br>+    int responseCode = 0;<br>+<br>+    if (fd < 0) {<br>+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "Invalid file descriptor: %d",<br>+                     fd);<br>+        goto cleanup;<br>+    }<br>+    <br>+    if (lseek(fd, (off_t) offset, SEEK_SET) < 0) {<br>+        virReportSystemError(errno, "%s",<br>+                _("Cannot seek file descriptor "));<br>+        goto cleanup;<br>+    }<br>+<br>+    virMutexLock(&curl->lock);<br>+<br>+    /* set CURL headers */<br>+    curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1L);<br>+    curl_easy_setopt(curl->handle, CURLOPT_URL, url);<br>+    curl_easy_setopt(curl->handle, CURLOPT_READDATA, fd);<br>+    curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE_LARGE, <br>+                     (curl_off_t) length);<br>+    curl_easy_setopt(curl->handle, CURLOPT_READFUNCTION, <br>+                     esxVI_CURL_read_callback);<br> <br>+    responseCode = esxVI_CURL_Perform(curl, url);<br>+<br>+    virMutexUnlock(&curl->lock);<br>+<br>+    if (responseCode < 0) {<br>+        goto cleanup;<br>+    } else if (responseCode != 200) {<br>+        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,<br>+                     _("HTTP response code %d for upload to '%s'"),<br>+                     responseCode, url);<br>+        goto cleanup;<br>+    }<br>+    error = 0;<br>+<br>+ cleanup:<br>+<br>+    return error;<br>+}<br> <br> /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *<br>  * SharedCURL<br>diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h<br>index 78d3986..f95ad1d 100644<br>--- a/src/esx/esx_vi.h<br>+++ b/src/esx/esx_vi.h<br>@@ -92,7 +92,6 @@ typedef struct _esxVI_EnumerationValue esxVI_EnumerationValue;<br> typedef struct _esxVI_List esxVI_List;<br> <br> <br>-<br> enum _esxVI_APIVersion {<br>     esxVI_APIVersion_Undefined = 0,<br>     esxVI_APIVersion_Unknown,<br>@@ -167,6 +166,9 @@ void esxVI_CURL_Free(esxVI_CURL **curl);<br> int esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri);<br> int esxVI_CURL_Download(esxVI_CURL *curl, const char *url, char **content);<br> int esxVI_CURL_Upload(esxVI_CURL *curl, const char *url, const char *content);<br>+int esxVI_CURL_UploadFile(esxVI_CURL *curl, const char *url, int fd, <br>+                          unsigned long long offset,<br>+                          unsigned long long length);<br> <br> <br> <br>diff --git a/src/libvirt.c b/src/libvirt.c<br>index 0aa50cb..508593b 100644<br>--- a/src/libvirt.c<br>+++ b/src/libvirt.c<br>@@ -12537,6 +12537,28 @@ error:<br>     return NULL;<br> }<br> <br>+/**<br>+ * virStorageVolGetPoolName:<br>+ * @vol: pointer to storage volume<br>+ *<br>+ * Fetch the storage volume pool name.<br>+ *<br>+ * Returns the pool name, or NULL on error<br>+ */<br>+const char*<br>+virStorageVolGetPoolName(virStorageVolPtr vol)<br>+{<br>+    VIR_DEBUG("vol=%p", vol);<br>+<br>+    virResetLastError();<br>+<br>+    if (!VIR_IS_STORAGE_VOL(vol)) {<br>+        virLibStorageVolError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);<br>+        virDispatchError(NULL);<br>+        return NULL;<br>+    }<br>+    return vol->pool;<br>+}<br> <br> /**<br>  * virStorageVolGetName:<br>diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms<br>index 2913a81..cdfbf15 100644<br>--- a/src/libvirt_public.syms<br>+++ b/src/libvirt_public.syms<br>@@ -542,6 +542,7 @@ LIBVIRT_0.9.13 {<br>         virDomainSnapshotIsCurrent;<br>         virDomainSnapshotListAllChildren;<br>         virDomainSnapshotRef;<br>+        virStorageVolGetPoolName;<br> } LIBVIRT_0.9.11;<br> <br> # .... define new API here using predicted next version number ....<br> <br>Thanks!<br>Ata<br> <br>Attachment:<br>1. StorageVolUpload.diff<br><br></div>
                                          </div></body>
</html>