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

Sebastian Wiedenroth sebastian.wiedenroth at skylime.net
Tue Jun 12 08:31:54 UTC 2012


Signed-off-by: Sebastian Wiedenroth <wiedi at frubar.net>
---

This patch adds support for sheepdog pools and volumes.
Thanks go to Frank Spijkerman who started the initial work on this
and Wido den Hollander for his RBD support on which this is partly based.


 configure.ac                                  |   23 ++
 docs/drivers.html.in                          |    1 +
 docs/schemas/storagepool.rng                  |   17 ++
 docs/schemas/storagevol.rng                   |    3 +-
 docs/storage.html.in                          |   62 +++++
 po/POTFILES.in                                |    1 +
 src/Makefile.am                               |    8 +
 src/conf/storage_conf.c                       |   17 +-
 src/conf/storage_conf.h                       |    1 +
 src/storage/storage_backend.c                 |    6 +
 src/storage/storage_backend_sheepdog.c        |  323 +++++++++++++++++++++++++
 src/storage/storage_backend_sheepdog.h        |   39 +++
 tests/Makefile.am                             |   13 +
 tests/storagebackendsheepdogtest.c            |  196 +++++++++++++++
 tests/storagepoolxml2xmlin/pool-sheepdog.xml  |    8 +
 tests/storagepoolxml2xmlout/pool-sheepdog.xml |   11 +
 tests/storagepoolxml2xmltest.c                |    1 +
 tests/storagevolxml2xmlin/vol-sheepdog.xml    |   10 +
 tests/storagevolxml2xmlout/vol-sheepdog.xml   |   17 ++
 tests/storagevolxml2xmltest.c                 |    1 +
 tools/virsh.c                                 |    3 +
 21 files changed, 757 insertions(+), 4 deletions(-)
 create mode 100644 src/storage/storage_backend_sheepdog.c
 create mode 100644 src/storage/storage_backend_sheepdog.h
 create mode 100644 tests/storagebackendsheepdogtest.c
 create mode 100644 tests/storagepoolxml2xmlin/pool-sheepdog.xml
 create mode 100644 tests/storagepoolxml2xmlout/pool-sheepdog.xml
 create mode 100644 tests/storagevolxml2xmlin/vol-sheepdog.xml
 create mode 100644 tests/storagevolxml2xmlout/vol-sheepdog.xml

diff --git a/configure.ac b/configure.ac
index dda764d..774a9dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1807,6 +1807,8 @@ AC_ARG_WITH([storage-disk],
   AC_HELP_STRING([--with-storage-disk], [with GPartd Disk backend for the storage driver @<:@default=check@:>@]),[],[with_storage_disk=check])
 AC_ARG_WITH([storage-rbd],
   AC_HELP_STRING([--with-storage-rbd], [with RADOS Block Device backend for the storage driver @<:@default=check@:>@]),[],[with_storage_rbd=check])
+AC_ARG_WITH([storage-sheepdog],
+  AC_HELP_STRING([--with-storage-sheepdog], [with Sheepdog backend for the storage driver @<:@default=check@:>@]),[],[with_storage_sheepdog=check])
 
 if test "$with_libvirtd" = "no"; then
   with_storage_dir=no
@@ -1817,6 +1819,7 @@ if test "$with_libvirtd" = "no"; then
   with_storage_mpath=no
   with_storage_disk=no
   with_storage_rbd=no
+  with_storage_sheepdog=no
 fi
 if test "$with_storage_dir" = "yes" ; then
   AC_DEFINE_UNQUOTED([WITH_STORAGE_DIR], 1, [whether directory backend for storage driver is enabled])
@@ -1991,6 +1994,25 @@ fi
 AM_CONDITIONAL([WITH_STORAGE_RBD], [test "$with_storage_rbd" = "yes"])
 AC_SUBST([LIBRBD_LIBS])
 
