qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
To: qemu-devel@nongnu.org
Cc: rtalur@redhat.com, deepakcs@redhat.com,
	Prasanna Kumar Kalever <prasanna.kalever@redhat.com>,
	bharata@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH 1/1] block/gluster: add support for multiple gluster backup volfile servers
Date: Tue,  8 Sep 2015 18:34:09 +0530	[thread overview]
Message-ID: <1441717449-31609-1-git-send-email-prasanna.kalever@redhat.com> (raw)

This patch adds a way to specify multiple backup volfile servers to the gluster
block backend of QEMU with both tcp and rdma transport types.

Problem:

Currenly VM Image on gluster volume is specified like this:

file=gluster[+tcp]://server1:24007/testvol/a.img

Assuming we have have three servers in trustred pool with replica 3 volume
in action and unfortunately server1 (mentioned in the command above) went down
for some reason, since the volume is replica 3 we now have other 2 servers
active from which we can boot the VM.

But currently there is no mechanism to pass the other 2 gluster server
addresses to qemu.

Solution:

New way of specifying VM Image on gluster volume with backup volfile servers:

file=gluster[+transport-type]://server1:24007/testvol/a.img\
     ?backup-volfile-servers=server2&backup-volfile-servers=server3

This patch gives a mechanism to provide all the server addresses which are in
replica set, so in case server1 is down VM can still boot from any of the
active servers.

This is equivalent to the backup-volfile-servers option supported by
mount.glusterfs (FUSE way of mounting gluster volume)

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
---
 block/gluster.c | 118 +++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 83 insertions(+), 35 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index 1eb3a8c..ad2fb94 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -25,17 +25,23 @@ typedef struct BDRVGlusterState {
 } BDRVGlusterState;
 
 typedef struct GlusterConf {
-    char *server;
+    GList *server;
     int port;
     char *volname;
     char *image;
     char *transport;
 } GlusterConf;
 
+typedef struct GlusterOptions {
+    struct glfs *glfs;
+    GlusterConf *gconf;
+} GlusterOptions;
+
+
 static void qemu_gluster_gconf_free(GlusterConf *gconf)
 {
     if (gconf) {
-        g_free(gconf->server);
+        g_list_foreach(gconf->server, (GFunc)g_free, NULL);
         g_free(gconf->volname);
         g_free(gconf->image);
         g_free(gconf->transport);
@@ -43,6 +49,7 @@ static void qemu_gluster_gconf_free(GlusterConf *gconf)
     }
 }
 
+
 static int parse_volume_options(GlusterConf *gconf, char *path)
 {
     char *p, *q;
@@ -68,8 +75,19 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
     return 0;
 }
 
