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 <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>
This commit is contained in:
Sebastian Wiedenroth 2012-07-18 20:06:58 +01:00 committed by Daniel P. Berrange
parent e00184291e
commit 29bc4fe646
24 changed files with 800 additions and 16 deletions

1
.gitignore vendored
View File

@ -145,6 +145,7 @@
/tests/sockettest /tests/sockettest
/tests/ssh /tests/ssh
/tests/statstest /tests/statstest
/tests/storagebackendsheepdogtest
/tests/utiltest /tests/utiltest
/tests/virauthconfigtest /tests/virauthconfigtest
/tests/virbuftest /tests/virbuftest

View File

@ -249,7 +249,7 @@ Patches have also been contributed by:
Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com> Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>
Sascha Peilicke <saschpe@suse.de> Sascha Peilicke <saschpe@suse.de>
Chuck Short <chuck.short@canonical.com> Chuck Short <chuck.short@canonical.com>
Sebastian Wiedenroth <wiedi@frubar.net>
[....send patches to get your name here....] [....send patches to get your name here....]
The libvirt Logo was designed by Diana Fong The libvirt Logo was designed by Diana Fong

View File

@ -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_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_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_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 if test "$with_libvirtd" = "no"; then
with_storage_dir=no with_storage_dir=no
@ -1835,6 +1837,7 @@ if test "$with_libvirtd" = "no"; then
with_storage_mpath=no with_storage_mpath=no
with_storage_disk=no with_storage_disk=no
with_storage_rbd=no with_storage_rbd=no
with_storage_sheepdog=no
fi fi
if test "$with_storage_dir" = "yes" ; then if test "$with_storage_dir" = "yes" ; then
AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver is enabled]) 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"]) AM_CONDITIONAL([WITH_STORAGE_RBD], [test "$with_storage_rbd" = "yes"])
AC_SUBST([LIBRBD_LIBS]) 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_CFLAGS=
LIBPARTED_LIBS= LIBPARTED_LIBS=
if test "$with_storage_disk" = "yes" || 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([ mpath: $with_storage_mpath])
AC_MSG_NOTICE([ Disk: $with_storage_disk]) AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([ RBD: $with_storage_rbd]) AC_MSG_NOTICE([ RBD: $with_storage_rbd])
AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog])
AC_MSG_NOTICE([]) AC_MSG_NOTICE([])
AC_MSG_NOTICE([Security Drivers]) AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([]) AC_MSG_NOTICE([])

View File

@ -43,6 +43,7 @@
<li><strong><a href="storage.html#StorageBackendSCSI">SCSI backend</a></strong></li> <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#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#StorageBackendRBD">RBD (RADOS Block Device) backend</a></strong></li>
<li><strong><a href="storage.html#StorageBackendSheepdog">Sheepdog backend</a></strong></li>
</ul> </ul>
</body> </body>
</html> </html>

View File

@ -20,6 +20,7 @@
<ref name='poolscsi'/> <ref name='poolscsi'/>
<ref name='poolmpath'/> <ref name='poolmpath'/>
<ref name='poolrbd'/> <ref name='poolrbd'/>
<ref name='poolsheepdog'/>
</choice> </choice>
</element> </element>
</define> </define>
@ -115,6 +116,15 @@
<ref name='sourcerbd'/> <ref name='sourcerbd'/>
</define> </define>
<define name='poolsheepdog'>
<attribute name='type'>
<value>sheepdog</value>
</attribute>
<ref name='commonmetadata'/>
<ref name='sizing'/>
<ref name='sourcesheepdog'/>
</define>
<define name='sourceinfovendor'> <define name='sourceinfovendor'>
<optional> <optional>
<element name='vendor'> <element name='vendor'>
@ -496,6 +506,13 @@
</element> </element>
</define> </define>
<define name='sourcesheepdog'>
<element name='source'>
<ref name='sourceinfohost'/>
<ref name='sourceinfoname'/>
</element>
</define>
<define name='name'> <define name='name'>
<data type='string'> <data type='string'>
<param name="pattern">[a-zA-Z0-9_\+\-]+</param> <param name="pattern">[a-zA-Z0-9_\+\-]+</param>

