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