+if test "$with_storage_sheepdog" = "yes" || test "$with_storage_sheepdog" = "check"; then
+  AC_PATH_PROG([COLLIE], [collie], [], [$PATH:/sbin:/usr/sbin])
+
+  if test "$with_storage_sheepdog" = "yes" ; then
+    if test -z "$COLLIE" ; then AC_MSG_ERROR([We need collie for Sheepdog storage driver]) ; fi
+  else
+    if test -z "$COLLIE" ; then with_storage_sheepdog=no ; fi
+
+    if test "$with_storage_sheepdog" = "check" ; then with_storage_sheepdog=yes ; fi
+  fi
+
+  if test "$with_storage_sheepdog" = "yes" ; then
+    AC_DEFINE_UNQUOTED([WITH_STORAGE_SHEEPDOG], 1, [whether Sheepdog backend for storage driver is enabled])
+    AC_DEFINE_UNQUOTED([COLLIE],["$COLLIE"],[Location of collie program])
+  fi
+fi
+AM_CONDITIONAL([WITH_STORAGE_SHEEPDOG], [test "$with_storage_sheepdog" = "yes"])
+
+
 LIBPARTED_CFLAGS=
 LIBPARTED_LIBS=
 if test "$with_storage_disk" = "yes" ||
@@ -2806,6 +2828,7 @@ AC_MSG_NOTICE([    SCSI: $with_storage_scsi])
 AC_MSG_NOTICE([   mpath: $with_storage_mpath])
 AC_MSG_NOTICE([    Disk: $with_storage_disk])
 AC_MSG_NOTICE([     RBD: $with_storage_rbd])
+AC_MSG_NOTICE([Sheepdog: $with_storage_sheepdog])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Security Drivers])
 AC_MSG_NOTICE([])
diff --git a/docs/drivers.html.in b/docs/drivers.html.in
index 8ad2c33..90b6196 100644
--- a/docs/drivers.html.in
+++ b/docs/drivers.html.in
@@ -43,6 +43,7 @@
       <li><strong><a href="storage.html#StorageBackendSCSI">SCSI backend</a></strong></li>
       <li><strong><a href="storage.html#StorageBackendMultipath">Multipath backend</a></strong></li>
       <li><strong><a href="storage.html#StorageBackendRBD">RBD (RADOS Block Device) backend</a></strong></li>
+      <li><strong><a href="storage.html#StorageBackendSheepdog">Sheepdog backend</a></strong></li>
     </ul>
   </body>
 </html>
diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
index 75b6b51..039798a 100644
--- a/docs/schemas/storagepool.rng
+++ b/docs/schemas/storagepool.rng
@@ -20,6 +20,7 @@
         <ref name='poolscsi'/>
         <ref name='poolmpath'/>
         <ref name='poolrbd'/>
+        <ref name='poolsheepdog'/>
       </choice>
     </element>
   </define>
@@ -115,6 +116,15 @@
     <ref name='sourcerbd'/>
   </define>
 
+  <define name='poolsheepdog'>
+    <attribute name='type'>
+      <value>sheepdog</value>
+    </attribute>
+    <ref name='commonmetadata'/>
+    <ref name='sizing'/>
+    <ref name='sourcesheepdog'/>
+  </define>
+
   <define name='sourceinfovendor'>
     <optional>
       <element name='vendor'>
@@ -496,6 +506,13 @@
     </element>
   </define>
 
+  <define name='sourcesheepdog'>
+    <element name='source'>
+      <ref name='sourceinfohost'/>
+      <ref name='sourceinfoname'/>
+    </element>
+  </define>
+
   <define name='name'>
     <data type='string'>
       <param name="pattern">[a-zA-Z0-9_\+\-]+</param>
diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng
index 8edb877..83148ca 100644
--- a/docs/schemas/storagevol.rng
+++ b/docs/schemas/storagevol.rng
@@ -67,7 +67,7 @@
     <element name='target'>
       <optional>
         <element name='path'>
-          <ref name='absFilePath'/>
+          <data type='anyURI'/>
         </element>
       </optional>
       <ref name='format'/>
@@ -144,6 +144,7 @@
 
   <define name='formatfile'>
     <choice>
