[libvirt] [PATCH v2] storage backend: Add sheepdog support

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@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@widodh.nl> + * Frank Spijkerman <frank.spijkerman@avira.com> + * Sebastian Wiedenroth <sebastian.wiedenroth@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@widodh.nl> + * Frank Spijkerman <frank.spijkerman@avira.com> + * Sebastian Wiedenroth <sebastian.wiedenroth@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

On Thu, Jun 14, 2012 at 01:14:56PM +0200, Sebastian Wiedenroth wrote:
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@frubar.net>
ACK, this patch addressed all the things I raised last time. Lets see if Eric has any more detailed code review feedback.... Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 06/14/2012 05:14 AM, Sebastian Wiedenroth wrote:
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.
Should we be checking at configure and/or runtime whether we are talking to a fixed collie?
Signed-off-by: Sebastian Wiedenroth <wiedi@frubar.net>
I've gone ahead and added you to AUTHORS in order to get 'make syntax-check' to pass; let me know if you prefer an alternate alias.
@@ -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.
s/formated/formatted/
+ + <h3>Example disk attachement</h3>
s/attachement/attachment/
+++ 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
/note to self - I really ought to finish the work I started on scrubbing copyright notices for consistency, but that doesn't affect the applicability of this patch
+ +void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd, virStoragePoolObjPtr pool)
Long line; I would have formatted it: void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd, virStoragePoolObjPtr pool)
+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);
Minor optimization - you could do this in one step: cmd = virCommandNewArgList(COLLIE, "node", "info", "-r", NULL);
+ +static int +virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + unsigned int flags)
And unfortunately this is as far as I got today; I'll have to resume my review later. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Am 20.06.2012 um 01:59 schrieb Eric Blake:
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.
Should we be checking at configure and/or runtime whether we are talking to a fixed collie?
I thought about that and am not sure how to do it best. To check for the fix one way would be to create a large enough vdi and check if the reported size comes back the same. But I'm not sure it's a good idea to write to the sheepdog cluster just for a check. This also needs the connection information and relies on the cluster already being formatted. Another way would be to check for a version number. Sadly the collie utility does not provide any. The server component "sheep" does, but then we rely on both being installed on the same system. So in the end this check might add more complexity than it might be worth. Later today I'll send a V3 with all the other suggestions fixed. If we can come up with a good way to check for the fix I'm happy to implement that. Best regards, Sebastian

On 06/14/2012 05:14 AM, Sebastian Wiedenroth wrote:
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.
Picking up where I left off yesterday...
tests/Makefile.am | 13 ++ tests/storagebackendsheepdogtest.c | 196 ++++++++++++++++
The built executable should be ignored in .gitignore. But thanks for adding tests!
+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
I didn't mention this yesterday, but I find it easier to avoid one-liner 'if...fi' and instead use multiple lines - it's easier to see the nesting if the fi always lines up with the if above it. Besides, that also avoids going over 80 columns.
+ 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])
Another long line issue; autoconf lets you start arguments on a new line.
+static int +virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
Now back to where I left off.
+ virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + unsigned int flags) +{ + + virCheckFlags(0, -1); + + virCommandPtr cmd = virCommandNew(COLLIE); + + virCommandAddArgList(cmd, "vdi", "delete", vol->name, NULL);
Another instance where these two lines can be merged into one with virCommandNewArgList. I won't point out any more.
+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 + */
It might also help to call out another comment describing the fields represented in that output, as in: type name id capacity allocation extra1 extra2
+ + /* skip name */ + while (*p != '\0' + && (*p != ' ' || (*p == ' ' && (*(p - 1) == '\\')))) + ++p;
This won't work if "\\" is a valid escape for a trailing backslash as the last byte in the name. If you are going to handle backslash escapes as part of a name, you have to skip all backslash escapes rather than just searching for the first space not preceded by a backslash.
+ VIR_FREE(vol->target.path); + if (virAsprintf(&vol->target.path, "sheepdog:%s", vol->name) == -1) { + virReportOOMError(); + goto cleanup; + } + + + +cleanup:
Lots of whitespace between lines here.
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>
Missing a copyright notice. Yeah, we aren't all that great in the tests directory (and I need to audit the entire source tree for improvements), but that's no excuse for new additions.
+ output = strdup(test.output); + if(!output) { + goto cleanup; + }
Formatting: space after 'if'. Also, for this one-liner, {} can be omitted.
+ + ret = virStorageBackendSheepdogParseNodeInfo(pool, output); + + if (ret != test.expected_return) + goto cleanup; + + if (ret != 0) { + ret = 0; + goto cleanup; + }
Why are you quitting the test early but still reporting success? Oh, I see, because you use ret for two orthogonal purposes (checking expected parse results, and returning test results). I would have written: if (virStorageBackendSheepdogParseNodeInfo(pool, output) != test.expected_return) goto cleanup; if (test.expected_return) { ret = 0; goto cleanup; } so that ret is only being used for test results.
+ + if (pool->capacity == test.expected_capacity + && pool->allocation == test.expected_allocation)
Style - libvirt prefers '&&' on the end of the first line, not the start of the second line.
+static int +test_vdi_list_parser(collie_test test, char *poolxml, char *volxml) +{
+ output = strdup(test.output); + if(!output) {
Style: space after 'if'.
+++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml @@ -0,0 +1,17 @@ +<volume> + <name>test2</name> + <key>(null)</key>
Is this the sign of an accidental NULL pointer dereference which would bite us on non-glibc platforms? Can we provide a non-NULL key instead? Overall, I think my findings are relatively minor, but I would prefer if you could polish up my findings and post a v3 to save me some time. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Thu, Jun 14, 2012 at 01:14:56PM +0200, Sebastian Wiedenroth wrote:
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.
+ + VIR_FREE(vol->target.path); + if (virAsprintf(&vol->target.path, "sheepdog:%s", vol->name) == -1) { + virReportOOMError(); + goto cleanup; + }
Since I justed approved the suggestion to reomve 'rbd:' prefix from RBD volume names, I think we should do the same here. So please remove the 'sheepdog:' prefix from the storage pool volume names. https://www.redhat.com/archives/libvir-list/2012-June/msg01090.html Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Sebastian Wiedenroth