Patchwork [BUG:1440] Cli volume add-brick validation

login
register
Submitter shishir gowda
Date 2010-08-26 09:02:21
Message ID <20100826090221.GA25190@dev.gluster.com>
Download mbox | patch
Permalink /patch/4315/
State Accepted
Headers show

Comments

shishir gowda - 2010-08-26 09:02:21
Signed-off-by: shishir gowda <shishirng@gluster.com>
---
 cli/src/cli3_1-cops.c                        |    2 +
 rpc/xdr/src/cli1-xdr.c                       |    2 +
 rpc/xdr/src/cli1-xdr.h                       |    1 +
 rpc/xdr/src/cli1.x                           |    1 +
 xlators/mgmt/glusterd/src/glusterd-handler.c |  134 ++++++++++++++++++++++++++
 xlators/mgmt/glusterd/src/glusterd-op-sm.c   |    1 +
 6 files changed, 141 insertions(+), 0 deletions(-)

Patch

diff --git a/cli/src/cli3_1-cops.c b/cli/src/cli3_1-cops.c
index 7200800..77fb385 100644
--- a/cli/src/cli3_1-cops.c
+++ b/cli/src/cli3_1-cops.c
@@ -662,6 +662,8 @@  gf_cli3_1_add_brick_cbk (struct rpc_req *req, struct iovec *iov,
         cli_out ("Add Brick %s", (rsp.op_ret) ? "unsuccessful":
                                         "successful");
 
+        if (rsp.op_ret && rsp.op_errstr)
+                cli_out ("%s", rsp.op_errstr);
         ret = rsp.op_ret;
 
 out:
diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c
index b850bde..ce16b66 100644
--- a/rpc/xdr/src/cli1-xdr.c
+++ b/rpc/xdr/src/cli1-xdr.c
@@ -375,6 +375,8 @@  xdr_gf1_cli_add_brick_rsp (XDR *xdrs, gf1_cli_add_brick_rsp *objp)
 		 return FALSE;
 	 if (!xdr_string (xdrs, &objp->volname, ~0))
 		 return FALSE;
+	 if (!xdr_string (xdrs, &objp->op_errstr, ~0)) 
+		 return FALSE;
 	return TRUE;
 }
 
diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h
index 77dbfb8..c6fd14f 100644
--- a/rpc/xdr/src/cli1-xdr.h
+++ b/rpc/xdr/src/cli1-xdr.h
@@ -226,6 +226,7 @@  struct gf1_cli_add_brick_rsp {
 	int op_ret;
 	int op_errno;
 	char *volname;
+	char *op_errstr;
 };
 typedef struct gf1_cli_add_brick_rsp gf1_cli_add_brick_rsp;
 
diff --git a/rpc/xdr/src/cli1.x b/rpc/xdr/src/cli1.x
index 6ca6002..ffb8ab2 100644
--- a/rpc/xdr/src/cli1.x
+++ b/rpc/xdr/src/cli1.x
@@ -145,6 +145,7 @@  struct gf1_cli_get_vol_rsp {
         int     op_ret;
         int     op_errno;
         string  volname<>;
+	 string  op_errstr<>;
 }  ;
 
  struct gf1_cli_remove_brick_req {
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index fb5a0df..65791d4 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -1165,6 +1165,19 @@  glusterd_handle_add_brick (rpcsvc_request_t *req)
         int32_t                         ret = -1;
         gf1_cli_add_brick_req          cli_req = {0,};
         dict_t                          *dict = NULL;
+        glusterd_brickinfo_t            *brickinfo = NULL;
+        char                            *brick = NULL;
+        char                            *bricks = NULL;
+        char                            *volname = NULL;
+        int                             brick_count = 0;
+        char                            *tmpptr = NULL;
+        int                             i = 0;
+        glusterd_peerinfo_t             *peerinfo = NULL;
+        char                            *brick_list = NULL;
+        void                            *cli_rsp = NULL;
+        char                            err_str[1048];
+        gf1_cli_add_brick_rsp           rsp = {0,};
+        glusterd_volinfo_t              *volinfo = NULL;
 
         GF_ASSERT (req);
 
@@ -1191,6 +1204,127 @@  glusterd_handle_add_brick (rpcsvc_request_t *req)
                 }
         }
 
