From 29bc4fe6460d80c2aca1b90e54faed1431efcfa7 Mon Sep 17 00:00:00 2001 From: Sebastian Wiedenroth Date: Wed, 18 Jul 2012 20:06:58 +0100 Subject: [PATCH] Add a sheepdog backend for the storage driver 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 has to be put into the . To use the volume as a disk source for virtual machines specify the vdi name as "name" attribute of the . The host and port information from the pool are specified inside the host tag. ... 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 --- .gitignore | 1 + AUTHORS | 2 +- configure.ac | 32 ++ 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 | 19 +- 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 | 214 ++++++++++++ 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 + 24 files changed, 800 insertions(+), 16 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/.gitignore b/.gitignore index e5d5db9170..46dbcdfcac 100644 --- a/.gitignore +++ b/.gitignore @@ -145,6 +145,7 @@ /tests/sockettest /tests/ssh /tests/statstest +/tests/storagebackendsheepdogtest /tests/utiltest /tests/virauthconfigtest /tests/virbuftest diff --git a/AUTHORS b/AUTHORS index 43cc0a17f7..092e279d1f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -249,7 +249,7 @@ Patches have also been contributed by: Eiichi Tsukata Sascha Peilicke Chuck Short - + Sebastian Wiedenroth [....send patches to get your name here....] The libvirt Logo was designed by Diana Fong diff --git a/configure.ac b/configure.ac index ae814cb866..3cc7b3c2fa 100644 --- a/configure.ac +++ b/configure.ac @@ -1825,6 +1825,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 @@ -1835,6 +1837,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]) @@ -2009,6 +2012,34 @@ 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" || @@ -2824,6 +2855,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 8ad2c33218..90b61962eb 100644 --- a/docs/drivers.html.in +++ b/docs/drivers.html.in @@ -43,6 +43,7 @@
  • SCSI backend
  • Multipath backend
  • RBD (RADOS Block Device) backend
  • +
  • Sheepdog backend
  • diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index 75b6b514b2..039798a9ba 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -20,6 +20,7 @@ + @@ -115,6 +116,15 @@ + + + sheepdog + + + + + + @@ -496,6 +506,13 @@ + + + + + + + [a-zA-Z0-9_\+\-]+ diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng index 7a74331cd7..0b9933d56c 100644 --- a/docs/schemas/storagevol.rng +++ b/docs/schemas/storagevol.rng @@ -67,7 +67,7 @@ - + @@ -144,6 +144,7 @@ + unknown raw dir bochs diff --git a/docs/storage.html.in b/docs/storage.html.in index b3484e811b..26a949a7d1 100644 --- a/docs/storage.html.in +++ b/docs/storage.html.in @@ -110,6 +110,9 @@
  • RBD (RADOS Block Device) backend
  • +
  • + Sheepdog backend +
  • Directory pool

    @@ -565,5 +568,64 @@ The RBD pool does not use the volume format type element.

    +

    Sheepdog pools

    +

    + 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 formatted. + + Since 0.9.13 +

    + +

    Example pool input

    +
    +      <pool type="sheepdog">
    +        <name>mysheeppool</name>
    +        <source>
    +          <name>mysheeppool</name>
    +          <host name='localhost' port='7000'/>
    +        </source>
    +      </pool>
    + +

    Example volume output

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

    Example disk attachment

    +

    Sheepdog images can be attached to Qemu guests. + Information about attaching a Sheepdog image to a + guest can be found + at the format domain + page.

    + +

    Valid pool format types

    +

    + The Sheepdog pool does not use the pool format type element. +

    + +

    Valid volume format types

    +

    + The Sheepdog pool does not use the volume format type element. +

    + diff --git a/libvirt.spec.in b/libvirt.spec.in index ec2b3b44e7..2253d8686a 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 6ca40d9913..594519a406 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 bfe74d39fd..4fc42c91bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -515,6 +515,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 @@ -1018,6 +1021,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 @@ -1116,6 +1123,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 44387b2631..6ce9208947 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -54,7 +54,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, @@ -208,6 +208,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, @@ -1014,9 +1025,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," \n"); if (def->target.path) @@ -1301,7 +1312,7 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool, virBufferAddLit(&buf, "\n"); virBufferAsprintf(&buf," %s\n", def->name); - virBufferAsprintf(&buf," %s\n", def->key); + virBufferAsprintf(&buf," %s\n", def->key ? def->key : "(null)"); virBufferAddLit(&buf, " \n"); if (def->source.nextent) { diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 6e63671325..6f84340504 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 0c17aea42c..10956155fc 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -79,6 +79,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 @@ -107,6 +110,9 @@ static virStorageBackendPtr backends[] = { #endif #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 0000000000..55ca5c1ae2 --- /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 + * Frank Spijkerman + * Sebastian Wiedenroth + */ + +#include + +#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) +{ + /* fields: + * node id/total, size, used, use%, [total vdi size] + * + * 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 = virCommandNewArgList(COLLIE, "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 = virCommandNewArgList(COLLIE, "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) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Sheepdog does not support encrypted volumes")); + return -1; + } + + virCommandPtr cmd = virCommandNewArgList(COLLIE, "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) +{ + /* fields: + * current/clone/snapshot, name, id, size, used, shared, creation time, vdi id, [tag] + * + * 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 != ' ') { + if (*p == '\\') + ++p; + ++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 = virCommandNewArgList(COLLIE, "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, "%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 = virCommandNewArgList(COLLIE, "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 0000000000..51ef7a4a70 --- /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 + * Frank Spijkerman + * Sebastian Wiedenroth + */ + +#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 e3bd6d1528..a46648047e 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 0000000000..08708296ea --- /dev/null +++ b/tests/storagebackendsheepdogtest.c @@ -0,0 +1,214 @@ +/* + * storagebackendsheepdogtest.c: storage backend for Sheepdog handling + * + * 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: Sebastian Wiedenroth + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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; + + if (virStorageBackendSheepdogParseNodeInfo(pool, output) != + test.expected_return) + goto cleanup; + + if (test.expected_return) { + 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; + + if (virStorageBackendSheepdogParseVdiList(vol, output) != + test.expected_return) + goto cleanup; + + if (test.expected_return) { + 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}, + {"= backslashattheend\\\\ 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 0000000000..1287047d2b --- /dev/null +++ b/tests/storagepoolxml2xmlin/pool-sheepdog.xml @@ -0,0 +1,8 @@ + + sheepdog + 65fcba04-5b13-bd93-cff3-52ce48e11ad7 + + + sheepdog + + diff --git a/tests/storagepoolxml2xmlout/pool-sheepdog.xml b/tests/storagepoolxml2xmlout/pool-sheepdog.xml new file mode 100644 index 0000000000..000c068677 --- /dev/null +++ b/tests/storagepoolxml2xmlout/pool-sheepdog.xml @@ -0,0 +1,11 @@ + + sheepdog + 65fcba04-5b13-bd93-cff3-52ce48e11ad7 + 0 + 0 + 0 + + + sheepdog + + diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c index d73fc8ae68..8cac978319 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 0000000000..49e221ca55 --- /dev/null +++ b/tests/storagevolxml2xmlin/vol-sheepdog.xml @@ -0,0 +1,10 @@ + + test2 + + + 1024 + 0 + + sheepdog:test2 + + diff --git a/tests/storagevolxml2xmlout/vol-sheepdog.xml b/tests/storagevolxml2xmlout/vol-sheepdog.xml new file mode 100644 index 0000000000..2f19af8f19 --- /dev/null +++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml @@ -0,0 +1,17 @@ + + test2 + (null) + + + 1024 + 0 + + sheepdog:test2 + + + 0600 + 4294967295 + 4294967295 + + + diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c index 37c92cd4ff..ee85988195 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 1e00049ca8..b9e159b34a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -20873,6 +20873,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) #endif #ifdef WITH_STORAGE_RBD vshPrint(ctl, " RBD"); +#endif +#ifdef WITH_STORAGE_SHEEPDOG + vshPrint(ctl, " Sheepdog"); #endif vshPrint(ctl, "\n");