View File

@ -67,7 +67,7 @@
<element name='target'> <element name='target'>
<optional> <optional>
<element name='path'> <element name='path'>
<ref name='absFilePath'/> <data type='anyURI'/>
</element> </element>
</optional> </optional>
<ref name='format'/> <ref name='format'/>
@ -144,6 +144,7 @@
<define name='formatfile'> <define name='formatfile'>
<choice> <choice>
<value>unknown</value>
<value>raw</value> <value>raw</value>
<value>dir</value> <value>dir</value>
<value>bochs</value> <value>bochs</value>

View File

@ -110,6 +110,9 @@
<li> <li>
<a href="#StorageBackendRBD">RBD (RADOS Block Device) backend</a> <a href="#StorageBackendRBD">RBD (RADOS Block Device) backend</a>
</li> </li>
<li>
<a href="#StorageBackendSheepdog">Sheepdog backend</a>
</li>
</ul> </ul>
<h2><a name="StorageBackendDir">Directory pool</a></h2> <h2><a name="StorageBackendDir">Directory pool</a></h2>
@ -565,5 +568,64 @@
The RBD pool does not use the volume format type element. The RBD pool does not use the volume format type element.
</p> </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>
&lt;pool type="sheepdog"&gt;
&lt;name&gt;mysheeppool&lt;/name&gt;
&lt;source&gt;
&lt;name&gt;mysheeppool&lt;/name&gt;
&lt;host name='localhost' port='7000'/&gt;
&lt;/source&gt;
&lt;/pool&gt;</pre>
<h3>Example volume output</h3>
<pre>
&lt;volume&gt;
&lt;name&gt;myvol&lt;/name&gt;
&lt;key&gt;sheep/myvol&lt;/key&gt;
&lt;source&gt;
&lt;/source&gt;
&lt;capacity unit='bytes'&gt;53687091200&lt;/capacity&gt;
&lt;allocation unit='bytes'&gt;53687091200&lt;/allocation&gt;
&lt;target&gt;
&lt;path&gt;sheepdog:myvol&lt;/path&gt;
&lt;format type='unknown'/&gt;
&lt;permissions&gt;
&lt;mode&gt;00&lt;/mode&gt;
&lt;owner&gt;0&lt;/owner&gt;
&lt;group&gt;0&lt;/group&gt;
&lt;/permissions&gt;
&lt;/target&gt;
&lt;/volume&gt;</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> </body>
</html> </html>

View File

@ -80,6 +80,11 @@
%else %else
%define with_storage_rbd 0 %define with_storage_rbd 0
%endif %endif
%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_numactl 0%{!?_without_numactl:%{server_drivers}}
%define with_selinux 0%{!?_without_selinux:%{server_drivers}} %define with_selinux 0%{!?_without_selinux:%{server_drivers}}
@ -224,6 +229,7 @@
%define with_storage_iscsi 0 %define with_storage_iscsi 0
%define with_storage_mpath 0 %define with_storage_mpath 0
%define with_storage_rbd 0 %define with_storage_rbd 0
%define with_storage_sheepdog 0
%define with_storage_disk 0 %define with_storage_disk 0
%endif %endif
@ -603,6 +609,10 @@ Requires: device-mapper
# For RBD support # For RBD support
Requires: ceph Requires: ceph
%endif %endif
%if %{with_storage_sheepdog}
# For Sheepdog support
Requires: sheepdog
%endif
%if %{with_cgconfig} %if %{with_cgconfig}
Requires: libcgroup Requires: libcgroup
%endif %endif
@ -1080,6 +1090,10 @@ of recent versions of Linux (and other OSes).
%define _without_storage_rbd --without-storage-rbd %define _without_storage_rbd --without-storage-rbd
%endif %endif
%if ! %{with_storage_sheepdog}
%define _without_storage_sheepdog --without-storage-sheepdog
%endif
%if ! %{with_numactl} %if ! %{with_numactl}
%define _without_numactl --without-numactl %define _without_numactl --without-numactl
%endif %endif
@ -1178,6 +1192,7 @@ autoreconf -if
%{?_without_storage_disk} \ %{?_without_storage_disk} \
%{?_without_storage_mpath} \ %{?_without_storage_mpath} \
%{?_without_storage_rbd} \ %{?_without_storage_rbd} \
%{?_without_storage_sheepdog} \
%{?_without_numactl} \ %{?_without_numactl} \
%{?_without_numad} \ %{?_without_numad} \
%{?_without_capng} \ %{?_without_capng} \

