[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] support sheepdog volumes



Sheepdog is a distributed storage system for QEMU. It provides highly
available block level storage volumes to VMs like Amazon EBS.  This
patch adds support for Sheepdog; we can create VMs with sheepdog
volumes, and attach sheepdog volumes to running machines via the
attach-device command.

Sheepdog volumes can be declared like this:

    <disk type='sheepdog' device='disk'>
      <driver name='qemu' type='raw' />
      <source vdi='volume_name' host='hostname' port='7000'/>
      <target dev='vda' bus='virtio' />
    </disk>

'host' and 'port' in the source element are optional.  If they are not
specified, sheepdog clients use the default value (localhost:7000).

Signed-off-by: MORITA Kazutaka <morita kazutaka lab ntt co jp>
---
 docs/schemas/domain.rng |   24 ++++++++++++++++++
 src/conf/domain_conf.c  |   26 ++++++++++++++++++-
 src/conf/domain_conf.h  |    3 ++
 src/qemu/qemu_conf.c    |   63 +++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 113 insertions(+), 3 deletions(-)

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index bbbc846..5802993 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -612,6 +612,30 @@
             <ref name="diskspec"/>
           </interleave>
         </group>
+        <group>
+          <attribute name="type">
+            <value>sheepdog</value>
+          </attribute>
+          <interleave>
+            <optional>
+              <element name="source">
+                <attribute name="vdi">
+                  <ref name="genericName"/>
+                </attribute>
+                <optional>
+                  <attribute name="host">
+                    <ref name="genericName"/>
+                  </attribute>
+                  <attribute name="port">
+                    <ref name="unsignedInt"/>
+                  </attribute>
+                </optional>
+                <empty/>
+              </element>
+            </optional>
+            <ref name="diskspec"/>
+          </interleave>
+        </group>
         <ref name="diskspec"/>
       </choice>
     </element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 30c27db..d0ea0bb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -113,7 +113,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
 VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
               "block",
               "file",
-              "dir")
+              "dir",
+              "sheepdog")
 
 VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
               "disk",
@@ -505,6 +506,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
 
     VIR_FREE(def->serial);
     VIR_FREE(def->src);
+    VIR_FREE(def->host);
+    VIR_FREE(def->port);
     VIR_FREE(def->dst);
     VIR_FREE(def->driverName);
     VIR_FREE(def->driverType);
@@ -1517,6 +1520,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     char *driverName = NULL;
     char *driverType = NULL;
     char *source = NULL;
+    char *host = NULL;
+    char *port = NULL;
     char *target = NULL;
     char *bus = NULL;
     char *cachetag = NULL;
@@ -1557,6 +1562,11 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                 case VIR_DOMAIN_DISK_TYPE_DIR:
                     source = virXMLPropString(cur, "dir");
                     break;
+                case VIR_DOMAIN_DISK_TYPE_SHEEPDOG:
+                    source = virXMLPropString(cur, "vdi");
+                    host = virXMLPropString(cur, "host");
+                    port = virXMLPropString(cur, "port");
+                    break;
                 default:
                     virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                                          _("unexpected disk type %s"),
@@ -1726,6 +1736,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
 
     def->src = source;
     source = NULL;
+    def->host = host;
+    host = NULL;
+    def->port = port;
+    port = NULL;
     def->dst = target;
     target = NULL;
     def->driverName = driverName;
@@ -1756,6 +1770,8 @@ cleanup:
     VIR_FREE(type);
     VIR_FREE(target);
     VIR_FREE(source);
+    VIR_FREE(host);
+    VIR_FREE(port);
     VIR_FREE(device);
     VIR_FREE(driverType);
     VIR_FREE(driverName);
