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

Sebastian Wiedenroth sebastian.wiedenroth at skylime.net
Wed Jul 18 08:48:38 UTC 2012


*ping* if this version addresses all previous concerns, what can i do to get this merged? ;-)


Am 26.06.2012 um 13:25 schrieb Sebastian Wiedenroth:

> 
> 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 <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 at frubar.net>
> ---
> .gitignore                                    |    1 +
> 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 +
> 23 files changed, 799 insertions(+), 15 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 cd978d2..098ba09 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/configure.ac b/configure.ac
> index c0ef9b1..13aa0e4 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 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 7a74331..0b9933d 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..26a949a 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 formatted.
> +
> +      <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 attachment</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 2309984..7effcd6 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
> 
> @@ -1019,6 +1022,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
> @@ -1117,6 +1124,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..cd17db6 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)
> @@ -1296,7 +1307,7 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool,
> 
>     virBufferAddLit(&buf, "<volume>\n");
>     virBufferAsprintf(&buf,"  <name>%s</name>\n", def->name);
> -    virBufferAsprintf(&buf,"  <key>%s</key>\n", def->key);
> +    virBufferAsprintf(&buf,"  <key>%s</key>\n", def->key ? def->key : "(null)");
>     virBufferAddLit(&buf, "  <source>\n");
> 
>     if (def->source.nextent) {
> 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..68633d4
> --- /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 at widodh.nl>
> + *         Frank Spijkerman <frank.spijkerman at avira.com>
> + *         Sebastian Wiedenroth <sebastian.wiedenroth at 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)
> +{
> +    /* 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) {
> +        virStorageReportError(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 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 at widodh.nl>
> + *         Frank Spijkerman <frank.spijkerman at avira.com>
> + *         Sebastian Wiedenroth <sebastian.wiedenroth at 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..0870829
> --- /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 <sebastian.wiedenroth at skylime.net>
> + */
> +
> +#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;
> +
> +    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 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 2b4cb2c..dd0261c 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -20696,6 +20696,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
> 
> 
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list





More information about the libvir-list mailing list