View File

@ -108,6 +108,7 @@ src/storage/storage_backend_logical.c
src/storage/storage_backend_mpath.c src/storage/storage_backend_mpath.c
src/storage/storage_backend_rbd.c src/storage/storage_backend_rbd.c
src/storage/storage_backend_scsi.c src/storage/storage_backend_scsi.c
src/storage/storage_backend_sheepdog.c
src/storage/storage_driver.c src/storage/storage_driver.c
src/test/test_driver.c src/test/test_driver.c
src/uml/uml_conf.c src/uml/uml_conf.c

View File

@ -515,6 +515,9 @@ STORAGE_DRIVER_DISK_SOURCES = \
STORAGE_DRIVER_RBD_SOURCES = \ STORAGE_DRIVER_RBD_SOURCES = \
storage/storage_backend_rbd.h storage/storage_backend_rbd.c 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_HELPER_DISK_SOURCES = \
storage/parthelper.c storage/parthelper.c
@ -1018,6 +1021,10 @@ libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_RBD_SOURCES)
libvirt_driver_storage_la_LIBADD += $(LIBRBD_LIBS) libvirt_driver_storage_la_LIBADD += $(LIBRBD_LIBS)
endif endif
if WITH_STORAGE_SHEEPDOG
libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SHEEPDOG_SOURCES)
endif
if WITH_NODE_DEVICES if WITH_NODE_DEVICES
# Needed to keep automake quiet about conditionals # Needed to keep automake quiet about conditionals
if WITH_DRIVER_MODULES if WITH_DRIVER_MODULES
@ -1116,6 +1123,7 @@ EXTRA_DIST += \
$(STORAGE_DRIVER_MPATH_SOURCES) \ $(STORAGE_DRIVER_MPATH_SOURCES) \
$(STORAGE_DRIVER_DISK_SOURCES) \ $(STORAGE_DRIVER_DISK_SOURCES) \
$(STORAGE_DRIVER_RBD_SOURCES) \ $(STORAGE_DRIVER_RBD_SOURCES) \
$(STORAGE_DRIVER_SHEEPDOG_SOURCES) \
$(NODE_DEVICE_DRIVER_SOURCES) \ $(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \ $(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \ $(NODE_DEVICE_DRIVER_UDEV_SOURCES) \

View File

@ -54,7 +54,7 @@ VIR_ENUM_IMPL(virStoragePool,
VIR_STORAGE_POOL_LAST, VIR_STORAGE_POOL_LAST,
"dir", "fs", "netfs", "dir", "fs", "netfs",
"logical", "disk", "iscsi", "logical", "disk", "iscsi",
"scsi", "mpath", "rbd") "scsi", "mpath", "rbd", "sheepdog")
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem, VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
VIR_STORAGE_POOL_FS_LAST, VIR_STORAGE_POOL_FS_LAST,
@ -208,6 +208,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.formatToString = virStoragePoolFormatDiskTypeToString, .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, { .poolType = VIR_STORAGE_POOL_MPATH,
.volOptions = { .volOptions = {
.formatToString = virStoragePoolFormatDiskTypeToString, .formatToString = virStoragePoolFormatDiskTypeToString,
@ -1014,9 +1025,9 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0) if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
goto cleanup; 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 */ * 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"); virBufferAddLit(&buf," <target>\n");
if (def->target.path) if (def->target.path)
@ -1301,7 +1312,7 @@ virStorageVolDefFormat(virStoragePoolDefPtr pool,
virBufferAddLit(&buf, "<volume>\n"); virBufferAddLit(&buf, "<volume>\n");
virBufferAsprintf(&buf," <name>%s</name>\n", def->name); 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"); virBufferAddLit(&buf, " <source>\n");
if (def->source.nextent) { if (def->source.nextent) {

View File

@ -121,6 +121,7 @@ enum virStoragePoolType {
VIR_STORAGE_POOL_SCSI, /* SCSI HBA */ VIR_STORAGE_POOL_SCSI, /* SCSI HBA */
VIR_STORAGE_POOL_MPATH, /* Multipath devices */ VIR_STORAGE_POOL_MPATH, /* Multipath devices */
VIR_STORAGE_POOL_RBD, /* RADOS Block Device */ VIR_STORAGE_POOL_RBD, /* RADOS Block Device */
VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */
VIR_STORAGE_POOL_LAST, VIR_STORAGE_POOL_LAST,
}; };

View File

@ -79,6 +79,9 @@
#if WITH_STORAGE_RBD #if WITH_STORAGE_RBD
# include "storage_backend_rbd.h" # include "storage_backend_rbd.h"
#endif #endif
#if WITH_STORAGE_SHEEPDOG
# include "storage_backend_sheepdog.h"
#endif
#define VIR_FROM_THIS VIR_FROM_STORAGE #define VIR_FROM_THIS VIR_FROM_STORAGE
@ -107,6 +110,9 @@ static virStorageBackendPtr backends[] = {
#endif #endif
#if WITH_STORAGE_RBD #if WITH_STORAGE_RBD
&virStorageBackendRBD, &virStorageBackendRBD,
#endif
#if WITH_STORAGE_SHEEPDOG
&virStorageBackendSheepdog,
#endif #endif
NULL NULL
}; };

View File

@ -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)
{
/* 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,
};

View File

@ -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__ */

View File

@ -141,6 +141,10 @@ if WITH_NETWORK
test_programs += networkxml2argvtest test_programs += networkxml2argvtest
endif endif
if WITH_STORAGE_SHEEPDOG
test_programs += storagebackendsheepdogtest
endif
test_programs += nwfilterxml2xmltest test_programs += nwfilterxml2xmltest
test_programs += storagevolxml2xmltest storagepoolxml2xmltest test_programs += storagevolxml2xmltest storagepoolxml2xmltest
@ -398,6 +402,15 @@ else
EXTRA_DIST += networkxml2argvtest.c EXTRA_DIST += networkxml2argvtest.c
endif 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_SOURCES = \
nwfilterxml2xmltest.c \ nwfilterxml2xmltest.c \
testutils.c testutils.h testutils.c testutils.h

View File

@ -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@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)

View File

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

View File

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

View File

@ -93,6 +93,7 @@ mymain(void)
DO_TEST("pool-mpath"); DO_TEST("pool-mpath");
DO_TEST("pool-iscsi-multiiqn"); DO_TEST("pool-iscsi-multiiqn");
DO_TEST("pool-iscsi-vendor-product"); DO_TEST("pool-iscsi-vendor-product");
DO_TEST("pool-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View File

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

View File

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

View File

@ -112,6 +112,7 @@ mymain(void)
DO_TEST("pool-disk", "vol-partition"); DO_TEST("pool-disk", "vol-partition");
DO_TEST("pool-logical", "vol-logical"); DO_TEST("pool-logical", "vol-logical");
DO_TEST("pool-logical", "vol-logical-backing"); DO_TEST("pool-logical", "vol-logical-backing");
DO_TEST("pool-sheepdog", "vol-sheepdog");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View File

@ -20873,6 +20873,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
#endif #endif
#ifdef WITH_STORAGE_RBD #ifdef WITH_STORAGE_RBD
vshPrint(ctl, " RBD"); vshPrint(ctl, " RBD");
#endif
#ifdef WITH_STORAGE_SHEEPDOG
vshPrint(ctl, " Sheepdog");
#endif #endif
vshPrint(ctl, "\n"); vshPrint(ctl, "\n");