+      <value>unknown</value>
       <value>raw</value>
       <value>dir</value>
       <value>bochs</value>
diff --git a/docs/storage.html.in b/docs/storage.html.in
index b3484e8..8730164 100644
--- a/docs/storage.html.in
+++ b/docs/storage.html.in
@@ -110,6 +110,9 @@
       <li>
         <a href="#StorageBackendRBD">RBD (RADOS Block Device) backend</a>
       </li>
+      <li>
+        <a href="#StorageBackendSheepdog">Sheepdog backend</a>
+      </li>
     </ul>
 
     <h2><a name="StorageBackendDir">Directory pool</a></h2>
@@ -565,5 +568,64 @@
       The RBD pool does not use the volume format type element.
     </p>
 
+    <h2><a name="StorageBackendSheepdog">Sheepdog pools</a></h2>
+    <p>
+      This provides a pool based on a Sheepdog Cluster.
+      Sheepdog is a distributed storage system for QEMU/KVM.
+      It provides highly available block level storage volumes that
+      can be attached to QEMU/KVM virtual machines.
+
+      The cluster must already be formated.
+
+      <span class="since">Since 0.9.13</span>
+    </p>
+
+    <h3>Example pool input</h3>
+    <pre>
+      <pool type="sheepdog">
+        <name>mysheeppool</name>
+        <source>
+          <name>mysheeppool</name>
+            <host name='localhost' port='7000'/>
+        </source>
+      </pool></pre>
+
+    <h3>Example volume output</h3>
+    <pre>
+       <volume>
+         <name>myvol</name>
+         <key>sheep/myvol</key>
+         <source>
+         </source>
+         <capacity unit='bytes'>53687091200</capacity>
+         <allocation unit='bytes'>53687091200</allocation>
+         <target>
+           <path>sheepdog:myvol</path>
+           <format type='unknown'/>
+           <permissions>
+             <mode>00</mode>
+             <owner>0</owner>
+             <group>0</group>
+           </permissions>
+         </target>
+       </volume></pre>
+
+    <h3>Example disk attachement</h3>
+    <p>Sheepdog images can be attached to Qemu guests.
+    Information about attaching a Sheepdog image to a
+    guest can be found
+    at the <a href="formatdomain.html#elementsDisks">format domain</a>
+    page.</p>
+
+    <h3>Valid pool format types</h3>
+    <p>
+      The Sheepdog pool does not use the pool format type element.
+    </p>
+
+    <h3>Valid volume format types</h3>
+    <p>
+      The Sheepdog pool does not use the volume format type element.
+    </p>
+
   </body>
 </html>
diff --git a/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 60f5442..82238b9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -506,6 +506,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
 
@@ -1009,6 +1012,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
@@ -1107,6 +1114,7 @@ EXTRA_DIST +=							\
 		$(STORAGE_DRIVER_MPATH_SOURCES)			\
 		$(STORAGE_DRIVER_DISK_SOURCES)			\
 		$(STORAGE_DRIVER_RBD_SOURCES)			\
+		$(STORAGE_DRIVER_SHEEPDOG_SOURCES)		\
 		$(NODE_DEVICE_DRIVER_SOURCES)			\
 		$(NODE_DEVICE_DRIVER_HAL_SOURCES)		\
 		$(NODE_DEVICE_DRIVER_UDEV_SOURCES)		\
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index bf4567f..8ca6b1e 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -52,7 +52,7 @@ VIR_ENUM_IMPL(virStoragePool,
               VIR_STORAGE_POOL_LAST,
               "dir", "fs", "netfs",
               "logical", "disk", "iscsi",
-              "scsi", "mpath", "rbd")
+              "scsi", "mpath", "rbd", "sheepdog")
 
 VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
               VIR_STORAGE_POOL_FS_LAST,
@@ -206,6 +206,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
             .formatToString = virStoragePoolFormatDiskTypeToString,
         }
     },