+
+static void parse_volfile_server_options(gpointer data, gpointer user_data)
+{
+    char *server = (char *) data;
+    GlusterOptions *options = (GlusterOptions *) user_data;
+
+    glfs_set_volfile_server(options->glfs, options->gconf->transport,
+            server, options->gconf->port);
+}
+
 /*
- * file=gluster[+transport]://[server[:port]]/volname/image[?socket=...]
+ * file=gluster[+transport]://[server[:port]]/volname/image[?socket=...] \
+ *      [?backup-volfile-servers=server2\&backup-volfile-servers=server3 ...]
  *
  * 'gluster' is the protocol.
  *
@@ -102,15 +120,23 @@ static int parse_volume_options(GlusterConf *gconf, char *path)
  * file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
  * file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
  * file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
+ * file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img\
+ *      ?backup-volfile-servers=server1&backup-volfile-servers=server2
  * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
  * file=gluster+rdma://1.2.3.4:24007/testvol/a.img
+ * file=gluster+rdma://1.2.3.4:24007/testvol/a.img\
+ *      ?backup-volfile-servers=4.5.6.7&backup-volfile-servers=8.9.10.11
  */
 static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
 {
-    URI *uri;
-    QueryParams *qp = NULL;
-    bool is_unix = false;
-    int ret = 0;
+    URI         *uri     = NULL;
+    QueryParams *qp      = NULL;
+    bool        is_unix  = false;
+    bool        is_tcp   = false;
+    bool        is_rdma  = false;
+    int         i        = 0;
+    int         ret      = 0;
+    int         nservers = 0;
 
     uri = uri_parse(filename);
     if (!uri) {
@@ -120,13 +146,16 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
     /* transport */
     if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
         gconf->transport = g_strdup("tcp");
+        is_tcp = true;
     } else if (!strcmp(uri->scheme, "gluster+tcp")) {
         gconf->transport = g_strdup("tcp");
+        is_tcp = true;
     } else if (!strcmp(uri->scheme, "gluster+unix")) {
         gconf->transport = g_strdup("unix");
         is_unix = true;
     } else if (!strcmp(uri->scheme, "gluster+rdma")) {
         gconf->transport = g_strdup("rdma");
+        is_rdma = true;
     } else {
         ret = -EINVAL;
         goto out;
@@ -138,23 +167,37 @@ static int qemu_gluster_parseuri(GlusterConf *gconf, const char *filename)
     }
 
     qp = query_params_parse(uri->query);
-    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
-        ret = -EINVAL;
-        goto out;
-    }
-
-    if (is_unix) {
-        if (uri->server || uri->port) {
-            ret = -EINVAL;
-            goto out;
+    if (!(qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n))) {
+        if (is_unix) {
+            if (uri->server || uri->port) {
+                ret = -EINVAL;
+                goto out;
+            }
+            if (strcmp(qp->p[0].name, "socket")) {
+                ret = -EINVAL;
+                goto out;
+            }
+            gconf->server = g_list_append(NULL, g_strdup(qp->p[0].value));
         }
-        if (strcmp(qp->p[0].name, "socket")) {
-            ret = -EINVAL;
-            goto out;
+    } else if (!(!qp->n || ((is_tcp || is_rdma) && !qp->n) ||
+                                        (!(is_tcp || is_rdma) && qp->n))) {
+        nservers = qp->n;
+        if (is_tcp || is_rdma) {
+            for (i = 0; i < nservers; i++) {
+                if (strcmp(qp->p[i].name, "backup-volfile-servers")) {
+                    ret = -EINVAL;
+                    goto out;
+                }
+            }
+            gconf->server = g_list_append(NULL, g_strdup(uri->server));
+            for (i = 0; i < nservers; i++) {
+                gconf->server = g_list_append(gconf->server,
+                                                    g_strdup(qp->p[i].value));
+            }
         }
-        gconf->server = g_strdup(qp->p[0].value);
     } else {
-        gconf->server = g_strdup(uri->server ? uri->server : "localhost");
+        gconf->server = g_list_append(NULL,
+                            g_strdup(uri->server ? uri->server : "localhost"));
         gconf->port = uri->port;
     }
 
@@ -169,28 +212,32 @@ out:
 static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
                                       Error **errp)
 {
-    struct glfs *glfs = NULL;
-    int ret;
-    int old_errno;
+    struct glfs     *glfs   = NULL;
+    GlusterOptions  *params = NULL;
+    int              ret    = -1;
+    int              old_errno;
 
     ret = qemu_gluster_parseuri(gconf, filename);
     if (ret < 0) {
         error_setg(errp, "Usage: file=gluster[+transport]://[server[:port]]/"
-                   "volname/image[?socket=...]");
+                  "volname/image[?socket=...][?backup-volfile-servers=server1"
+                   "&backup-volfile-servers=server2...]");
         errno = -ret;
         goto out;
     }
 
+    params = g_malloc(sizeof(GlusterOptions));
+
     glfs = glfs_new(gconf->volname);
     if (!glfs) {
         goto out;
     }
 
-    ret = glfs_set_volfile_server(glfs, gconf->transport, gconf->server,
-            gconf->port);
-    if (ret < 0) {
-        goto out;
-    }
+    params->glfs  = glfs;
+    params->gconf = gconf;
+
+    g_list_foreach(gconf->server, (GFunc) parse_volfile_server_options,
+                        (GlusterOptions *)params);
 
     /*
      * TODO: Use GF_LOG_ERROR instead of hard code value of 4 here when
@@ -204,17 +251,17 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
     ret = glfs_init(glfs);
     if (ret) {
         error_setg_errno(errp, errno,
-                         "Gluster connection failed for server=%s port=%d "
-                         "volume=%s image=%s transport=%s", gconf->server,
-                         gconf->port, gconf->volname, gconf->image,
-                         gconf->transport);
-
+                         "Gluster connection failed for "
+                         "volume=%s image=%s transport=%s port=%d",
+                         gconf->volname, gconf->image,
+                         gconf->transport, gconf->port);
         /* glfs_init sometimes doesn't set errno although docs suggest that */
         if (errno == 0)
             errno = EINVAL;
 
         goto out;
     }
+    g_free(params);
     return glfs;
 
 out:
@@ -223,6 +270,7 @@ out:
         glfs_fini(glfs);
         errno = old_errno;
     }
+    g_free(params);
     return NULL;
 }
 
-- 
2.1.0

             reply	other threads:[~2015-09-08 13:04 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-08 13:04 Prasanna Kumar Kalever [this message]
2015-09-08 14:43 ` [Qemu-devel] [PATCH 1/1] block/gluster: add support for multiple gluster backup volfile servers Peter Krempa
2015-09-08 15:02 ` Daniel P. Berrange
2015-09-08 15:10   ` Deepak Shetty
2015-09-09  6:06     ` Deepak C Shetty
2015-09-09  9:46     ` Stefan Hajnoczi
2015-09-09 10:19       ` Deepak C Shetty
2015-09-09 12:29         ` Stefan Hajnoczi
2015-09-09 17:07           ` Raghavendra Talur
2015-09-10  5:42             ` Deepak Shetty
2015-09-10  9:30               ` Daniel P. Berrange
2015-09-10 11:47               ` Kevin Wolf
2015-09-09 10:33       ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1441717449-31609-1-git-send-email-prasanna.kalever@redhat.com \
    --to=prasanna.kalever@redhat.com \
    --cc=bharata@linux.vnet.ibm.com \
    --cc=deepakcs@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rtalur@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).