<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>