+    { .poolType = VIR_STORAGE_POOL_SHEEPDOG,
+      .poolOptions = {
+             .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+                       VIR_STORAGE_POOL_SOURCE_NETWORK |
+                       VIR_STORAGE_POOL_SOURCE_NAME),
+        },
+       .volOptions = {
+            .defaultFormat = VIR_STORAGE_FILE_RAW,
+            .formatToString = virStoragePoolFormatDiskTypeToString,
+        }
+    },
     { .poolType = VIR_STORAGE_POOL_MPATH,
       .volOptions = {
             .formatToString = virStoragePoolFormatDiskTypeToString,
@@ -1011,9 +1022,9 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
     if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
         goto cleanup;
 
-    /* RBD devices are not local block devs nor files, so it doesn't
+    /* RBD and Sheepdog devices are not local block devs nor files, so it doesn't
      * have a target */
-    if (def->type != VIR_STORAGE_POOL_RBD) {
+    if (def->type != VIR_STORAGE_POOL_RBD && def->type != VIR_STORAGE_POOL_SHEEPDOG) {
         virBufferAddLit(&buf,"  <target>\n");
 
         if (def->target.path)
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 5733b57..dcf976f 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -121,6 +121,7 @@ enum virStoragePoolType {
     VIR_STORAGE_POOL_SCSI,     /* SCSI HBA */
     VIR_STORAGE_POOL_MPATH,    /* Multipath devices */
     VIR_STORAGE_POOL_RBD,      /* RADOS Block Device */
+    VIR_STORAGE_POOL_SHEEPDOG, /* Sheepdog device */
 
     VIR_STORAGE_POOL_LAST,
 };
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index e2e9b51..93964d6 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -80,6 +80,9 @@
 #if WITH_STORAGE_RBD
 # include "storage_backend_rbd.h"
 #endif
+#if WITH_STORAGE_SHEEPDOG
+# include "storage_backend_sheepdog.h"
+#endif
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
@@ -109,6 +112,9 @@ static virStorageBackendPtr backends[] = {
 #if WITH_STORAGE_RBD
     &virStorageBackendRBD,
 #endif
+#if WITH_STORAGE_SHEEPDOG
+    &virStorageBackendSheepdog,
+#endif
     NULL
 };
 
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
new file mode 100644
index 0000000..b003856
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.c
@@ -0,0 +1,323 @@
+/*
+ * 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)
+{
+    /* example output:
+     * 0 15245667872 117571104 0%
+     * Total 15245667872 117571104 0% 20972341
+     */
+
+    const char *p, *next;
+
+    pool->allocation = pool->capacity = pool->available = 0;
+
+    p = output;
+    do {
+        char *end;
+
+        if ((next = strchr(p, '\n')))
+            ++next;
+        else
+            return -1;
+
+        if (!STRPREFIX(p, "Total "))
+            continue;
+
+        p = p + 6;
+
+        if (virStrToLong_ull(p, &end, 10, &pool->capacity) < 0)
+            return -1;
+
+        if ((p = end + 1) > next)
+            return -1;
+
+        if (virStrToLong_ull(p, &end, 10, &pool->allocation) < 0)
+            return -1;
+
+        pool->available = pool->capacity - pool->allocation;
+        return 0;
+
+    } while ((p = next));
+
+    return -1;
+}
+
+void virStorageBackendSheepdogAddHostArg(virCommandPtr cmd, virStoragePoolObjPtr pool)
+{
+    const char *address = "localhost";
+    int port = 7000;
+    if (pool->def->source.nhost > 0) {
+        if (pool->def->source.hosts[0].name != NULL) {
+            address = pool->def->source.hosts[0].name;
+        }
+        if (pool->def->source.hosts[0].port) {
+            port = pool->def->source.hosts[0].port;
+        }
+    }
+    virCommandAddArg(cmd, "-a");
+    virCommandAddArgFormat(cmd, "%s", address);
+    virCommandAddArg(cmd, "-p");
+    virCommandAddArgFormat(cmd, "%d", port);
+}
+
+
+static int
+virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                     virStoragePoolObjPtr pool)
+{
+    int ret;
+
+    char *output = NULL;
+
+    virCommandPtr cmd;
+
+    cmd = virCommandNew(COLLIE);
+    virCommandAddArgList(cmd, "node", "info", "-r", NULL);
+    virStorageBackendSheepdogAddHostArg(cmd, pool);
+    virCommandSetOutputBuffer(cmd, &output);
+    ret = virCommandRun(cmd, NULL);
+    if (ret == 0)
+        ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);
+
+    virCommandFree(cmd);
+    VIR_FREE(output);
+    return ret;
+}
+
+
+static int
+virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                   virStoragePoolObjPtr pool
+                                   ATTRIBUTE_UNUSED,
+                                   virStorageVolDefPtr vol,
+                                   unsigned int flags)
+{
+
+    if (flags & VIR_STORAGE_VOL_DELETE_ZEROED) {
+        VIR_WARN("%s", _("This storage backend does not supported zeroed removal of volumes"));
+    }
+
+    virCommandPtr cmd = virCommandNew(COLLIE);
+
+    virCommandAddArgList(cmd, "vdi", "delete", vol->name, NULL);
+    virStorageBackendSheepdogAddHostArg(cmd, pool);
+    int ret = virCommandRun(cmd, NULL);
+
+    virCommandFree(cmd);
+    return ret;
+}
+
+
+static int
+virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                   virStoragePoolObjPtr pool
+                                   ATTRIBUTE_UNUSED,
+                                   virStorageVolDefPtr vol)
+{
+
+    int ret;
+
+    if (vol->target.encryption != NULL) {
+        virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                              _("storage pool does not support encrypted volumes"));
+        return -1;
+    }
+
+    virCommandPtr cmd = virCommandNew(COLLIE);
+
+    virCommandAddArgList(cmd, "vdi", "create", vol->name, NULL);
+    virCommandAddArgFormat(cmd, "%llu", vol->capacity);
+    virStorageBackendSheepdogAddHostArg(cmd, pool);
+    ret = virCommandRun(cmd, NULL);
+
+    virStorageBackendSheepdogRefreshVol(conn, pool, vol);
+
+    virCommandFree(cmd);
+    return ret;
+}
+
+
+int
+virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
+                                      char *output)
+{
+    /* example output:
+     * s test 1 10 0 0 1336556634 7c2b25
+     * s test 2 10 0 0 1336557203 7c2b26
+     * = test 3 10 0 0 1336557216 7c2b27
+     */
+
+    int id;
+
+    const char *p, *next;
+
+    vol->allocation = vol->capacity = 0;
+
+    p = output;
+    do {
+        char *end;
+
+        if ((next = strchr(p, '\n')))
+            ++next;
+
+        /* ignore snapshots */
+        if (*p != '=')
+            continue;
+
+        /* skip space */
+        if (p + 2 < next) {
+            p += 2;
+        } else {
+            return -1;
+        }
+
+        /* skip name */
+        while (*p != '\0'
+               && (*p != ' ' || (*p == ' ' && (*(p - 1) == '\\'))))
+            ++p;
+
+        if (virStrToLong_i(p, &end, 10, &id) < 0)
+            return -1;
+
+        p = end + 1;
+
+        if (virStrToLong_ull(p, &end, 10, &vol->capacity) < 0)
+            return -1;
+
+        p = end + 1;
+
+        if (virStrToLong_ull(p, &end, 10, &vol->allocation) < 0)
+            return -1;
+
+        return 0;
+    } while ((p = next));
+
+    return -1;
+}
+
+static int
+virStorageBackendSheepdogRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                    virStoragePoolObjPtr pool
+                                    ATTRIBUTE_UNUSED,
+                                    virStorageVolDefPtr vol)
+{
+    int ret;
+
+    char *output = NULL;
+
+    virCommandPtr cmd;
+
+    cmd = virCommandNew(COLLIE);
+    virCommandAddArgList(cmd, "vdi", "list", vol->name, "-r", NULL);
+    virStorageBackendSheepdogAddHostArg(cmd, pool);
+    virCommandSetOutputBuffer(cmd, &output);
+    ret = virCommandRun(cmd, NULL);
+
+    if (ret < 0)
+        goto cleanup;
+
+    if ((ret = virStorageBackendSheepdogParseVdiList(vol, output)) < 0)
+        goto cleanup;
+
+    vol->type = VIR_STORAGE_VOL_NETWORK;
+
+    VIR_FREE(vol->key);
+    if (virAsprintf(&vol->key, "%s/%s",
+                    pool->def->source.name, vol->name) == -1) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    VIR_FREE(vol->target.path);
+    if (virAsprintf(&vol->target.path, "sheepdog:%s", vol->name) == -1) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+
+
+cleanup:
+    virCommandFree(cmd);
+    return ret;
+}
+
+
+static int
+virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                   virStoragePoolObjPtr pool
+                                   ATTRIBUTE_UNUSED,
+                                   virStorageVolDefPtr vol,
+                                   unsigned long long capacity,
+                                   unsigned int flags)
+{
+
+    virCheckFlags(0, -1);
+
+    virCommandPtr cmd = virCommandNew(COLLIE);
+
+    virCommandAddArgList(cmd, "vdi", "resize", vol->name, NULL);
+    virCommandAddArgFormat(cmd, "%llu", capacity);
+    virStorageBackendSheepdogAddHostArg(cmd, pool);
+    int ret = virCommandRun(cmd, NULL);
+
+    virCommandFree(cmd);
+    return ret;
+
+}
+
+
+
+virStorageBackend virStorageBackendSheepdog = {
+    .type = VIR_STORAGE_POOL_SHEEPDOG,
+
+    .refreshPool = virStorageBackendSheepdogRefreshPool,
+    .createVol = virStorageBackendSheepdogCreateVol,
+    .refreshVol = virStorageBackendSheepdogRefreshVol,
+    .deleteVol = virStorageBackendSheepdogDeleteVol,
+    .resizeVol = virStorageBackendSheepdogResizeVol,
+};
diff --git a/src/storage/storage_backend_sheepdog.h b/src/storage/storage_backend_sheepdog.h
new file mode 100644
index 0000000..51ef7a4
--- /dev/null
+++ b/src/storage/storage_backend_sheepdog.h
@@ -0,0 +1,39 @@
+/*
+ * storage_backend_sheepog.h: storage backend for Sheepdog handling
+ *
+ * Copyright (C) 2012 Wido den Hollander
+ * Copyright (C) 2012 Frank Spijkerman
+ * Copyright (C) 2012 Sebastian Wiedenroth
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Wido den Hollander <wido 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..a8f62a4
--- /dev/null
+++ b/tests/storagebackendsheepdogtest.c
@@ -0,0 +1,196 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "storage/storage_backend_sheepdog.h"
+
+
+typedef struct {
+    const char *output;
+    int expected_return;
+    uint64_t expected_capacity;
+    uint64_t expected_allocation;
+} collie_test;
+
+
+static int
+test_node_info_parser(collie_test test, char *poolxml)
+{
+    int ret = -1;
+    char *output = NULL;
+    char *poolXmlData = NULL;
+    virStoragePoolDefPtr pool = NULL;
+
+    if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+        goto cleanup;
+
+    if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+        goto cleanup;
+
+    output = strdup(test.output);
+    if(!output) {
+        goto cleanup;
+    }
+
+    ret = virStorageBackendSheepdogParseNodeInfo(pool, output);
+
+    if (ret != test.expected_return)
+        goto cleanup;
+
+    if (ret != 0) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (pool->capacity == test.expected_capacity
+        && pool->allocation == test.expected_allocation)
+        ret = 0;
+
+  cleanup:
+    VIR_FREE(output);
+    VIR_FREE(poolXmlData);
+    virStoragePoolDefFree(pool);
+    return ret;
+}
+
+static int
+test_vdi_list_parser(collie_test test, char *poolxml, char *volxml)
+{
+    int ret = -1;
+    char *poolXmlData = NULL;
+    char *volXmlData = NULL;
+    char *output = NULL;
+    virStoragePoolDefPtr pool = NULL;
+    virStorageVolDefPtr vol = NULL;
+
+    if (virtTestLoadFile(poolxml, &poolXmlData) < 0)
+        goto cleanup;
+    if (virtTestLoadFile(volxml, &volXmlData) < 0)
+        goto cleanup;
+
+    if (!(pool = virStoragePoolDefParseString(poolXmlData)))
+        goto cleanup;
+
+    if (!(vol = virStorageVolDefParseString(pool, volXmlData)))
+        goto cleanup;
+
+    output = strdup(test.output);
+    if(!output) {
+        goto cleanup;
+    }
+
+    ret = virStorageBackendSheepdogParseVdiList(vol, output);
+
+
+    if (ret != test.expected_return)
+        goto cleanup;
+
+    if (ret != 0) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (vol->capacity == test.expected_capacity
+        && vol->allocation == test.expected_allocation)
+        ret = 0;
+
+  cleanup:
+    VIR_FREE(output);
+    VIR_FREE(poolXmlData);
+    VIR_FREE(volXmlData);
+    virStoragePoolDefFree(pool);
+    virStorageVolDefFree(vol);
+    return ret;
+}
+
+
+static int
+mymain(void)
+{
+    int ret = -1;
+    char *poolxml = NULL;
+    char *volxml = NULL;
+
+    collie_test node_info_tests[] = {
+        {"", -1, 0, 0},
+        {"Total 15245667872 117571104 0% 20972341\n", 0, 15245667872, 117571104},
+        {"To", -1, 0, 0},
+        {"asdf\nasdf", -1, 0, 0},
+        {"Total ", -1, 0, 0},
+        {"Total 1", -1, 0, 0},
+        {"Total 1\n", -1, 0, 0},
+        {"Total 1 ", -1, 0, 0},
+        {"Total 1 2", -1, 0, 0},
+        {"Total 1 2 ", -1, 0, 0},
+        {"Total 1 2\n", 0, 1, 2},
+        {"Total 1 2 \n", 0, 1, 2},
+        {"Total a 2 \n", -1, 0, 0},
+        {"Total 1 b \n", -1, 0, 0},
+        {"Total a b \n", -1, 0, 0},
+        {"stuff\nTotal 1 2 \n", 0, 1, 2},
+        {"0 1 2 3\nTotal 1 2 \n", 0, 1, 2},
+        {NULL, 0, 0, 0}
+    };
+
+    collie_test vdi_list_tests[] = {
+        {"", -1, 0, 0},
+        {"= test 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+        {"= test\\ with\\ spaces 3 10 20 0 1336557216 7c2b27\n", 0, 10, 20},
+        {"s test 1 10 20 0 1336556634 7c2b25\n= test 3 50 60 0 1336557216 7c2b27\n", 0, 50, 60},
+        {"=", -1, 0, 0},
+        {"= test", -1, 0, 0},
+        {"= test ", -1, 0, 0},
+        {"= test 1", -1, 0, 0},
+        {"= test 1 ", -1, 0, 0},
+        {"= test 1 2", -1, 0, 0},
+        {"= test 1 2 ", -1, 0, 0},
+        {"= test 1 2 3", -1, 0, 0},
+        {NULL, 0, 0, 0}
+    };
+
+    collie_test *test = node_info_tests;
+
+    if (virAsprintf(&poolxml, "%s/storagepoolxml2xmlin/pool-sheepdog.xml",
+                    abs_srcdir) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&volxml, "%s/storagevolxml2xmlin/vol-sheepdog.xml",
+                    abs_srcdir) < 0)
+        goto cleanup;
+
+    while (test->output != NULL) {
+        ret = test_node_info_parser(*test, poolxml);
+        virtTestResult("node_info_parser", ret, NULL);
+        ++test;
+        if (ret < 0)
+            return EXIT_FAILURE;
+    }
+
+    test = vdi_list_tests;
+
+    while (test->output != NULL) {
+        ret = test_vdi_list_parser(*test, poolxml, volxml);
+        virtTestResult("vdi_list_parser", ret, NULL);
+        ++test;
+        if (ret < 0)
+            return EXIT_FAILURE;
+    }
+
+    ret = 0;
+
+  cleanup:
+    VIR_FREE(poolxml);
+    VIR_FREE(volxml);
+    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
diff --git a/tests/storagepoolxml2xmlin/pool-sheepdog.xml b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
new file mode 100644
index 0000000..1287047
--- /dev/null
+++ b/tests/storagepoolxml2xmlin/pool-sheepdog.xml
@@ -0,0 +1,8 @@
+<pool type='sheepdog'>
+  <name>sheepdog</name>
+  <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+  <source>
+    <host name='localhost' port='7000'/>
+    <name>sheepdog</name>
+  </source>
+</pool>
diff --git a/tests/storagepoolxml2xmlout/pool-sheepdog.xml b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
new file mode 100644
index 0000000..000c068
--- /dev/null
+++ b/tests/storagepoolxml2xmlout/pool-sheepdog.xml
@@ -0,0 +1,11 @@
+<pool type='sheepdog'>
+  <name>sheepdog</name>
+  <uuid>65fcba04-5b13-bd93-cff3-52ce48e11ad7</uuid>
+  <capacity unit='bytes'>0</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <available unit='bytes'>0</available>
+  <source>
+    <host name='localhost' port='7000'/>
+    <name>sheepdog</name>
+  </source>
+</pool>
diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
index d73fc8a..8cac978 100644
--- a/tests/storagepoolxml2xmltest.c
+++ b/tests/storagepoolxml2xmltest.c
@@ -93,6 +93,7 @@ mymain(void)
     DO_TEST("pool-mpath");
     DO_TEST("pool-iscsi-multiiqn");
     DO_TEST("pool-iscsi-vendor-product");
+    DO_TEST("pool-sheepdog");
 
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/tests/storagevolxml2xmlin/vol-sheepdog.xml b/tests/storagevolxml2xmlin/vol-sheepdog.xml
new file mode 100644
index 0000000..49e221c
--- /dev/null
+++ b/tests/storagevolxml2xmlin/vol-sheepdog.xml
@@ -0,0 +1,10 @@
+<volume>
+  <name>test2</name>
+  <source>
+  </source>
+  <capacity unit='bytes'>1024</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <target>
+    <path>sheepdog:test2</path>
+  </target>
+</volume>
diff --git a/tests/storagevolxml2xmlout/vol-sheepdog.xml b/tests/storagevolxml2xmlout/vol-sheepdog.xml
new file mode 100644
index 0000000..2f19af8
--- /dev/null
+++ b/tests/storagevolxml2xmlout/vol-sheepdog.xml
@@ -0,0 +1,17 @@
+<volume>
+  <name>test2</name>
+  <key>(null)</key>
+  <source>
+  </source>
+  <capacity unit='bytes'>1024</capacity>
+  <allocation unit='bytes'>0</allocation>
+  <target>
+    <path>sheepdog:test2</path>
+    <format type='unknown'/>
+    <permissions>
+      <mode>0600</mode>
+      <owner>4294967295</owner>
+      <group>4294967295</group>
+    </permissions>
+  </target>
+</volume>
diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c
index 37c92cd..ee85988 100644
--- a/tests/storagevolxml2xmltest.c
+++ b/tests/storagevolxml2xmltest.c
@@ -112,6 +112,7 @@ mymain(void)
     DO_TEST("pool-disk", "vol-partition");
     DO_TEST("pool-logical", "vol-logical");
     DO_TEST("pool-logical", "vol-logical-backing");
+    DO_TEST("pool-sheepdog", "vol-sheepdog");
 
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/tools/virsh.c b/tools/virsh.c
index 744b629..3f24a34 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -20229,6 +20229,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






More information about the libvir-list mailing list