New APIs are added allowing streaming of content to/from
storage volumes.
* include/libvirt/libvirt.h.in: Add virStorageVolUpload and
virStorageVolDownload APIs
* src/driver.h, src/libvirt.c, src/libvirt_public.syms: Stub
code for new APIs
* src/storage/storage_driver.c, src/esx/esx_storage_driver.c:
Add dummy entries in driver table for new APIs
---
include/libvirt/libvirt.h.in | 10 +++
include/libvirt/virterror.h | 1 +
src/driver.h | 14 ++++
src/esx/esx_storage_driver.c | 2 +
src/libvirt.c | 140 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 2 +
src/storage/storage_driver.c | 2 +
src/util/virterror.c | 6 ++
8 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 1cf9273..bd36015 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1504,6 +1504,16 @@ virStorageVolPtr virStorageVolCreateXMLFrom
(virStoragePoolPtr pool,
const char *xmldesc,
virStorageVolPtr clonevol,
unsigned int flags);
+int virStorageVolDownload (virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags);
+int virStorageVolUpload (virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags);
int virStorageVolDelete (virStorageVolPtr vol,
unsigned int flags);
int virStorageVolWipe (virStorageVolPtr vol,
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 1d8275b..59f7731 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -230,6 +230,7 @@ typedef enum {
VIR_ERR_HOOK_SCRIPT_FAILED = 70, /* a synchronous hook script failed */
VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71,/* invalid domain snapshot */
VIR_ERR_NO_DOMAIN_SNAPSHOT = 72, /* domain snapshot not found */
+ VIR_ERR_INVALID_STREAM = 73 /* stream pointer not valid */
} virErrorNumber;
/**
diff --git a/src/driver.h b/src/driver.h
index 286130a..e5f91ca 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -905,6 +905,18 @@ typedef virStorageVolPtr
const char *xmldesc,
virStorageVolPtr clone,
unsigned int flags);
+typedef int
+ (*virDrvStorageVolDownload) (virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags);
+typedef int
+ (*virDrvStorageVolUpload) (virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags);
typedef int
(*virDrvStoragePoolIsActive)(virStoragePoolPtr pool);
@@ -959,6 +971,8 @@ struct _virStorageDriver {
virDrvStorageVolLookupByPath volLookupByPath;
virDrvStorageVolCreateXML volCreateXML;
virDrvStorageVolCreateXMLFrom volCreateXMLFrom;
+ virDrvStorageVolDownload volDownload;
+ virDrvStorageVolUpload volUpload;
virDrvStorageVolDelete volDelete;
virDrvStorageVolWipe volWipe;
virDrvStorageVolGetInfo volGetInfo;
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 136a90b..9e4dd9e 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -1671,6 +1671,8 @@ static virStorageDriver esxStorageDriver = {
esxStorageVolumeLookupByPath, /* volLookupByPath */
esxStorageVolumeCreateXML, /* volCreateXML */
esxStorageVolumeCreateXMLFrom, /* volCreateXMLFrom */
+ NULL, /* volDownload */
+ NULL, /* volUpload */
esxStorageVolumeDelete, /* volDelete */
esxStorageVolumeWipe, /* volWipe */
esxStorageVolumeGetInfo, /* volGetInfo */
diff --git a/src/libvirt.c b/src/libvirt.c
index e46c18b..d2f18d3 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -9066,6 +9066,146 @@ error:
/**
+ * virStorageVolDownload:
+ * @vol: pointer to volume to download from
+ * @stream: stream to use as output
+ * @offset: position in @vol to start reading from
+ * @length: limit on amount of data to download
+ * @flags: future flags (unused, pass 0)
+ *
+ * Download the content of the volume as a stream. If @length
+ * is zero, then the remaining contents of the volume after
+ * @offset will be downloaded.
+ *
+ * This call sets up an asynchronous stream; subsequent use of
+ * stream APIs is necessary to transfer the actual data,
+ * determine how much data is successfully transferred, and
+ * detect any errors. The results will be unpredictable if
+ * another active stream is writing to the storage volume.
+ *
+ * Returns 0, or -1 upon error.
+ */
+int
+virStorageVolDownload(virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags)
+{
+ VIR_DEBUG("vol=%p stream=%p offset=%llu length=%llu flags=%u",
+ vol, stream, offset, length, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_STORAGE_VOL(vol)) {
+ virLibConnError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+ return -1;
+ }
+
+ if (!VIR_IS_STREAM(stream)) {
+ virLibConnError(VIR_ERR_INVALID_STREAM, __FUNCTION__);
+ return -1;
+ }
+
+ if (vol->conn->flags & VIR_CONNECT_RO ||
+ stream->conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (vol->conn->storageDriver &&
+ vol->conn->storageDriver->volDownload) {
+ int ret;
+ ret = vol->conn->storageDriver->volDownload(vol,
+ stream,
+ offset,
+ length,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(vol->conn);
+ return -1;
+}
+
+
+/**
+ * virStorageVolUpload:
+ * @vol: pointer to volume to download
+ * @stream: stream to use as output
+ * @offset: position to start writing to
+ * @length: limit on amount of data to upload
+ * @flags: flags for creation (unused, pass 0)
+ *
+ * Upload new content to the volume from a stream. This call
+ * will fail if @offset + @length exceeds the size of the
+ * volume. Otherwise, if @length is non-zero, and an error
+ * will be raised if an attempt is made to upload greater
+ * than @length bytes of data.
+ *
+ * This call sets up an asynchronous stream; subsequent use of
+ * stream APIs is necessary to transfer the actual data,
+ * determine how much data is successfully transferred, and
+ * detect any errors. The results will be unpredictable if
+ * another active stream is writing to the storage volume.
+ *
+ * Returns 0, or -1 upon error.
+ */
+int
+virStorageVolUpload(virStorageVolPtr vol,
+ virStreamPtr stream,
+ unsigned long long offset,
+ unsigned long long length,
+ unsigned int flags)
+{
+ VIR_DEBUG("vol=%p stream=%p offset=%llu length=%llu flags=%u",
+ vol, stream, offset, length, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_STORAGE_VOL(vol)) {
+ virLibConnError(VIR_ERR_INVALID_STORAGE_VOL, __FUNCTION__);
+ return -1;
+ }
+
+ if (!VIR_IS_STREAM(stream)) {
+ virLibConnError(VIR_ERR_INVALID_STREAM, __FUNCTION__);
+ return -1;
+ }
+
+ if (vol->conn->flags & VIR_CONNECT_RO ||
+ stream->conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (vol->conn->storageDriver &&
+ vol->conn->storageDriver->volUpload) {
+ int ret;
+ ret = vol->conn->storageDriver->volUpload(vol,
+ stream,
+ offset,
+ length,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(vol->conn);
+ return -1;
+}
+
+
+/**
* virStorageVolDelete:
* @vol: pointer to storage volume
* @flags: future flags, use 0 for now
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 5caab4c..b4aed41 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -432,6 +432,8 @@ LIBVIRT_0.9.0 {
virDomainSetMemoryFlags;
virEventRegisterDefaultImpl;
virEventRunDefaultImpl;
+ virStorageVolDownload;
+ virStorageVolUpload;
} LIBVIRT_0.8.8;
# .... define new API here using predicted next version number ....
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 5373025..ce528cf 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1989,6 +1989,8 @@ static virStorageDriver storageDriver = {
.volLookupByPath = storageVolumeLookupByPath,
.volCreateXML = storageVolumeCreateXML,
.volCreateXMLFrom = storageVolumeCreateXMLFrom,
+ .volDownload = NULL,
+ .volUpload = NULL,
.volDelete = storageVolumeDelete,
.volWipe = storageVolumeWipe,
.volGetInfo = storageVolumeGetInfo,
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 160c953..b7d8924 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -1201,6 +1201,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("Domain snapshot not found: %s");
break;
+ case VIR_ERR_INVALID_STREAM:
+ if (info == NULL)
+ errmsg = _("invalid stream pointer");
+ else
+ errmsg = _("invalid stream pointer in %s");
+ break;
}
return (errmsg);
}
--
1.7.4