@@ -5831,6 +5847,14 @@ virDomainDiskDefFormat(virBufferPtr buf,
             virBufferEscapeString(buf, "      <source dir='%s'/>\n",
                                   def->src);
             break;
+        case VIR_DOMAIN_DISK_TYPE_SHEEPDOG:
+            virBufferEscapeString(buf, "      <source vdi='%s'", def->src);
+            if (def->host && def->port) {
+                virBufferEscapeString(buf, " host='%s'", def->host);
+                virBufferEscapeString(buf, " port='%s'", def->port);
+            }
+            virBufferVSprintf(buf, "/>\n");
+            break;
         default:
             virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                                  _("unexpected disk type %s"),
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7d2d6f5..9c929c4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -120,6 +120,7 @@ enum virDomainDiskType {
     VIR_DOMAIN_DISK_TYPE_BLOCK,
     VIR_DOMAIN_DISK_TYPE_FILE,
     VIR_DOMAIN_DISK_TYPE_DIR,
+    VIR_DOMAIN_DISK_TYPE_SHEEPDOG,
 
     VIR_DOMAIN_DISK_TYPE_LAST
 };
@@ -172,6 +173,8 @@ struct _virDomainDiskDef {
     int device;
     int bus;
     char *src;
+    char *host;
+    char *port;
     char *dst;
     char *driverName;
     char *driverType;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 83a117a..84f55cb 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2731,6 +2731,11 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
                 virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
             else
                 virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
+        } else if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+            if (disk->host && disk->port)
+                virBufferVSprintf(&opt, "file=sheepdog:%s:%s:%s,", disk->host, disk->port, disk->src);
+            else
+                virBufferVSprintf(&opt, "file=sheepdog:%s,", disk->src);
         } else {
             virBufferVSprintf(&opt, "file=%s,", disk->src);
         }
@@ -4720,6 +4725,11 @@ int qemudBuildCommandLine(virConnectPtr conn,
                     snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
                 else
                     snprintf(file, PATH_MAX, "fat:%s", disk->src);
+            } else if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+                if (disk->host && disk->port)
+                    snprintf(file, PATH_MAX, "sheepdog:%s:%s:%s", disk->host, disk->port, disk->src);
+                else
+                    snprintf(file, PATH_MAX, "sheepdog:%s", disk->src);
             } else {
                 snprintf(file, PATH_MAX, "%s", disk->src);
             }
@@ -5792,7 +5802,32 @@ qemuParseCommandLineDisk(virCapsPtr caps,
                 values[i] = NULL;
                 if (STRPREFIX(def->src, "/dev/"))
                     def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
-                else
+                else if (STRPREFIX(def->src, "sheepdog:")) {
+                    char *p = def->src;
+                    char *port, *vdi;
+
+                    def->type = VIR_DOMAIN_DISK_TYPE_SHEEPDOG;
+                    def->src = strdup(p + strlen("sheepdog:"));
+
+                    /* def->src must be [vdiname] or [host]:[port]:[vdiname] */
+                    port = strchr(def->src, ':');
+                    if (port) {
+                        *port++ = '\0';
+                        vdi = strchr(port, ':');
+                        if (!vdi) {
+                            def = NULL;
+                            qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                            _("cannot parse sheepdog filename '%s'"), p);
+                            goto cleanup;
+                        }
+                        *vdi++ = '\0';
+                        def->host = def->src;
+                        def->port = strdup(port);
+                        def->src = strdup(vdi);
+                    }
+
+                    VIR_FREE(p);
+                } else
                     def->type = VIR_DOMAIN_DISK_TYPE_FILE;
             } else {
                 def->type = VIR_DOMAIN_DISK_TYPE_FILE;
@@ -6729,7 +6764,10 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
 
             if (STRPREFIX(val, "/dev/"))
                 disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
-            else
+            else if (STRPREFIX(val, "sheepdog:")) {
+                disk->type = VIR_DOMAIN_DISK_TYPE_SHEEPDOG;
+                val = STRSKIP(val, "sheepdog:");
+            } else
                 disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
             if (STREQ(arg, "-cdrom")) {
                 disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
@@ -6749,6 +6787,27 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
                 disk->dst = strdup(arg + 1);
             }
             disk->src = strdup(val);
+
+            if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+                char *port, *vdi;
+
+                /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
+                port = strchr(disk->src, ':');
+                if (port) {
+                    *port++ = '\0';
+                    vdi = strchr(port, ':');
+                    if (!vdi) {
+                        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                        _("cannot parse sheepdog filename '%s'"), val);
+                        goto error;
+                    }
+                    *vdi++ = '\0';
+                    disk->host = disk->src;
+                    disk->port = strdup(port);
+                    disk->src = strdup(vdi);
+                }
+            }
+
             if (!disk->src ||
                 !disk->dst) {
                 virDomainDiskDefFree(disk);
-- 
1.7.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]