This patch brings support to manage sheepdog pools and volumes to libvirt.
It uses the "collie" command-line utility that comes with sheepdog for that.
A sheepdog pool in libvirt maps to a sheepdog cluster.
It needs a host and port to connect to, which in most cases
is just going to be the default of localhost on port 7000.
A sheepdog volume in libvirt maps to a sheepdog vdi.
To create one specify the pool, a name and the capacity.
Volumes can also be resized later.
In the volume XML the vdi name is prefixed with "sheepdog:"
and put into the <target><path>. To use the volume as a disk source for
virtual machines specify the vdi name as "name" attribute of the
<source>.
The host and port information from the pool are specified inside the host tag.
<disk type='network'>
...
<source protocol="sheepdog" name="vdi_name">
<host name="localhost" port="7000"/>
</source>
</disk>
To work right this patch parses the output of collie,
so it relies on the raw output option. There recently was a bug which caused
size information to be reported wrong. This is fixed upstream already and
will be in the next release.
Signed-off-by: Sebastian Wiedenroth <wiedi(a)frubar.net>
---
configure.ac | 23 ++
docs/drivers.html.in | 1 +
docs/schemas/storagepool.rng | 17 ++
docs/schemas/storagevol.rng | 3 +-
docs/storage.html.in | 62 +++++
libvirt.spec.in | 35 ++-
po/POTFILES.in | 1 +
src/Makefile.am | 8 +
src/conf/storage_conf.c | 17 +-
src/conf/storage_conf.h | 1 +
src/storage/storage_backend.c | 6 +
src/storage/storage_backend_sheepdog.c | 311 +++++++++++++++++++++++++
src/storage/storage_backend_sheepdog.h | 39 ++++
tests/Makefile.am | 13 ++
tests/storagebackendsheepdogtest.c | 196 ++++++++++++++++
tests/storagepoolxml2xmlin/pool-sheepdog.xml | 8 +
tests/storagepoolxml2xmlout/pool-sheepdog.xml | 11 +
tests/storagepoolxml2xmltest.c | 1 +
tests/storagevolxml2xmlin/vol-sheepdog.xml | 10 +
tests/storagevolxml2xmlout/vol-sheepdog.xml | 17 ++
tests/storagevolxml2xmltest.c | 1 +
tools/virsh.c | 3 +
22 files changed, 770 insertions(+), 14 deletions(-)
create mode 100644 src/storage/storage_backend_sheepdog.c
create mode 100644 src/storage/storage_backend_sheepdog.h
create mode 100644 tests/storagebackendsheepdogtest.c
create mode 100644 tests/storagepoolxml2xmlin/pool-sheepdog.xml
create mode 100644 tests/storagepoolxml2xmlout/pool-sheepdog.xml
create mode 100644 tests/storagevolxml2xmlin/vol-sheepdog.xml
create mode 100644 tests/storagevolxml2xmlout/vol-sheepdog.xml
diff --git a/configure.ac b/configure.ac
index dda764d..774a9dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1807,6 +1807,8 @@ AC_ARG_WITH([storage-disk],
AC_HELP_STRING([--with-storage-disk], [with GPartd Disk backend for the storage driver
@<:@default=check@:>@]),[],[with_storage_disk=check])
AC_ARG_WITH([storage-rbd],
AC_HELP_STRING([--with-storage-rbd], [with RADOS Block Device backend for the storage
driver @<:@default=check@:>@]),[],[with_storage_rbd=check])
+AC_ARG_WITH([storage-sheepdog],
+ AC_HELP_STRING([--with-storage-sheepdog], [with Sheepdog backend for the storage driver
@<:@default=check@:>@]),[],[with_storage_sheepdog=check])
if test "$with_libvirtd" = "no"; then
with_storage_dir=no
@@ -1817,6 +1819,7 @@ if test "$with_libvirtd" = "no"; then
with_storage_mpath=no
with_storage_disk=no
with_storage_rbd=no
+ with_storage_sheepdog=no
fi
if test "$with_storage_dir" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver
is enabled])
@@ -1991,6 +1994,25 @@ fi
AM_CONDITIONAL([WITH_STORAGE_RBD], [test "$with_storage_rbd" =
"yes"])
AC_SUBST([LIBRBD_LIBS])
+if test "$with_storage_sheepdog" = "yes" || test
"$with_storage_sheepdog" = "check"; then
+ AC_PATH_PROG([COLLIE], [collie], [], [$PATH:/sbin:/usr/sbin])
+
+ if test "$with_storage_sheepdog" = "yes" ; then
+ if test -z "$COLLIE" ; then AC_MSG_ERROR([We need collie for Sheepdog
storage driver]) ; fi
+ else
+ if test -z "$COLLIE" ; then with_storage_sheepdog=no ; fi
+
+ if test "$with_storage_sheepdog" = "check" ; then
with_storage_sheepdog=yes ; fi
+ fi
+
+ if test "$with_storage_sheepdog" = "yes" ; then
+ AC_DEFINE_UNQUOTED([WITH_STORAGE_SHEEPDOG], 1, [whether Sheepdog backend for storage
driver is enabled])
+ AC_DEFINE_UNQUOTED([COLLIE],["$COLLIE"],[Location of collie program])
+ fi
+fi
+AM_CONDITIONAL([WITH_STORAGE_SHEEPDOG], [test "$with_storage_sheepdog" =
"yes"])
+
+
LIBPARTED_CFLAGS=
LIBPARTED_LIBS=
if test "$with_storage_disk" = "yes" ||
@@ -2806,6 +2828,7 @@ AC_MSG_NOTICE([ SCSI: $with_storage_scsi])
AC_MSG_NOTICE([ mpath: $with_storage_mpath])
AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([ RBD: $with_storage_rbd])
+AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([])
diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index 8ad2c33..90b6196 100644
--- a/docs/drivers.html.in
+++ b/docs/drivers.html.in
@@ -43,6 +43,7 @@
<li><strong><a
href="storage.html#StorageBackendSCSI">SCSI
backend</a></strong></li>
<li><strong><a
href="storage.html#StorageBackendMultipath">Multipath
backend</a></strong></li>
<li><strong><a
href="storage.html#StorageBackendRBD">RBD (RADOS Block Device)
backend</a></strong></li>
+ <li><strong><a
href="storage.html#StorageBackendSheepdog">Sheepdog
backend</a></strong></li>
</ul>
</body>
</html>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 75b6b51..039798a 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -20,6 +20,7 @@
<ref name='poolscsi'/>
<ref name='poolmpath'/>
<ref name='poolrbd'/>
+ <ref name='poolsheepdog'/>
</choice>
</element>
</define>
@@ -115,6 +116,15 @@
<ref name='sourcerbd'/>
</define>
+ <define name='poolsheepdog'>
+ <attribute name='type'>
+ <value>sheepdog</value>
+ </attribute>
+ <ref name='commonmetadata'/>
+ <ref name='sizing'/>
+ <ref name='sourcesheepdog'/>
+ </define>
+
<define name='sourceinfovendor'>
<optional>
<element name='vendor'>
@@ -496,6 +506,13 @@
</element>
</define>
+ <define name='sourcesheepdog'>
+ <element name='source'>
+ <ref name='sourceinfohost'/>
+ <ref name='sourceinfoname'/>
+ </element>
+ </define>
+
<define name='name'>
<data type='string'>
<param name="pattern">[a-zA-Z0-9_\+\-]+</param>
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 8edb877..83148ca 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -67,7 +67,7 @@
<element name='target'>
<optional>
<element name='path'>
- <ref name='absFilePath'/>
+ <data type='anyURI'/>
</element>
</optional>
<ref name='format'/>
@@ -144,6 +144,7 @@
<define name='formatfile'>
<choice>
+ <value>unknown</value>
<value>raw</value>
<value>dir</value>
<value>bochs</value>
diff --git a/docs/storage.html.in b/docs/storage.html.in
index b3484e8..e1dbbdf 100644
--- a/docs/storage.html.in
+++ b/docs/storage.html.in
@@ -110,6 +110,9 @@
<li>
<a href="#StorageBackendRBD">RBD (RADOS Block Device)
backend</a>
</li>
+ <li>
+ <a href="#StorageBackendSheepdog">Sheepdog backend</a>
+ </li>
</ul>
<h2><a name="StorageBackendDir">Directory
pool</a></h2>
@@ -565,5 +568,64 @@
The RBD pool does not use the volume format type element.
</p>
+ <h2><a name="StorageBackendSheepdog">Sheepdog
pools</a></h2>
+ <p>
+ This provides a pool based on a Sheepdog Cluster.
+ Sheepdog is a distributed storage system for QEMU/KVM.
+ It provides highly available block level storage volumes that
+ can be attached to QEMU/KVM virtual machines.
+
+ The cluster must already be formated.
+
+ <span class="since">Since 0.9.13</span>
+ </p>
+
+ <h3>Example pool input</h3>
+ <pre>
+ <pool type="sheepdog">
+ <name>mysheeppool</name>
+ <source>
+ <name>mysheeppool</name>
+ <host name='localhost' port='7000'/>
+ </source>
+ </pool></pre>
+
+ <h3>Example volume output</h3>
+ <pre>
+ <volume>
+ <name>myvol</name>
+ <key>sheep/myvol</key>
+ <source>
+ </source>
+ <capacity
unit='bytes'>53687091200</capacity>
+ <allocation
unit='bytes'>53687091200</allocation>
+ <target>
+ <path>sheepdog:myvol</path>
+ <format type='unknown'/>
+ <permissions>
+ <mode>00</mode>
+ <owner>0</owner>
+ <group>0</group>
+ </permissions>
+ </target>
+ </volume></pre>
+
+ <h3>Example disk attachement</h3>
+ <p>Sheepdog images can be attached to Qemu guests.
+ Information about attaching a Sheepdog image to a
+ guest can be found
+ at the <a href="formatdomain.html#elementsDisks">format
domain</a>
+ page.</p>
+
+ <h3>Valid pool format types</h3>
+ <p>
+ The Sheepdog pool does not use the pool format type element.
+ </p>
+
+ <h3>Valid volume format types</h3>
+ <p>
+ The Sheepdog pool does not use the volume format type element.
+ </p>
+
</body>
</html>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 896ef51..e80259e 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -69,19 +69,24 @@
%define with_xenapi 0%{!?_without_xenapi:1}
# Then the secondary host drivers, which run inside libvirtd
-%define with_network 0%{!?_without_network:%{server_drivers}}
-%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
-%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
-%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
-%define with_storage_disk 0%{!?_without_storage_disk:%{server_drivers}}
-%define with_storage_mpath 0%{!?_without_storage_mpath:%{server_drivers}}
+%define with_network 0%{!?_without_network:%{server_drivers}}
+%define with_storage_fs 0%{!?_without_storage_fs:%{server_drivers}}
+%define with_storage_lvm 0%{!?_without_storage_lvm:%{server_drivers}}
+%define with_storage_iscsi 0%{!?_without_storage_iscsi:%{server_drivers}}
+%define with_storage_disk 0%{!?_without_storage_disk:%{server_drivers}}
+%define with_storage_mpath 0%{!?_without_storage_mpath:%{server_drivers}}
%if 0%{?fedora} >= 16
-%define with_storage_rbd 0%{!?_without_storage_rbd:%{server_drivers}}
+%define with_storage_rbd 0%{!?_without_storage_rbd:%{server_drivers}}
%else
-%define with_storage_rbd 0
+%define with_storage_rbd 0
%endif
-%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
-%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
+%if 0%{?fedora} >= 17
+%define with_storage_sheepdog 0%{!?_without_storage_sheepdog:%{server_drivers}}
+%else
+%define with_storage_sheepdog 0
+%endif
+%define with_numactl 0%{!?_without_numactl:%{server_drivers}}
+%define with_selinux 0%{!?_without_selinux:%{server_drivers}}
# A few optional bits off by default, we enable later
%define with_polkit 0%{!?_without_polkit:0}
@@ -224,6 +229,7 @@
%define with_storage_iscsi 0
%define with_storage_mpath 0
%define with_storage_rbd 0
+%define with_storage_sheepdog 0
%define with_storage_disk 0
%endif
@@ -603,6 +609,10 @@ Requires: device-mapper
# For RBD support
Requires: ceph
%endif
+%if %{with_storage_sheepdog}
+# For Sheepdog support
+Requires: sheepdog
+%endif
%if %{with_cgconfig}
Requires: libcgroup
%endif
@@ -1080,6 +1090,10 @@ of recent versions of Linux (and other OSes).
%define _without_storage_rbd --without-storage-rbd
%endif
+%if ! %{with_storage_sheepdog}
+%define _without_storage_sheepdog --without-storage-sheepdog
+%endif
+
%if ! %{with_numactl}
%define _without_numactl --without-numactl
%endif
@@ -1178,6 +1192,7 @@ autoreconf -if
%{?_without_storage_disk} \
%{?_without_storage_mpath} \
%{?_without_storage_rbd} \
+ %{?_without_storage_sheepdog} \
%{?_without_numactl} \
%{?_without_numad} \
%{?_without_capng} \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 31246f7..33a2ace 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -108,6 +108,7 @@ src/storage/storage_backend_logical.c
src/storage/storage_backend_mpath.c
src/storage/storage_backend_rbd.c
src/storage/storage_backend_scsi.c
+src/storage/storage_backend_sheepdog.c
src/storage/storage_driver.c
src/test/test_driver.c
src/uml/uml_conf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 2bcebcf..a562f4d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -509,6 +509,9 @@ STORAGE_DRIVER_DISK_SOURCES = \
STORAGE_DRIVER_RBD_SOURCES = \
storage/storage_backend_rbd.h storage/storage_backend_rbd.c
+STORAGE_DRIVER_SHEEPDOG_SOURCES = \
+ storage/storage_backend_sheepdog.h storage/storage_backend_sheepdog.c
+
STORAGE_HELPER_DISK_SOURCES = \
storage/parthelper.c
@@ -1012,6 +1015,10 @@ libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_RBD_SOURCES)
libvirt_driver_storage_la_LIBADD += $(LIBRBD_LIBS)
endif
+if WITH_STORAGE_SHEEPDOG
+libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SHEEPDOG_SOURCES)
+endif
+
if WITH_NODE_DEVICES
# Needed to keep automake quiet about conditionals
if WITH_DRIVER_MODULES
@@ -1110,6 +1117,7 @@ EXTRA_DIST += \
$(STORAGE_DRIVER_MPATH_SOURCES) \
$(STORAGE_DRIVER_DISK_SOURCES) \
$(STORAGE_DRIVER_RBD_SOURCES) \
+ $(STORAGE_DRIVER_SHEEPDOG_SOURCES) \
$(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index bf4567f..8ca6b1e 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -52,7 +52,7 @@ VIR_ENUM_IMPL(virStoragePool,
VIR_STORAGE_POOL_LAST,
"dir", "fs", "netfs",
"logical", "disk", "iscsi",
- "scsi", "mpath", "rbd")
+ "scsi", "mpath", "rbd",
"sheepdog")
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
VIR_STORAGE_POOL_FS_LAST,
@@ -206,6 +206,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.formatToString = virStoragePoolFormatDiskTypeToString,
}
},
+ { .poolType = VIR_STORAGE_POOL_SHEEPDOG,
+ .poolOptions = {
+ .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+ VIR_STORAGE_POOL_SOURCE_NETWORK |
+ VIR_STORAGE_POOL_SOURCE_NAME),
+ },
+ .volOptions = {
+ .defaultFormat = VIR_STORAGE_FILE_RAW,
+ .formatToString = virStoragePoolFormatDiskTypeToString,
+ }
+ },
{ .poolType = VIR_STORAGE_POOL_MPATH,
.volOptions = {
.formatToString = virStoragePoolFormatDiskTypeToString,
@@ -1011,9 +1022,9 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
goto cleanup;
- /* RBD devices are not local block devs nor files, so it doesn't
+ /* RBD and Sheepdog devices are not local block devs nor files, so it doesn't
* have a target */
- if (def->type != VIR_STORAGE_POOL_RBD) {
+ if (def->type != VIR_STORAGE_POOL_RBD && def->type !=
VIR_STORAGE_POOL_SHEEPDOG) {
virBufferAddLit(&buf," <target>\n");
if (def->target.path)
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 5733b57..dcf976f 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -121,6 +121,7 @@ enum virStoragePoolType {
VIR_STORAGE_POOL_SCSI, /* SCSI HBA */
VIR_STORAGE_POOL_MPATH, /* Multipath devices */
VIR_STORAGE_POOL_RBD, /* RADOS Block Device */
+ VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */
VIR_STORAGE_POOL_LAST,
};
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index e2e9b51..93964d6 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -80,6 +80,9 @@
#if WITH_STORAGE_RBD
# include "storage_backend_rbd.h"
#endif
+#if WITH_STORAGE_SHEEPDOG
+# include "storage_backend_sheepdog.h"
+#endif
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -109,6 +112,9 @@ static virStorageBackendPtr backends[] = {
#if WITH_STORAGE_RBD
&virStorageBackendRBD,
#endif
+#if WITH_STORAGE_SHEEPDOG
+ &virStorageBackendSheepdog,
+#endif
NULL
};
diff --git a/src/storage/storage_backend_sheepdog.c
b/src/storage/storage_backend_sheepdog.c
new file mode 100644
index 0000000..d324613
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.c
@@ -0,0 +1,311 @@
+/*
+ * storage_backend_sheepdog.c: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Wido den Hollander
+ * Copyright (C) 2012 Frank Spijkerman
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Wido den Hollander <wido(a)widodh.nl>
+ * Frank Spijkerman <frank.spijkerman(a)avira.com>
+ * Sebastian Wiedenroth <sebastian.wiedenroth(a)skylime.net>
+ */
+
+#include <config.h>
+
+#include "virterror_internal.h"
+#include "storage_backend_sheepdog.h"
+#include "storage_conf.h"
+#include "util/command.h"
+#include "util.h"
+#include "memory.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+static int virStorageBackendSheepdogRefreshVol(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol);
+
+void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd,
+ virStoragePoolObjPtr pool);
+
+int
+virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
+ char *output)
+{
+ /* example output:
+ * 0 15245667872 117571104 0%
+ * Total 15245667872 117571104 0% 20972341
+ */
+
+ const char *p, *next;
+
+ pool->allocation = pool->capacity = pool->available = 0;
+
+ p = output;
+ do {
+ char *end;
+
+ if ((next = strchr(p, '\n')))
+ ++next;
+ else
+ return -1;
+
+ if (!STRPREFIX(p, "Total "))
+ continue;
+
+ p = p + 6;
+
+ if (virStrToLong_ull(p, &end, 10, &pool->capacity) < 0)
+ return -1;
+
+ if ((p = end + 1) > next)
+ return -1;
+
+ if (virStrToLong_ull(p, &end, 10, &pool->allocation) < 0)
+ return -1;
+
+ pool->available = pool->capacity - pool->allocation;
+ return 0;
+
+ } while ((p = next));
+
+ return -1;
+}
+
+void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd, virStoragePoolObjPtr pool)
+{
+ const char *address = "localhost";
+ int port = 7000;
+ if (pool->def->source.nhost > 0) {
+ if (pool->def->source.hosts[0].name != NULL) {
+ address = pool->def->source.hosts[0].name;
+ }
+ if (pool->def->source.hosts[0].port) {
+ port = pool->def->source.hosts[0].port;
+ }
+ }
+ virCommandAddArg(cmd, "-a");
+ virCommandAddArgFormat(cmd, "%s", address);
+ virCommandAddArg(cmd, "-p");
+ virCommandAddArgFormat(cmd, "%d", port);
+}
+
+
+static int
+virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool)
+{
+ int ret;
+ char *output = NULL;
+ virCommandPtr cmd;
+
+ cmd = virCommandNew(COLLIE);
+ virCommandAddArgList(cmd, "node", "info", "-r", NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ virCommandSetOutputBuffer(cmd, &output);
+ ret = virCommandRun(cmd, NULL);
+ if (ret == 0)
+ ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);
+
+ virCommandFree(cmd);
+ VIR_FREE(output);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned int flags)
+{
+
+ virCheckFlags(0, -1);
+
+ virCommandPtr cmd = virCommandNew(COLLIE);
+
+ virCommandAddArgList(cmd, "vdi", "delete", vol->name, NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ int ret = virCommandRun(cmd, NULL);
+
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+
+ int ret;
+
+ if (vol->target.encryption != NULL) {
+ virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Sheepdog does not support encrypted
volumes"));
+ return -1;
+ }
+
+ virCommandPtr cmd = virCommandNew(COLLIE);
+
+ virCommandAddArgList(cmd, "vdi", "create", vol->name, NULL);
+ virCommandAddArgFormat(cmd, "%llu", vol->capacity);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ ret = virCommandRun(cmd, NULL);
+
+ virStorageBackendSheepdogRefreshVol(conn, pool, vol);
+
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+int
+virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
+ char *output)
+{
+ /* example output:
+ * s test 1 10 0 0 1336556634 7c2b25
+ * s test 2 10 0 0 1336557203 7c2b26
+ * = test 3 10 0 0 1336557216 7c2b27
+ */
+
+ int id;
+ const char *p, *next;
+
+ vol->allocation = vol->capacity = 0;
+
+ p = output;
+ do {
+ char *end;
+
+ if ((next = strchr(p, '\n')))
+ ++next;
+
+ /* ignore snapshots */
+ if (*p != '=')
+ continue;
+
+ /* skip space */
+ if (p + 2 < next) {
+ p += 2;
+ } else {
+ return -1;
+ }
+
+ /* skip name */
+ while (*p != '\0'
+ && (*p != ' ' || (*p == ' ' && (*(p - 1)
== '\\'))))
+ ++p;
+
+ if (virStrToLong_i(p, &end, 10, &id) < 0)
+ return -1;
+
+ p = end + 1;
+
+ if (virStrToLong_ull(p, &end, 10, &vol->capacity) < 0)
+ return -1;
+
+ p = end + 1;
+
+ if (virStrToLong_ull(p, &end, 10, &vol->allocation) < 0)
+ return -1;
+
+ return 0;
+ } while ((p = next));
+
+ return -1;
+}
+
+static int
+virStorageBackendSheepdogRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+ int ret;
+ char *output = NULL;
+ virCommandPtr cmd;
+
+ cmd = virCommandNew(COLLIE);
+ virCommandAddArgList(cmd, "vdi", "list", vol->name,
"-r", NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ virCommandSetOutputBuffer(cmd, &output);
+ ret = virCommandRun(cmd, NULL);
+
+ if (ret < 0)
+ goto cleanup;
+
+ if ((ret = virStorageBackendSheepdogParseVdiList(vol, output)) < 0)
+ goto cleanup;
+
+ vol->type = VIR_STORAGE_VOL_NETWORK;
+
+ VIR_FREE(vol->key);
+ if (virAsprintf(&vol->key, "%s/%s",
+ pool->def->source.name, vol->name) == -1) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ VIR_FREE(vol->target.path);
+ if (virAsprintf(&vol->target.path, "sheepdog:%s", vol->name) ==
-1) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+
+
+cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ unsigned long long capacity,
+ unsigned int flags)
+{
+
+ virCheckFlags(0, -1);
+
+ virCommandPtr cmd = virCommandNew(COLLIE);
+ virCommandAddArgList(cmd, "vdi", "resize", vol->name, NULL);
+ virCommandAddArgFormat(cmd, "%llu", capacity);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ int ret = virCommandRun(cmd, NULL);
+
+ virCommandFree(cmd);
+ return ret;
+
+}
+
+
+
+virStorageBackend virStorageBackendSheepdog = {
+ .type = VIR_STORAGE_POOL_SHEEPDOG,
+
+ .refreshPool = virStorageBackendSheepdogRefreshPool,
+ .createVol = virStorageBackendSheepdogCreateVol,
+ .refreshVol = virStorageBackendSheepdogRefreshVol,
+ .deleteVol = virStorageBackendSheepdogDeleteVol,
+ .resizeVol = virStorageBackendSheepdogResizeVol,
+};
diff --git a/src/storage/storage_backend_sheepdog.h
b/src/storage/storage_backend_sheepdog.h
new file mode 100644
index 0000000..51ef7a4
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.h
@@ -0,0 +1,39 @@
+/*
+ * storage_backend_sheepog.h: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Wido den Hollander
+ * Copyright (C) 2012 Frank Spijkerman
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Wido den Hollander <wido(a)widodh.nl>
+ * Frank Spijkerman <frank.spijkerman(a)avira.com>
+ * Sebastian Wiedenroth <sebastian.wiedenroth(a)skylime.net>
+ */
+
+#ifndef __VIR_STORAGE_BACKEND_SHEEPDOG_H__
+# define __VIR_STORAGE_BACKEND_SHEEPDOG_H__
+
+# include "storage_backend.h"
+
+int virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
+ char *output);
+int virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
+ char *output);
+
+extern virStorageBackend virStorageBackendSheepdog;
+
+#endif /* __VIR_STORAGE_BACKEND_SHEEPDOG_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e3bd6d1..a466480 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -141,6 +141,10 @@ if WITH_NETWORK
test_programs += networkxml2argvtest
endif
+if WITH_STORAGE_SHEEPDOG
+test_programs += storagebackendsheepdogtest
+endif
+
test_programs += nwfilterxml2xmltest
test_programs += storagevolxml2xmltest storagepoolxml2xmltest
@@ -398,6 +402,15 @@ else
EXTRA_DIST += networkxml2argvtest.c
endif
+if WITH_STORAGE_SHEEPDOG
+storagebackendsheepdogtest_SOURCES = \
+ storagebackendsheepdogtest.c \
+ testutils.c testutils.h
+storagebackendsheepdogtest_LDADD = ../src/libvirt_driver_storage.la $(LDADDS)
+else
+EXTRA_DIST += storagebackendsheepdogtest.c
+endif
+
nwfilterxml2xmltest_SOURCES = \
nwfilterxml2xmltest.c \
testutils.c testutils.h
diff --git a/tests/storagebackendsheepdogtest.c b/tests/storagebackendsheepdogtest.c
new file mode 100644
index 0000000..a8f62a4
--- /dev/null
+++ b/tests/storagebackendsheepdogtest.c
@@ -0,0 +1,196 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "storage/storage_backend_sheepdog.h"
+
+
+typedef struct {
+ const char *output;
+ int expected_return;
+ uint64_t expected_capacity;
+ uint64_t expected_allocation;
+} collie_test;
+
+
+static int
+test_node_info_parser(collie_test test, char *poolxml)
+{
+ int ret = -1;
+ char *output = NULL;
+ char *poolXmlData = NULL;
+ virStoragePoolDefPtr pool = NULL;
+
+ if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+ goto cleanup;
+
+ if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+ goto cleanup;
+
+ output = strdup(test.output);
+ if(!output) {
+ goto cleanup;
+ }
+
+ ret = virStorageBackendSheepdogParseNodeInfo(pool, output);
+
+ if (ret != test.expected_return)
+ goto cleanup;
+
+ if (ret != 0) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (pool->capacity == test.expected_capacity
+ && pool->allocation == test.expected_allocation)
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(output);
+ VIR_FREE(poolXmlData);
+ virStoragePoolDefFree(pool);
+ return ret;
+}
+
+static int
+test_vdi_list_parser(collie_test test, char *poolxml, char *volxml)
+{
+ int ret = -1;
+ char *poolXmlData = NULL;
+ char *volXmlData = NULL;
+ char *output = NULL;
+ virStoragePoolDefPtr pool = NULL;
+ virStorageVolDefPtr vol = NULL;
+
+ if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+ goto cleanup;
+ if (virtTestLoadFile(volxml, &volXmlData) < 0)
+ goto cleanup;
+
+ if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+ goto cleanup;
+
+ if (!(vol = virStorageVolDefParseString(pool, volXmlData)))
+ goto cleanup;
+
+ output = strdup(test.output);
+ if(!output) {
+ goto cleanup;
+ }
+
+ ret = virStorageBackendSheepdogParseVdiList(vol, output);
+
+
+ if (ret != test.expected_return)
+ goto cleanup;
+
+ if (ret != 0) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (vol->capacity == test.expected_capacity
+ && vol->allocation == test.expected_allocation)
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(output);
+ VIR_FREE(poolXmlData);
+ VIR_FREE(volXmlData);
+ virStoragePoolDefFree(pool);
+ virStorageVolDefFree(vol);
+ return ret;
+}
+
+
+static int
+mymain(void)
+{
+ int ret = -1;
+ char *poolxml = NULL;
+ char *volxml = NULL;
+
+ collie_test node_info_tests[] = {
+ {"", -1, 0, 0},
+ {"Total 15245667872 117571104 0% 20972341\n", 0, 15245667872,
117571104},
+ {"To", -1, 0, 0},
+ {"asdf\nasdf", -1, 0, 0},
+ {"Total ", -1, 0, 0},
+ {"Total 1", -1, 0, 0},
+ {"Total 1\n", -1, 0, 0},
+ {"Total 1 ", -1, 0, 0},
+ {"Total 1 2", -1, 0, 0},
+ {"Total 1 2 ", -1, 0, 0},
+ {"Total 1 2\n", 0, 1, 2},
+ {"Total 1 2 \n", 0, 1, 2},
+ {"Total a 2 \n", -1, 0, 0},
+ {"Total 1 b \n", -1, 0, 0},
+ {"Total a b \n", -1, 0, 0},
+ {"stuff\nTotal 1 2 \n", 0, 1, 2},
+ {"0 1 2 3\nTotal 1 2 \n", 0, 1, 2},
+ {NULL, 0, 0, 0}
+ };
+
+ collie_test vdi_list_tests[] = {
+ {"", -1, 0, 0},
+ {"= test 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+ {"= test\\ with\\ spaces 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+ {"s test 1 10 20 0 1336556634 7c2b25\n= test 3 50 60 0 1336557216
7c2b27\n", 0, 50, 60},
+ {"=", -1, 0, 0},
+ {"= test", -1, 0, 0},
+ {"= test ", -1, 0, 0},
+ {"= test 1", -1, 0, 0},
+ {"= test 1 ", -1, 0, 0},
+ {"= test 1 2", -1, 0, 0},
+ {"= test 1 2 ", -1, 0, 0},
+ {"= test 1 2 3", -1, 0, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ collie_test *test = node_info_tests;
+
+ if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/pool-sheepdog.xml",
+ abs_srcdir) < 0)
+ goto cleanup;
+
+ if (virAsprintf(&volxml, "%s/storagevolxml2xmlin/vol-sheepdog.xml",
+ abs_srcdir) < 0)
+ goto cleanup;
+
+ while (test->output != NULL) {
+ ret = test_node_info_parser(*test, poolxml);
+ virtTestResult("node_info_parser", ret, NULL);
+ ++test;
+ if (ret < 0)
+ return EXIT_FAILURE;
+ }
+
+ test = vdi_list_tests;
+
+ while (test->output != NULL) {
+ ret = test_vdi_list_parser(*test, poolxml, volxml);
+ virtTestResult("vdi_list_parser", ret, NULL);
+ ++test;
+ if (ret < 0)
+ return EXIT_FAILURE;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(poolxml);
+ VIR_FREE(volxml);
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
diff --git a/tests/storagepoolxml2xmlin/pool-sheepdog.xml
b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
new file mode 100644
index 0000000..1287047
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
@@ -0,0 +1,8 @@
+<pool type='sheepdog'>
+ <name>sheepdog</name>
+ <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+ <source>
+ <host name='localhost' port='7000'/>
+ <name>sheepdog</name>
+ </source>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-sheepdog.xml
b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
new file mode 100644
index 0000000..000c068
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
@@ -0,0 +1,11 @@
+<pool type='sheepdog'>
+ <name>sheepdog</name>
+ <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+ <capacity unit='bytes'>0</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <available unit='bytes'>0</available>
+ <source>
+ <host name='localhost' port='7000'/>
+ <name>sheepdog</name>
+ </source>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index d73fc8a..8cac978 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -93,6 +93,7 @@ mymain(void)
DO_TEST("pool-mpath");
DO_TEST("pool-iscsi-multiiqn");
DO_TEST("pool-iscsi-vendor-product");
+ DO_TEST("pool-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/tests/storagevolxml2xmlin/vol-sheepdog.xml
b/tests/storagevolxml2xmlin/vol-sheepdog.xml
new file mode 100644
index 0000000..49e221c
--- /dev/null
+++ b/tests/storagevolxml2xmlin/vol-sheepdog.xml
@@ -0,0 +1,10 @@
+<volume>
+ <name>test2</name>
+ <source>
+ </source>
+ <capacity unit='bytes'>1024</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <target>
+ <path>sheepdog:test2</path>
+ </target>
+</volume>
diff --git a/tests/storagevolxml2xmlout/vol-sheepdog.xml
b/tests/storagevolxml2xmlout/vol-sheepdog.xml
new file mode 100644
index 0000000..2f19af8
--- /dev/null
+++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml
@@ -0,0 +1,17 @@
+<volume>
+ <name>test2</name>
+ <key>(null)</key>
+ <source>
+ </source>
+ <capacity unit='bytes'>1024</capacity>
+ <allocation unit='bytes'>0</allocation>
+ <target>
+ <path>sheepdog:test2</path>
+ <format type='unknown'/>
+ <permissions>
+ <mode>0600</mode>
+ <owner>4294967295</owner>
+ <group>4294967295</group>
+ </permissions>
+ </target>
+</volume>
diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c
index 37c92cd..ee85988 100644
--- a/tests/storagevolxml2xmltest.c
+++ b/tests/storagevolxml2xmltest.c
@@ -112,6 +112,7 @@ mymain(void)
DO_TEST("pool-disk", "vol-partition");
DO_TEST("pool-logical", "vol-logical");
DO_TEST("pool-logical", "vol-logical-backing");
+ DO_TEST("pool-sheepdog", "vol-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index 98305c0..0dbc9d9 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -20245,6 +20245,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
#ifdef WITH_STORAGE_RBD
vshPrint(ctl, " RBD");
#endif
+#ifdef WITH_STORAGE_SHEEPDOG
+ vshPrint(ctl, " Sheepdog");
+#endif
vshPrint(ctl, "\n");
vshPrint(ctl, "%s", _(" Miscellaneous:"));
--
1.7.9.4