+        ret = dict_get_str (dict, "volname", &volname);
+
+        if (ret) {
+                gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+                goto out;
+        }
+
+        if (!(ret = glusterd_check_volume_exists (volname))) {
+                gf_log ("", GF_LOG_ERROR, "Volname %s does not exist",
+                        volname);
+                rsp.op_ret = -1;
+                rsp.op_errno = 0;
+                rsp.volname = "";
+                snprintf(err_str, 1048, "Volname %s does not exist",
+                         volname);
+                rsp.op_errstr = err_str;
+                cli_rsp = &rsp;
+                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL,
+                                      gf_xdr_serialize_cli_add_brick_rsp);
+                if (!glusterd_opinfo_unlock())
+                        gf_log ("glusterd", GF_LOG_ERROR, "Unlock on opinfo"
+                                " failed");
+
+                ret = 0; //sent error to cli, prevent second reply
+                goto out;
+        }
+
+        ret = dict_get_int32 (dict, "count", &brick_count);
+        if (ret) {
+                gf_log ("", GF_LOG_ERROR, "Unable to get count");
+                goto out;
+        }
+
+        if (!(ret = glusterd_volinfo_find (volname, &volinfo))) {
+                if (volinfo->type == GF_CLUSTER_TYPE_NONE)
+                        goto brick_val;
+                if (!brick_count || !volinfo->sub_count)
+                        goto brick_val;
+                if ((brick_count % volinfo->sub_count) != 0) {
+                        rsp.op_ret = -1;
+                        rsp.op_errno = -1;
+                        rsp.volname = "";
+                        snprintf(err_str, 2048, "Incorrect number of bricks"
+                                " supplied %d for type %s with count %d",
+                                brick_count, (volinfo->type == 1)? "STRIPE":
+                                "REPLICATE", volinfo->sub_count);  
+                        rsp.op_errstr = err_str;
+                        cli_rsp = &rsp;
+                        glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL,
+                                            gf_xdr_serialize_cli_add_brick_rsp);
+                        if (!glusterd_opinfo_unlock())
+                                  gf_log ("glusterd", GF_LOG_ERROR, "Unlock on opinfo"
+                                          " failed");
+
+                        ret = 0; //sent error to cli, prevent second reply
+                        goto out;
+                }       
+        } else {
+                gf_log("", GF_LOG_ERROR, "Unable to get volinfo for volname"
+                       " %s", volname);
+                goto out; 
+        }
+
+brick_val:
+        ret = dict_get_str (dict, "bricks", &bricks);
+        if (ret) {
+                gf_log ("", GF_LOG_ERROR, "Unable to get bricks");
+                goto out;
+        }
+
+        if (bricks)
+                brick_list = gf_strdup (bricks);
+
+        while ( i < brick_count) {
+                i++;
+                brick= strtok_r (brick_list, " \n", &tmpptr);
+                brick_list = tmpptr;
+                ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
+                if (ret)
+                        goto out;
+                if(!(ret = glusterd_is_local_addr(brickinfo->hostname)))
+                        continue;       //localhost, continue without validation        
+                ret = glusterd_friend_find_by_hostname(brickinfo->hostname,
+                                                        &peerinfo);
+                if (ret) {
+                        rsp.op_ret = -1;
+                        rsp.op_errno = 0;
+                        rsp.volname = "";
+                        snprintf(err_str, 1048, "Host %s not a friend",
+                                 brickinfo->hostname);
+                        rsp.op_errstr = err_str;
+                        cli_rsp = &rsp;
+                        glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL,
+                                              gf_xdr_serialize_cli_add_brick_rsp);
+                        if (!glusterd_opinfo_unlock())
+                                gf_log ("glusterd", GF_LOG_ERROR, "Unlock on "
+                                        "opinfo failed");
+
+                        ret = 0; //sent error to cli, prevent second reply
+                        goto out;
+                }
+                if ((!peerinfo->connected) &&
+                    (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED)) {
+                        rsp.op_ret = -1;
+                        rsp.op_errno = 0;
+                        rsp.volname = "";
+                        snprintf(err_str, 1048, "Host %s not connected",
+                                 brickinfo->hostname);
+                        rsp.op_errstr = err_str;
+                        cli_rsp = &rsp;
+                        glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL,
+                                              gf_xdr_serialize_cli_add_brick_rsp);
+                        if (!glusterd_opinfo_unlock())
+                                gf_log ("glusterd", GF_LOG_ERROR, "Unlock on "
+                                        "opinfo failed");
+
+                        ret = 0; //sent error to cli, prevent second reply
+                        goto out;
+                }
+        }
+
         ret = glusterd_add_brick (req, dict);
 
 out:
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 5d3323f..03c1190 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -2408,6 +2408,7 @@  glusterd_op_send_cli_response (int32_t op, int32_t op_ret,
                                 rsp.op_ret = op_ret;
                                 rsp.op_errno = op_errno;
                                 rsp.volname = "";
+                                rsp.op_errstr = "";
                                 cli_rsp = &rsp;
                                 sfunc = gf_xdr_serialize_cli_add_brick_rsp;
                                 break;