From 992e580df4a38bb96b0114a3b033d0dc0b8425b7 Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Tue, 23 Aug 2011 10:25:35 +0530 Subject: mgmt/glusterd: code re-structuring created new files per operations, (or group of operations) Change-Id: Iccb2a6a0cd9661bf940118344b2f7f723e23ab8b BUG: 3158 Reviewed-on: http://review.gluster.com/281 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/mgmt/glusterd/src/Makefile.am | 8 +- xlators/mgmt/glusterd/src/glusterd-brick-ops.c | 920 +++ xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 1579 +++++ xlators/mgmt/glusterd/src/glusterd-handler.c | 1325 +--- xlators/mgmt/glusterd/src/glusterd-log-ops.c | 804 +++ xlators/mgmt/glusterd/src/glusterd-op-sm.c | 6578 ++------------------ xlators/mgmt/glusterd/src/glusterd-quota.c | 810 +++ xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 1929 ++++++ xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 1038 +++ xlators/mgmt/glusterd/src/glusterd.h | 53 + 10 files changed, 7657 insertions(+), 7387 deletions(-) create mode 100644 xlators/mgmt/glusterd/src/glusterd-brick-ops.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-geo-rep.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-log-ops.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-quota.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-replace-brick.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-volume-ops.c (limited to 'xlators/mgmt/glusterd') diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 714b78e62..01fbbd064 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -3,10 +3,12 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mgmt glusterd_la_LDFLAGS = -module -avoidversion $(LIBXML2_LIBS) glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c glusterd-op-sm.c \ glusterd-utils.c glusterd-rpc-ops.c glusterd-store.c glusterd-handshake.c \ - glusterd-pmap.c glusterd-volgen.c glusterd-rebalance.c + glusterd-pmap.c glusterd-volgen.c glusterd-rebalance.c glusterd-quota.c \ + glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \ + glusterd-volume-ops.c glusterd-brick-ops.c -glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\ - $(top_builddir)/rpc/xdr/src/libgfxdr.la\ +glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ + $(top_builddir)/rpc/xdr/src/libgfxdr.la \ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h glusterd-sm.h \ diff --git a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c new file mode 100644 index 000000000..d05dd49a1 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c @@ -0,0 +1,920 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +int +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; + char *brick_list = NULL; + void *cli_rsp = NULL; + char err_str[2048] = {0,}; + gf1_cli_add_brick_rsp rsp = {0,}; + glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + char *free_ptr = NULL; + glusterd_brickinfo_t *tmpbrkinfo = NULL; + glusterd_volinfo_t tmpvolinfo = {{0},}; + int total_bricks = 0; + + this = THIS; + GF_ASSERT(this); + + priv = this->private; + + GF_ASSERT (req); + + INIT_LIST_HEAD (&tmpvolinfo.bricks); + + if (!gf_xdr_to_cli_add_brick_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + snprintf (err_str, sizeof (err_str), "Garbage args received"); + goto out; + } + + gf_cmd_log ("Volume add-brick", "on volname: %s attempted", + cli_req.volname); + gf_log ("glusterd", GF_LOG_INFO, "Received add brick req"); + + if (cli_req.bricks.bricks_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (cli_req.bricks.bricks_val, + cli_req.bricks.bricks_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, + "failed to " + "unserialize req-buffer to dictionary"); + snprintf (err_str, sizeof (err_str), "Unable to decode " + "the buffer"); + goto out; + } else { + dict->extra_stdfree = cli_req.bricks.bricks_val; + } + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "name"); + goto out; + } + + if (!(ret = glusterd_check_volume_exists (volname))) { + ret = -1; + snprintf(err_str, 2048, "Volume %s does not exist", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); + goto out; + } + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "brick 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; + + total_bricks = volinfo->brick_count + brick_count; + /* If the brick count is less than sub_count then, allow add-brick only for + plain replicate volume since in plain stripe brick_count becoming less than + the sub_count is not allowed */ + if (volinfo->brick_count < volinfo->sub_count && + (volinfo->type == GF_CLUSTER_TYPE_REPLICATE)) { + if (total_bricks <= volinfo->sub_count) + goto brick_val; + } + + if ((brick_count % volinfo->sub_count) != 0) { + 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); + gf_log("glusterd", GF_LOG_ERROR, "%s", err_str); + ret = -1; + goto out; + } + } else { + snprintf (err_str, sizeof (err_str), "Unable to get volinfo " + "for volume name %s", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); + goto out; + } + +brick_val: + ret = dict_get_str (dict, "bricks", &bricks); + if (ret) { + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "bricks"); + gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); + goto out; + } + + if (bricks) + brick_list = gf_strdup (bricks); + if (!brick_list) { + ret = -1; + snprintf (err_str, sizeof (err_str), "Out of memory"); + goto out; + } else { + free_ptr = brick_list; + } + + gf_cmd_log ("Volume add-brick", "volname: %s type %s count:%d bricks:%s" + ,volname, ((volinfo->type == 0)? "DEFAULT" : ((volinfo->type + == 1)? "STRIPE": "REPLICATE")), brick_count, brick_list); + + + while ( i < brick_count) { + i++; + brick= strtok_r (brick_list, " \n", &tmpptr); + brick_list = tmpptr; + brickinfo = NULL; + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) { + snprintf (err_str, sizeof (err_str), "Unable to get " + "brick info from brick %s", brick); + goto out; + } + ret = glusterd_new_brick_validate (brick, brickinfo, err_str, + sizeof (err_str)); + if (ret) + goto out; + ret = glusterd_volume_brickinfo_get (brickinfo->uuid, + brickinfo->hostname, + brickinfo->path, + &tmpvolinfo, &tmpbrkinfo); + if (!ret) { + ret = -1; + snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" + " one of the arguments contain the other", + tmpbrkinfo->hostname, tmpbrkinfo->path, brick); + goto out; + } + list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); + brickinfo = NULL; + } + + ret = glusterd_op_begin (req, GD_OP_ADD_BRICK, dict); + gf_cmd_log ("Volume add-brick","on volname: %s %s", volname, + (ret != 0)? "FAILED" : "SUCCESS"); + +out: + if (ret) { + if (dict) + dict_unref (dict); + rsp.op_ret = -1; + rsp.op_errno = 0; + rsp.volname = ""; + if (err_str[0] == '\0') + snprintf (err_str, sizeof (err_str), "Operation failed"); + rsp.op_errstr = err_str; + cli_rsp = &rsp; + glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, + gf_xdr_serialize_cli_add_brick_rsp, + (xdrproc_t)xdr_gf1_cli_add_brick_rsp); + ret = 0; //sent error to cli, prevent second reply + } + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (free_ptr) + GF_FREE (free_ptr); + glusterd_volume_brickinfos_delete (&tmpvolinfo); + if (brickinfo) + glusterd_brickinfo_delete (brickinfo); + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + return ret; +} + +int +glusterd_handle_remove_brick (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_remove_brick_req cli_req = {0,}; + dict_t *dict = NULL; + int32_t count = 0; + char *brick = NULL; + char key[256] = {0,}; + char *brick_list = NULL; + int i = 1; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int32_t pos = 0; + int32_t sub_volume = 0; + int32_t sub_volume_start = 0; + int32_t sub_volume_end = 0; + glusterd_brickinfo_t *tmp = NULL; + char err_str[2048] = {0}; + gf1_cli_remove_brick_rsp rsp = {0,}; + void *cli_rsp = NULL; + char vol_type[256] = {0,}; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_remove_brick_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_cmd_log ("Volume remove-brick","on volname: %s attempted",cli_req.volname); + gf_log ("glusterd", GF_LOG_INFO, "Received rem brick req"); + + if (cli_req.bricks.bricks_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (cli_req.bricks.bricks_val, + cli_req.bricks.bricks_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, + "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } else { + dict->extra_stdfree = cli_req.bricks.bricks_val; + } + } + + ret = dict_get_int32 (dict, "count", &count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + ret = glusterd_volinfo_find (cli_req.volname, &volinfo); + if (ret) { + snprintf (err_str, 2048, "Volume %s does not exist", + cli_req.volname); + gf_log ("", GF_LOG_ERROR, "%s", err_str); + goto out; + } + + if (volinfo->type == GF_CLUSTER_TYPE_REPLICATE) + strcpy (vol_type, "replica"); + else if (volinfo->type == GF_CLUSTER_TYPE_STRIPE) + strcpy (vol_type, "stripe"); + else + strcpy (vol_type, "distribute"); + + /* Do not allow remove-brick if the volume is plain stripe */ + if ((volinfo->type == GF_CLUSTER_TYPE_STRIPE) && (volinfo->brick_count == volinfo->sub_count)) { + snprintf (err_str, 2048, "Removing brick from a plain stripe is not allowed"); + gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); + ret = -1; + goto out; + } + + /* Do not allow remove-brick if the bricks given is less than the replica count + or stripe count */ + if (((volinfo->type == GF_CLUSTER_TYPE_REPLICATE) || (volinfo->type == GF_CLUSTER_TYPE_STRIPE)) + && !(volinfo->brick_count <= volinfo->sub_count)) { + if (volinfo->sub_count && (count % volinfo->sub_count != 0)) { + snprintf (err_str, 2048, "Remove brick incorrect" + " brick count of %d for %s %d", + count, vol_type, volinfo->sub_count); + gf_log ("", GF_LOG_ERROR, "%s", err_str); + ret = -1; + goto out; + } + } + + brick_list = GF_MALLOC (120000 * sizeof(*brick_list),gf_common_mt_char); + + if (!brick_list) { + ret = -1; + goto out; + } + + strcpy (brick_list, " "); + while ( i <= count) { + snprintf (key, 256, "brick%d", i); + ret = dict_get_str (dict, key, &brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); + goto out; + } + gf_log ("", GF_LOG_DEBUG, "Remove brick count %d brick: %s", + i, brick); + + ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo); + if (ret) { + snprintf(err_str, 2048,"Incorrect brick %s for volume" + " %s", brick, cli_req.volname); + gf_log ("", GF_LOG_ERROR, "%s", err_str); + goto out; + } + strcat(brick_list, brick); + strcat(brick_list, " "); + + i++; + if ((volinfo->type == GF_CLUSTER_TYPE_NONE) || + (volinfo->brick_count <= volinfo->sub_count)) + continue; + + pos = 0; + list_for_each_entry (tmp, &volinfo->bricks, brick_list) { + + if ((!strcmp (tmp->hostname,brickinfo->hostname)) && + !strcmp (tmp->path, brickinfo->path)) { + gf_log ("", GF_LOG_INFO, "Found brick"); + if (!sub_volume && volinfo->sub_count) { + sub_volume = (pos / volinfo-> + sub_count) + 1; + sub_volume_start = volinfo->sub_count * + (sub_volume - 1); + sub_volume_end = (volinfo->sub_count * + sub_volume) -1 ; + } else { + if (pos < sub_volume_start || + pos >sub_volume_end) { + ret = -1; + snprintf(err_str, 2048,"Bricks" + " not from same subvol" + " for %s", vol_type); + gf_log ("",GF_LOG_ERROR, + "%s", err_str); + goto out; + } + } + break; + } + pos++; + } + } + gf_cmd_log ("Volume remove-brick","volname: %s count:%d bricks:%s", + cli_req.volname, count, brick_list); + + ret = glusterd_op_begin (req, GD_OP_REMOVE_BRICK, dict); + gf_cmd_log ("Volume remove-brick","on volname: %s %s",cli_req.volname, + (ret) ? "FAILED" : "SUCCESS"); + +out: + if (ret) { + if (dict) + dict_unref (dict); + rsp.op_ret = -1; + rsp.op_errno = 0; + rsp.volname = ""; + if (err_str[0] == '\0') + snprintf (err_str, sizeof (err_str), "Operation failed"); + gf_log ("", GF_LOG_ERROR, "%s", err_str); + rsp.op_errstr = err_str; + cli_rsp = &rsp; + glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, + gf_xdr_serialize_cli_remove_brick_rsp, + (xdrproc_t)xdr_gf1_cli_remove_brick_rsp); + + ret = 0; //sent error to cli, prevent second reply + + } + if (brick_list) + GF_FREE (brick_list); + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + return ret; +} + + +/* op-sm */ + +int +glusterd_op_perform_add_bricks (glusterd_volinfo_t *volinfo, int32_t count, + char *bricks) +{ + glusterd_brickinfo_t *brickinfo = NULL; + char *brick = NULL; + int32_t i = 1; + char *brick_list = NULL; + char *free_ptr1 = NULL; + char *free_ptr2 = NULL; + char *saveptr = NULL; + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + + GF_ASSERT (volinfo); + + if (bricks) { + brick_list = gf_strdup (bricks); + free_ptr1 = brick_list; + } + + if (count) + brick = strtok_r (brick_list+1, " \n", &saveptr); + + while ( i <= count) { + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) + goto out; + + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; + list_add_tail (&brickinfo->brick_list, &volinfo->bricks); + brick = strtok_r (NULL, " \n", &saveptr); + i++; + volinfo->brick_count++; + + } + + brick_list = gf_strdup (bricks); + free_ptr2 = brick_list; + i = 1; + + if (count) + brick = strtok_r (brick_list+1, " \n", &saveptr); + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) + goto out; + + while (i <= count) { + + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + &brickinfo); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_brick_start (volinfo, brickinfo); + if (ret) + goto out; + } + i++; + brick = strtok_r (NULL, " \n", &saveptr); + } + +out: + if (free_ptr1) + GF_FREE (free_ptr1); + if (free_ptr2) + GF_FREE (free_ptr2); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + + +int +glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick) +{ + + glusterd_brickinfo_t *brickinfo = NULL; + char *dup_brick = NULL; + glusterd_conf_t *priv = NULL; + int32_t ret = -1; + + GF_ASSERT (volinfo); + GF_ASSERT (brick); + + priv = THIS->private; + + dup_brick = gf_strdup (brick); + if (!dup_brick) + goto out; + + ret = glusterd_volume_brickinfo_get_by_brick (dup_brick, volinfo, &brickinfo); + if (ret) + goto out; + + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_brick_stop (volinfo, brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to stop " + "glusterfs, ret: %d", ret); + goto out; + } + } + glusterd_delete_brick (volinfo, brickinfo); +out: + if (dup_brick) + GF_FREE (dup_brick); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + int count = 0; + int i = 0; + char *bricks = NULL; + char *brick_list = NULL; + char *saveptr = NULL; + char *free_ptr = NULL; + char *brick = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + char cmd_str[1024]; + glusterd_conf_t *priv = NULL; + char msg[2048] = {0,}; + gf_boolean_t brick_alloc = _gf_false; + char *all_bricks = NULL; + char *str_ret = NULL; + + priv = THIS->private; + if (!priv) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to find volume: %s", volname); + goto out; + } + + if (glusterd_is_defrag_on(volinfo)) { + snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " + "progress. Please retry after completion", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + ret = dict_get_int32 (dict, "count", &count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + 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); + all_bricks = gf_strdup (bricks); + free_ptr = brick_list; + } + + /* Check whether any of the bricks given is the destination brick of the + replace brick running */ + + str_ret = glusterd_check_brick_rb_part (all_bricks, count, volinfo); + if (str_ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "%s", str_ret); + *op_errstr = gf_strdup (str_ret); + ret = -1; + goto out; + } + + if (count) + brick = strtok_r (brick_list+1, " \n", &saveptr); + + + while ( i < count) { + if (!glusterd_store_is_valid_brickpath (volname, brick) || + !glusterd_is_valid_volfpath (volname, brick)) { + snprintf (msg, sizeof (msg), "brick path %s is too " + "long.", brick); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + + ret = -1; + goto out; + + } + + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + &brickinfo); + if (!ret) { + gf_log ("", GF_LOG_ERROR, "Adding duplicate brick: %s", + brick); + ret = -1; + goto out; + } else { + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" + " to get brickinfo"); + goto out; + } + brick_alloc = _gf_true; + } + + snprintf (cmd_str, 1024, "%s", brickinfo->path); + ret = glusterd_resolve_brick (brickinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "resolve brick failed"); + goto out; + } + + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + ret = glusterd_brick_create_path (brickinfo->hostname, + brickinfo->path, + volinfo->volume_id, + 0777, op_errstr); + if (ret) + goto out; + } + + glusterd_brickinfo_delete (brickinfo); + brick_alloc = _gf_false; + brickinfo = NULL; + brick = strtok_r (NULL, " \n", &saveptr); + i++; + } + +out: + if (free_ptr) + GF_FREE (free_ptr); + if (brick_alloc && brickinfo) + glusterd_brickinfo_delete (brickinfo); + if (str_ret) + GF_FREE (str_ret); + if (all_bricks) + GF_FREE (all_bricks); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stage_remove_brick (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + dict_t *ctx = NULL; + char *errstr = NULL; + int32_t brick_count = 0; + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Volume %s does not exist", volname); + goto out; + } + + if (glusterd_is_defrag_on(volinfo)) { + ctx = glusterd_op_get_ctx (); + errstr = gf_strdup("Rebalance is in progress. Please retry" + " after completion"); + if (!errstr) { + ret = -1; + goto out; + } + gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); + ret = dict_set_dynstr (ctx, "errstr", errstr); + if (ret) { + GF_FREE (errstr); + gf_log ("", GF_LOG_DEBUG, + "failed to set errstr ctx"); + goto out; + } + + ret = -1; + goto out; + } + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); + goto out; + } + + if (volinfo->brick_count == brick_count) { + ctx = glusterd_op_get_ctx (); + if (!ctx) { + gf_log ("", GF_LOG_ERROR, + "Operation Context is not present"); + ret = -1; + goto out; + } + errstr = gf_strdup ("Deleting all the bricks of the " + "volume is not allowed"); + if (!errstr) { + gf_log ("", GF_LOG_ERROR, "Out of memory"); + ret = -1; + goto out; + } + + ret = dict_set_dynstr (ctx, "errstr", errstr); + if (ret) { + GF_FREE (errstr); + gf_log ("", GF_LOG_DEBUG, + "failed to set pump status in ctx"); + goto out; + } + + ret = -1; + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_add_brick (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + char *bricks = NULL; + int32_t count = 0; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_int32 (dict, "count", &count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + + ret = dict_get_str (dict, "bricks", &bricks); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + goto out; + } + + ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); + goto out; + } + + volinfo->defrag_status = 0; + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (); + +out: + return ret; +} + +int +glusterd_op_remove_brick (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + char *brick = NULL; + int32_t count = 0; + int32_t i = 1; + char key[256] = {0,}; + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_int32 (dict, "count", &count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + + while ( i <= count) { + snprintf (key, 256, "brick%d", i); + ret = dict_get_str (dict, key, &brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); + goto out; + } + + ret = glusterd_op_perform_remove_brick (volinfo, brick); + if (ret) + goto out; + i++; + } + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) + goto out; + + volinfo->defrag_status = 0; + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (); + +out: + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c new file mode 100644 index 000000000..49654220b --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c @@ -0,0 +1,1579 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#include + +static char *gsync_reserved_opts[] = { + "gluster-command", + "pid-file", + "state-file", + "session-owner", + NULL +}; + +int +glusterd_handle_gsync_set (rpcsvc_request_t *req) +{ + int32_t ret = 0; + dict_t *dict = NULL; + gf1_cli_gsync_set_req cli_req = {{0},}; + glusterd_op_t cli_op = GD_OP_GSYNC_SET; + char *master = NULL; + char *slave = NULL; + char operation[256] = {0,}; + int type = 0; + glusterd_conf_t *priv = NULL; + char *host_uuid = NULL; + + GF_ASSERT (req); + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + if (!gf_xdr_to_cli_gsync_set_req (req->msg[0], &cli_req)) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + if (cli_req.dict.dict_len) { + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_unserialize (cli_req.dict.dict_val, + cli_req.dict.dict_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } else { + dict->extra_stdfree = cli_req.dict.dict_val; + } + + host_uuid = gf_strdup (uuid_utoa(priv->uuid)); + if (host_uuid == NULL) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to get" + "the uuid of the host machine"); + ret = -1; + goto out; + } + ret = dict_set_dynstr (dict, "host-uuid", host_uuid); + if (ret) + goto out; + + } + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) { + gf_log ("", GF_LOG_INFO, "master not found, while handling" + GEOREP" options"); + master = "(No Master)"; + } + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) { + gf_log ("", GF_LOG_INFO, "slave not not found, while" + "handling "GEOREP" options"); + slave = "(No Slave)"; + } + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "command type not found, while" + "handling "GEOREP" options"); + goto out; + } + + switch (type) { + + case GF_GSYNC_OPTION_TYPE_START: + strncpy (operation, "start", sizeof (operation)); + break; + + case GF_GSYNC_OPTION_TYPE_STOP: + strncpy (operation, "stop", sizeof (operation)); + break; + + case GF_GSYNC_OPTION_TYPE_CONFIG: + strncpy (operation, "config", sizeof (operation)); + break; + + case GF_GSYNC_OPTION_TYPE_STATUS: + strncpy (operation, "status", sizeof (operation)); + break; + } + + gf_cmd_log ("volume "GEOREP, " %s command on %s,%s", operation, master, + slave); + ret = glusterd_op_begin (req, GD_OP_GSYNC_SET, dict); + gf_cmd_log ("volume "GEOREP, " %s command on %s,%s %s ", operation, + master, slave, (ret != 0)? "FAILED" : "SUCCEEDED"); + +out: + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) { + if (dict) + dict_unref (dict); + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + } + return ret; +} + + +/***** + * + * glusterd_urltransform* internal API + * + *****/ + +static void +glusterd_urltransform_init (runner_t *runner, const char *transname) +{ + runinit (runner); + runner_add_arg (runner, GSYNCD_PREFIX"/gsyncd"); + runner_argprintf (runner, "--%s-url", transname); +} + +static void +glusterd_urltransform_add (runner_t *runner, const char *url) +{ + runner_add_arg (runner, url); +} + +static void +_glusterd_urltransform_add_iter (dict_t *dict, char *key, data_t *value, void *data) +{ + runner_t *runner = (runner_t *)data; + char *slave = NULL; + + slave = strchr (value->data, ':'); + GF_ASSERT (slave); + slave++; + runner_add_arg (runner, slave); +} + +static void +glusterd_urltransform_free (char **linearr, unsigned n) +{ + int i = 0; + + for (; i < n; i++) + GF_FREE (linearr[i]); + + GF_FREE (linearr); +} + +static int +glusterd_urltransform (runner_t *runner, char ***linearrp) +{ + char **linearr = NULL; + char *line = NULL; + unsigned arr_len = 32; + unsigned arr_idx = 0; + gf_boolean_t error = _gf_false; + + linearr = GF_CALLOC (arr_len, sizeof (char *), gf_gld_mt_linearr); + if (!linearr) { + error = _gf_true; + goto out; + } + + runner_redir (runner, STDOUT_FILENO, RUN_PIPE); + if (runner_start (runner) != 0) { + gf_log ("", GF_LOG_ERROR, "spawning child failed"); + + error = _gf_true; + goto out; + } + + arr_idx = 0; + for (;;) { + line = GF_MALLOC (1024, gf_gld_mt_linebuf); + if (!line) { + error = _gf_true; + goto out; + } + + if (fgets (line, 1024, runner_chio (runner, STDOUT_FILENO)) == + NULL) + break; + + if (line[strlen (line) - 1] != '\n') { + GF_FREE (line); + error = _gf_true; + goto out; + } + line[strlen (line) - 1] = '\0'; + + if (arr_idx == arr_len) { + arr_len <<= 1; + linearr = GF_REALLOC (linearr, arr_len); + if (!linearr) { + GF_FREE (line); + error = _gf_true; + goto out; + } + } + linearr[arr_idx] = line; + + arr_idx++; + } + + out: + + /* XXX chpid field is not exported by run API + * but runner_end() does not abort the invoked + * process (ie. it might block in waitpid(2)) + * so we resort to a manual kill a the private field + */ + if (error && runner->chpid > 0) + kill (runner->chpid, SIGKILL); + + if (runner_end (runner) != 0) + error = _gf_true; + + if (error) { + gf_log ("", GF_LOG_ERROR, "reading data from child failed"); + glusterd_urltransform_free (linearr, arr_idx); + return -1; + } + + *linearrp = linearr; + return arr_idx; +} + +static int +glusterd_urltransform_single (const char *url, const char *transname, + char ***linearrp) +{ + runner_t runner = {0,}; + + glusterd_urltransform_init (&runner, transname); + glusterd_urltransform_add (&runner, url); + return glusterd_urltransform (&runner, linearrp); +} + + +struct dictidxmark { + unsigned isrch; + unsigned ithis; + char *ikey; +}; + +static void +_dict_mark_atindex (dict_t *dict, char *key, data_t *value, void *data) +{ + struct dictidxmark *dim = data; + + if (dim->isrch == dim->ithis) + dim->ikey = key; + + dim->ithis++; +} + +static char * +dict_get_by_index (dict_t *dict, unsigned i) +{ + struct dictidxmark dim = {0,}; + + dim.isrch = i; + dict_foreach (dict, _dict_mark_atindex, &dim); + + return dim.ikey; +} + +static int +glusterd_get_slave (glusterd_volinfo_t *vol, const char *slaveurl, char **slavekey) +{ + runner_t runner = {0,}; + int n = 0; + int i = 0; + char **linearr = NULL; + + glusterd_urltransform_init (&runner, "canonicalize"); + dict_foreach (vol->gsync_slaves, _glusterd_urltransform_add_iter, &runner); + glusterd_urltransform_add (&runner, slaveurl); + + n = glusterd_urltransform (&runner, &linearr); + if (n == -1) + return -2; + + for (i = 0; i < n - 1; i++) { + if (strcmp (linearr[i], linearr[n - 1]) == 0) + break; + } + glusterd_urltransform_free (linearr, i); + + if (i < n - 1) + *slavekey = dict_get_by_index (vol->gsync_slaves, i); + else + i = -1; + + return i; +} + + +static int +glusterd_query_extutil (char *resbuf, runner_t *runner) +{ + char *ptr = NULL; + int ret = 0; + + runner_redir (runner, STDOUT_FILENO, RUN_PIPE); + if (runner_start (runner) != 0) { + gf_log ("", GF_LOG_ERROR, "spawning child failed"); + + return -1; + } + + ptr = fgets(resbuf, PATH_MAX, runner_chio (runner, STDOUT_FILENO)); + if (ptr) + resbuf[strlen(resbuf)-1] = '\0'; //strip off \n + + ret = runner_end (runner); + if (ret) + gf_log ("", GF_LOG_ERROR, "reading data from child failed"); + + return ret ? -1 : 0; +} + +int +glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, + char *slave, char *gl_workdir) +{ + runner_t runner = {0,}; + + runinit (&runner); + runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); + runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); + runner_argprintf (&runner, ":%s", master); + runner_add_args (&runner, slave, "--config-get", NULL); + runner_argprintf (&runner, "%s-file", param); + + return glusterd_query_extutil (prmfile, &runner); +} + +static int +gsyncd_getpidfile (char *master, char *slave, char *pidfile) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + GF_VALIDATE_OR_GOTO ("gsync", master, out); + GF_VALIDATE_OR_GOTO ("gsync", slave, out); + + ret = glusterd_gsync_get_param_file (pidfile, "pid", master, + slave, priv->workdir); + if (ret == -1) { + ret = -2; + gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); + goto out; + } + + ret = open (pidfile, O_RDWR); + + out: + return ret; +} + +static int +gsync_status_byfd (int fd) +{ + GF_ASSERT (fd >= -1); + + if (lockf (fd, F_TEST, 0) == -1 && + (errno == EAGAIN || errno == EACCES)) + /* gsyncd keeps the pidfile locked */ + return 0; + + return -1; +} + +/* status: return 0 when gsync is running + * return -1 when not running + */ +int +gsync_status (char *master, char *slave, int *status) +{ + char pidfile[PATH_MAX] = {0,}; + int fd = -1; + + fd = gsyncd_getpidfile (master, slave, pidfile); + if (fd == -2) + return -1; + + *status = gsync_status_byfd (fd); + + close (fd); + return 0; +} + + +int32_t +glusterd_gsync_volinfo_dict_set (glusterd_volinfo_t *volinfo, + char *key, char *value) +{ + int32_t ret = -1; + char *gsync_status = NULL; + + gsync_status = gf_strdup (value); + if (!gsync_status) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_set_dynstr (volinfo->dict, key, gsync_status); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to set dict"); + goto out; + } + + ret = 0; +out: + return 0; +} + +int +gsync_verify_config_options (dict_t *dict, char **op_errstr) +{ + char **resopt = NULL; + int i = 0; + char *subop = NULL; + char *slave = NULL; + char *op_name = NULL; + char *op_value = NULL; + gf_boolean_t banned = _gf_true; + + if (dict_get_str (dict, "subop", &subop) != 0) { + gf_log ("", GF_LOG_WARNING, "missing subop"); + *op_errstr = gf_strdup ("Invalid config request"); + return -1; + } + + if (dict_get_str (dict, "slave", &slave) != 0) { + gf_log ("", GF_LOG_WARNING, GEOREP" CONFIG: no slave given"); + *op_errstr = gf_strdup ("Slave required"); + return -1; + } + + if (strcmp (subop, "get-all") == 0) + return 0; + + if (dict_get_str (dict, "op_name", &op_name) != 0) { + gf_log ("", GF_LOG_WARNING, "option name missing"); + *op_errstr = gf_strdup ("Option name missing"); + return -1; + } + + if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { + gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name); + *op_errstr = gf_strdup ("Invalid option"); + + return -1; + } + + if (strcmp (subop, "get") == 0) + return 0; + + if (strcmp (subop, "set") != 0 && strcmp (subop, "del") != 0) { + gf_log ("", GF_LOG_WARNING, "unknown subop %s", subop); + *op_errstr = gf_strdup ("Invalid config request"); + return -1; + } + + if (strcmp (subop, "set") == 0 && + dict_get_str (dict, "op_value", &op_value) != 0) { + gf_log ("", GF_LOG_WARNING, "missing value for set"); + *op_errstr = gf_strdup ("missing value"); + } + + /* match option name against reserved options, modulo -/_ + * difference + */ + for (resopt = gsync_reserved_opts; *resopt; resopt++) { + banned = _gf_true; + for (i = 0; (*resopt)[i] && op_name[i]; i++) { + if ((*resopt)[i] == op_name[i] || + ((*resopt)[i] == '-' && op_name[i] == '_')) + continue; + banned = _gf_false; + } + if (banned) { + gf_log ("", GF_LOG_WARNING, "Reserved option %s", op_name); + *op_errstr = gf_strdup ("Reserved option"); + + return -1; + break; + } + } + + return 0; +} + +static void +_get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data) +{ + glusterd_gsync_status_temp_t *param = NULL; + char *slave = NULL; + int ret = 0; + + param = (glusterd_gsync_status_temp_t *)data; + + GF_ASSERT (param); + GF_ASSERT (param->volinfo); + + slave = strchr(value->data, ':'); + if (slave) + slave ++; + else + return; + + ret = glusterd_get_gsync_status_mst_slv(param->volinfo, + slave, param->rsp_dict); + +} + + +static void +_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) +{ + int tmp_slvnum = 0; + int *slvnum = (int *)data; + + sscanf (key, "slave%d", &tmp_slvnum); + if (tmp_slvnum > *slvnum) + *slvnum = tmp_slvnum; +} + +static int +glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, + char **op_errstr) +{ + int ret = 0; + char *slavekey = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (slave); + + ret = glusterd_get_slave (volinfo, slave, &slavekey); + if (ret < 0) { + ret++; + goto out; + } + + dict_del (volinfo->gsync_slaves, slavekey); + + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + *op_errstr = gf_strdup ("Failed to store the Volume" + "information"); + goto out; + } + out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; + +} + +static int +glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol, + uuid_t uuid) +{ + int ret = 0; + char *slavekey = NULL; + char *slaveentry = NULL; + char *t = NULL; + + GF_ASSERT (vol); + GF_ASSERT (slave); + + ret = glusterd_get_slave (vol, slave, &slavekey); + if (ret < 0) { + /* XXX colliding cases of failure and non-extant + * slave... now just doing this as callers of this + * function can make sense only of -1 and 0 as retvals; + * getting at the proper semanticals will involve + * fixing callers as well. + */ + ret = -1; + goto out; + } + + ret = dict_get_str (vol->gsync_slaves, slavekey, &slaveentry); + GF_ASSERT (ret == 0); + + t = strchr (slaveentry, ':'); + GF_ASSERT (t); + *t = '\0'; + ret = uuid_parse (slaveentry, uuid); + *t = ':'; + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_check_gsync_running_local (char *master, char *slave, + gf_boolean_t *is_run) +{ + int ret = -1; + int ret_status = 0; + + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (is_run); + + *is_run = _gf_false; + ret = gsync_status (master, slave, &ret_status); + if (ret == 0 && ret_status == 0) { + *is_run = _gf_true; + } else if (ret == -1) { + gf_log ("", GF_LOG_WARNING, GEOREP" validation " + " failed"); + goto out; + } + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int +glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, + char *host_uuid, char **op_errstr) +{ + int ret = 0; + int maxslv = 0; + char **linearr = NULL; + char *value = NULL; + char *slavekey = NULL; + char *slaveentry = NULL; + char key[512] = {0, }; + char *t = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (slave); + GF_ASSERT (host_uuid); + + ret = glusterd_get_slave (volinfo, slave, &slavekey); + switch (ret) { + case -2: + ret = -1; + goto out; + case -1: + break; + default: + GF_ASSERT (ret > 0); + ret = dict_get_str (volinfo->gsync_slaves, slavekey, &slaveentry); + GF_ASSERT (ret == 0); + + /* same-name + same-uuid slave entries should have been filtered + * out in glusterd_op_verify_gsync_start_options(), so we can + * assert an uuid mismatch + */ + t = strtail (slaveentry, host_uuid); + GF_ASSERT (!t || *t != ':') + + gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for " + "the %s (master) and %s (slave) " + "from a different machine", + volinfo->volname, slave); + *op_errstr = gf_strdup (GEOREP" already running in an an" + "another machine"); + ret = -1; + goto out; + } + + ret = glusterd_urltransform_single (slave, "normalize", &linearr); + if (ret == -1) + goto out; + + ret = gf_asprintf (&value, "%s:%s", host_uuid, linearr[0]); + glusterd_urltransform_free (linearr, 1); + if (ret == -1) + goto out; + + dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &maxslv); + snprintf (key, 512, "slave%d", maxslv + 1); + ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); + if (ret) + goto out; + + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + *op_errstr = gf_strdup ("Failed to store the Volume " + "information"); + goto out; + } + ret = 0; + out: + return ret; +} + + +static int +glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, + char *slave, char **op_errstr) +{ + int ret = -1; + gf_boolean_t is_running = _gf_false; + char msg[2048] = {0}; + uuid_t uuid = {0}; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + + GF_ASSERT (volinfo); + GF_ASSERT (slave); + GF_ASSERT (op_errstr); + GF_ASSERT (this && this->private); + + priv = this->private; + + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + snprintf (msg, sizeof (msg), "Volume %s needs to be started " + "before "GEOREP" start", volinfo->volname); + goto out; + } + /*Check if the gsync is already started in cmd. inited host + * If so initiate add it into the glusterd's priv*/ + ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); + if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { + ret = glusterd_check_gsync_running_local (volinfo->volname, + slave, &is_running); + if (ret) { + snprintf (msg, sizeof (msg), GEOREP" start option " + "validation failed "); + goto out; + } + if (_gf_true == is_running) { + snprintf (msg, sizeof (msg), GEOREP " session between" + " %s & %s already started", volinfo->volname, + slave); + ret = -1; + goto out; + } + } + ret = 0; +out: + if (ret && (msg[0] != '\0')) { + *op_errstr = gf_strdup (msg); + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) +{ + + GF_ASSERT (volinfo); + GF_ASSERT (flag); + + if (volinfo->gsync_slaves->count) + *flag = _gf_true; + else + *flag = _gf_false; + + return 0; +} + +static int +glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, + char *slave, char **op_errstr) +{ + int ret = -1; + char msg[2048] = {0}; + uuid_t uuid = {0}; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS && THIS->private); + GF_ASSERT (volinfo); + GF_ASSERT (slave); + GF_ASSERT (op_errstr); + + priv = THIS->private; + + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + snprintf (msg, sizeof (msg), "Volume %s needs to be started " + "before "GEOREP" start", volinfo->volname); + + goto out; + } + ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); + if (ret == -1) { + snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" + " not active", volinfo->volname, slave); + goto out; + } + + ret = 0; +out: + if (ret && (msg[0] != '\0')) { + *op_errstr = gf_strdup (msg); + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) +{ + char *slave = NULL; + char *volname = NULL; + char errmsg[PATH_MAX] = {0, }; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + + ret = dict_get_str (dict, "master", &volname); + if (ret < 0) { + ret = 0; + goto out; + } + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if ((ret) || (!exists)) { + gf_log ("", GF_LOG_WARNING, "volume name does not exist"); + snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" + " exist", volname); + *op_errstr = gf_strdup (errmsg); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) { + ret = 0; + goto out; + } + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + + +static int +glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, + char **master, char **slave) +{ + + int ret = -1; + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + GF_ASSERT (master); + GF_ASSERT (slave); + + ret = dict_get_str (dict, "master", master); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "master not found"); + *op_errstr = gf_strdup ("master not found"); + goto out; + } + + ret = dict_get_str (dict, "slave", slave); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "slave not found"); + *op_errstr = gf_strdup ("slave not found"); + goto out; + } + + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) +{ + int ret = 0; + int type = 0; + char *volname = NULL; + char *slave = NULL; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + char errmsg[PATH_MAX] = {0,}; + + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "command type not found"); + *op_errstr = gf_strdup ("command unsuccessful"); + goto out; + } + + switch (type) { + case GF_GSYNC_OPTION_TYPE_STATUS: + ret = glusterd_verify_gsync_status_opts (dict, op_errstr); + + goto out; + case GF_GSYNC_OPTION_TYPE_CONFIG: + ret = gsync_verify_config_options (dict, op_errstr); + + goto out; + } + + ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); + if (ret) + goto out; + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if ((ret) || (!exists)) { + gf_log ("", GF_LOG_WARNING, "volume name does not exist"); + snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" + " exist", volname); + *op_errstr = gf_strdup (errmsg); + ret = -1; + goto out; + } + + switch (type) { + case GF_GSYNC_OPTION_TYPE_START: + ret = glusterd_op_verify_gsync_start_options (volinfo, slave, + op_errstr); + break; + case GF_GSYNC_OPTION_TYPE_STOP: + ret = glusterd_op_verify_gsync_running (volinfo, slave, + op_errstr); + break; + } + +out: + return ret; +} + +int +stop_gsync (char *master, char *slave, char **msg) +{ + int32_t ret = 0; + int pfd = -1; + pid_t pid = 0; + char pidfile[PATH_MAX] = {0,}; + char buf [1024] = {0,}; + int i = 0; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + pfd = gsyncd_getpidfile (master, slave, pidfile); + if (pfd == -2) { + gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " + " failed for %s & %s", master, slave); + ret = -1; + goto out; + } + if (gsync_status_byfd (pfd) == -1) { + gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" + " running", master, slave); + if (msg) + *msg = gf_strdup ("Warning: "GEOREP" session was in " + "corrupt state"); + /* monitor gsyncd already dead */ + goto out; + } + + ret = read (pfd, buf, 1024); + if (ret > 0) { + pid = strtol (buf, NULL, 10); + ret = kill (-pid, SIGTERM); + if (ret) { + gf_log ("", GF_LOG_WARNING, + "failed to kill gsyncd"); + goto out; + } + for (i = 0; i < 20; i++) { + if (gsync_status_byfd (pfd) == -1) { + /* monitor gsyncd is dead but worker may + * still be alive, give some more time + * before SIGKILL (hack) + */ + usleep (50000); + break; + } + usleep (50000); + } + kill (-pid, SIGKILL); + unlink (pidfile); + } + ret = 0; + +out: + close (pfd); + return ret; +} + +int +glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, + dict_t *resp_dict); + +int +glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, + dict_t *dict, dict_t *resp_dict, char **op_errstr) +{ + int32_t ret = -1; + char *op_name = NULL; + char *op_value = NULL; + runner_t runner = {0,}; + glusterd_conf_t *priv = NULL; + char *subop = NULL; + char *master = NULL; + + GF_ASSERT (slave); + GF_ASSERT (op_errstr); + GF_ASSERT (dict); + GF_ASSERT (resp_dict); + + ret = dict_get_str (dict, "subop", &subop); + if (ret != 0) + goto out; + + if (strcmp (subop, "get") == 0 || strcmp (subop, "get-all") == 0) { + /* deferred to cli */ + gf_log ("", GF_LOG_DEBUG, "Returning 0"); + return 0; + } + + ret = dict_get_str (dict, "op_name", &op_name); + if (ret != 0) + goto out; + + if (strcmp (subop, "set") == 0) { + ret = dict_get_str (dict, "op_value", &op_value); + if (ret != 0) + goto out; + } + + if (THIS) + priv = THIS->private; + if (priv == NULL) { + gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); + *op_errstr = gf_strdup ("glusterd defunct"); + goto out; + } + + master = ""; + runinit (&runner); + runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); + runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); + if (volinfo) { + master = volinfo->volname; + runner_argprintf (&runner, ":%s", master); + } + runner_add_arg (&runner, slave); + runner_argprintf (&runner, "--config-%s", subop); + runner_add_arg (&runner, op_name); + if (op_value) + runner_add_arg (&runner, op_value); + ret = runner_run (&runner); + if (ret) { + gf_log ("", GF_LOG_WARNING, "gsyncd failed to " + "%s %s option for %s %s peers", + subop, op_name, master, slave); + + gf_asprintf (op_errstr, GEOREP" config-%s failed for %s %s", + subop, master, slave); + + goto out; + } + ret = 0; + gf_asprintf (op_errstr, "config-%s successful", subop); + +out: + if (!ret && volinfo) { + ret = glusterd_check_restart_gsync_session (volinfo, slave, + resp_dict); + if (ret) + *op_errstr = gf_strdup ("internal error"); + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterd_gsync_read_frm_status (char *path, char *data) +{ + int ret = 0; + FILE *status_file = NULL; + + GF_ASSERT (path); + GF_ASSERT (data); + status_file = fopen (path, "r"); + if (status_file == NULL) { + gf_log ("", GF_LOG_WARNING, "Unable to read gsyncd status" + " file"); + return -1; + } + ret = fread (data, PATH_MAX, 1, status_file); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "Status file of gsyncd is corrupt"); + return -1; + } + + data[strlen(data)-1] = '\0'; + + return 0; +} + +int +glusterd_read_status_file (char *master, char *slave, + dict_t *dict) +{ + glusterd_conf_t *priv = NULL; + int ret = 0; + char statusfile[PATH_MAX] = {0, }; + char buff[PATH_MAX] = {0, }; + char mst[PATH_MAX] = {0, }; + char slv[PATH_MAX] = {0, }; + char sts[PATH_MAX] = {0, }; + int gsync_count = 0; + int status = 0; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + ret = glusterd_gsync_get_param_file (statusfile, "state", master, + slave, priv->workdir); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" + "file for %s(master), %s(slave)", master, slave); + goto out; + + } + + ret = gsync_status (master, slave, &status); + if (ret == 0 && status == -1) { + strncpy (buff, "corrupt", sizeof (buff)); + goto done; + } else if (ret == -1) + goto out; + + ret = glusterd_gsync_read_frm_status (statusfile, buff); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to read the status" + "file for %s(master), %s(slave)", master, slave); + goto out; + + } + + done: + ret = dict_get_int32 (dict, "gsync-count", &gsync_count); + + if (ret) + gsync_count = 1; + else + gsync_count++; + + snprintf (mst, sizeof (mst), "master%d", gsync_count); + ret = dict_set_dynstr (dict, mst, gf_strdup (master)); + if (ret) + goto out; + + snprintf (slv, sizeof (slv), "slave%d", gsync_count); + ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); + if (ret) + goto out; + + snprintf (sts, sizeof (slv), "status%d", gsync_count); + ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); + if (ret) + goto out; + ret = dict_set_int32 (dict, "gsync-count", gsync_count); + if (ret) + goto out; + + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); + return ret; +} + +int +glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, + dict_t *resp_dict) +{ + + int ret = 0; + uuid_t uuid = {0, }; + glusterd_conf_t *priv = NULL; + char *status_msg = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (slave); + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) + /* session does not exist, nothing to do */ + goto out; + if (uuid_compare (priv->uuid, uuid) == 0) { + ret = stop_gsync (volinfo->volname, slave, &status_msg); + if (ret == 0 && status_msg) + ret = dict_set_str (resp_dict, "gsync-status", + status_msg); + if (ret == 0) + ret = glusterd_start_gsync (volinfo, slave, + uuid_utoa(priv->uuid), NULL); + } + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) +{ + int32_t ret = 0; + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile" + " for setting of marker while '"GEOREP" start'"); + ret = -1; + goto out; + } + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (); + ret = 0; +out: + return ret; +} + +int +glusterd_set_marker_gsync (glusterd_volinfo_t *volinfo) +{ + int ret = -1; + int marker_set = _gf_false; + char *gsync_status = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); + if (marker_set == -1) { + gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); + ret = -1; + goto out; + } + + if (marker_set == _gf_false) { + gsync_status = gf_strdup ("on"); + if (gsync_status == NULL) { + ret = -1; + goto out; + } + + ret = glusterd_gsync_volinfo_dict_set (volinfo, + VKEY_MARKER_XTIME, gsync_status); + if (ret < 0) + goto out; + + ret = glusterd_marker_create_volfile (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Setting dict failed"); + goto out; + } + } + ret = 0; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + + + + +int +glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, + char *slave, dict_t *rsp_dict) +{ + uuid_t uuid = {0, }; + glusterd_conf_t *priv = NULL; + int ret = 0; + + GF_ASSERT (volinfo); + GF_ASSERT (slave); + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); + if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) + goto out; + + if (ret) { + ret = 0; + gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :" + "session is not active", volinfo->volname, slave); + goto out; + } + + ret = glusterd_read_status_file (volinfo->volname, slave, rsp_dict); + out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +static int +glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) +{ + glusterd_gsync_status_temp_t param = {0, }; + + GF_ASSERT (volinfo); + + param.rsp_dict = rsp_dict; + param.volinfo = volinfo; + dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); + + return 0; +} + +static int +glusterd_get_gsync_status_all ( dict_t *rsp_dict) +{ + + int32_t ret = 0; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + + GF_ASSERT (THIS); + priv = THIS->private; + + GF_ASSERT (priv); + + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); + if (ret) + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; + +} + +static int +glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + char *slave = NULL; + char *volname = NULL; + char errmsg[PATH_MAX] = {0, }; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + + + ret = dict_get_str (dict, "master", &volname); + if (ret < 0){ + ret = glusterd_get_gsync_status_all (rsp_dict); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if ((ret) || (!exists)) { + gf_log ("", GF_LOG_WARNING, "volume name does not exist"); + snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" + " exist", volname); + *op_errstr = gf_strdup (errmsg); + ret = -1; + goto out; + } + + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) { + ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); + goto out; + } + + ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, rsp_dict); + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + + +} + + +int +glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + int32_t ret = -1; + int32_t type = -1; + dict_t *ctx = NULL; + dict_t *resp_dict = NULL; + char *host_uuid = NULL; + char *slave = NULL; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; + char *status_msg = NULL; + uuid_t uuid = {0, }; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + + priv = THIS->private; + + ret = dict_get_int32 (dict, "type", &type); + if (ret < 0) + goto out; + + ret = dict_get_str (dict, "host-uuid", &host_uuid); + if (ret < 0) + goto out; + + ctx = glusterd_op_get_ctx (); + resp_dict = ctx ? ctx : rsp_dict; + GF_ASSERT (resp_dict); + + if (type == GF_GSYNC_OPTION_TYPE_STATUS) { + ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); + goto out; + } + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) + goto out; + + if (dict_get_str (dict, "master", &volname) == 0) { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Volinfo for %s (master) not found", + volname); + goto out; + } + } + + if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { + ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, + op_errstr); + goto out; + } + + if (!volinfo) { + ret = -1; + goto out; + } + + if (type == GF_GSYNC_OPTION_TYPE_START) { + + ret = glusterd_set_marker_gsync (volinfo); + if (ret != 0) { + gf_log ("", GF_LOG_WARNING, "marker start failed"); + *op_errstr = gf_strdup ("failed to initialize indexing"); + ret = -1; + goto out; + } + ret = glusterd_store_slave_in_info(volinfo, slave, + host_uuid, op_errstr); + if (ret) + goto out; + + ret = glusterd_start_gsync (volinfo, slave, host_uuid, + op_errstr); + } + + if (type == GF_GSYNC_OPTION_TYPE_STOP) { + + ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); + if (ret) { + gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for" + "%s(master) and %s(slave)", volname, slave); + *op_errstr = strdup (GEOREP" is not set up"); + goto out; + } + + ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); + if (ret) + goto out; + + if (uuid_compare (priv->uuid, uuid) != 0) { + goto out; + } + + ret = stop_gsync (volname, slave, &status_msg); + if (ret == 0 && status_msg) + ret = dict_set_str (resp_dict, "gsync-status", + status_msg); + if (ret != 0) + *op_errstr = gf_strdup ("internal error"); + } + +out: + gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index d13f32500..08ba9bc46 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -855,679 +855,6 @@ glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx) return ret; } -int -glusterd_handle_create_volume (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_create_vol_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; - char *brick_list = NULL; - void *cli_rsp = NULL; - char err_str[2048] = {0,}; - gf1_cli_create_vol_rsp rsp = {0,}; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char *free_ptr = NULL; - char *trans_type = NULL; - uuid_t volume_id = {0,}; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - glusterd_volinfo_t tmpvolinfo = {{0},}; - - GF_ASSERT (req); - - INIT_LIST_HEAD (&tmpvolinfo.bricks); - - this = THIS; - GF_ASSERT(this); - - priv = this->private; - - ret = -1; - if (!gf_xdr_to_cli_create_vol_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - snprintf (err_str, sizeof (err_str), "Garbage args received"); - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received create volume req"); - - if (cli_req.bricks.bricks_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - ret = dict_unserialize (cli_req.bricks.bricks_val, - cli_req.bricks.bricks_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, - "failed to " - "unserialize req-buffer to dictionary"); - snprintf (err_str, sizeof (err_str), "Unable to decode " - "the buffer"); - goto out; - } else { - dict->extra_stdfree = cli_req.bricks.bricks_val; - } - } - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "name"); - goto out; - } - gf_cmd_log ("Volume create", "on volname: %s attempted", volname); - - if ((ret = glusterd_check_volume_exists (volname))) { - snprintf(err_str, 2048, "Volume %s already exists", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); - goto out; - } - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "brick count"); - goto out; - } - - ret = dict_get_str (dict, "transport", &trans_type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get transport-type"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "transport-type"); - goto out; - } - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "bricks"); - goto out; - } - - uuid_generate (volume_id); - free_ptr = gf_strdup (uuid_utoa (volume_id)); - ret = dict_set_dynstr (dict, "volume-id", free_ptr); - if (ret) { - gf_log ("", GF_LOG_ERROR, "unable to set volume-id"); - snprintf (err_str, sizeof (err_str), "Unable to set volume " - "id"); - goto out; - } - free_ptr = NULL; - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr = brick_list; - } - - gf_cmd_log ("Volume create", "on volname: %s type:%s count:%d bricks:%s", - cli_req.volname, ((cli_req.type == 0)? "DEFAULT": - ((cli_req.type == 1)? "STRIPE":"REPLICATE")), cli_req.count, - 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) { - snprintf (err_str, sizeof (err_str), "Unable to get " - "brick info from brick %s", brick); - goto out; - } - - ret = glusterd_new_brick_validate (brick, brickinfo, err_str, - sizeof (err_str)); - if (ret) - goto out; - ret = glusterd_volume_brickinfo_get (brickinfo->uuid, - brickinfo->hostname, - brickinfo->path, - &tmpvolinfo, &tmpbrkinfo); - if (!ret) { - ret = -1; - snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" - " one of the arguments contain the other", - tmpbrkinfo->hostname, tmpbrkinfo->path, brick); - goto out; - } - list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); - brickinfo = NULL; - } - - ret = glusterd_op_begin (req, GD_OP_CREATE_VOLUME, dict); - gf_cmd_log ("Volume create", "on volname: %s %s", volname, - (ret != 0) ? "FAILED": "SUCCESS"); - -out: - if (ret) { - if (dict) - dict_unref (dict); - rsp.op_ret = -1; - rsp.op_errno = 0; - rsp.volname = ""; - if (err_str[0] == '\0') - snprintf (err_str, sizeof (err_str), "Operation failed"); - rsp.op_errstr = err_str; - cli_rsp = &rsp; - glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, - gf_xdr_serialize_cli_create_vol_rsp, - (xdrproc_t)xdr_gf1_cli_create_vol_rsp); - - ret = 0; //Client response sent, prevent second response - } - - if (free_ptr) - GF_FREE(free_ptr); - - glusterd_volume_brickinfos_delete (&tmpvolinfo); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (cli_req.volname) - free (cli_req.volname); // its a malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - return ret; -} - -int -glusterd_handle_cli_start_volume (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_start_vol_req cli_req = {0,}; - char *dup_volname = NULL; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_START_VOLUME; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_start_vol_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received start vol req" - "for volume %s", cli_req.volname); - - dict = dict_new (); - - if (!dict) - goto out; - - dup_volname = gf_strdup (cli_req.volname); - if (!dup_volname) - goto out; - - ret = dict_set_dynstr (dict, "volname", dup_volname); - if (ret) - goto out; - - ret = dict_set_int32 (dict, "flags", cli_req.flags); - if (ret) - goto out; - ret = glusterd_op_begin (req, GD_OP_START_VOLUME, dict); - - gf_cmd_log ("volume start","on volname: %s %s", cli_req.volname, - ((ret == 0) ? "SUCCESS": "FAILED")); - -out: - if (ret && dict) - dict_unref (dict); - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - - return ret; -} - - -int -glusterd_handle_cli_stop_volume (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_stop_vol_req cli_req = {0,}; - char *dup_volname = NULL; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_STOP_VOLUME; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_stop_vol_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received stop vol req" - "for volume %s", cli_req.volname); - - dict = dict_new (); - - if (!dict) - goto out; - - dup_volname = gf_strdup (cli_req.volname); - if (!dup_volname) - goto out; - - ret = dict_set_dynstr (dict, "volname", dup_volname); - if (ret) - goto out; - - ret = dict_set_int32 (dict, "flags", cli_req.flags); - if (ret) - goto out; - - ret = glusterd_op_begin (req, GD_OP_STOP_VOLUME, dict); - gf_cmd_log ("Volume stop","on volname: %s %s", cli_req.volname, - ((ret)?"FAILED":"SUCCESS")); - -out: - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) { - if (dict) - dict_unref (dict); - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - } - - return ret; -} - -int -glusterd_handle_cli_delete_volume (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_delete_vol_req cli_req = {0,}; - glusterd_op_delete_volume_ctx_t *ctx = NULL; - glusterd_op_t cli_op = GD_OP_DELETE_VOLUME; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_delete_vol_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - gf_cmd_log ("Volume delete","on volname: %s attempted", cli_req.volname); - - gf_log ("glusterd", GF_LOG_INFO, "Received delete vol req" - "for volume %s", cli_req.volname); - - - ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_delete_volume_ctx_t); - if (!ctx) - goto out; - - strncpy (ctx->volume_name, cli_req.volname, GD_VOLUME_NAME_MAX); - - ret = glusterd_op_begin (req, GD_OP_DELETE_VOLUME, ctx); - gf_cmd_log ("Volume delete", "on volname: %s %s", cli_req.volname, - ((ret) ? "FAILED" : "SUCCESS")); - -out: - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) { - if (ctx) - GF_FREE (ctx); - - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - } - - return ret; -} - -int -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; - char *brick_list = NULL; - void *cli_rsp = NULL; - char err_str[2048] = {0,}; - gf1_cli_add_brick_rsp rsp = {0,}; - glusterd_volinfo_t *volinfo = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char *free_ptr = NULL; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - glusterd_volinfo_t tmpvolinfo = {{0},}; - int total_bricks = 0; - - this = THIS; - GF_ASSERT(this); - - priv = this->private; - - GF_ASSERT (req); - - INIT_LIST_HEAD (&tmpvolinfo.bricks); - - if (!gf_xdr_to_cli_add_brick_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - snprintf (err_str, sizeof (err_str), "Garbage args received"); - goto out; - } - - gf_cmd_log ("Volume add-brick", "on volname: %s attempted", - cli_req.volname); - gf_log ("glusterd", GF_LOG_INFO, "Received add brick req"); - - if (cli_req.bricks.bricks_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - ret = dict_unserialize (cli_req.bricks.bricks_val, - cli_req.bricks.bricks_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, - "failed to " - "unserialize req-buffer to dictionary"); - snprintf (err_str, sizeof (err_str), "Unable to decode " - "the buffer"); - goto out; - } else { - dict->extra_stdfree = cli_req.bricks.bricks_val; - } - } - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "name"); - goto out; - } - - if (!(ret = glusterd_check_volume_exists (volname))) { - ret = -1; - snprintf(err_str, 2048, "Volume %s does not exist", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); - goto out; - } - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "brick 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; - - total_bricks = volinfo->brick_count + brick_count; - /* If the brick count is less than sub_count then, allow add-brick only for - plain replicate volume since in plain stripe brick_count becoming less than - the sub_count is not allowed */ - if (volinfo->brick_count < volinfo->sub_count && - (volinfo->type == GF_CLUSTER_TYPE_REPLICATE)) { - if (total_bricks <= volinfo->sub_count) - goto brick_val; - } - - if ((brick_count % volinfo->sub_count) != 0) { - 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); - gf_log("glusterd", GF_LOG_ERROR, "%s", err_str); - ret = -1; - goto out; - } - } else { - snprintf (err_str, sizeof (err_str), "Unable to get volinfo " - "for volume name %s", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); - goto out; - } - -brick_val: - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - snprintf (err_str, sizeof (err_str), "Unable to get volume " - "bricks"); - gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); - goto out; - } - - if (bricks) - brick_list = gf_strdup (bricks); - if (!brick_list) { - ret = -1; - snprintf (err_str, sizeof (err_str), "Out of memory"); - goto out; - } else { - free_ptr = brick_list; - } - - gf_cmd_log ("Volume add-brick", "volname: %s type %s count:%d bricks:%s" - ,volname, ((volinfo->type == 0)? "DEFAULT" : ((volinfo->type - == 1)? "STRIPE": "REPLICATE")), brick_count, brick_list); - - - while ( i < brick_count) { - i++; - brick= strtok_r (brick_list, " \n", &tmpptr); - brick_list = tmpptr; - brickinfo = NULL; - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) { - snprintf (err_str, sizeof (err_str), "Unable to get " - "brick info from brick %s", brick); - goto out; - } - ret = glusterd_new_brick_validate (brick, brickinfo, err_str, - sizeof (err_str)); - if (ret) - goto out; - ret = glusterd_volume_brickinfo_get (brickinfo->uuid, - brickinfo->hostname, - brickinfo->path, - &tmpvolinfo, &tmpbrkinfo); - if (!ret) { - ret = -1; - snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" - " one of the arguments contain the other", - tmpbrkinfo->hostname, tmpbrkinfo->path, brick); - goto out; - } - list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); - brickinfo = NULL; - } - - ret = glusterd_op_begin (req, GD_OP_ADD_BRICK, dict); - gf_cmd_log ("Volume add-brick","on volname: %s %s", volname, - (ret != 0)? "FAILED" : "SUCCESS"); - -out: - if (ret) { - if (dict) - dict_unref (dict); - rsp.op_ret = -1; - rsp.op_errno = 0; - rsp.volname = ""; - if (err_str[0] == '\0') - snprintf (err_str, sizeof (err_str), "Operation failed"); - rsp.op_errstr = err_str; - cli_rsp = &rsp; - glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, - gf_xdr_serialize_cli_add_brick_rsp, - (xdrproc_t)xdr_gf1_cli_add_brick_rsp); - ret = 0; //sent error to cli, prevent second reply - } - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (free_ptr) - GF_FREE (free_ptr); - glusterd_volume_brickinfos_delete (&tmpvolinfo); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - return ret; -} - -int -glusterd_handle_replace_brick (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_replace_brick_req cli_req = {0,}; - dict_t *dict = NULL; - char *src_brick = NULL; - char *dst_brick = NULL; - int32_t op = 0; - char operation[256]; - glusterd_op_t cli_op = GD_OP_REPLACE_BRICK; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_replace_brick_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received replace brick req"); - - if (cli_req.bricks.bricks_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - ret = dict_unserialize (cli_req.bricks.bricks_val, - cli_req.bricks.bricks_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, - "failed to " - "unserialize req-buffer to dictionary"); - goto out; - } else { - dict->extra_stdfree = cli_req.bricks.bricks_val; - } - } - - ret = dict_get_int32 (dict, "operation", &op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } - - ret = dict_get_str (dict, "src-brick", &src_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - gf_log ("", GF_LOG_DEBUG, - "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - switch (op) { - case GF_REPLACE_OP_START: strcpy (operation, "start"); - break; - case GF_REPLACE_OP_COMMIT: strcpy (operation, "commit"); - break; - case GF_REPLACE_OP_PAUSE: strcpy (operation, "pause"); - break; - case GF_REPLACE_OP_ABORT: strcpy (operation, "abort"); - break; - case GF_REPLACE_OP_STATUS: strcpy (operation, "status"); - break; - case GF_REPLACE_OP_COMMIT_FORCE: strcpy (operation, "commit-force"); - break; - default:strcpy (operation, "unknown"); - break; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received replace brick %s request", operation); - gf_cmd_log ("Volume replace-brick","volname: %s src_brick:%s" - " dst_brick:%s op:%s",cli_req.volname, src_brick, dst_brick - ,operation); - - ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict); - gf_cmd_log ("Volume replace-brick","on volname: %s %s", cli_req.volname, - (ret) ? "FAILED" : "SUCCESS"); - -out: - if (ret && dict) - dict_unref (dict); - if (cli_req.volname) - free (cli_req.volname);//malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - - return ret; -} - - int @@ -1582,206 +909,7 @@ out: return ret; } - -int -glusterd_handle_gsync_set (rpcsvc_request_t *req) -{ - int32_t ret = 0; - dict_t *dict = NULL; - gf1_cli_gsync_set_req cli_req = {{0},}; - glusterd_op_t cli_op = GD_OP_GSYNC_SET; - char *master = NULL; - char *slave = NULL; - char operation[256] = {0,}; - int type = 0; - glusterd_conf_t *priv = NULL; - char *host_uuid = NULL; - - GF_ASSERT (req); - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - if (!gf_xdr_to_cli_gsync_set_req (req->msg[0], &cli_req)) { - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - if (cli_req.dict.dict_len) { - dict = dict_new (); - if (!dict) - goto out; - - ret = dict_unserialize (cli_req.dict.dict_val, - cli_req.dict.dict_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, "failed to " - "unserialize req-buffer to dictionary"); - goto out; - } else { - dict->extra_stdfree = cli_req.dict.dict_val; - } - - host_uuid = gf_strdup (uuid_utoa(priv->uuid)); - if (host_uuid == NULL) { - gf_log ("glusterd", GF_LOG_ERROR, "failed to get" - "the uuid of the host machine"); - ret = -1; - goto out; - } - ret = dict_set_dynstr (dict, "host-uuid", host_uuid); - if (ret) - goto out; - - } - - ret = dict_get_str (dict, "master", &master); - if (ret < 0) { - gf_log ("", GF_LOG_INFO, "master not found, while handling" - GEOREP" options"); - master = "(No Master)"; - } - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - gf_log ("", GF_LOG_INFO, "slave not not found, while" - "handling "GEOREP" options"); - slave = "(No Slave)"; - } - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "command type not found, while" - "handling "GEOREP" options"); - goto out; - } - - switch (type) { - - case GF_GSYNC_OPTION_TYPE_START: - strncpy (operation, "start", sizeof (operation)); - break; - - case GF_GSYNC_OPTION_TYPE_STOP: - strncpy (operation, "stop", sizeof (operation)); - break; - - case GF_GSYNC_OPTION_TYPE_CONFIG: - strncpy (operation, "config", sizeof (operation)); - break; - - case GF_GSYNC_OPTION_TYPE_STATUS: - strncpy (operation, "status", sizeof (operation)); - break; - } - - gf_cmd_log ("volume "GEOREP, " %s command on %s,%s", operation, master, - slave); - ret = glusterd_op_begin (req, GD_OP_GSYNC_SET, dict); - gf_cmd_log ("volume "GEOREP, " %s command on %s,%s %s ", operation, - master, slave, (ret != 0)? "FAILED" : "SUCCEEDED"); - -out: - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) { - if (dict) - dict_unref (dict); - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - } - return ret; -} - -int -glusterd_handle_quota (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_quota_req cli_req = {0,}; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_QUOTA; - char operation[256] = {0, }; - char *volname = NULL; - int32_t type = 0; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_quota_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - if (cli_req.dict.dict_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - ret = dict_unserialize (cli_req.dict.dict_val, - cli_req.dict.dict_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, "failed to " - "unserialize req-buffer to dictionary"); - goto out; - } else { - dict->extra_stdfree = cli_req.dict.dict_val; - } - } - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to get volume name, while" - "handling quota command"); - goto out; - } - - ret = dict_get_int32 (dict, "type", &type); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to get type of cmd. , while" - "handling quota command"); - goto out; - } - - switch (type) { - case GF_QUOTA_OPTION_TYPE_ENABLE: - strncpy (operation, "enable", sizeof (operation)); - break; - - case GF_QUOTA_OPTION_TYPE_DISABLE: - strncpy (operation, "disable", sizeof (operation)); - break; - - case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: - strncpy (operation, "limit-usage", sizeof (operation)); - break; - - case GF_QUOTA_OPTION_TYPE_REMOVE: - strncpy (operation, "remove", sizeof (operation)); - break; - } - gf_cmd_log ("volume quota", " %s command on %s", operation, volname); - ret = glusterd_op_begin (req, GD_OP_QUOTA, dict); - gf_cmd_log ("volume quota", " %s command on %s %s", operation,volname, - (ret != 0)? "FAILED" : "SUCCEEDED"); - -out: - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) { - if (dict) - dict_unref (dict); - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - } - if (cli_req.volname) - free (cli_req.volname); //malloced by xdr - - return ret; -} + int glusterd_handle_set_volume (rpcsvc_request_t *req) @@ -1866,457 +994,6 @@ out: return ret; } -int -glusterd_handle_remove_brick (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_remove_brick_req cli_req = {0,}; - dict_t *dict = NULL; - int32_t count = 0; - char *brick = NULL; - char key[256] = {0,}; - char *brick_list = NULL; - int i = 1; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - int32_t pos = 0; - int32_t sub_volume = 0; - int32_t sub_volume_start = 0; - int32_t sub_volume_end = 0; - glusterd_brickinfo_t *tmp = NULL; - char err_str[2048] = {0}; - gf1_cli_remove_brick_rsp rsp = {0,}; - void *cli_rsp = NULL; - char vol_type[256] = {0,}; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_remove_brick_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_cmd_log ("Volume remove-brick","on volname: %s attempted",cli_req.volname); - gf_log ("glusterd", GF_LOG_INFO, "Received rem brick req"); - - if (cli_req.bricks.bricks_len) { - /* Unserialize the dictionary */ - dict = dict_new (); - - ret = dict_unserialize (cli_req.bricks.bricks_val, - cli_req.bricks.bricks_len, - &dict); - if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, - "failed to " - "unserialize req-buffer to dictionary"); - goto out; - } else { - dict->extra_stdfree = cli_req.bricks.bricks_val; - } - } - - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - ret = glusterd_volinfo_find (cli_req.volname, &volinfo); - if (ret) { - snprintf (err_str, 2048, "Volume %s does not exist", - cli_req.volname); - gf_log ("", GF_LOG_ERROR, "%s", err_str); - goto out; - } - - if (volinfo->type == GF_CLUSTER_TYPE_REPLICATE) - strcpy (vol_type, "replica"); - else if (volinfo->type == GF_CLUSTER_TYPE_STRIPE) - strcpy (vol_type, "stripe"); - else - strcpy (vol_type, "distribute"); - - /* Do not allow remove-brick if the volume is plain stripe */ - if ((volinfo->type == GF_CLUSTER_TYPE_STRIPE) && (volinfo->brick_count == volinfo->sub_count)) { - snprintf (err_str, 2048, "Removing brick from a plain stripe is not allowed"); - gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); - ret = -1; - goto out; - } - - /* Do not allow remove-brick if the bricks given is less than the replica count - or stripe count */ - if (((volinfo->type == GF_CLUSTER_TYPE_REPLICATE) || (volinfo->type == GF_CLUSTER_TYPE_STRIPE)) - && !(volinfo->brick_count <= volinfo->sub_count)) { - if (volinfo->sub_count && (count % volinfo->sub_count != 0)) { - snprintf (err_str, 2048, "Remove brick incorrect" - " brick count of %d for %s %d", - count, vol_type, volinfo->sub_count); - gf_log ("", GF_LOG_ERROR, "%s", err_str); - ret = -1; - goto out; - } - } - - brick_list = GF_MALLOC (120000 * sizeof(*brick_list),gf_common_mt_char); - - if (!brick_list) { - ret = -1; - goto out; - } - - strcpy (brick_list, " "); - while ( i <= count) { - snprintf (key, 256, "brick%d", i); - ret = dict_get_str (dict, key, &brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); - goto out; - } - gf_log ("", GF_LOG_DEBUG, "Remove brick count %d brick: %s", - i, brick); - - ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo); - if (ret) { - snprintf(err_str, 2048,"Incorrect brick %s for volume" - " %s", brick, cli_req.volname); - gf_log ("", GF_LOG_ERROR, "%s", err_str); - goto out; - } - strcat(brick_list, brick); - strcat(brick_list, " "); - - i++; - if ((volinfo->type == GF_CLUSTER_TYPE_NONE) || - (volinfo->brick_count <= volinfo->sub_count)) - continue; - - pos = 0; - list_for_each_entry (tmp, &volinfo->bricks, brick_list) { - - if ((!strcmp (tmp->hostname,brickinfo->hostname)) && - !strcmp (tmp->path, brickinfo->path)) { - gf_log ("", GF_LOG_INFO, "Found brick"); - if (!sub_volume && volinfo->sub_count) { - sub_volume = (pos / volinfo-> - sub_count) + 1; - sub_volume_start = volinfo->sub_count * - (sub_volume - 1); - sub_volume_end = (volinfo->sub_count * - sub_volume) -1 ; - } else { - if (pos < sub_volume_start || - pos >sub_volume_end) { - ret = -1; - snprintf(err_str, 2048,"Bricks" - " not from same subvol" - " for %s", vol_type); - gf_log ("",GF_LOG_ERROR, - "%s", err_str); - goto out; - } - } - break; - } - pos++; - } - } - gf_cmd_log ("Volume remove-brick","volname: %s count:%d bricks:%s", - cli_req.volname, count, brick_list); - - ret = glusterd_op_begin (req, GD_OP_REMOVE_BRICK, dict); - gf_cmd_log ("Volume remove-brick","on volname: %s %s",cli_req.volname, - (ret) ? "FAILED" : "SUCCESS"); - -out: - if (ret) { - if (dict) - dict_unref (dict); - rsp.op_ret = -1; - rsp.op_errno = 0; - rsp.volname = ""; - if (err_str[0] == '\0') - snprintf (err_str, sizeof (err_str), "Operation failed"); - gf_log ("", GF_LOG_ERROR, "%s", err_str); - rsp.op_errstr = err_str; - cli_rsp = &rsp; - glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, - gf_xdr_serialize_cli_remove_brick_rsp, - (xdrproc_t)xdr_gf1_cli_remove_brick_rsp); - - ret = 0; //sent error to cli, prevent second reply - - } - if (brick_list) - GF_FREE (brick_list); - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - return ret; -} - -int -glusterd_handle_log_filename (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_log_filename_req cli_req = {0,}; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_LOG_FILENAME; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_log_filename_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received log filename req " - "for volume %s", cli_req.volname); - - dict = dict_new (); - if (!dict) - goto out; - - ret = dict_set_dynmstr (dict, "volname", cli_req.volname); - if (ret) - goto out; - ret = dict_set_dynmstr (dict, "brick", cli_req.brick); - if (ret) - goto out; - ret = dict_set_dynmstr (dict, "path", cli_req.path); - if (ret) - goto out; - - ret = glusterd_op_begin (req, GD_OP_LOG_FILENAME, dict); - -out: - if (ret && dict) - dict_unref (dict); - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - - return ret; -} - -int -glusterd_handle_log_locate (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_log_locate_req cli_req = {0,}; - gf1_cli_log_locate_rsp rsp = {0,}; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - char tmp_str[PATH_MAX] = {0,}; - char *tmp_brick = NULL; - uint32_t found = 0; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - - GF_ASSERT (req); - - priv = THIS->private; - - if (!gf_xdr_to_cli_log_locate_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received log locate req " - "for volume %s", cli_req.volname); - - if (strchr (cli_req.brick, ':')) { - /* TODO: need to get info of only that brick and then - tell what is the exact location */ - tmp_brick = gf_strdup (cli_req.brick); - if (!tmp_brick) - goto out; - - gf_log ("", GF_LOG_DEBUG, "brick : %s", cli_req.brick); - ret = glusterd_brickinfo_from_brick (tmp_brick, &tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "Cannot get brickinfo from the brick"); - goto out; - } - } - - ret = glusterd_volinfo_find (cli_req.volname, &volinfo); - if (ret) { - rsp.path = "request sent on non-existent volume"; - goto out; - } - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (tmpbrkinfo) { - ret = glusterd_resolve_brick (tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot resolve the brick"); - goto out; - } - if (uuid_compare (tmpbrkinfo->uuid, brickinfo->uuid) || strcmp (brickinfo->path, tmpbrkinfo->path)) - continue; - } - - if (brickinfo->logfile) { - strcpy (tmp_str, brickinfo->logfile); - rsp.path = dirname (tmp_str); - found = 1; - } else { - snprintf (tmp_str, PATH_MAX, "%s/bricks/", - DEFAULT_LOG_FILE_DIRECTORY); - rsp.path = tmp_str; - found = 1; - } - break; - } - - if (!found) { - snprintf (tmp_str, PATH_MAX, "brick %s:%s does not exitst in the volume %s", - tmpbrkinfo->hostname, tmpbrkinfo->path, cli_req.volname); - rsp.path = tmp_str; - } - - ret = 0; -out: - if (tmp_brick) - GF_FREE (tmp_brick); - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); - rsp.op_ret = ret; - if (!rsp.path) - rsp.path = "Operation failed"; - - ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, - gf_xdr_serialize_cli_log_locate_rsp, - (xdrproc_t)xdr_gf1_cli_log_locate_rsp); - - if (cli_req.brick) - free (cli_req.brick); //its malloced by xdr - if (cli_req.volname) - free (cli_req.volname); //its malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); - - return ret; -} - -int -glusterd_handle_log_level (rpcsvc_request_t *req) -{ - int32_t ret = -1; - dict_t *dict = NULL; - gf1_cli_log_level_req cli_req = {0,}; - glusterd_op_t cli_op = GD_OP_LOG_LEVEL; - - GF_ASSERT(req); - - - if (!gf_xdr_to_cli_log_level_req(req->msg[0], &cli_req)) { - gf_log ("glusterd", GF_LOG_ERROR, "Failed to decode rpc message"); - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_DEBUG, "Got log level request for: Volume [%s]" - " Xlator [%s] LogLevel [\"%s\"]", cli_req.volname, cli_req.xlator, cli_req.loglevel); - - dict = dict_new (); - if (!dict) - goto out; - - ret = dict_set_dynmstr (dict, "volname", cli_req.volname); - if (ret) - goto out; - - ret = dict_set_dynmstr (dict, "xlator", cli_req.xlator); - if (ret) - goto out; - - ret = dict_set_dynmstr (dict, "loglevel", cli_req.loglevel); - if (ret) - goto out; - - ret = glusterd_op_begin (req, cli_op, dict); - - out: - if (ret && dict) - dict_unref (dict); - - glusterd_friend_sm(); - glusterd_op_sm(); - - if (ret) - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, NULL, - "Operation failed"); - - return ret; -} - -int -glusterd_handle_log_rotate (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf1_cli_log_rotate_req cli_req = {0,}; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_LOG_ROTATE; - - GF_ASSERT (req); - - if (!gf_xdr_to_cli_log_rotate_req (req->msg[0], &cli_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received log rotate req " - "for volume %s", cli_req.volname); - - dict = dict_new (); - if (!dict) - goto out; - - ret = dict_set_dynmstr (dict, "volname", cli_req.volname); - if (ret) - goto out; - - ret = dict_set_dynmstr (dict, "brick", cli_req.brick); - if (ret) - goto out; - - ret = dict_set_uint64 (dict, "rotate-key", (uint64_t)time (NULL)); - if (ret) - goto out; - - ret = glusterd_op_begin (req, GD_OP_LOG_ROTATE, dict); - -out: - if (ret && dict) - dict_unref (dict); - - glusterd_friend_sm (); - glusterd_op_sm (); - - if (ret) - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); - - return ret; -} - int glusterd_handle_sync_volume (rpcsvc_request_t *req) { diff --git a/xlators/mgmt/glusterd/src/glusterd-log-ops.c b/xlators/mgmt/glusterd/src/glusterd-log-ops.c new file mode 100644 index 000000000..017698291 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-log-ops.c @@ -0,0 +1,804 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" + +#include + +int +glusterd_handle_log_filename (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_log_filename_req cli_req = {0,}; + dict_t *dict = NULL; + glusterd_op_t cli_op = GD_OP_LOG_FILENAME; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_log_filename_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received log filename req " + "for volume %s", cli_req.volname); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) + goto out; + ret = dict_set_dynmstr (dict, "brick", cli_req.brick); + if (ret) + goto out; + ret = dict_set_dynmstr (dict, "path", cli_req.path); + if (ret) + goto out; + + ret = glusterd_op_begin (req, GD_OP_LOG_FILENAME, dict); + +out: + if (ret && dict) + dict_unref (dict); + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + + return ret; +} + +int +glusterd_handle_log_locate (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_log_locate_req cli_req = {0,}; + gf1_cli_log_locate_rsp rsp = {0,}; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char tmp_str[PATH_MAX] = {0,}; + char *tmp_brick = NULL; + uint32_t found = 0; + glusterd_brickinfo_t *tmpbrkinfo = NULL; + + GF_ASSERT (req); + + priv = THIS->private; + + if (!gf_xdr_to_cli_log_locate_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received log locate req " + "for volume %s", cli_req.volname); + + if (strchr (cli_req.brick, ':')) { + /* TODO: need to get info of only that brick and then + tell what is the exact location */ + tmp_brick = gf_strdup (cli_req.brick); + if (!tmp_brick) + goto out; + + gf_log ("", GF_LOG_DEBUG, "brick : %s", cli_req.brick); + ret = glusterd_brickinfo_from_brick (tmp_brick, &tmpbrkinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "Cannot get brickinfo from the brick"); + goto out; + } + } + + ret = glusterd_volinfo_find (cli_req.volname, &volinfo); + if (ret) { + rsp.path = "request sent on non-existent volume"; + goto out; + } + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (tmpbrkinfo) { + ret = glusterd_resolve_brick (tmpbrkinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "cannot resolve the brick"); + goto out; + } + if (uuid_compare (tmpbrkinfo->uuid, brickinfo->uuid) || strcmp (brickinfo->path, tmpbrkinfo->path)) + continue; + } + + if (brickinfo->logfile) { + strcpy (tmp_str, brickinfo->logfile); + rsp.path = dirname (tmp_str); + found = 1; + } else { + snprintf (tmp_str, PATH_MAX, "%s/bricks/", + DEFAULT_LOG_FILE_DIRECTORY); + rsp.path = tmp_str; + found = 1; + } + break; + } + + if (!found) { + snprintf (tmp_str, PATH_MAX, "brick %s:%s does not exitst in the volume %s", + tmpbrkinfo->hostname, tmpbrkinfo->path, cli_req.volname); + rsp.path = tmp_str; + } + + ret = 0; +out: + if (tmp_brick) + GF_FREE (tmp_brick); + if (tmpbrkinfo) + glusterd_brickinfo_delete (tmpbrkinfo); + rsp.op_ret = ret; + if (!rsp.path) + rsp.path = "Operation failed"; + + ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, + gf_xdr_serialize_cli_log_locate_rsp, + (xdrproc_t)xdr_gf1_cli_log_locate_rsp); + + if (cli_req.brick) + free (cli_req.brick); //its malloced by xdr + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + return ret; +} + +int +glusterd_handle_log_level (rpcsvc_request_t *req) +{ + int32_t ret = -1; + dict_t *dict = NULL; + gf1_cli_log_level_req cli_req = {0,}; + glusterd_op_t cli_op = GD_OP_LOG_LEVEL; + + GF_ASSERT(req); + + + if (!gf_xdr_to_cli_log_level_req(req->msg[0], &cli_req)) { + gf_log ("glusterd", GF_LOG_ERROR, "Failed to decode rpc message"); + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_DEBUG, "Got log level request for: Volume [%s]" + " Xlator [%s] LogLevel [\"%s\"]", cli_req.volname, cli_req.xlator, cli_req.loglevel); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) + goto out; + + ret = dict_set_dynmstr (dict, "xlator", cli_req.xlator); + if (ret) + goto out; + + ret = dict_set_dynmstr (dict, "loglevel", cli_req.loglevel); + if (ret) + goto out; + + ret = glusterd_op_begin (req, cli_op, dict); + + out: + if (ret && dict) + dict_unref (dict); + + glusterd_friend_sm(); + glusterd_op_sm(); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, NULL, + "Operation failed"); + + return ret; +} + +int +glusterd_handle_log_rotate (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_log_rotate_req cli_req = {0,}; + dict_t *dict = NULL; + glusterd_op_t cli_op = GD_OP_LOG_ROTATE; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_log_rotate_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received log rotate req " + "for volume %s", cli_req.volname); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) + goto out; + + ret = dict_set_dynmstr (dict, "brick", cli_req.brick); + if (ret) + goto out; + + ret = dict_set_uint64 (dict, "rotate-key", (uint64_t)time (NULL)); + if (ret) + goto out; + + ret = glusterd_op_begin (req, GD_OP_LOG_ROTATE, dict); + +out: + if (ret && dict) + dict_unref (dict); + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + + return ret; +} + +/* op-sm */ +int +glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + char msg[2048] = {0}; + char *path = NULL; + char hostname[2048] = {0}; + char *brick = NULL; + glusterd_volinfo_t *volinfo = NULL; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if (!exists || ret) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + if (strchr (brick, ':')) { + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + NULL); + if (ret) { + snprintf (msg, sizeof (msg), "Incorrect brick %s " + "for volume %s", brick, volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + } + + ret = dict_get_str (dict, "path", &path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "path not found"); + goto out; + } + + ret = gethostname (hostname, sizeof (hostname)); + if (ret) { + snprintf (msg, sizeof (msg), "Failed to get hostname, error:%s", + strerror (errno)); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = glusterd_brick_create_path (hostname, path, volinfo->volume_id, + 0777, op_errstr); + if (ret) + goto out; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + gf_boolean_t exists = _gf_false; + char msg[2048] = {0}; + char *brick = NULL; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + if (_gf_false == glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "Volume %s needs to be started before" + " log rotate.", volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + if (strchr (brick, ':')) { + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + NULL); + if (ret) { + snprintf (msg, sizeof (msg), "Incorrect brick %s " + "for volume %s", brick, volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + } +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stage_log_level (dict_t *dict, char **op_errstr) +{ + int ret = -1; + gf_boolean_t exists = _gf_false; + dict_t *val_dict = NULL; + char *volname = NULL; + char *xlator = NULL; + char *loglevel = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + char msg[2048] = {0,}; + + GF_ASSERT (dict); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT(priv); + + val_dict = dict_new (); + if (!val_dict) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + /* + * check for existence of the gieven volume + */ + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if (!exists || ret) { + snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + + *op_errstr = gf_strdup(msg); + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "xlator", &xlator); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); + goto out; + } + + ret = dict_get_str (dict, "loglevel", &loglevel); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get loglevel"); + goto out; + } + + ret = 0; + + out: + if (val_dict) + dict_unref (val_dict); + + if (ret) { + if (!(*op_errstr)) { + *op_errstr = gf_strdup ("Error, Validation Failed"); + gf_log ("glusterd", GF_LOG_DEBUG, "Error, Cannot Validate option: %s", + *op_errstr); + } + } + + gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); + return ret; +} + +int +glusterd_op_log_filename (dict_t *dict) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + char *volname = NULL; + char *brick = NULL; + char *path = NULL; + char logfile[PATH_MAX] = {0,}; + char exp_path[PATH_MAX] = {0,}; + struct stat stbuf = {0,}; + int valid_brick = 0; + glusterd_brickinfo_t *tmpbrkinfo = NULL; + char* new_logdir = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "volname not found"); + goto out; + } + + ret = dict_get_str (dict, "path", &path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "path not found"); + goto out; + } + + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) + goto out; + + if (!strchr (brick, ':')) { + brick = NULL; + ret = stat (path, &stbuf); + if (ret || !S_ISDIR (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "not a directory"); + goto out; + } + new_logdir = gf_strdup (path); + if (!new_logdir) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Out of memory"); + goto out; + } + if (volinfo->logdir) + GF_FREE (volinfo->logdir); + volinfo->logdir = new_logdir; + } else { + ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "cannot get brickinfo from brick"); + goto out; + } + } + + + ret = -1; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + + if (uuid_is_null (brickinfo->uuid)) { + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; + } + + /* check if the brickinfo belongs to the 'this' machine */ + if (uuid_compare (brickinfo->uuid, priv->uuid)) + continue; + + if (brick && strcmp (tmpbrkinfo->path,brickinfo->path)) + continue; + + valid_brick = 1; + + /* If there are more than one brick in 'this' server, its an + * extra check, but it doesn't harm functionality + */ + ret = stat (path, &stbuf); + if (ret || !S_ISDIR (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "not a directory"); + goto out; + } + + GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); + + snprintf (logfile, PATH_MAX, "%s/%s.log", path, exp_path); + + if (brickinfo->logfile) + GF_FREE (brickinfo->logfile); + brickinfo->logfile = gf_strdup (logfile); + ret = 0; + + /* If request was for brick, only one iteration is enough */ + if (brick) + break; + } + + if (ret && !valid_brick) + ret = 0; +out: + if (tmpbrkinfo) + glusterd_brickinfo_delete (tmpbrkinfo); + + return ret; +} + +int +glusterd_op_log_rotate (dict_t *dict) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + char *volname = NULL; + char *brick = NULL; + char path[PATH_MAX] = {0,}; + char logfile[PATH_MAX] = {0,}; + char pidfile[PATH_MAX] = {0,}; + FILE *file = NULL; + pid_t pid = 0; + uint64_t key = 0; + int valid_brick = 0; + glusterd_brickinfo_t *tmpbrkinfo = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "volname not found"); + goto out; + } + + ret = dict_get_uint64 (dict, "rotate-key", &key); + if (ret) { + gf_log ("", GF_LOG_ERROR, "rotate key not found"); + goto out; + } + + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + if (!strchr (brick, ':')) + brick = NULL; + else { + ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "cannot get brickinfo from brick"); + goto out; + } + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) + goto out; + + ret = -1; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_compare (brickinfo->uuid, priv->uuid)) + continue; + + if (brick && + (strcmp (tmpbrkinfo->hostname, brickinfo->hostname) || + strcmp (tmpbrkinfo->path,brickinfo->path))) + continue; + + valid_brick = 1; + + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, + brickinfo->path); + + file = fopen (pidfile, "r+"); + if (!file) { + gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", + pidfile); + ret = -1; + goto out; + } + + ret = fscanf (file, "%d", &pid); + if (ret <= 0) { + gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", + pidfile); + ret = -1; + goto out; + } + fclose (file); + file = NULL; + + snprintf (logfile, PATH_MAX, "%s.%"PRIu64, + brickinfo->logfile, key); + + ret = rename (brickinfo->logfile, logfile); + if (ret) + gf_log ("", GF_LOG_WARNING, "rename failed"); + + ret = kill (pid, SIGHUP); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); + goto out; + } + ret = 0; + + /* If request was for brick, only one iteration is enough */ + if (brick) + break; + } + + if (ret && !valid_brick) + ret = 0; + +out: + if (tmpbrkinfo) + glusterd_brickinfo_delete (tmpbrkinfo); + + return ret; +} + +int +glusterd_op_log_level (dict_t *dict) +{ + int32_t ret = -1; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + char *xlator = NULL; + char *loglevel = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = dict_get_str (dict, "xlator", &xlator); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); + goto out; + } + + ret = dict_get_str (dict, "loglevel", &loglevel); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get Loglevel to use"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Cannot find volume: %s", volname); + goto out; + } + + xlator = gf_strdup (xlator); + + ret = dict_set_dynstr (volinfo->dict, "xlator", xlator); + if (ret) + goto out; + + loglevel = gf_strdup (loglevel); + + ret = dict_set_dynstr (volinfo->dict, "loglevel", loglevel); + if (ret) + goto out; + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to create volfile for command" + " 'log level'"); + ret = -1; + goto out; + } + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + ret = 0; + + out: + gf_log ("glusterd", GF_LOG_DEBUG, "(cli log level) Returning: %d", ret); + return ret; +} + diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index a36d10b68..a460582a0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -54,8 +54,6 @@ #include #include #include -#define glusterd_op_start_volume_args_get(dict, volname, flags) \ - glusterd_op_stop_volume_args_get (dict, volname, flags) static struct list_head gd_op_sm_queue; pthread_mutex_t gd_op_sm_lock; @@ -98,13 +96,6 @@ static char *glusterd_op_sm_event_names[] = { "GD_OP_EVENT_INVALID" }; -static char *gsync_reserved_opts[] = { - "gluster-command", - "pid-file", - "state-file", - "session-owner", - NULL -}; static int glusterd_restart_brick_servers (glusterd_volinfo_t *); @@ -274,239 +265,284 @@ out: return ret; } + static int -glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) +glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) { - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char *bricks = NULL; - char *brick_list = NULL; - char *free_ptr = NULL; - glusterd_brickinfo_t *brick_info = NULL; - int32_t brick_count = 0; - int32_t i = 0; - char *brick = NULL; - char *tmpptr = NULL; - char cmd_str[1024]; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char msg[2048] = {0}; - uuid_t volume_uuid; - char *volume_uuid_str; + int ret = 0; + char *volname = NULL; + int exists = 0; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char str[100] = {0, }; + int count = 0; + int dict_count = 0; + char errstr[2048] = {0, }; + glusterd_volinfo_t *volinfo = NULL; + dict_t *val_dict = NULL; + gf_boolean_t global_opt = _gf_false; + glusterd_volinfo_t *voliter = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + GF_ASSERT (dict); this = THIS; - if (!this) { - gf_log ("glusterd", GF_LOG_ERROR, - "this is NULL"); - goto out; - } - + GF_ASSERT (this); priv = this->private; - if (!priv) { - gf_log ("glusterd", GF_LOG_ERROR, - "priv is NULL"); + GF_ASSERT (priv); + + val_dict = dict_new(); + if (!val_dict) goto out; - } - ret = dict_get_str (dict, "volname", &volname); + ret = dict_get_int32 (dict, "count", &dict_count); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + gf_log ("", GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); goto out; } - exists = glusterd_check_volume_exists (volname); + if ( dict_count == 0 ) { + /*No options would be specified of volume set help */ + if (dict_get (dict, "help" )) { + ret = 0; + goto out; + } - if (exists) { - snprintf (msg, sizeof (msg), "Volume %s already exists", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + if (dict_get (dict, "help-xml" )) { + +#if (HAVE_LIB_XML) + ret = 0; + goto out; +#else + ret = -1; + gf_log ("", GF_LOG_ERROR, "libxml not present in the" + "system"); + *op_errstr = gf_strdup ("Error: xml libraries not " + "present to produce xml-output"); + goto out; +#endif + } + gf_log ("", GF_LOG_ERROR, "No options received "); + *op_errstr = gf_strdup ("Options not specified"); ret = -1; goto out; - } else { - ret = 0; - } - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; } - ret = dict_get_str (dict, "volume-id", &volume_uuid_str); + + ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume id"); + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); goto out; } - ret = uuid_parse (volume_uuid_str, volume_uuid); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to parse volume id"); + + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (errstr, sizeof (errstr), "Volume %s does not exist", + volname); + gf_log ("", GF_LOG_ERROR, "%s", errstr); + *op_errstr = gf_strdup (errstr); + ret = -1; goto out; } - ret = dict_get_str (dict, "bricks", &bricks); + ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } - if (bricks) { - brick_list = gf_strdup (bricks); - if (!brick_list) { + for ( count = 1; ret != 1 ; count++ ) { + global_opt = _gf_false; + sprintf (str, "key%d", count); + ret = dict_get_str (dict, str, &key); + + + if (ret) + break; + + exists = glusterd_check_option_exists (key, &key_fixed); + if (exists == -1) { ret = -1; - gf_log ("", GF_LOG_ERROR, "Out of memory"); goto out; - } else { - free_ptr = brick_list; } - } + if (!exists) { + gf_log ("", GF_LOG_ERROR, "Option with name: %s " + "does not exist", key); + ret = snprintf (errstr, 2048, + "option : %s does not exist", + key); + if (key_fixed) + snprintf (errstr + ret, 2048 - ret, + "\nDid you mean %s?", key_fixed); + *op_errstr = gf_strdup (errstr); + ret = -1; + goto out; + } - while ( i < brick_count) { - i++; - brick= strtok_r (brick_list, " \n", &tmpptr); - brick_list = tmpptr; - - if (!glusterd_store_is_valid_brickpath (volname, brick) || - !glusterd_is_valid_volfpath (volname, brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + sprintf (str, "value%d", count); + ret = dict_get_str (dict, str, &value); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "invalid key,value pair in 'volume set'"); ret = -1; goto out; } - ret = glusterd_brickinfo_from_brick (brick, &brick_info); + if (key_fixed) + key = key_fixed; + + ret = glusterd_check_globaloption (key); if (ret) + global_opt = _gf_true; + + ret = dict_set_str (val_dict, key, value); + + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Unable to set the options in 'volume set'"); + ret = -1; goto out; - snprintf (cmd_str, 1024, "%s", brick_info->path); - ret = glusterd_resolve_brick (brick_info); + } + + *op_errstr = NULL; + if (!global_opt) + ret = glusterd_validate_reconfopts (volinfo, val_dict, op_errstr); + else { + voliter = NULL; + list_for_each_entry (voliter, &priv->volumes, vol_list) { + ret = glusterd_validate_globalopts (voliter, val_dict, op_errstr); + if (ret) + break; + } + } + if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " - "brick: %s:%s", brick_info->hostname, - brick_info->path); + gf_log ("glusterd", GF_LOG_DEBUG, "Could not create temp " + "volfile, some option failed: %s", *op_errstr); goto out; } + dict_del (val_dict, key); - if (!uuid_compare (brick_info->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brick_info->hostname, - brick_info->path, - volume_uuid, - 0777, op_errstr); - if (ret) - goto out; - brick_list = tmpptr; + if (key_fixed) { + GF_FREE (key_fixed); + key_fixed = NULL; } - glusterd_brickinfo_delete (brick_info); - brick_info = NULL; } + + + ret = 0; + out: - if (free_ptr) - GF_FREE (free_ptr); - if (brick_info) - glusterd_brickinfo_delete (brick_info); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (val_dict) + dict_unref (val_dict); + + if (key_fixed) + GF_FREE (key_fixed); + if (ret) { + if (!(*op_errstr)) { + *op_errstr = gf_strdup ("Error, Validation Failed"); + gf_log ("glsuterd", GF_LOG_DEBUG, + "Error, Cannot Validate option :%s", + *op_errstr); + } else { + gf_log ("glsuterd", GF_LOG_DEBUG, + "Error, Cannot Validate option"); + } + } return ret; } static int -glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, - int *flags) +glusterd_op_stage_reset_volume (dict_t *dict, char **op_errstr) { - int ret = -1; + int ret = 0; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + char msg[2048] = {0}; - if (!dict || !volname || !flags) - goto out; + ret = dict_get_str (dict, "volname", &volname); - ret = dict_get_str (dict, "volname", volname); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); goto out; } - ret = dict_get_int32 (dict, "flags", flags); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get flags"); + exists = glusterd_check_volume_exists (volname); + + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s does not " + "exist", volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; goto out; } + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; } + + static int -glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr) +glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) { - int ret = 0; + int ret = -1; char *volname = NULL; - int flags = 0; + char *hostname = NULL; gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - char msg[2048]; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - if (!priv) { - gf_log ("glusterd", GF_LOG_ERROR, - "priv is NULL"); - ret = -1; - goto out; - } - - ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; - - exists = glusterd_check_volume_exists (volname); + glusterd_peerinfo_t *peerinfo = NULL; + char msg[2048] = {0,}; - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", - msg); + ret = dict_get_str (dict, "hostname", &hostname); + if (ret) { + snprintf (msg, sizeof (msg), "hostname couldn't be " + "retrieved from msg"); *op_errstr = gf_strdup (msg); - ret = -1; - } else { - ret = 0; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) goto out; + } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_resolve_brick (brickinfo); + ret = glusterd_is_local_addr (hostname); + if (ret) { + ret = glusterd_friend_find (NULL, hostname, &peerinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to resolve brick %s:%s", - brickinfo->hostname, brickinfo->path); + snprintf (msg, sizeof (msg), "%s, is not a friend", + hostname); + *op_errstr = gf_strdup (msg); goto out; } - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - volinfo->volume_id, - 0777, op_errstr); - if (ret) - goto out; + if (!peerinfo->connected) { + snprintf (msg, sizeof (msg), "%s, is not connected at " + "the moment", hostname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; } + } else { - if (!(flags & GF_CLI_FLAG_OP_FORCE)) { - if (glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s already" - " started", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + //volname is not present in case of sync all + ret = dict_get_str (dict, "volname", &volname); + if (!ret) { + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s " + "does not exist", volname); *op_errstr = gf_strdup (msg); ret = -1; goto out; } + } else { + ret = 0; } } - ret = 0; out: gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); @@ -514,5903 +550,496 @@ out: } static int -glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) +glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) { - int ret = -1; - char *volname = NULL; - int flags = 0; - gf_boolean_t exists = _gf_false; - gf_boolean_t is_run = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char msg[2048] = {0}; - - - ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; - - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } else { - ret = 0; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; - - if (!(flags & GF_CLI_FLAG_OP_FORCE)) { - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof(msg), "Volume %s " - "is not in the started state", volname); - gf_log ("", GF_LOG_ERROR, "Volume %s " - "has not been started", volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - ret = glusterd_check_gsync_running (volinfo, &is_run); - if (ret && (is_run == _gf_false)) - gf_log ("", GF_LOG_WARNING, "Unable to get the status" - " of active "GEOREP" session"); - if (is_run) { - gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" - "for the volume %s ", volname); - snprintf (msg, sizeof(msg), GEOREP" sessions are active " - "for the volume '%s'.\nUse 'volume "GEOREP" " - "status' command for more info. Use 'force'" - "option to ignore and stop stop the volume", - volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - } - - -out: - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + int ret = -1; + gf_boolean_t exists = _gf_false; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + char msg[2048] = {0,}; - return ret; -} + GF_ASSERT (dict); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT(priv); -static int -glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char msg[2048] = {0}; ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); goto out; } exists = glusterd_check_volume_exists (volname); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } else { - ret = 0; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; + snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - if (glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s has been started." - "Volume needs to be stopped before deletion.", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + *op_errstr = gf_strdup(msg); ret = -1; goto out; } ret = 0; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + out: + if (ret && !(*op_errstr)) + *op_errstr = gf_strdup ("Validation Failed for Status"); + gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); return ret; } + +static gf_boolean_t +glusterd_is_profile_on (glusterd_volinfo_t *volinfo) +{ + int ret = -1; + gf_boolean_t is_latency_on = _gf_false; + gf_boolean_t is_fd_stats_on = _gf_false; + + GF_ASSERT (volinfo); + + ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_CNT_FOP_HITS); + if (ret != -1) + is_fd_stats_on = ret; + ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_LAT_MEASUREMENT); + if (ret != -1) + is_latency_on = ret; + if ((_gf_true == is_latency_on) && + (_gf_true == is_fd_stats_on)) + return _gf_true; + return _gf_false; +} + static int -glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) +glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) { - int ret = 0; + int ret = -1; char *volname = NULL; - int count = 0; - int i = 0; - char *bricks = NULL; - char *brick_list = NULL; - char *saveptr = NULL; - char *free_ptr = NULL; - char *brick = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_volinfo_t *volinfo = NULL; - char cmd_str[1024]; - glusterd_conf_t *priv = NULL; + gf_boolean_t exists = _gf_false; char msg[2048] = {0,}; - gf_boolean_t brick_alloc = _gf_false; - char *all_bricks = NULL; - char *str_ret = NULL; - - priv = THIS->private; - if (!priv) - goto out; + int32_t stats_op = GF_CLI_STATS_NONE; + glusterd_volinfo_t *volinfo = NULL; ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + snprintf (msg, sizeof (msg), "Volume name get failed"); goto out; } + exists = glusterd_check_volume_exists (volname); ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to find volume: %s", volname); - goto out; - } - - if (glusterd_is_defrag_on(volinfo)) { - snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " - "progress. Please retry after completion", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + if ((!exists) || (ret < 0)) { + snprintf (msg, sizeof (msg), "Volume %s, " + "doesn't exist", volname); ret = -1; goto out; } - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - ret = dict_get_str (dict, "bricks", &bricks); + ret = dict_get_int32 (dict, "op", &stats_op); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - if (bricks) { - brick_list = gf_strdup (bricks); - all_bricks = gf_strdup (bricks); - free_ptr = brick_list; - } - - /* Check whether any of the bricks given is the destination brick of the - replace brick running */ - - str_ret = glusterd_check_brick_rb_part (all_bricks, count, volinfo); - if (str_ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "%s", str_ret); - *op_errstr = gf_strdup (str_ret); - ret = -1; - goto out; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - - while ( i < count) { - if (!glusterd_store_is_valid_brickpath (volname, brick) || - !glusterd_is_valid_volfpath (volname, brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - - ret = -1; - goto out; - - } - - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - &brickinfo); - if (!ret) { - gf_log ("", GF_LOG_ERROR, "Adding duplicate brick: %s", - brick); - ret = -1; - goto out; - } else { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" - " to get brickinfo"); - goto out; - } - brick_alloc = _gf_true; - } - - snprintf (cmd_str, 1024, "%s", brickinfo->path); - ret = glusterd_resolve_brick (brickinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "resolve brick failed"); - goto out; - } - - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - volinfo->volume_id, - 0777, op_errstr); - if (ret) - goto out; - } - - glusterd_brickinfo_delete (brickinfo); - brick_alloc = _gf_false; - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - -out: - if (free_ptr) - GF_FREE (free_ptr); - if (brick_alloc && brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (str_ret) - GF_FREE (str_ret); - if (all_bricks) - GF_FREE (all_bricks); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -char * -glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) -{ - char *saveptr = NULL; - char *brick = NULL; - char *brick_list = NULL; - int ret = 0; - glusterd_brickinfo_t *brickinfo = NULL; - uint32_t i = 0; - char *str = NULL; - char msg[2048] = {0,}; - - brick_list = gf_strdup (bricks); - if (!brick_list) { - gf_log ("glusterd", GF_LOG_ERROR, - "Out of memory"); - ret = -1; + snprintf (msg, sizeof (msg), "Volume profile op get failed"); goto out; } - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - - while ( i < count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) { - snprintf (msg, sizeof(msg), "Unable to" - " get brickinfo"); - gf_log ("", GF_LOG_ERROR, "%s", msg); - ret = -1; - goto out; - } - - if (glusterd_is_replace_running (volinfo, brickinfo)) { - snprintf (msg, sizeof(msg), "Volume %s: replace brick is running" - " and the brick %s:%s you are trying to add is the destination brick" - " for replace brick", volinfo->volname, brickinfo->hostname, brickinfo->path); + if (GF_CLI_STATS_START == stats_op) { + if (_gf_true == glusterd_is_profile_on (volinfo)) { + snprintf (msg, sizeof (msg), "Profile on Volume %s is" + " already started", volinfo->volname); ret = -1; goto out; } - glusterd_brickinfo_delete (brickinfo); - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - -out: - if (brick_list) - GF_FREE(brick_list); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (ret) - str = gf_strdup (msg); - return str; -} - -static int -glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t **brickinfo) -{ - int32_t ret = -1; - - if (!volinfo || !brickinfo) - goto out; - - *brickinfo = volinfo->dst_brick; - - ret = 0; - -out: - return ret; -} - -static int -glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) -{ - int ret = 0; - char *src_brick = NULL; - char *dst_brick = NULL; - char *volname = NULL; - int replace_op = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - char *host = NULL; - char *path = NULL; - char msg[2048] = {0}; - char *dup_dstbrick = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; - gf_boolean_t is_run = _gf_false; - - ret = dict_get_str (dict, "src-brick", &src_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); - goto out; } + if ((GF_CLI_STATS_STOP == stats_op) || + (GF_CLI_STATS_INFO == stats_op)) { + if (_gf_false == glusterd_is_profile_on (volinfo)) { + snprintf (msg, sizeof (msg), "Profile on Volume %s is" + " not started", volinfo->volname); + ret = -1; - gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict get on replace-brick operation failed"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (msg, sizeof (msg), "volume: %s does not exist", - volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - ret = -1; - snprintf (msg, sizeof (msg), "volume: %s is not started", - volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!glusterd_store_is_valid_brickpath (volname, dst_brick) || - !glusterd_is_valid_volfpath (volname, dst_brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", dst_brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - - ret = -1; - goto out; - } - - ret = glusterd_check_gsync_running (volinfo, &is_run); - if (ret && (is_run == _gf_false)) - gf_log ("", GF_LOG_WARNING, "Unable to get the status" - " of active "GEOREP" session"); - if (is_run) { - gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" - "for the volume %s ", volname); - snprintf (msg, sizeof(msg), GEOREP" sessions are active " - "for the volume %s.\nStop "GEOREP "sessions " - "involved in this volume. Use 'volume "GEOREP - " status' command for more info.", - volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if (glusterd_is_defrag_on(volinfo)) { - snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " - "progress. Please retry after completion", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - switch (replace_op) { - case GF_REPLACE_OP_START: - if (glusterd_is_rb_started (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "started for volume "); - ret = -1; - goto out; - } - break; - case GF_REPLACE_OP_PAUSE: - if (glusterd_is_rb_paused (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "paused for volume "); - ret = -1; - goto out; - } else if (!glusterd_is_rb_started(volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not" - " started for volume "); - ret = -1; - goto out; - } - break; - - case GF_REPLACE_OP_ABORT: - if ((!glusterd_is_rb_paused (volinfo)) && - (!glusterd_is_rb_started (volinfo))) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not" - " started or paused for volume "); - ret = -1; - goto out; - } - break; - - case GF_REPLACE_OP_COMMIT: - if (!glusterd_is_rb_started (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not " - "started for volume "); - ret = -1; - goto out; - } - break; - - case GF_REPLACE_OP_COMMIT_FORCE: break; - case GF_REPLACE_OP_STATUS: - break; - default: - ret = -1; - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, - &src_brickinfo); - if (ret) { - snprintf (msg, sizeof (msg), "brick: %s does not exist in " - "volume: %s", src_brick, volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - gf_log ("", GF_LOG_DEBUG, - "I AM THE SOURCE HOST"); - if (src_brickinfo->port && rsp_dict) { - ret = dict_set_int32 (rsp_dict, "src-brick-port", - src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick-port=%d", - src_brickinfo->port); - } - } - - } - - dup_dstbrick = gf_strdup (dst_brick); - if (!dup_dstbrick) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); - goto out; - } - host = strtok (dup_dstbrick, ":"); - path = strtok (NULL, ":"); - - if (!host || !path) { - gf_log ("", GF_LOG_ERROR, - "dst brick %s is not of form :", - dst_brick); - ret = -1; - goto out; - } - if (!glusterd_brickinfo_get (NULL, host, path, NULL)) { - snprintf(msg, sizeof(msg), "Brick: %s:%s already in use", - host, path); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && - (replace_op == GF_REPLACE_OP_START)) { - ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); - volinfo->src_brick = src_brickinfo; - volinfo->dst_brick = dst_brickinfo; - } else { - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - } - - if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { - gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" - " destination bricks specified"); - ret = -1; - goto out; - } - if (!glusterd_is_local_addr (host)) { - ret = glusterd_brick_create_path (host, path, - volinfo->volume_id, 0777, - op_errstr); - if (ret) - goto out; - } else { - ret = glusterd_friend_find (NULL, host, &peerinfo); - if (ret) { - snprintf (msg, sizeof (msg), "%s, is not a friend", - host); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!peerinfo->connected) { - snprintf (msg, sizeof (msg), "%s, is not connected at " - "the moment", host); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) { - snprintf (msg, sizeof (msg), "%s, is not befriended " - "at the moment", host); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } - ret = 0; - -out: - if (dup_dstbrick) - GF_FREE (dup_dstbrick); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_log_level (dict_t *dict, char **op_errstr) -{ - int ret = -1; - gf_boolean_t exists = _gf_false; - dict_t *val_dict = NULL; - char *volname = NULL; - char *xlator = NULL; - char *loglevel = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char msg[2048] = {0,}; - - GF_ASSERT (dict); - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT(priv); - - val_dict = dict_new (); - if (!val_dict) - goto out; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - /* - * check for existence of the gieven volume - */ - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if (!exists || ret) { - snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - - *op_errstr = gf_strdup(msg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "xlator", &xlator); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); - goto out; - } - - ret = dict_get_str (dict, "loglevel", &loglevel); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get loglevel"); - goto out; - } - - ret = 0; - - out: - if (val_dict) - dict_unref (val_dict); - - if (ret) { - if (!(*op_errstr)) { - *op_errstr = gf_strdup ("Error, Validation Failed"); - gf_log ("glusterd", GF_LOG_DEBUG, "Error, Cannot Validate option: %s", - *op_errstr); - } - } - - gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); - return ret; -} - -static int -glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - char *path = NULL; - char hostname[2048] = {0}; - char *brick = NULL; - glusterd_volinfo_t *volinfo = NULL; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if (!exists || ret) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; - - if (strchr (brick, ':')) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - NULL); - if (ret) { - snprintf (msg, sizeof (msg), "Incorrect brick %s " - "for volume %s", brick, volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - goto out; - } - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "path not found"); - goto out; - } - - ret = gethostname (hostname, sizeof (hostname)); - if (ret) { - snprintf (msg, sizeof (msg), "Failed to get hostname, error:%s", - strerror (errno)); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - goto out; - } - - ret = glusterd_brick_create_path (hostname, path, volinfo->volume_id, - 0777, op_errstr); - if (ret) - goto out; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - char *brick = NULL; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started before" - " log rotate.", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; - - if (strchr (brick, ':')) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - NULL); - if (ret) { - snprintf (msg, sizeof (msg), "Incorrect brick %s " - "for volume %s", brick, volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - goto out; - } - } -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - int exists = 0; - char *key = NULL; - char *key_fixed = NULL; - char *value = NULL; - char str[100] = {0, }; - int count = 0; - int dict_count = 0; - char errstr[2048] = {0, }; - glusterd_volinfo_t *volinfo = NULL; - dict_t *val_dict = NULL; - gf_boolean_t global_opt = _gf_false; - glusterd_volinfo_t *voliter = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - - GF_ASSERT (dict); - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - val_dict = dict_new(); - if (!val_dict) - goto out; - - ret = dict_get_int32 (dict, "count", &dict_count); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); - goto out; - } - - if ( dict_count == 0 ) { - /*No options would be specified of volume set help */ - if (dict_get (dict, "help" )) { - ret = 0; - goto out; - } - - if (dict_get (dict, "help-xml" )) { - -#if (HAVE_LIB_XML) - ret = 0; - goto out; -#else - ret = -1; - gf_log ("", GF_LOG_ERROR, "libxml not present in the" - "system"); - *op_errstr = gf_strdup ("Error: xml libraries not " - "present to produce xml-output"); - goto out; -#endif - } - gf_log ("", GF_LOG_ERROR, "No options received "); - *op_errstr = gf_strdup ("Options not specified"); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - if (!exists) { - snprintf (errstr, sizeof (errstr), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", errstr); - *op_errstr = gf_strdup (errstr); - ret = -1; - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - for ( count = 1; ret != 1 ; count++ ) { - global_opt = _gf_false; - sprintf (str, "key%d", count); - ret = dict_get_str (dict, str, &key); - - - if (ret) - break; - - exists = glusterd_check_option_exists (key, &key_fixed); - if (exists == -1) { - ret = -1; - goto out; - } - if (!exists) { - gf_log ("", GF_LOG_ERROR, "Option with name: %s " - "does not exist", key); - ret = snprintf (errstr, 2048, - "option : %s does not exist", - key); - if (key_fixed) - snprintf (errstr + ret, 2048 - ret, - "\nDid you mean %s?", key_fixed); - *op_errstr = gf_strdup (errstr); - ret = -1; - goto out; - } - - sprintf (str, "value%d", count); - ret = dict_get_str (dict, str, &value); - - if (ret) { - gf_log ("", GF_LOG_ERROR, - "invalid key,value pair in 'volume set'"); - ret = -1; - goto out; - } - - if (key_fixed) - key = key_fixed; - - ret = glusterd_check_globaloption (key); - if (ret) - global_opt = _gf_true; - - ret = dict_set_str (val_dict, key, value); - - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set the options in 'volume set'"); - ret = -1; - goto out; - } - - *op_errstr = NULL; - if (!global_opt) - ret = glusterd_validate_reconfopts (volinfo, val_dict, op_errstr); - else { - voliter = NULL; - list_for_each_entry (voliter, &priv->volumes, vol_list) { - ret = glusterd_validate_globalopts (voliter, val_dict, op_errstr); - if (ret) - break; - } - } - - if (ret) { - gf_log ("glusterd", GF_LOG_DEBUG, "Could not create temp " - "volfile, some option failed: %s", *op_errstr); - goto out; - } - dict_del (val_dict, key); - - if (key_fixed) { - GF_FREE (key_fixed); - key_fixed = NULL; - } - } - - - ret = 0; - -out: - if (val_dict) - dict_unref (val_dict); - - if (key_fixed) - GF_FREE (key_fixed); - - if (ret) { - if (!(*op_errstr)) { - *op_errstr = gf_strdup ("Error, Validation Failed"); - gf_log ("glsuterd", GF_LOG_DEBUG, - "Error, Cannot Validate option :%s", - *op_errstr); - } else { - gf_log ("glsuterd", GF_LOG_DEBUG, - "Error, Cannot Validate option"); - } - } - return ret; -} - -static int -glusterd_op_stage_reset_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not " - "exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - - -static int -glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick) -{ - - glusterd_brickinfo_t *brickinfo = NULL; - char *dup_brick = NULL; - glusterd_conf_t *priv = NULL; - int32_t ret = -1; - - GF_ASSERT (volinfo); - GF_ASSERT (brick); - - priv = THIS->private; - - dup_brick = gf_strdup (brick); - if (!dup_brick) - goto out; - - ret = glusterd_volume_brickinfo_get_by_brick (dup_brick, volinfo, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_stop (volinfo, brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop " - "glusterfs, ret: %d", ret); - goto out; - } - } - glusterd_delete_brick (volinfo, brickinfo); -out: - if (dup_brick) - GF_FREE (dup_brick); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, - char *old_brick, char *new_brick) -{ - glusterd_brickinfo_t *old_brickinfo = NULL; - glusterd_brickinfo_t *new_brickinfo = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GF_ASSERT (volinfo); - - ret = glusterd_brickinfo_from_brick (new_brick, - &new_brickinfo); - if (ret) - goto out; - - ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, - &old_brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (new_brickinfo); - if (ret) - goto out; - - list_add_tail (&new_brickinfo->brick_list, - &old_brickinfo->brick_list); - - volinfo->brick_count++; - - ret = glusterd_op_perform_remove_brick (volinfo, old_brick); - if (ret) - goto out; - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, new_brickinfo); - if (ret) - goto out; - } - - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_perform_add_bricks (glusterd_volinfo_t *volinfo, int32_t count, - char *bricks) -{ - glusterd_brickinfo_t *brickinfo = NULL; - char *brick = NULL; - int32_t i = 1; - char *brick_list = NULL; - char *free_ptr1 = NULL; - char *free_ptr2 = NULL; - char *saveptr = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GF_ASSERT (volinfo); - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr1 = brick_list; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - while ( i <= count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - list_add_tail (&brickinfo->brick_list, &volinfo->bricks); - brick = strtok_r (NULL, " \n", &saveptr); - i++; - volinfo->brick_count++; - - } - - brick_list = gf_strdup (bricks); - free_ptr2 = brick_list; - i = 1; - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - while (i <= count) { - - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - &brickinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, brickinfo); - if (ret) - goto out; - } - i++; - brick = strtok_r (NULL, " \n", &saveptr); - } - -out: - if (free_ptr1) - GF_FREE (free_ptr1); - if (free_ptr2) - GF_FREE (free_ptr2); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - -static int -glusterd_op_stage_remove_brick (dict_t *dict) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - dict_t *ctx = NULL; - char *errstr = NULL; - int32_t brick_count = 0; - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume %s does not exist", volname); - goto out; - } - - if (glusterd_is_defrag_on(volinfo)) { - ctx = glusterd_op_get_ctx (); - errstr = gf_strdup("Rebalance is in progress. Please retry" - " after completion"); - if (!errstr) { - ret = -1; - goto out; - } - gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); - ret = dict_set_dynstr (ctx, "errstr", errstr); - if (ret) { - GF_FREE (errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set errstr ctx"); - goto out; - } - - ret = -1; - goto out; - } - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); - goto out; - } - - if (volinfo->brick_count == brick_count) { - ctx = glusterd_op_get_ctx (); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, - "Operation Context is not present"); - ret = -1; - goto out; - } - errstr = gf_strdup ("Deleting all the bricks of the " - "volume is not allowed"); - if (!errstr) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - ret = -1; - goto out; - } - - ret = dict_set_dynstr (ctx, "errstr", errstr); - if (ret) { - GF_FREE (errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); - goto out; - } - - ret = -1; - goto out; - } - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - char *hostname = NULL; - gf_boolean_t exists = _gf_false; - glusterd_peerinfo_t *peerinfo = NULL; - char msg[2048] = {0,}; - - ret = dict_get_str (dict, "hostname", &hostname); - if (ret) { - snprintf (msg, sizeof (msg), "hostname couldn't be " - "retrieved from msg"); - *op_errstr = gf_strdup (msg); - goto out; - } - - ret = glusterd_is_local_addr (hostname); - if (ret) { - ret = glusterd_friend_find (NULL, hostname, &peerinfo); - if (ret) { - snprintf (msg, sizeof (msg), "%s, is not a friend", - hostname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!peerinfo->connected) { - snprintf (msg, sizeof (msg), "%s, is not connected at " - "the moment", hostname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } else { - - //volname is not present in case of sync all - ret = dict_get_str (dict, "volname", &volname); - if (!ret) { - exists = glusterd_check_volume_exists (volname); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s " - "does not exist", volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } else { - ret = 0; - } - } - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - gf_boolean_t exists = _gf_false; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char msg[2048] = {0,}; - - GF_ASSERT (dict); - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT(priv); - - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - if (!exists) { - snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - - *op_errstr = gf_strdup(msg); - ret = -1; - goto out; - } - - ret = 0; - - out: - if (ret && !(*op_errstr)) - *op_errstr = gf_strdup ("Validation Failed for Status"); - - gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); - return ret; -} - -/***** - * - * glusterd_urltransform* internal API - * - *****/ - -static void -glusterd_urltransform_init (runner_t *runner, const char *transname) -{ - runinit (runner); - runner_add_arg (runner, GSYNCD_PREFIX"/gsyncd"); - runner_argprintf (runner, "--%s-url", transname); -} - -static void -glusterd_urltransform_add (runner_t *runner, const char *url) -{ - runner_add_arg (runner, url); -} - -static void -_glusterd_urltransform_add_iter (dict_t *dict, char *key, data_t *value, void *data) -{ - runner_t *runner = (runner_t *)data; - char *slave = NULL; - - slave = strchr (value->data, ':'); - GF_ASSERT (slave); - slave++; - runner_add_arg (runner, slave); -} - -static void -glusterd_urltransform_free (char **linearr, unsigned n) -{ - int i = 0; - - for (; i < n; i++) - GF_FREE (linearr[i]); - - GF_FREE (linearr); -} - -static int -glusterd_urltransform (runner_t *runner, char ***linearrp) -{ - char **linearr = NULL; - char *line = NULL; - unsigned arr_len = 32; - unsigned arr_idx = 0; - gf_boolean_t error = _gf_false; - - linearr = GF_CALLOC (arr_len, sizeof (char *), gf_gld_mt_linearr); - if (!linearr) { - error = _gf_true; - goto out; - } - - runner_redir (runner, STDOUT_FILENO, RUN_PIPE); - if (runner_start (runner) != 0) { - gf_log ("", GF_LOG_ERROR, "spawning child failed"); - - error = _gf_true; - goto out; - } - - arr_idx = 0; - for (;;) { - line = GF_MALLOC (1024, gf_gld_mt_linebuf); - if (!line) { - error = _gf_true; - goto out; - } - - if (fgets (line, 1024, runner_chio (runner, STDOUT_FILENO)) == - NULL) - break; - - if (line[strlen (line) - 1] != '\n') { - GF_FREE (line); - error = _gf_true; - goto out; - } - line[strlen (line) - 1] = '\0'; - - if (arr_idx == arr_len) { - arr_len <<= 1; - linearr = GF_REALLOC (linearr, arr_len); - if (!linearr) { - GF_FREE (line); - error = _gf_true; - goto out; - } - } - linearr[arr_idx] = line; - - arr_idx++; - } - - out: - - /* XXX chpid field is not exported by run API - * but runner_end() does not abort the invoked - * process (ie. it might block in waitpid(2)) - * so we resort to a manual kill a the private field - */ - if (error && runner->chpid > 0) - kill (runner->chpid, SIGKILL); - - if (runner_end (runner) != 0) - error = _gf_true; - - if (error) { - gf_log ("", GF_LOG_ERROR, "reading data from child failed"); - glusterd_urltransform_free (linearr, arr_idx); - return -1; - } - - *linearrp = linearr; - return arr_idx; -} - -static int -glusterd_urltransform_single (const char *url, const char *transname, - char ***linearrp) -{ - runner_t runner = {0,}; - - glusterd_urltransform_init (&runner, transname); - glusterd_urltransform_add (&runner, url); - return glusterd_urltransform (&runner, linearrp); -} - - -struct dictidxmark { - unsigned isrch; - unsigned ithis; - char *ikey; -}; - -static void -_dict_mark_atindex (dict_t *dict, char *key, data_t *value, void *data) -{ - struct dictidxmark *dim = data; - - if (dim->isrch == dim->ithis) - dim->ikey = key; - - dim->ithis++; -} - -static char * -dict_get_by_index (dict_t *dict, unsigned i) -{ - struct dictidxmark dim = {0,}; - - dim.isrch = i; - dict_foreach (dict, _dict_mark_atindex, &dim); - - return dim.ikey; -} - -static int -glusterd_get_slave (glusterd_volinfo_t *vol, const char *slaveurl, char **slavekey) -{ - runner_t runner = {0,}; - int n = 0; - int i = 0; - char **linearr = NULL; - - glusterd_urltransform_init (&runner, "canonicalize"); - dict_foreach (vol->gsync_slaves, _glusterd_urltransform_add_iter, &runner); - glusterd_urltransform_add (&runner, slaveurl); - - n = glusterd_urltransform (&runner, &linearr); - if (n == -1) - return -2; - - for (i = 0; i < n - 1; i++) { - if (strcmp (linearr[i], linearr[n - 1]) == 0) - break; - } - glusterd_urltransform_free (linearr, i); - - if (i < n - 1) - *slavekey = dict_get_by_index (vol->gsync_slaves, i); - else - i = -1; - - return i; -} - - -static int -glusterd_query_extutil (char *resbuf, runner_t *runner) -{ - char *ptr = NULL; - int ret = 0; - - runner_redir (runner, STDOUT_FILENO, RUN_PIPE); - if (runner_start (runner) != 0) { - gf_log ("", GF_LOG_ERROR, "spawning child failed"); - - return -1; - } - - ptr = fgets(resbuf, PATH_MAX, runner_chio (runner, STDOUT_FILENO)); - if (ptr) - resbuf[strlen(resbuf)-1] = '\0'; //strip off \n - - ret = runner_end (runner); - if (ret) - gf_log ("", GF_LOG_ERROR, "reading data from child failed"); - - return ret ? -1 : 0; -} - -int -glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, - char *slave, char *gl_workdir) -{ - runner_t runner = {0,}; - - runinit (&runner); - runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); - runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); - runner_argprintf (&runner, ":%s", master); - runner_add_args (&runner, slave, "--config-get", NULL); - runner_argprintf (&runner, "%s-file", param); - - return glusterd_query_extutil (prmfile, &runner); -} - -static int -gsyncd_getpidfile (char *master, char *slave, char *pidfile) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - GF_VALIDATE_OR_GOTO ("gsync", master, out); - GF_VALIDATE_OR_GOTO ("gsync", slave, out); - - ret = glusterd_gsync_get_param_file (pidfile, "pid", master, - slave, priv->workdir); - if (ret == -1) { - ret = -2; - gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); - goto out; - } - - ret = open (pidfile, O_RDWR); - - out: - return ret; -} - -static int -gsync_status_byfd (int fd) -{ - GF_ASSERT (fd >= -1); - - if (lockf (fd, F_TEST, 0) == -1 && - (errno == EAGAIN || errno == EACCES)) - /* gsyncd keeps the pidfile locked */ - return 0; - - return -1; -} - -/* status: return 0 when gsync is running - * return -1 when not running - */ -int -gsync_status (char *master, char *slave, int *status) -{ - char pidfile[PATH_MAX] = {0,}; - int fd = -1; - - fd = gsyncd_getpidfile (master, slave, pidfile); - if (fd == -2) - return -1; - - *status = gsync_status_byfd (fd); - - close (fd); - return 0; -} - - -int32_t -glusterd_gsync_volinfo_dict_set (glusterd_volinfo_t *volinfo, - char *key, char *value) -{ - int32_t ret = -1; - char *gsync_status = NULL; - - gsync_status = gf_strdup (value); - if (!gsync_status) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, key, gsync_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set dict"); - goto out; - } - - ret = 0; -out: - return 0; -} - -int -gsync_verify_config_options (dict_t *dict, char **op_errstr) -{ - char **resopt = NULL; - int i = 0; - char *subop = NULL; - char *slave = NULL; - char *op_name = NULL; - char *op_value = NULL; - gf_boolean_t banned = _gf_true; - - if (dict_get_str (dict, "subop", &subop) != 0) { - gf_log ("", GF_LOG_WARNING, "missing subop"); - *op_errstr = gf_strdup ("Invalid config request"); - return -1; - } - - if (dict_get_str (dict, "slave", &slave) != 0) { - gf_log ("", GF_LOG_WARNING, GEOREP" CONFIG: no slave given"); - *op_errstr = gf_strdup ("Slave required"); - return -1; - } - - if (strcmp (subop, "get-all") == 0) - return 0; - - if (dict_get_str (dict, "op_name", &op_name) != 0) { - gf_log ("", GF_LOG_WARNING, "option name missing"); - *op_errstr = gf_strdup ("Option name missing"); - return -1; - } - - if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { - gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name); - *op_errstr = gf_strdup ("Invalid option"); - - return -1; - } - - if (strcmp (subop, "get") == 0) - return 0; - - if (strcmp (subop, "set") != 0 && strcmp (subop, "del") != 0) { - gf_log ("", GF_LOG_WARNING, "unknown subop %s", subop); - *op_errstr = gf_strdup ("Invalid config request"); - return -1; - } - - if (strcmp (subop, "set") == 0 && - dict_get_str (dict, "op_value", &op_value) != 0) { - gf_log ("", GF_LOG_WARNING, "missing value for set"); - *op_errstr = gf_strdup ("missing value"); - } - - /* match option name against reserved options, modulo -/_ - * difference - */ - for (resopt = gsync_reserved_opts; *resopt; resopt++) { - banned = _gf_true; - for (i = 0; (*resopt)[i] && op_name[i]; i++) { - if ((*resopt)[i] == op_name[i] || - ((*resopt)[i] == '-' && op_name[i] == '_')) - continue; - banned = _gf_false; - } - if (banned) { - gf_log ("", GF_LOG_WARNING, "Reserved option %s", op_name); - *op_errstr = gf_strdup ("Reserved option"); - - return -1; - break; - } - } - - return 0; -} - -static void -_get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data) -{ - glusterd_gsync_status_temp_t *param = NULL; - char *slave = NULL; - int ret = 0; - - param = (glusterd_gsync_status_temp_t *)data; - - GF_ASSERT (param); - GF_ASSERT (param->volinfo); - - slave = strchr(value->data, ':'); - if (slave) - slave ++; - else - return; - - ret = glusterd_get_gsync_status_mst_slv(param->volinfo, - slave, param->rsp_dict); - -} - -static void -_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) -{ - int tmp_slvnum = 0; - int *slvnum = (int *)data; - - sscanf (key, "slave%d", &tmp_slvnum); - if (tmp_slvnum > *slvnum) - *slvnum = tmp_slvnum; -} - -static int -glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, - char **op_errstr) -{ - int ret = 0; - char *slavekey = NULL; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - - ret = glusterd_get_slave (volinfo, slave, &slavekey); - if (ret < 0) { - ret++; - goto out; - } - - dict_del (volinfo->gsync_slaves, slavekey); - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - *op_errstr = gf_strdup ("Failed to store the Volume" - "information"); - goto out; - } - out: - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; - -} - -static int -glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol, - uuid_t uuid) -{ - int ret = 0; - char *slavekey = NULL; - char *slaveentry = NULL; - char *t = NULL; - - GF_ASSERT (vol); - GF_ASSERT (slave); - - ret = glusterd_get_slave (vol, slave, &slavekey); - if (ret < 0) { - /* XXX colliding cases of failure and non-extant - * slave... now just doing this as callers of this - * function can make sense only of -1 and 0 as retvals; - * getting at the proper semanticals will involve - * fixing callers as well. - */ - ret = -1; - goto out; - } - - ret = dict_get_str (vol->gsync_slaves, slavekey, &slaveentry); - GF_ASSERT (ret == 0); - - t = strchr (slaveentry, ':'); - GF_ASSERT (t); - *t = '\0'; - ret = uuid_parse (slaveentry, uuid); - *t = ':'; - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_check_gsync_running_local (char *master, char *slave, - gf_boolean_t *is_run) -{ - int ret = -1; - int ret_status = 0; - - GF_ASSERT (master); - GF_ASSERT (slave); - GF_ASSERT (is_run); - - *is_run = _gf_false; - ret = gsync_status (master, slave, &ret_status); - if (ret == 0 && ret_status == 0) { - *is_run = _gf_true; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, GEOREP" validation " - " failed"); - goto out; - } - ret = 0; - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; - -} - -static int -glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, - char *host_uuid, char **op_errstr) -{ - int ret = 0; - int maxslv = 0; - char **linearr = NULL; - char *value = NULL; - char *slavekey = NULL; - char *slaveentry = NULL; - char key[512] = {0, }; - char *t = NULL; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (host_uuid); - - ret = glusterd_get_slave (volinfo, slave, &slavekey); - switch (ret) { - case -2: - ret = -1; - goto out; - case -1: - break; - default: - GF_ASSERT (ret > 0); - ret = dict_get_str (volinfo->gsync_slaves, slavekey, &slaveentry); - GF_ASSERT (ret == 0); - - /* same-name + same-uuid slave entries should have been filtered - * out in glusterd_op_verify_gsync_start_options(), so we can - * assert an uuid mismatch - */ - t = strtail (slaveentry, host_uuid); - GF_ASSERT (!t || *t != ':') - - gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for " - "the %s (master) and %s (slave) " - "from a different machine", - volinfo->volname, slave); - *op_errstr = gf_strdup (GEOREP" already running on an " - "another machine"); - ret = -1; - goto out; - } - - ret = glusterd_urltransform_single (slave, "normalize", &linearr); - if (ret == -1) - goto out; - ret = gf_asprintf (&value, "%s:%s", host_uuid, linearr[0]); - glusterd_urltransform_free (linearr, 1); - if (ret == -1) - goto out; - - dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &maxslv); - snprintf (key, 512, "slave%d", maxslv + 1); - ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); - if (ret) - goto out; - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - *op_errstr = gf_strdup ("Failed to store the Volume " - "information"); - goto out; - } - ret = 0; - out: - return ret; -} - - -static int -glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, - char *slave, char **op_errstr) -{ - int ret = -1; - gf_boolean_t is_running = _gf_false; - char msg[2048] = {0}; - uuid_t uuid = {0}; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - - this = THIS; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - GF_ASSERT (this && this->private); - - priv = this->private; - - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started " - "before "GEOREP" start", volinfo->volname); - goto out; - } - /*Check if the gsync is already started in cmd. inited host - * If so initiate add it into the glusterd's priv*/ - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { - ret = glusterd_check_gsync_running_local (volinfo->volname, - slave, &is_running); - if (ret) { - snprintf (msg, sizeof (msg), GEOREP" start option " - "validation failed "); - goto out; - } - if (_gf_true == is_running) { - snprintf (msg, sizeof (msg), GEOREP " session between" - " %s & %s already started", volinfo->volname, - slave); - ret = -1; - goto out; - } - } - ret = 0; -out: - if (ret && (msg[0] != '\0')) { - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int -glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) -{ - - GF_ASSERT (volinfo); - GF_ASSERT (flag); - - if (volinfo->gsync_slaves->count) - *flag = _gf_true; - else - *flag = _gf_false; - - return 0; -} - -static int -glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, - char *slave, char **op_errstr) -{ - int ret = -1; - char msg[2048] = {0}; - uuid_t uuid = {0}; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS && THIS->private); - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started " - "before "GEOREP" start", volinfo->volname); - - goto out; - } - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if (ret == -1) { - snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" - " not active", volinfo->volname, slave); - goto out; - } - - ret = 0; -out: - if (ret && (msg[0] != '\0')) { - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) -{ - char *slave = NULL; - char *volname = NULL; - char errmsg[PATH_MAX] = {0, }; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - int ret = 0; - - ret = dict_get_str (dict, "master", &volname); - if (ret < 0) { - ret = 0; - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - ret = 0; - goto out; - } - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; - -} - - -static int -glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, - char **master, char **slave) -{ - - int ret = -1; - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (master); - GF_ASSERT (slave); - - ret = dict_get_str (dict, "master", master); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "master not found"); - *op_errstr = gf_strdup ("master not found"); - goto out; - } - - ret = dict_get_str (dict, "slave", slave); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "slave not found"); - *op_errstr = gf_strdup ("slave not found"); - goto out; - } - - - ret = 0; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) -{ - int ret = 0; - int type = 0; - char *volname = NULL; - char *slave = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char errmsg[PATH_MAX] = {0,}; - - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "command type not found"); - *op_errstr = gf_strdup ("command unsuccessful"); - goto out; - } - - switch (type) { - case GF_GSYNC_OPTION_TYPE_STATUS: - ret = glusterd_verify_gsync_status_opts (dict, op_errstr); - - goto out; - case GF_GSYNC_OPTION_TYPE_CONFIG: - ret = gsync_verify_config_options (dict, op_errstr); - - goto out; - } - - ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); - if (ret) - goto out; - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } - - switch (type) { - case GF_GSYNC_OPTION_TYPE_START: - ret = glusterd_op_verify_gsync_start_options (volinfo, slave, - op_errstr); - break; - case GF_GSYNC_OPTION_TYPE_STOP: - ret = glusterd_op_verify_gsync_running (volinfo, slave, - op_errstr); - break; - } - -out: - return ret; -} - -static gf_boolean_t -glusterd_is_profile_on (glusterd_volinfo_t *volinfo) -{ - int ret = -1; - gf_boolean_t is_latency_on = _gf_false; - gf_boolean_t is_fd_stats_on = _gf_false; - - GF_ASSERT (volinfo); - - ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_CNT_FOP_HITS); - if (ret != -1) - is_fd_stats_on = ret; - ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_LAT_MEASUREMENT); - if (ret != -1) - is_latency_on = ret; - if ((_gf_true == is_latency_on) && - (_gf_true == is_fd_stats_on)) - return _gf_true; - return _gf_false; -} - -static int -glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0,}; - int32_t stats_op = GF_CLI_STATS_NONE; - glusterd_volinfo_t *volinfo = NULL; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - snprintf (msg, sizeof (msg), "Volume name get failed"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((!exists) || (ret < 0)) { - snprintf (msg, sizeof (msg), "Volume %s, " - "doesn't exist", volname); - ret = -1; - goto out; - } - - ret = dict_get_int32 (dict, "op", &stats_op); - if (ret) { - snprintf (msg, sizeof (msg), "Volume profile op get failed"); - goto out; - } - - if (GF_CLI_STATS_START == stats_op) { - if (_gf_true == glusterd_is_profile_on (volinfo)) { - snprintf (msg, sizeof (msg), "Profile on Volume %s is" - " already started", volinfo->volname); - ret = -1; - goto out; - } - } - if ((GF_CLI_STATS_STOP == stats_op) || - (GF_CLI_STATS_INFO == stats_op)) { - if (_gf_false == glusterd_is_profile_on (volinfo)) { - snprintf (msg, sizeof (msg), "Profile on Volume %s is" - " not started", volinfo->volname); - ret = -1; - goto out; - } - } - if ((GF_CLI_STATS_TOP == stats_op) || - (GF_CLI_STATS_INFO == stats_op)) { - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s is not started.", - volinfo->volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - ret = -1; - goto out; - } - } - ret = 0; -out: - if (msg[0] != '\0') { - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_create_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - gf_boolean_t vol_added = _gf_false; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *brick = NULL; - int32_t count = 0; - int32_t i = 1; - char *bricks = NULL; - char *brick_list = NULL; - char *free_ptr = NULL; - char *saveptr = NULL; - int32_t sub_count = 0; - char *trans_type = NULL; - char *str = NULL; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = glusterd_volinfo_new (&volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); - GF_ASSERT (volinfo->volname); - - ret = dict_get_int32 (dict, "type", &volinfo->type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get type"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &volinfo->brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - ret = dict_get_int32 (dict, "port", &volinfo->port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get port"); - goto out; - } - - count = volinfo->brick_count; - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { - ret = dict_get_int32 (dict, "replica-count", - &sub_count); - if (ret) - goto out; - } else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) { - ret = dict_get_int32 (dict, "stripe-count", - &sub_count); - if (ret) - goto out; - } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { - ret = dict_get_int32 (dict, "stripe-count", - &volinfo->stripe_count); - if (ret) - goto out; - ret = dict_get_int32 (dict, "replica-count", - &volinfo->replica_count); - if (ret) - goto out; - - sub_count = volinfo->stripe_count * volinfo->replica_count; - } - - ret = dict_get_str (dict, "transport", &trans_type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get transport"); - goto out; - } - - ret = dict_get_str (dict, "volume-id", &str); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume-id"); - goto out; - } - ret = uuid_parse (str, volinfo->volume_id); - if (ret) { - gf_log ("", GF_LOG_ERROR, "unable to parse uuid %s", str); - goto out; - } - - if (strcasecmp (trans_type, "rdma") == 0) { - volinfo->transport_type = GF_TRANSPORT_RDMA; - volinfo->nfs_transport_type = GF_TRANSPORT_RDMA; - } else if (strcasecmp (trans_type, "tcp") == 0) { - volinfo->transport_type = GF_TRANSPORT_TCP; - volinfo->nfs_transport_type = GF_TRANSPORT_TCP; - } else { - volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; - volinfo->nfs_transport_type = GF_DEFAULT_NFS_TRANSPORT; - } - - volinfo->sub_count = sub_count; - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr = brick_list; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - while ( i <= count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - list_add_tail (&brickinfo->brick_list, &volinfo->bricks); - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - glusterd_store_delete_volume (volinfo); - *op_errstr = gf_strdup ("Failed to store the Volume information"); - goto out; - } - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - *op_errstr = gf_strdup ("Failed to create volume files"); - goto out; - } - - ret = glusterd_volume_compute_cksum (volinfo); - if (ret) { - *op_errstr = gf_strdup ("Failed to compute checksum of volume"); - goto out; - } - - volinfo->defrag_status = 0; - list_add_tail (&volinfo->vol_list, &priv->volumes); - vol_added = _gf_true; -out: - if (free_ptr) - GF_FREE(free_ptr); - if (!vol_added && volinfo) - glusterd_volinfo_delete (volinfo); - return ret; -} - -static int -glusterd_op_add_brick (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - xlator_t *this = NULL; - char *bricks = NULL; - int32_t count = 0; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); - goto out; - } - - volinfo->defrag_status = 0; - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - -out: - return ret; -} - -static int -rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo, - int32_t pump_needed) -{ - dict_t *dict = NULL; - int ret = 0; - - dict = volinfo->dict; - - gf_log ("", GF_LOG_DEBUG, - "attempting to set pump value=%d", pump_needed); - - ret = dict_set_int32 (dict, "enable-pump", pump_needed); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "could not dict_set enable-pump"); - goto out; - } - - ret = glusterd_create_rb_volfiles (volinfo, brickinfo); - -out: - return ret; -} - -static int -rb_src_brick_restart (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - int activate_pump) -{ - int ret = 0; - - gf_log ("", GF_LOG_DEBUG, - "Attempting to kill src"); - - ret = glusterd_nfs_server_stop (); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop nfs, ret: %d", - ret); - } - - ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop " - "glusterfs, ret: %d", ret); - goto out; - } - - glusterd_delete_volfile (volinfo, src_brickinfo); - - if (activate_pump) { - ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 1); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not regenerate volfiles with pump"); - goto out; - } - } else { - ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not regenerate volfiles without pump"); - goto out; - } - - } - - sleep (2); - ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to start " - "glusterfs, ret: %d", ret); - goto out; - } - -out: - ret = glusterd_nfs_server_start (); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to start nfs, ret: %d", - ret); - } - return ret; -} - -static int -rb_send_xattr_command (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo, - const char *xattr_key, - const char *value) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Could not send " - " %s command", xattr_key); - goto out; - } - - ret = sys_lsetxattr (mount_point_path, xattr_key, - value, - strlen (value) + 1, - 0); - - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "setxattr failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo) -{ - glusterd_conf_t *priv = NULL; - runner_t runner = {0,}; - int ret = -1; - int32_t port = 0; - - priv = THIS->private; - - port = pmap_registry_alloc (THIS); - brickinfo->port = port; - - GF_ASSERT (port); - - runinit (&runner); - runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); - runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_DSTBRICKVOL_FILENAME, - priv->workdir, volinfo->volname); - runner_argprintf (&runner, "-p" "%s/vols/%s/"RB_DSTBRICK_PIDFILE, - priv->workdir, volinfo->volname); - runner_add_arg (&runner, "--xlator-option"); - runner_argprintf (&runner, "src-server.listen-port=%d", port); - - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_glusterfs_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo) -{ - glusterd_conf_t *priv = NULL; - char cmd_str[8192] = {0,}; - runner_t runner = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - runinit (&runner); - runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); - runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_CLIENTVOL_FILENAME, - priv->workdir, volinfo->volname); - runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, - priv->workdir, volinfo->volname); - - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); - - memset (cmd_str, 0, sizeof (cmd_str)); - - snprintf (cmd_str, 4096, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (cmd_str, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint failed"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint succeeded"); - - ret = 0; - -out: - return ret; -} - -static const char *client_volfile_str = "volume mnt-client\n" - " type protocol/client\n" - " option remote-host %s\n" - " option remote-subvolume %s\n" - " option remote-port %d\n" - " option transport-type %s\n" - "end-volume\n" - "volume mnt-wb\n" - " type performance/write-behind\n" - " subvolumes mnt-client\n" - "end-volume\n"; - -static int -rb_generate_client_volfile (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - FILE *file = NULL; - char filename[PATH_MAX] = {0, }; - int ret = -1; - char *ttype = NULL; - - priv = THIS->private; - - gf_log ("", GF_LOG_DEBUG, - "Creating volfile"); - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME); - - file = fopen (filename, "w+"); - if (!file) { - gf_log ("", GF_LOG_DEBUG, - "Open of volfile failed"); - ret = -1; - goto out; - } - - GF_ASSERT (src_brickinfo->port); - - ttype = glusterd_get_trans_type_rb (volinfo->transport_type); - if (NULL == ttype){ - ret = -1; - goto out; - } - - fprintf (file, client_volfile_str, src_brickinfo->hostname, - src_brickinfo->path, src_brickinfo->port, ttype); - - fclose (file); - GF_FREE (ttype); - - ret = 0; - -out: - return ret; -} - -static const char *dst_brick_volfile_str = "volume src-posix\n" - " type storage/posix\n" - " option directory %s\n" - "end-volume\n" - "volume %s\n" - " type features/locks\n" - " subvolumes src-posix\n" - "end-volume\n" - "volume src-server\n" - " type protocol/server\n" - " option auth.addr.%s.allow *\n" - " option transport-type %s\n" - " subvolumes %s\n" - "end-volume\n"; - -static int -rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - glusterd_conf_t *priv = NULL; - FILE *file = NULL; - char filename[PATH_MAX] = {0, }; - int ret = -1; - char *trans_type = NULL; - - priv = THIS->private; - - gf_log ("", GF_LOG_DEBUG, - "Creating volfile"); - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_DSTBRICKVOL_FILENAME); - - file = fopen (filename, "w+"); - if (!file) { - gf_log ("", GF_LOG_DEBUG, - "Open of volfile failed"); - ret = -1; - goto out; - } - - trans_type = glusterd_get_trans_type_rb (volinfo->transport_type); - if (NULL == trans_type){ - ret = -1; - goto out; - } - - fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, - dst_brickinfo->path, dst_brickinfo->path, - trans_type, dst_brickinfo->path); - - GF_FREE (trans_type); - - fclose (file); - - ret = 0; - -out: - return ret; -} - - -static int -rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = mkdir (mount_point_path, 0777); - if (ret && (errno != EEXIST)) { - gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", - errno); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_mountpoint_rmdir (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = rmdir (mount_point_path); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "rmdir failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - runner_t runner = {0,}; - char filename[PATH_MAX] = {0,}; - struct stat buf; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Cannot destroy maintenance " - "client"); - goto out; - } - - runinit (&runner); - runner_add_args (&runner, "/bin/umount", "-f", NULL); - runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, - priv->workdir, volinfo->volname); - - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "umount failed on maintenance client"); - goto out; - } - - ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "rmdir of mountpoint failed"); - goto out; - } - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME); - - ret = unlink (filename); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "unlink failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - int ret = -1; - - ret = rb_generate_client_volfile (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to generate client " - "volfile"); - goto out; - } - - ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " - "mountpoint"); - goto out; - } - - ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); - goto out; - } - - ret = 0; -out: - return ret; -} - -static int -rb_spawn_destination_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) - -{ - int ret = -1; - - ret = rb_generate_dst_brick_volfile (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to generate client " - "volfile"); - goto out; - } - - ret = rb_spawn_dst_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); - goto out; - } - - ret = 0; -out: - return ret; -} - -static int -rb_do_operation_start (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char start_value[8192] = {0,}; - int ret = -1; - - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending start xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - snprintf (start_value, 8192, "%s:%s:%d", - dst_brickinfo->hostname, - dst_brickinfo->path, - dst_brickinfo->port); - - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_START_CMD, - start_value); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - ret = 0; - -out: - return ret; -} - -static int -rb_do_operation_pause (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_INFO, - "replace-brick send pause xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_PAUSE_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -out: - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - } - } - return ret; -} - -static int -rb_kill_destination_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX] = {0,}; - - priv = THIS->private; - - snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_DSTBRICK_PIDFILE); - - return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); -} - -static int -rb_do_operation_commit (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - int cmd_ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending commit xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - cmd_ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_COMMIT_CMD, - "jargon"); - if (cmd_ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -out: - return cmd_ret || ret; -} - -static int -rb_do_operation_abort (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending abort xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_ABORT_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -out: - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - } - } - return ret; -} - - -static int -rb_get_xattr_command (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo, - const char *xattr_key, - char *value) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Could not send " - " %s command", xattr_key); - goto out; - } - - ret = sys_lgetxattr (mount_point_path, xattr_key, value, 8192); - - if (ret < 0) { - gf_log ("", GF_LOG_DEBUG, - "getxattr failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_do_operation_status (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char status[8192] = {0,}; - char *status_reply = NULL; - dict_t *ctx = NULL; - int ret = 0; - gf_boolean_t origin = _gf_false; - - ctx = glusterd_op_get_ctx (); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, - "Operation Context is not present"); - goto out; - } - - origin = _gf_true; - - if (origin) { - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_get_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_STATUS_CMD, - status); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to get status from pump"); - goto umount; - } - - gf_log ("", GF_LOG_DEBUG, - "pump status is %s", status); - - status_reply = gf_strdup (status); - if (!status_reply) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - ret = -1; - goto umount; - } - - ret = dict_set_dynstr (ctx, "status-reply", - status_reply); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); - - } - - umount: - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); -out: - return ret; -} - -/* Set src-brick's port number to be used in the maintainance mount - * after all commit acks are received. - */ -static int -rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, - dict_t *req_dict, int32_t replace_op) -{ - xlator_t *this = NULL; - dict_t *ctx = NULL; - int ret = 0; - int dict_ret = 0; - int src_port = 0; - - this = THIS; - - ctx = glusterd_op_get_ctx (); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); - if (src_port) - src_brickinfo->port = src_port; - } - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - gf_log ("", GF_LOG_INFO, - "adding src-brick port no"); - - src_brickinfo->port = pmap_registry_search (this, - src_brickinfo->path, GF_PMAP_PORT_BRICKSERVER); - if (!src_brickinfo->port && - replace_op != GF_REPLACE_OP_COMMIT_FORCE ) { - gf_log ("", GF_LOG_ERROR, - "Src brick port not available"); - ret = -1; - goto out; - } - - if (rsp_dict) { - ret = dict_set_int32 (rsp_dict, "src-brick-port", src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick port no"); - goto out; - } - } - - ctx = glusterd_op_get_ctx (); - if (ctx) { - ret = dict_set_int32 (ctx, "src-brick-port", src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick port no"); - goto out; - } - } - - } - -out: - return ret; - -} - -static int -rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, - dict_t *req_dict, int32_t replace_op) -{ - dict_t *ctx = NULL; - int ret = 0; - int dict_ret = 0; - int dst_port = 0; - - ctx = glusterd_op_get_ctx (); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); - if (dst_port) - dst_brickinfo->port = dst_port; - - } - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_INFO, - "adding dst-brick port no"); - - if (rsp_dict) { - ret = dict_set_int32 (rsp_dict, "dst-brick-port", - dst_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set dst-brick port no in rsp dict"); - goto out; - } - } - - ctx = glusterd_op_get_ctx (); - if (ctx) { - ret = dict_set_int32 (ctx, "dst-brick-port", - dst_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set dst-brick port no"); - goto out; - } - } - } -out: - return ret; -} - - - -static int -glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) -{ - int ret = 0; - dict_t *ctx = NULL; - int replace_op = 0; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char *src_brick = NULL; - char *dst_brick = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "src-brick", &src_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, - "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); - goto out; - } - - - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get " - "replace brick destination brickinfo"); - goto out; - } - - ret = glusterd_resolve_brick (dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); - goto out; - } - - ret = rb_update_srcbrick_port (src_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - - if ((GF_REPLACE_OP_START != replace_op)) { - ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - } - - switch (replace_op) { - case GF_REPLACE_OP_START: - { - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_INFO, - "I AM THE DESTINATION HOST"); - if (!glusterd_is_rb_paused (volinfo)) { - ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to spawn destination brick"); - goto out; - } - } else { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "started=> no need to restart dst brick "); - } - } - - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 1); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - goto out; - } - } - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_INFO, - "adding dst-brick port no"); - - ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - } - - glusterd_set_rb_status (volinfo, GF_RB_STATUS_STARTED); - break; - } - - case GF_REPLACE_OP_COMMIT: - case GF_REPLACE_OP_COMMIT_FORCE: - { - ctx = glusterd_op_get_ctx (); - if (ctx) { - ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Commit operation failed"); - goto out; - } - } - - ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); - gf_log ("", GF_LOG_DEBUG, - "Received commit - will be adding dst brick and " - "removing src brick"); - - if (!glusterd_is_local_addr (dst_brickinfo->hostname) && - replace_op != GF_REPLACE_OP_COMMIT_FORCE) { - gf_log ("", GF_LOG_INFO, - "I AM THE DESTINATION HOST"); - ret = rb_kill_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to kill destination brick"); - goto out; - } - } - - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "Unable to cleanup dst brick"); - goto out; - } - - - ret = glusterd_nfs_server_stop (); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to stop nfs server, ret: %d", ret); - } - - ret = glusterd_op_perform_replace_brick (volinfo, src_brick, - dst_brick); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, "Unable to add " - "dst-brick: %s to volume: %s", - dst_brick, volinfo->volname); - (void) glusterd_check_generate_start_nfs (); - goto out; - } - - volinfo->defrag_status = 0; - - ret = glusterd_check_generate_start_nfs (); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "Failed to generate nfs volume file"); - } - - - ret = glusterd_fetchspec_notify (THIS); - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - glusterd_brickinfo_delete (volinfo->dst_brick); - volinfo->src_brick = volinfo->dst_brick = NULL; - } - break; - - case GF_REPLACE_OP_PAUSE: - { - gf_log ("", GF_LOG_DEBUG, - "Received pause - doing nothing"); - ctx = glusterd_op_get_ctx (); - if (ctx) { - ret = rb_do_operation_pause (volinfo, src_brickinfo, - dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Pause operation failed"); - goto out; - } - } - - glusterd_set_rb_status (volinfo, GF_RB_STATUS_PAUSED); - } - break; - - case GF_REPLACE_OP_ABORT: - { - - ctx = glusterd_op_get_ctx (); - if (ctx) { - ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, - "Abort operation failed"); - goto out; - } - } - - ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); - if (ret) { - gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to disable pump"); - } - - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log (THIS->name, GF_LOG_INFO, - "I AM THE DESTINATION HOST"); - ret = rb_kill_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to kill destination brick"); - goto out; - } - } - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - glusterd_brickinfo_delete (volinfo->dst_brick); - volinfo->src_brick = volinfo->dst_brick = NULL; - } - break; - - case GF_REPLACE_OP_STATUS: - { - gf_log ("", GF_LOG_DEBUG, - "received status - doing nothing"); - ctx = glusterd_op_get_ctx (); - if (ctx) { - if (glusterd_is_rb_paused (volinfo)) { - ret = dict_set_str (ctx, "status-reply", - "replace brick has been paused"); - if (ret) - gf_log (THIS->name, GF_LOG_ERROR, - "failed to set pump status" - "in ctx"); - goto out; - } - - ret = rb_do_operation_status (volinfo, src_brickinfo, - dst_brickinfo); - if (ret) - goto out; - } - - } - break; - - default: - ret = -1; - goto out; - } - if (!ret && replace_op != GF_REPLACE_OP_STATUS) - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - gf_log (THIS->name, GF_LOG_ERROR, "Couldn't store" - " replace brick operation's state"); - -out: - return ret; -} - -void -_delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) -{ - int exists = 0; - int32_t is_force = 0; - - GF_ASSERT (data); - is_force = *((int32_t*)data); - exists = glusterd_check_option_exists(key, NULL); - - if (exists != 1) - goto out; - - if ((!is_force) && - (_gf_true == glusterd_check_voloption_flags (key, - OPT_FLAG_FORCE))) - goto out; - - gf_log ("", GF_LOG_DEBUG, "deleting dict with key=%s,value=%s", - key, value->data); - dict_del (this, key); -out: - return; -} - -int -glusterd_options_reset (glusterd_volinfo_t *volinfo, int32_t is_force) -{ - int ret = 0; - - gf_log ("", GF_LOG_DEBUG, "Received volume set reset command"); - - GF_ASSERT (volinfo->dict); - - dict_foreach (volinfo->dict, _delete_reconfig_opt, &is_force); - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - if (ret) - goto out; - - ret = 0; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - -static int -glusterd_op_reset_volume (dict_t *dict) -{ - glusterd_volinfo_t *volinfo = NULL; - int ret = -1; - char *volname = NULL; - int32_t is_force = 0; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); - goto out; - } - - ret = dict_get_int32 (dict, "force", &is_force); - if (ret) - is_force = 0; - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_options_reset (volinfo, is_force); - -out: - gf_log ("", GF_LOG_DEBUG, "'volume reset' returning %d", ret); - return ret; - -} - -int -stop_gsync (char *master, char *slave, char **msg) -{ - int32_t ret = 0; - int pfd = -1; - pid_t pid = 0; - char pidfile[PATH_MAX] = {0,}; - char buf [1024] = {0,}; - int i = 0; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - pfd = gsyncd_getpidfile (master, slave, pidfile); - if (pfd == -2) { - gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " - " failed for %s & %s", master, slave); - ret = -1; - goto out; - } - if (gsync_status_byfd (pfd) == -1) { - gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" - " running", master, slave); - if (msg) - *msg = gf_strdup ("Warning: "GEOREP" session was in " - "corrupt state"); - /* monitor gsyncd already dead */ - goto out; - } - - ret = read (pfd, buf, 1024); - if (ret > 0) { - pid = strtol (buf, NULL, 10); - ret = kill (-pid, SIGTERM); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "failed to kill gsyncd"); - goto out; - } - for (i = 0; i < 20; i++) { - if (gsync_status_byfd (pfd) == -1) { - /* monitor gsyncd is dead but worker may - * still be alive, give some more time - * before SIGKILL (hack) - */ - usleep (50000); - break; - } - usleep (50000); - } - kill (-pid, SIGKILL); - unlink (pidfile); - } - ret = 0; - -out: - close (pfd); - return ret; -} - -int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, - dict_t *resp_dict); - -int -glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, - dict_t *dict, dict_t *resp_dict, char **op_errstr) -{ - int32_t ret = -1; - char *op_name = NULL; - char *op_value = NULL; - runner_t runner = {0,}; - glusterd_conf_t *priv = NULL; - char *subop = NULL; - char *master = NULL; - - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - GF_ASSERT (dict); - GF_ASSERT (resp_dict); - - ret = dict_get_str (dict, "subop", &subop); - if (ret != 0) - goto out; - - if (strcmp (subop, "get") == 0 || strcmp (subop, "get-all") == 0) { - /* deferred to cli */ - gf_log ("", GF_LOG_DEBUG, "Returning 0"); - return 0; - } - - ret = dict_get_str (dict, "op_name", &op_name); - if (ret != 0) - goto out; - - if (strcmp (subop, "set") == 0) { - ret = dict_get_str (dict, "op_value", &op_value); - if (ret != 0) - goto out; - } - - if (THIS) - priv = THIS->private; - if (priv == NULL) { - gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); - *op_errstr = gf_strdup ("glusterd defunct"); - goto out; - } - - master = ""; - runinit (&runner); - runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); - runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); - if (volinfo) { - master = volinfo->volname; - runner_argprintf (&runner, ":%s", master); - } - runner_add_arg (&runner, slave); - runner_argprintf (&runner, "--config-%s", subop); - runner_add_arg (&runner, op_name); - if (op_value) - runner_add_arg (&runner, op_value); - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_WARNING, "gsyncd failed to " - "%s %s option for %s %s peers", - subop, op_name, master, slave); - - gf_asprintf (op_errstr, GEOREP" config-%s failed for %s %s", - subop, master, slave); - - goto out; - } - ret = 0; - gf_asprintf (op_errstr, "config-%s successful", subop); - -out: - if (!ret && volinfo) { - ret = glusterd_check_restart_gsync_session (volinfo, slave, - resp_dict); - if (ret) - *op_errstr = gf_strdup ("internal error"); - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int -glusterd_gsync_read_frm_status (char *path, char *data) -{ - int ret = 0; - FILE *status_file = NULL; - - GF_ASSERT (path); - GF_ASSERT (data); - status_file = fopen (path, "r"); - if (status_file == NULL) { - gf_log ("", GF_LOG_WARNING, "Unable to read gsyncd status" - " file"); - return -1; - } - ret = fread (data, PATH_MAX, 1, status_file); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "Status file of gsyncd is corrupt"); - return -1; - } - - data[strlen(data)-1] = '\0'; - - return 0; -} - -int -glusterd_read_status_file (char *master, char *slave, - dict_t *dict) -{ - glusterd_conf_t *priv = NULL; - int ret = 0; - char statusfile[PATH_MAX] = {0, }; - char buff[PATH_MAX] = {0, }; - char mst[PATH_MAX] = {0, }; - char slv[PATH_MAX] = {0, }; - char sts[PATH_MAX] = {0, }; - int gsync_count = 0; - int status = 0; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - ret = glusterd_gsync_get_param_file (statusfile, "state", master, - slave, priv->workdir); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" - "file for %s(master), %s(slave)", master, slave); - goto out; - - } - - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == -1) { - strncpy (buff, "corrupt", sizeof (buff)); - goto done; - } else if (ret == -1) - goto out; - - ret = glusterd_gsync_read_frm_status (statusfile, buff); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to read the status" - "file for %s(master), %s(slave)", master, slave); - goto out; - - } - - done: - ret = dict_get_int32 (dict, "gsync-count", &gsync_count); - - if (ret) - gsync_count = 1; - else - gsync_count++; - - snprintf (mst, sizeof (mst), "master%d", gsync_count); - ret = dict_set_dynstr (dict, mst, gf_strdup (master)); - if (ret) - goto out; - - snprintf (slv, sizeof (slv), "slave%d", gsync_count); - ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); - if (ret) - goto out; - - snprintf (sts, sizeof (slv), "status%d", gsync_count); - ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); - if (ret) - goto out; - ret = dict_set_int32 (dict, "gsync-count", gsync_count); - if (ret) - goto out; - - ret = 0; - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); - return ret; -} - -int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, - dict_t *resp_dict) -{ - - int ret = 0; - uuid_t uuid = {0, }; - glusterd_conf_t *priv = NULL; - char *status_msg = NULL; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) - /* session does not exist, nothing to do */ - goto out; - if (uuid_compare (priv->uuid, uuid) == 0) { - ret = stop_gsync (volinfo->volname, slave, &status_msg); - if (ret == 0 && status_msg) - ret = dict_set_str (resp_dict, "gsync-status", - status_msg); - if (ret == 0) - ret = glusterd_start_gsync (volinfo, slave, - uuid_utoa(priv->uuid), NULL); - } - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) -{ - int32_t ret = 0; - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile" - " for setting of marker while '"GEOREP" start'"); - ret = -1; - goto out; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - ret = 0; -out: - return ret; -} - -int -glusterd_set_marker_gsync (glusterd_volinfo_t *volinfo) -{ - int ret = -1; - int marker_set = _gf_false; - char *gsync_status = NULL; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); - if (marker_set == -1) { - gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); - ret = -1; - goto out; - } - - if (marker_set == _gf_false) { - gsync_status = gf_strdup ("on"); - if (gsync_status == NULL) { - ret = -1; - goto out; - } - - ret = glusterd_gsync_volinfo_dict_set (volinfo, - VKEY_MARKER_XTIME, gsync_status); - if (ret < 0) - goto out; - - ret = glusterd_marker_create_volfile (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Setting dict failed"); - goto out; - } - } - ret = 0; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - - - -int -glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, - char *slave, dict_t *rsp_dict) -{ - uuid_t uuid = {0, }; - glusterd_conf_t *priv = NULL; - int ret = 0; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) - goto out; - - if (ret) { - ret = 0; - gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :" - "session is not active", volinfo->volname, slave); - goto out; - } - - ret = glusterd_read_status_file (volinfo->volname, slave, rsp_dict); - out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - return ret; -} - -static int -glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) -{ - glusterd_gsync_status_temp_t param = {0, }; - - GF_ASSERT (volinfo); - - param.rsp_dict = rsp_dict; - param.volinfo = volinfo; - dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); - - return 0; -} - -static int -glusterd_get_gsync_status_all ( dict_t *rsp_dict) -{ - - int32_t ret = 0; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - - GF_ASSERT (THIS); - priv = THIS->private; - - GF_ASSERT (priv); - - list_for_each_entry (volinfo, &priv->volumes, vol_list) { - ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); - if (ret) - goto out; - } - -out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - return ret; - -} - -static int -glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - char *slave = NULL; - char *volname = NULL; - char errmsg[PATH_MAX] = {0, }; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - int ret = 0; - - - ret = dict_get_str (dict, "master", &volname); - if (ret < 0){ - ret = glusterd_get_gsync_status_all (rsp_dict); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } - - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); - goto out; - } - - ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, rsp_dict); - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; - - -} - - -int -glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - int32_t ret = -1; - int32_t type = -1; - dict_t *ctx = NULL; - dict_t *resp_dict = NULL; - char *host_uuid = NULL; - char *slave = NULL; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_conf_t *priv = NULL; - char *status_msg = NULL; - uuid_t uuid = {0, }; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) - goto out; - - ret = dict_get_str (dict, "host-uuid", &host_uuid); - if (ret < 0) - goto out; - - ctx = glusterd_op_get_ctx (); - resp_dict = ctx ? ctx : rsp_dict; - GF_ASSERT (resp_dict); - - if (type == GF_GSYNC_OPTION_TYPE_STATUS) { - ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); - goto out; - } - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) - goto out; - - if (dict_get_str (dict, "master", &volname) == 0) { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Volinfo for %s (master) not found", - volname); - goto out; - } - } - - if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { - ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, - op_errstr); - goto out; - } - - if (!volinfo) { - ret = -1; - goto out; - } - - if (type == GF_GSYNC_OPTION_TYPE_START) { - - ret = glusterd_set_marker_gsync (volinfo); - if (ret != 0) { - gf_log ("", GF_LOG_WARNING, "marker start failed"); - *op_errstr = gf_strdup ("failed to initialize indexing"); - ret = -1; - goto out; - } - ret = glusterd_store_slave_in_info(volinfo, slave, - host_uuid, op_errstr); - if (ret) - goto out; - - ret = glusterd_start_gsync (volinfo, slave, host_uuid, - op_errstr); - } - - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if (ret) { - gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for" - "%s(master) and %s(slave)", volname, slave); - *op_errstr = strdup (GEOREP" is not set up"); - goto out; - } - - ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); - if (ret) - goto out; - - if (uuid_compare (priv->uuid, uuid) != 0) { - goto out; - } - - ret = stop_gsync (volname, slave, &status_msg); - if (ret == 0 && status_msg) - ret = dict_set_str (resp_dict, "gsync-status", - status_msg); - if (ret != 0) - *op_errstr = gf_strdup ("internal error"); - } - -out: - gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); - return ret; -} - -int32_t -glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) -{ - int32_t ret = 0; - int flag = _gf_false; - - flag = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); - if (flag == -1) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); - ret = -1; - goto out; - } - - if (flag == _gf_false) { - gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); - ret = -1; - goto out; - } - ret = 0; -out: - return ret; -} - -/* At the end of the function, the variable found will be set - * to true if the path to be removed was present in the limit-list, - * else will be false. - */ -int32_t -_glusterd_quota_remove_limits (char **quota_limits, char *path, - gf_boolean_t *found) -{ - int ret = 0; - int i = 0; - int size = 0; - int len = 0; - int pathlen = 0; - int skiplen = 0; - int flag = 0; - char *limits = NULL; - char *qlimits = NULL; - - if (found != NULL) - *found = _gf_false; - - if (*quota_limits == NULL) - return -1; - - qlimits = *quota_limits; - - pathlen = strlen (path); - - len = strlen (qlimits); - - limits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); - if (!limits) - return -1; - - while (i < len) { - if (!memcmp ((void *) &qlimits [i], (void *)path, pathlen)) - if (qlimits [i + pathlen] == ':') { - flag = 1; - if (found != NULL) - *found = _gf_true; - } - - while (qlimits [i + size] != ',' && - qlimits [i + size] != '\0') - size++; - - if (!flag) { - memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); - } else { - skiplen = size + 1; - size = len - i - size; - memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size); - break; - } - - i += size + 1; - size = 0; - } - - if (!flag) { - ret = 1; - } else { - len = strlen (limits); - - if (len == 0) { - GF_FREE (qlimits); - - *quota_limits = NULL; - - goto out; - } - - if (limits[len - 1] == ',') { - limits[len - 1] = '\0'; - len --; - } - - GF_FREE (qlimits); - - qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); - - if (!qlimits) { - ret = -1; - goto out; - } - - memcpy ((void *) qlimits, (void *) limits, len + 1); - - *quota_limits = qlimits; - - ret = 0; - } - -out: - if (limits) - GF_FREE (limits); - - return ret; -} - -int32_t -glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) -{ - int32_t ret = 0; - pid_t pid; - char mountdir [] = "/tmp/mntXXXXXX"; - runner_t runner = {0,}; - int status = 0; - - if (mkdtemp (mountdir) == NULL) { - gf_log ("glusterd", GF_LOG_DEBUG, - "failed to create a temporary mount directory"); - ret = -1; - goto out; - } - - runinit (&runner); - runner_add_args (&runner, GFS_PREFIX"/sbin/glusterfs", "-s", - "localhost", "--volfile-id", volname, "-l", - DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", - mountdir, NULL); - - ret = runner_run_reuse (&runner); - if (ret == -1) { - runner_log (&runner, "glusterd", GF_LOG_DEBUG, "command failed"); - runner_end (&runner); - goto out; - } - runner_end (&runner); - - if ((pid = fork ()) < 0) { - gf_log ("glusterd", GF_LOG_WARNING, "fork from parent failed"); - ret = -1; - goto out; - } else if (pid == 0) {//first child - /* fork one more to not hold back main process on - * blocking call below - */ - pid = fork (); - if (pid) - _exit (pid > 0 ? EXIT_SUCCESS : EXIT_FAILURE); - - ret = chdir (mountdir); - if (ret == -1) { - gf_log ("glusterd", GF_LOG_WARNING, "chdir %s failed, " - "reason: %s", mountdir, strerror (errno)); - exit (EXIT_FAILURE); - } - runinit (&runner); - runner_add_args (&runner, "/usr/bin/find", "find", ".", NULL); - if (runner_start (&runner) == -1) - _exit (EXIT_FAILURE); - -#ifndef GF_LINUX_HOST_OS - runner_end (&runner); /* blocks in waitpid */ - runcmd ("umount", mountdir, NULL); -#else - runcmd ("umount", "-l", mountdir, NULL); -#endif - rmdir (mountdir); - _exit (EXIT_SUCCESS); - } - ret = (waitpid (pid, &status, 0) == pid && - WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) ? 0 : -1; - -out: - return ret; -} - -char * -glusterd_quota_get_limit_value (char *quota_limits, char *path) -{ - int32_t i, j, k, l, len; - int32_t pat_len, diff; - char *ret_str = NULL; - - len = strlen (quota_limits); - pat_len = strlen (path); - i = 0; - j = 0; - - while (i < len) { - j = i; - k = 0; - while (path [k] == quota_limits [j]) { - j++; - k++; - } - - l = j; - - while (quota_limits [j] != ',' && - quota_limits [j] != '\0') - j++; - - if (quota_limits [l] == ':' && pat_len == (l - i)) { - diff = j - i; - ret_str = GF_CALLOC (diff + 1, sizeof (char), - gf_gld_mt_char); - - strncpy (ret_str, "a_limits [i], diff); - - break; - } - i = ++j; //skip ',' - } - - return ret_str; -} - -char* -_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, - char *path, char **op_errstr) -{ - int32_t ret = 0; - char *quota_limits = NULL; - char *ret_str = NULL; - - if (volinfo == NULL) - return NULL; - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) - return NULL; - if (quota_limits == NULL) { - ret_str = NULL; - *op_errstr = gf_strdup ("Limit not set on any directory"); - } else if (path == NULL) - ret_str = gf_strdup (quota_limits); - else - ret_str = glusterd_quota_get_limit_value (quota_limits, path); - - return ret_str; -} - -int32_t -glusterd_quota_get_limit_usages (glusterd_conf_t *priv, - glusterd_volinfo_t *volinfo, - char *volname, - dict_t *dict, - char **op_errstr) -{ - int32_t i = 0; - int32_t ret = 0; - int32_t count = 0; - char *path = NULL; - dict_t *ctx = NULL; - char cmd_str [1024] = {0, }; - char *ret_str = NULL; - - ctx = glusterd_op_get_ctx (); - if (ctx == NULL) - return 0; - - ret = dict_get_int32 (dict, "count", &count); - if (ret < 0) - goto out; - - if (count == 0) { - ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL, - op_errstr); - } else { - i = 0; - while (count--) { - snprintf (cmd_str, 1024, "path%d", i++); - - ret = dict_get_str (dict, cmd_str, &path); - if (ret < 0) - goto out; - - ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); - } - } - - if (ret_str) { - ret = dict_set_dynstr (ctx, "limit_list", ret_str); - } -out: - return ret; -} - -int32_t -glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, - gf_boolean_t *crawl) -{ - int32_t ret = -1; - char *quota_status = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", crawl, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - if (glusterd_is_volume_started (volinfo) == 0) { - *op_errstr = gf_strdup ("Volume is stopped, start volume " - "to enable quota."); - goto out; - } - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == 0) { - *op_errstr = gf_strdup ("Quota is already enabled"); - goto out; - } - - quota_status = gf_strdup ("on"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); - goto out; - } - - *op_errstr = gf_strdup ("Enabling quota has been successful"); - - *crawl = _gf_true; - - ret = 0; -out: - return ret; -} - -int32_t -glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) -{ - int32_t ret = -1; - char *quota_status = NULL, *quota_limits = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("Quota is already disabled"); - goto out; - } - - quota_status = gf_strdup ("off"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); - goto out; - } - - *op_errstr = gf_strdup ("Disabling quota has been successful"); - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) { - gf_log ("", GF_LOG_WARNING, "failed to get the quota limits"); - } else { - GF_FREE (quota_limits); - } - - dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); - -out: - return ret; -} - -int32_t -glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char *path = NULL; - char *limit = NULL; - char *value = NULL; - char msg [1024] = {0,}; - char *quota_limits = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", dict, out); - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - ret = dict_get_str (dict, "limit", &limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - if (quota_limits) { - ret = _glusterd_quota_remove_limits ("a_limits, path, NULL); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - } - - if (quota_limits == NULL) { - ret = gf_asprintf (&value, "%s:%s", path, limit); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - } else { - ret = gf_asprintf (&value, "%s,%s:%s", - quota_limits, path, limit); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - GF_FREE (quota_limits); - } - - quota_limits = value; - - ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, - quota_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - snprintf (msg, 1024, "limit set on %s", path); - *op_errstr = gf_strdup (msg); - - ret = 0; -out: - return ret; -} - -int32_t -glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char str [PATH_MAX + 1024] = {0,}; - char *quota_limits = NULL; - char *path = NULL; - gf_boolean_t flag = _gf_false; - - GF_VALIDATE_OR_GOTO ("glusterd", dict, out); - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("Quota is disabled, please enable quota"); - goto out; - } - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - goto out; - } - - ret = _glusterd_quota_remove_limits ("a_limits, path, &flag); - if (ret == -1) { - if (flag == _gf_true) - snprintf (str, sizeof (str), "Removing limit on %s has " - "been unsuccessful", path); - else - snprintf (str, sizeof (str), "%s has no limit set", path); - *op_errstr = gf_strdup (str); - goto out; - } else { - if (flag == _gf_true) - snprintf (str, sizeof (str), "Removed quota limit on " - "%s", path); - else - snprintf (str, sizeof (str), "no limit set on %s", - path); - *op_errstr = gf_strdup (str); - } - - if (quota_limits) { - ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, - quota_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); - goto out; - } - } else { - dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); - } - - ret = 0; - -out: - return ret; -} - - -int -glusterd_op_quota (dict_t *dict, char **op_errstr) -{ - glusterd_volinfo_t *volinfo = NULL; - int32_t ret = -1; - char *volname = NULL; - dict_t *ctx = NULL; - int type = -1; - gf_boolean_t start_crawl = _gf_false; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "type", &type); - - if (type == GF_QUOTA_OPTION_TYPE_ENABLE) { - ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_DISABLE) { - ret = glusterd_quota_disable (volinfo, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { - ret = glusterd_quota_limit_usage (volinfo, dict, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_REMOVE) { - ret = glusterd_quota_remove_limits (volinfo, dict, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_LIST) { - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("cannot list the limits, " - "quota is disabled"); - goto out; - } - - ret = glusterd_quota_get_limit_usages (priv, volinfo, volname, - dict, op_errstr); - - goto out; - } -create_vol: - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for" - " 'quota'"); - ret = -1; - goto out; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - - ret = 0; - -out: - ctx = glusterd_op_get_ctx (); - if (ctx && start_crawl == _gf_true) - glusterd_quota_initiate_fs_crawl (priv, volname); - - if (ctx && *op_errstr) { - ret = dict_set_dynstr (ctx, "errstr", *op_errstr); - if (ret) { - GF_FREE (*op_errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set error message in ctx"); - } - *op_errstr = NULL; - } - - return ret; -} - -int -glusterd_stop_bricks (glusterd_volinfo_t *volinfo) -{ - glusterd_brickinfo_t *brickinfo = NULL; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_brick_stop (volinfo, brickinfo)) - return -1; - } - - return 0; -} - -int -glusterd_start_bricks (glusterd_volinfo_t *volinfo) -{ - glusterd_brickinfo_t *brickinfo = NULL; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_brick_start (volinfo, brickinfo)) - return -1; - } - - return 0; -} - -static int -glusterd_restart_brick_servers (glusterd_volinfo_t *volinfo) -{ - if (!volinfo) - return -1; - if (glusterd_stop_bricks (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " - "stop brick servers"); - return -1; - } - usleep (500000); - if (glusterd_start_bricks (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " - "start brick servers"); - return -1; - } - return 0; -} - -static int -glusterd_op_log_level (dict_t *dict) -{ - int32_t ret = -1; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - char *xlator = NULL; - char *loglevel = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = dict_get_str (dict, "xlator", &xlator); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); - goto out; - } - - ret = dict_get_str (dict, "loglevel", &loglevel); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get Loglevel to use"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Cannot find volume: %s", volname); - goto out; - } - - xlator = gf_strdup (xlator); - - ret = dict_set_dynstr (volinfo->dict, "xlator", xlator); - if (ret) - goto out; - - loglevel = gf_strdup (loglevel); - - ret = dict_set_dynstr (volinfo->dict, "loglevel", loglevel); - if (ret) - goto out; - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to create volfile for command" - " 'log level'"); - ret = -1; - goto out; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - ret = 0; - - out: - gf_log ("glusterd", GF_LOG_DEBUG, "(cli log level) Returning: %d", ret); - return ret; -} - -static int -glusterd_volset_help (dict_t *dict) -{ - int ret = -1; - gf_boolean_t xml_out = _gf_false; - - if (dict_get (dict, "help" )) - xml_out = _gf_false; - else if (dict_get (dict, "help-xml" )) - xml_out = _gf_true; - else - goto out; - - ret = glusterd_get_volopt_content (xml_out); - out: - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_set_volume (dict_t *dict) -{ - int ret = 0; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - int count = 1; - int restart_flag = 0; - char *key = NULL; - char *key_fixed = NULL; - char *value = NULL; - char str[50] = {0, }; - gf_boolean_t global_opt = _gf_false; - glusterd_volinfo_t *voliter = NULL; - int32_t dict_count = 0; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_int32 (dict, "count", &dict_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); - goto out; - } - - if ( dict_count == 0 ) { - ret = glusterd_volset_help (dict); - if (ret) - gf_log ("glusterd", GF_LOG_ERROR, "Volume set help" - "internal error"); - goto out; - } - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - for ( count = 1; ret != -1 ; count++ ) { - - global_opt = _gf_false; - sprintf (str, "key%d", count); - ret = dict_get_str (dict, str, &key); - - if (ret) { - break; - } - - if (!ret) { - ret = glusterd_check_option_exists (key, &key_fixed); - GF_ASSERT (ret); - if (ret == -1) { - key_fixed = NULL; - goto out; - } - ret = 0; - } - - ret = glusterd_check_globaloption (key); - if (ret) - global_opt = _gf_true; - - sprintf (str, "value%d", count); - ret = dict_get_str (dict, str, &value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "invalid key,value pair in 'volume set'"); - ret = -1; - goto out; - } - - if (!global_opt) - value = gf_strdup (value); - - if (!value) { - gf_log ("", GF_LOG_ERROR, - "Unable to set the options in 'volume set'"); - ret = -1; - goto out; - } - - if (key_fixed) - key = key_fixed; - - if (global_opt) { - list_for_each_entry (voliter, &priv->volumes, vol_list) { - value = gf_strdup (value); - ret = dict_set_dynstr (voliter->dict, key, value); - if (ret) - goto out; - } - } - else { - ret = dict_set_dynstr (volinfo->dict, key, value); - if (ret) - goto out; - } - - if (key_fixed) { - GF_FREE (key_fixed); - - key_fixed = NULL; - } - } - - if ( count == 1 ) { - gf_log ("", GF_LOG_ERROR, "No options received "); - ret = -1; - goto out; - } - - if (!global_opt) { - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; - } - - if (restart_flag) { - if (glusterd_restart_brick_servers (volinfo)) { - ret = -1; - goto out; - } - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_check_generate_start_nfs (); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "Unable to restart NFS-Server"); - goto out; - } - } - - } - else { - list_for_each_entry (voliter, &priv->volumes, vol_list) { - volinfo = voliter; - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; - } - - if (restart_flag) { - if (glusterd_restart_brick_servers (volinfo)) { - ret = -1; - goto out; - } - } - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_check_generate_start_nfs (); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "Unable to restart NFS-Server"); - goto out; - } - } - } - } - - ret = 0; - out: - if (key_fixed) - GF_FREE (key_fixed); - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; -} - -static int -glusterd_op_remove_brick (dict_t *dict) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - char *brick = NULL; - int32_t count = 0; - int32_t i = 1; - char key[256] = {0,}; - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - - while ( i <= count) { - snprintf (key, 256, "brick%d", i); - ret = dict_get_str (dict, key, &brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); goto out; } - - ret = glusterd_op_perform_remove_brick (volinfo, brick); - if (ret) + } + if ((GF_CLI_STATS_TOP == stats_op) || + (GF_CLI_STATS_INFO == stats_op)) { + if (_gf_false == glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "Volume %s is not started.", + volinfo->volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + ret = -1; goto out; - i++; + } } - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - volinfo->defrag_status = 0; - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - + ret = 0; out: + if (msg[0] != '\0') { + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } -static int -glusterd_op_delete_volume (dict_t *dict) +void +_delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) { - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - xlator_t *this = NULL; + int exists = 0; + int32_t is_force = 0; - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); + GF_ASSERT (data); + is_force = *((int32_t*)data); + exists = glusterd_check_option_exists(key, NULL); - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + if (exists != 1) goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) + if ((!is_force) && + (_gf_true == glusterd_check_voloption_flags (key, + OPT_FLAG_FORCE))) goto out; - ret = glusterd_delete_volume (volinfo); + gf_log ("", GF_LOG_DEBUG, "deleting dict with key=%s,value=%s", + key, value->data); + dict_del (this, key); out: - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; + return; } -static int -glusterd_op_start_volume (dict_t *dict, char **op_errstr) +int +glusterd_options_reset (glusterd_volinfo_t *volinfo, int32_t is_force) { - int ret = 0; - char *volname = NULL; - int flags = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; + int ret = 0; - ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; + gf_log ("", GF_LOG_DEBUG, "Received volume set reset command"); - ret = glusterd_volinfo_find (volname, &volinfo); + GF_ASSERT (volinfo->dict); - if (ret) + dict_foreach (volinfo->dict, _delete_reconfig_opt, &is_force); + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + " 'volume set'"); + ret = -1; goto out; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_start (volinfo, brickinfo); - if (ret) - goto out; } - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; - ret = glusterd_check_generate_start_nfs (); + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (); + if (ret) + goto out; + + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } + static int -glusterd_op_log_filename (dict_t *dict) +glusterd_op_reset_volume (dict_t *dict) { - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *volname = NULL; - char *brick = NULL; - char *path = NULL; - char logfile[PATH_MAX] = {0,}; - char exp_path[PATH_MAX] = {0,}; - struct stat stbuf = {0,}; - int valid_brick = 0; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - char* new_logdir = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); + glusterd_volinfo_t *volinfo = NULL; + int ret = -1; + char *volname = NULL; + int32_t is_force = 0; ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "volname not found"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "path not found"); + gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); goto out; } - ret = dict_get_str (dict, "brick", &brick); + ret = dict_get_int32 (dict, "force", &is_force); if (ret) - goto out; + is_force = 0; - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; - - if (!strchr (brick, ':')) { - brick = NULL; - ret = stat (path, &stbuf); - if (ret || !S_ISDIR (stbuf.st_mode)) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "not a directory"); - goto out; - } - new_logdir = gf_strdup (path); - if (!new_logdir) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "Out of memory"); - goto out; - } - if (volinfo->logdir) - GF_FREE (volinfo->logdir); - volinfo->logdir = new_logdir; - } else { - ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot get brickinfo from brick"); - goto out; - } } + ret = glusterd_options_reset (volinfo, is_force); - ret = -1; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +out: + gf_log ("", GF_LOG_DEBUG, "'volume reset' returning %d", ret); + return ret; - if (uuid_is_null (brickinfo->uuid)) { - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - } +} - /* check if the brickinfo belongs to the 'this' machine */ - if (uuid_compare (brickinfo->uuid, priv->uuid)) - continue; - if (brick && strcmp (tmpbrkinfo->path,brickinfo->path)) - continue; +int +glusterd_stop_bricks (glusterd_volinfo_t *volinfo) +{ + glusterd_brickinfo_t *brickinfo = NULL; - valid_brick = 1; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (glusterd_brick_stop (volinfo, brickinfo)) + return -1; + } - /* If there are more than one brick in 'this' server, its an - * extra check, but it doesn't harm functionality - */ - ret = stat (path, &stbuf); - if (ret || !S_ISDIR (stbuf.st_mode)) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "not a directory"); - goto out; - } + return 0; +} - GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); +int +glusterd_start_bricks (glusterd_volinfo_t *volinfo) +{ + glusterd_brickinfo_t *brickinfo = NULL; - snprintf (logfile, PATH_MAX, "%s/%s.log", path, exp_path); + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (glusterd_brick_start (volinfo, brickinfo)) + return -1; + } - if (brickinfo->logfile) - GF_FREE (brickinfo->logfile); - brickinfo->logfile = gf_strdup (logfile); - ret = 0; + return 0; +} - /* If request was for brick, only one iteration is enough */ - if (brick) - break; +static int +glusterd_restart_brick_servers (glusterd_volinfo_t *volinfo) +{ + if (!volinfo) + return -1; + if (glusterd_stop_bricks (volinfo)) { + gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " + "stop brick servers"); + return -1; + } + usleep (500000); + if (glusterd_start_bricks (volinfo)) { + gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " + "start brick servers"); + return -1; } + return 0; +} - if (ret && !valid_brick) - ret = 0; -out: - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); +static int +glusterd_volset_help (dict_t *dict) +{ + int ret = -1; + gf_boolean_t xml_out = _gf_false; + + if (dict_get (dict, "help" )) + xml_out = _gf_false; + else if (dict_get (dict, "help-xml" )) + xml_out = _gf_true; + else + goto out; + ret = glusterd_get_volopt_content (xml_out); + out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int -glusterd_op_log_rotate (dict_t *dict) +glusterd_op_set_volume (dict_t *dict) { - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *volname = NULL; - char *brick = NULL; - char path[PATH_MAX] = {0,}; - char logfile[PATH_MAX] = {0,}; - char pidfile[PATH_MAX] = {0,}; - FILE *file = NULL; - pid_t pid = 0; - uint64_t key = 0; - int valid_brick = 0; - glusterd_brickinfo_t *tmpbrkinfo = NULL; + int ret = 0; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int count = 1; + int restart_flag = 0; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char str[50] = {0, }; + gf_boolean_t global_opt = _gf_false; + glusterd_volinfo_t *voliter = NULL; + int32_t dict_count = 0; this = THIS; GF_ASSERT (this); + priv = this->private; GF_ASSERT (priv); - ret = dict_get_str (dict, "volname", &volname); + ret = dict_get_int32 (dict, "count", &dict_count); if (ret) { - gf_log ("", GF_LOG_ERROR, "volname not found"); + gf_log ("", GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); goto out; } - ret = dict_get_uint64 (dict, "rotate-key", &key); - if (ret) { - gf_log ("", GF_LOG_ERROR, "rotate key not found"); + if ( dict_count == 0 ) { + ret = glusterd_volset_help (dict); + if (ret) + gf_log ("glusterd", GF_LOG_ERROR, "Volume set help" + "internal error"); goto out; } - ret = dict_get_str (dict, "brick", &brick); - if (ret) + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); goto out; - - if (!strchr (brick, ':')) - brick = NULL; - else { - ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot get brickinfo from brick"); - goto out; - } } ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) - goto out; - - ret = -1; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (uuid_compare (brickinfo->uuid, priv->uuid)) - continue; - - if (brick && - (strcmp (tmpbrkinfo->hostname, brickinfo->hostname) || - strcmp (tmpbrkinfo->path,brickinfo->path))) - continue; + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } - valid_brick = 1; + for ( count = 1; ret != -1 ; count++ ) { - GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); - GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, - brickinfo->path); + global_opt = _gf_false; + sprintf (str, "key%d", count); + ret = dict_get_str (dict, str, &key); - file = fopen (pidfile, "r+"); - if (!file) { - gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", - pidfile); - ret = -1; - goto out; + if (ret) { + break; } - ret = fscanf (file, "%d", &pid); - if (ret <= 0) { - gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", - pidfile); - ret = -1; - goto out; + if (!ret) { + ret = glusterd_check_option_exists (key, &key_fixed); + GF_ASSERT (ret); + if (ret == -1) { + key_fixed = NULL; + goto out; + } + ret = 0; } - fclose (file); - file = NULL; - snprintf (logfile, PATH_MAX, "%s.%"PRIu64, - brickinfo->logfile, key); - - ret = rename (brickinfo->logfile, logfile); + ret = glusterd_check_globaloption (key); if (ret) - gf_log ("", GF_LOG_WARNING, "rename failed"); + global_opt = _gf_true; - ret = kill (pid, SIGHUP); + sprintf (str, "value%d", count); + ret = dict_get_str (dict, str, &value); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); + gf_log ("", GF_LOG_ERROR, + "invalid key,value pair in 'volume set'"); + ret = -1; goto out; } - ret = 0; - /* If request was for brick, only one iteration is enough */ - if (brick) - break; - } + if (!global_opt) + value = gf_strdup (value); - if (ret && !valid_brick) - ret = 0; + if (!value) { + gf_log ("", GF_LOG_ERROR, + "Unable to set the options in 'volume set'"); + ret = -1; + goto out; + } -out: - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); + if (key_fixed) + key = key_fixed; - return ret; -} + if (global_opt) { + list_for_each_entry (voliter, &priv->volumes, vol_list) { + value = gf_strdup (value); + ret = dict_set_dynstr (voliter->dict, key, value); + if (ret) + goto out; + } + } + else { + ret = dict_set_dynstr (volinfo->dict, key, value); + if (ret) + goto out; + } + if (key_fixed) { + GF_FREE (key_fixed); -static int -glusterd_op_stop_volume (dict_t *dict) -{ - int ret = 0; - int flags = 0; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; + key_fixed = NULL; + } + } - ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); - if (ret) + if ( count == 1 ) { + gf_log ("", GF_LOG_ERROR, "No options received "); + ret = -1; goto out; + } - ret = glusterd_volinfo_find (volname, &volinfo); + if (!global_opt) { + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + " 'volume set'"); + ret = -1; + goto out; + } - if (ret) - goto out; + if (restart_flag) { + if (glusterd_restart_brick_servers (volinfo)) { + ret = -1; + goto out; + } + } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_stop (volinfo, brickinfo); + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; - } - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_check_generate_start_nfs (); + if (ret) { + gf_log ("", GF_LOG_WARNING, + "Unable to restart NFS-Server"); + goto out; + } + } - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; + } + else { + list_for_each_entry (voliter, &priv->volumes, vol_list) { + volinfo = voliter; + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + " 'volume set'"); + ret = -1; + goto out; + } + + if (restart_flag) { + if (glusterd_restart_brick_servers (volinfo)) { + ret = -1; + goto out; + } + } - if (glusterd_are_all_volumes_stopped ()) { - if (glusterd_is_nfs_started ()) { - ret = glusterd_nfs_server_stop (); + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_check_generate_start_nfs (); + if (ret) { + gf_log ("", GF_LOG_WARNING, + "Unable to restart NFS-Server"); + goto out; + } + } } - } else { - ret = glusterd_check_generate_start_nfs (); } -out: + ret = 0; + out: + if (key_fixed) + GF_FREE (key_fixed); + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); return ret; } + static int glusterd_op_sync_volume (dict_t *dict, char **op_errstr, dict_t *rsp_dict) @@ -7289,145 +1918,6 @@ glusterd_op_brick_disconnect (void *data) glusterd_op_sm (); } -void -glusterd_do_replace_brick (void *data) -{ - glusterd_volinfo_t *volinfo = NULL; - int32_t op = 0; - int32_t src_port = 0; - int32_t dst_port = 0; - dict_t *dict = NULL; - char *src_brick = NULL; - char *dst_brick = NULL; - char *volname = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; - glusterd_conf_t *priv = NULL; - - int ret = 0; - - dict = data; - - GF_ASSERT (THIS); - - priv = THIS->private; - - if (priv->timer) { - gf_timer_call_cancel (THIS->ctx, priv->timer); - priv->timer = NULL; - gf_log ("", GF_LOG_DEBUG, - "Cancelled timer thread"); - } - - gf_log ("", GF_LOG_DEBUG, - "Replace brick operation detected"); - - ret = dict_get_int32 (dict, "operation", &op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } - ret = dict_get_str (dict, "src-brick", &src_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); - goto out; - } - - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - if (!dst_brickinfo) { - gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); - goto out; - } - - ret = glusterd_resolve_brick (dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); - goto out; - } - - ret = dict_get_int32 (dict, "src-brick-port", &src_port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); - goto out; - } - - ret = dict_get_int32 (dict, "dst-brick-port", &dst_port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst-brick port"); - } - - dst_brickinfo->port = dst_port; - src_brickinfo->port = src_port; - - switch (op) { - case GF_REPLACE_OP_START: - if (!dst_port) { - ret = -1; - goto out; - } - - ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - goto out; - } - break; - case GF_REPLACE_OP_PAUSE: - case GF_REPLACE_OP_ABORT: - case GF_REPLACE_OP_COMMIT: - case GF_REPLACE_OP_COMMIT_FORCE: - case GF_REPLACE_OP_STATUS: - break; - default: - ret = -1; - goto out; - } - -out: - if (ret) - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); - else - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); - - if (dict) - dict_unref (dict); - - glusterd_op_sm (); -} - - static int glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) @@ -7598,38 +2088,6 @@ glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx) return ret; } -static int -glusterd_op_stage_quota (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - if (!exists) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "does not exist", - volname); - *op_errstr = gf_strdup ("Invalid volume name"); - ret = -1; - goto out; - } - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - static int glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) { diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c new file mode 100644 index 000000000..809b56efe --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-quota.c @@ -0,0 +1,810 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#include + +int +glusterd_handle_quota (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_quota_req cli_req = {0,}; + dict_t *dict = NULL; + glusterd_op_t cli_op = GD_OP_QUOTA; + char operation[256] = {0, }; + char *volname = NULL; + int32_t type = 0; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_quota_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + if (cli_req.dict.dict_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (cli_req.dict.dict_val, + cli_req.dict.dict_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } else { + dict->extra_stdfree = cli_req.dict.dict_val; + } + } + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to get volume name, while" + "handling quota command"); + goto out; + } + + ret = dict_get_int32 (dict, "type", &type); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to get type of cmd. , while" + "handling quota command"); + goto out; + } + + switch (type) { + case GF_QUOTA_OPTION_TYPE_ENABLE: + strncpy (operation, "enable", sizeof (operation)); + break; + + case GF_QUOTA_OPTION_TYPE_DISABLE: + strncpy (operation, "disable", sizeof (operation)); + break; + + case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: + strncpy (operation, "limit-usage", sizeof (operation)); + break; + + case GF_QUOTA_OPTION_TYPE_REMOVE: + strncpy (operation, "remove", sizeof (operation)); + break; + } + gf_cmd_log ("volume quota", " %s command on %s", operation, volname); + ret = glusterd_op_begin (req, GD_OP_QUOTA, dict); + gf_cmd_log ("volume quota", " %s command on %s %s", operation,volname, + (ret != 0)? "FAILED" : "SUCCEEDED"); + +out: + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) { + if (dict) + dict_unref (dict); + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + } + if (cli_req.volname) + free (cli_req.volname); //malloced by xdr + + return ret; +} + +int32_t +glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) +{ + int32_t ret = 0; + int flag = _gf_false; + + flag = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); + if (flag == -1) { + gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); + ret = -1; + goto out; + } + + if (flag == _gf_false) { + gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); + ret = -1; + goto out; + } + ret = 0; +out: + return ret; +} + +/* At the end of the function, the variable found will be set + * to true if the path to be removed was present in the limit-list, + * else will be false. + */ +int32_t +_glusterd_quota_remove_limits (char **quota_limits, char *path, + gf_boolean_t *found) +{ + int ret = 0; + int i = 0; + int size = 0; + int len = 0; + int pathlen = 0; + int skiplen = 0; + int flag = 0; + char *limits = NULL; + char *qlimits = NULL; + + if (found != NULL) + *found = _gf_false; + + if (*quota_limits == NULL) + return -1; + + qlimits = *quota_limits; + + pathlen = strlen (path); + + len = strlen (qlimits); + + limits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); + if (!limits) + return -1; + + while (i < len) { + if (!memcmp ((void *) &qlimits [i], (void *)path, pathlen)) + if (qlimits [i + pathlen] == ':') { + flag = 1; + if (found != NULL) + *found = _gf_true; + } + + while (qlimits [i + size] != ',' && + qlimits [i + size] != '\0') + size++; + + if (!flag) { + memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); + } else { + skiplen = size + 1; + size = len - i - size; + memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size); + break; + } + + i += size + 1; + size = 0; + } + + if (!flag) { + ret = 1; + } else { + len = strlen (limits); + + if (len == 0) { + GF_FREE (qlimits); + + *quota_limits = NULL; + + goto out; + } + + if (limits[len - 1] == ',') { + limits[len - 1] = '\0'; + len --; + } + + GF_FREE (qlimits); + + qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); + + if (!qlimits) { + ret = -1; + goto out; + } + + memcpy ((void *) qlimits, (void *) limits, len + 1); + + *quota_limits = qlimits; + + ret = 0; + } + +out: + if (limits) + GF_FREE (limits); + + return ret; +} + +int32_t +glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) +{ + int32_t ret = 0; + pid_t pid; + char mountdir [] = "/tmp/mntXXXXXX"; + runner_t runner = {0,}; + int status = 0; + + if (mkdtemp (mountdir) == NULL) { + gf_log ("glusterd", GF_LOG_DEBUG, + "failed to create a temporary mount directory"); + ret = -1; + goto out; + } + + runinit (&runner); + runner_add_args (&runner, GFS_PREFIX"/sbin/glusterfs", "-s", + "localhost", "--volfile-id", volname, "-l", + DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", + mountdir, NULL); + + ret = runner_run_reuse (&runner); + if (ret == -1) { + runner_log (&runner, "glusterd", GF_LOG_DEBUG, "command failed"); + runner_end (&runner); + goto out; + } + runner_end (&runner); + + if ((pid = fork ()) < 0) { + gf_log ("glusterd", GF_LOG_WARNING, "fork from parent failed"); + ret = -1; + goto out; + } else if (pid == 0) {//first child + /* fork one more to not hold back main process on + * blocking call below + */ + pid = fork (); + if (pid) + _exit (pid > 0 ? EXIT_SUCCESS : EXIT_FAILURE); + + ret = chdir (mountdir); + if (ret == -1) { + gf_log ("glusterd", GF_LOG_WARNING, "chdir %s failed, " + "reason: %s", mountdir, strerror (errno)); + exit (EXIT_FAILURE); + } + runinit (&runner); + runner_add_args (&runner, "/usr/bin/find", "find", ".", NULL); + if (runner_start (&runner) == -1) + _exit (EXIT_FAILURE); + +#ifndef GF_LINUX_HOST_OS + runner_end (&runner); /* blocks in waitpid */ + runcmd ("umount", mountdir, NULL); +#else + runcmd ("umount", "-l", mountdir, NULL); +#endif + rmdir (mountdir); + _exit (EXIT_SUCCESS); + } + ret = (waitpid (pid, &status, 0) == pid && + WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) ? 0 : -1; + +out: + return ret; +} + +char * +glusterd_quota_get_limit_value (char *quota_limits, char *path) +{ + int32_t i, j, k, l, len; + int32_t pat_len, diff; + char *ret_str = NULL; + + len = strlen (quota_limits); + pat_len = strlen (path); + i = 0; + j = 0; + + while (i < len) { + j = i; + k = 0; + while (path [k] == quota_limits [j]) { + j++; + k++; + } + + l = j; + + while (quota_limits [j] != ',' && + quota_limits [j] != '\0') + j++; + + if (quota_limits [l] == ':' && pat_len == (l - i)) { + diff = j - i; + ret_str = GF_CALLOC (diff + 1, sizeof (char), + gf_gld_mt_char); + + strncpy (ret_str, "a_limits [i], diff); + + break; + } + i = ++j; //skip ',' + } + + return ret_str; +} + +char* +_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, + char *path, char **op_errstr) +{ + int32_t ret = 0; + char *quota_limits = NULL; + char *ret_str = NULL; + + if (volinfo == NULL) + return NULL; + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, + "a_limits); + if (ret) + return NULL; + if (quota_limits == NULL) { + ret_str = NULL; + *op_errstr = gf_strdup ("Limit not set on any directory"); + } else if (path == NULL) + ret_str = gf_strdup (quota_limits); + else + ret_str = glusterd_quota_get_limit_value (quota_limits, path); + + return ret_str; +} + +int32_t +glusterd_quota_get_limit_usages (glusterd_conf_t *priv, + glusterd_volinfo_t *volinfo, + char *volname, + dict_t *dict, + char **op_errstr) +{ + int32_t i = 0; + int32_t ret = 0; + int32_t count = 0; + char *path = NULL; + dict_t *ctx = NULL; + char cmd_str [1024] = {0, }; + char *ret_str = NULL; + + ctx = glusterd_op_get_ctx (); + if (ctx == NULL) + return 0; + + ret = dict_get_int32 (dict, "count", &count); + if (ret < 0) + goto out; + + if (count == 0) { + ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL, + op_errstr); + } else { + i = 0; + while (count--) { + snprintf (cmd_str, 1024, "path%d", i++); + + ret = dict_get_str (dict, cmd_str, &path); + if (ret < 0) + goto out; + + ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); + } + } + + if (ret_str) { + ret = dict_set_dynstr (ctx, "limit_list", ret_str); + } +out: + return ret; +} + +int32_t +glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, + gf_boolean_t *crawl) +{ + int32_t ret = -1; + char *quota_status = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", crawl, out); + GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + + if (glusterd_is_volume_started (volinfo) == 0) { + *op_errstr = gf_strdup ("Volume is stopped, start volume " + "to enable quota."); + goto out; + } + + ret = glusterd_check_if_quota_trans_enabled (volinfo); + if (ret == 0) { + *op_errstr = gf_strdup ("Quota is already enabled"); + goto out; + } + + quota_status = gf_strdup ("on"); + if (!quota_status) { + gf_log ("", GF_LOG_ERROR, "memory allocation failed"); + *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); + goto out; + } + + ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); + if (ret) { + gf_log ("", GF_LOG_ERROR, "dict set failed"); + *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); + goto out; + } + + *op_errstr = gf_strdup ("Enabling quota has been successful"); + + *crawl = _gf_true; + + ret = 0; +out: + return ret; +} + +int32_t +glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) +{ + int32_t ret = -1; + char *quota_status = NULL, *quota_limits = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + + ret = glusterd_check_if_quota_trans_enabled (volinfo); + if (ret == -1) { + *op_errstr = gf_strdup ("Quota is already disabled"); + goto out; + } + + quota_status = gf_strdup ("off"); + if (!quota_status) { + gf_log ("", GF_LOG_ERROR, "memory allocation failed"); + *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); + goto out; + } + + ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); + if (ret) { + gf_log ("", GF_LOG_ERROR, "dict set failed"); + *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); + goto out; + } + + *op_errstr = gf_strdup ("Disabling quota has been successful"); + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, + "a_limits); + if (ret) { + gf_log ("", GF_LOG_WARNING, "failed to get the quota limits"); + } else { + GF_FREE (quota_limits); + } + + dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); + +out: + return ret; +} + +int32_t +glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + char *path = NULL; + char *limit = NULL; + char *value = NULL; + char msg [1024] = {0,}; + char *quota_limits = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", dict, out); + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, + "a_limits); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + + ret = dict_get_str (dict, "path", &path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + + ret = dict_get_str (dict, "limit", &limit); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + + if (quota_limits) { + ret = _glusterd_quota_remove_limits ("a_limits, path, NULL); + if (ret == -1) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + } + + if (quota_limits == NULL) { + ret = gf_asprintf (&value, "%s:%s", path, limit); + if (ret == -1) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + } else { + ret = gf_asprintf (&value, "%s,%s:%s", + quota_limits, path, limit); + if (ret == -1) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + + GF_FREE (quota_limits); + } + + quota_limits = value; + + ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, + quota_limits); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); + *op_errstr = gf_strdup ("failed to set limit"); + goto out; + } + snprintf (msg, 1024, "limit set on %s", path); + *op_errstr = gf_strdup (msg); + + ret = 0; +out: + return ret; +} + +int32_t +glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + char str [PATH_MAX + 1024] = {0,}; + char *quota_limits = NULL; + char *path = NULL; + gf_boolean_t flag = _gf_false; + + GF_VALIDATE_OR_GOTO ("glusterd", dict, out); + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + + ret = glusterd_check_if_quota_trans_enabled (volinfo); + if (ret == -1) { + *op_errstr = gf_strdup ("Quota is disabled, please enable quota"); + goto out; + } + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, + "a_limits); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); + goto out; + } + + ret = dict_get_str (dict, "path", &path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); + goto out; + } + + ret = _glusterd_quota_remove_limits ("a_limits, path, &flag); + if (ret == -1) { + if (flag == _gf_true) + snprintf (str, sizeof (str), "Removing limit on %s has " + "been unsuccessful", path); + else + snprintf (str, sizeof (str), "%s has no limit set", path); + *op_errstr = gf_strdup (str); + goto out; + } else { + if (flag == _gf_true) + snprintf (str, sizeof (str), "Removed quota limit on " + "%s", path); + else + snprintf (str, sizeof (str), "no limit set on %s", + path); + *op_errstr = gf_strdup (str); + } + + if (quota_limits) { + ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, + quota_limits); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); + goto out; + } + } else { + dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); + } + + ret = 0; + +out: + return ret; +} + + +int +glusterd_op_quota (dict_t *dict, char **op_errstr) +{ + glusterd_volinfo_t *volinfo = NULL; + int32_t ret = -1; + char *volname = NULL; + dict_t *ctx = NULL; + int type = -1; + gf_boolean_t start_crawl = _gf_false; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + + priv = THIS->private; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_int32 (dict, "type", &type); + + if (type == GF_QUOTA_OPTION_TYPE_ENABLE) { + ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl); + if (ret < 0) + goto out; + + goto create_vol; + } + + if (type == GF_QUOTA_OPTION_TYPE_DISABLE) { + ret = glusterd_quota_disable (volinfo, op_errstr); + if (ret < 0) + goto out; + + goto create_vol; + } + + if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { + ret = glusterd_quota_limit_usage (volinfo, dict, op_errstr); + if (ret < 0) + goto out; + + goto create_vol; + } + + if (type == GF_QUOTA_OPTION_TYPE_REMOVE) { + ret = glusterd_quota_remove_limits (volinfo, dict, op_errstr); + if (ret < 0) + goto out; + + goto create_vol; + } + + if (type == GF_QUOTA_OPTION_TYPE_LIST) { + ret = glusterd_check_if_quota_trans_enabled (volinfo); + if (ret == -1) { + *op_errstr = gf_strdup ("cannot list the limits, " + "quota is disabled"); + goto out; + } + + ret = glusterd_quota_get_limit_usages (priv, volinfo, volname, + dict, op_errstr); + + goto out; + } +create_vol: + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for" + " 'quota'"); + ret = -1; + goto out; + } + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (); + + ret = 0; + +out: + ctx = glusterd_op_get_ctx (); + if (ctx && start_crawl == _gf_true) + glusterd_quota_initiate_fs_crawl (priv, volname); + + if (ctx && *op_errstr) { + ret = dict_set_dynstr (ctx, "errstr", *op_errstr); + if (ret) { + GF_FREE (*op_errstr); + gf_log ("", GF_LOG_DEBUG, + "failed to set error message in ctx"); + } + *op_errstr = NULL; + } + + return ret; +} + +int +glusterd_op_stage_quota (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + if (!exists) { + gf_log ("", GF_LOG_ERROR, "Volume with name: %s " + "does not exist", + volname); + *op_errstr = gf_strdup ("Invalid volume name"); + ret = -1; + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c new file mode 100644 index 000000000..16fd0bb82 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -0,0 +1,1929 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" +#include "syscall.h" + +#include + +int +glusterd_handle_replace_brick (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_replace_brick_req cli_req = {0,}; + dict_t *dict = NULL; + char *src_brick = NULL; + char *dst_brick = NULL; + int32_t op = 0; + char operation[256]; + glusterd_op_t cli_op = GD_OP_REPLACE_BRICK; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_replace_brick_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received replace brick req"); + + if (cli_req.bricks.bricks_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (cli_req.bricks.bricks_val, + cli_req.bricks.bricks_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, + "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } else { + dict->extra_stdfree = cli_req.bricks.bricks_val; + } + } + + ret = dict_get_int32 (dict, "operation", &op); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "dict_get on operation failed"); + goto out; + } + + ret = dict_get_str (dict, "src-brick", &src_brick); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + goto out; + } + gf_log ("", GF_LOG_DEBUG, + "src brick=%s", src_brick); + + ret = dict_get_str (dict, "dst-brick", &dst_brick); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "dst brick=%s", dst_brick); + + switch (op) { + case GF_REPLACE_OP_START: strcpy (operation, "start"); + break; + case GF_REPLACE_OP_COMMIT: strcpy (operation, "commit"); + break; + case GF_REPLACE_OP_PAUSE: strcpy (operation, "pause"); + break; + case GF_REPLACE_OP_ABORT: strcpy (operation, "abort"); + break; + case GF_REPLACE_OP_STATUS: strcpy (operation, "status"); + break; + case GF_REPLACE_OP_COMMIT_FORCE: strcpy (operation, "commit-force"); + break; + default:strcpy (operation, "unknown"); + break; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received replace brick %s request", operation); + gf_cmd_log ("Volume replace-brick","volname: %s src_brick:%s" + " dst_brick:%s op:%s",cli_req.volname, src_brick, dst_brick + ,operation); + + ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict); + gf_cmd_log ("Volume replace-brick","on volname: %s %s", cli_req.volname, + (ret) ? "FAILED" : "SUCCESS"); + +out: + if (ret && dict) + dict_unref (dict); + if (cli_req.volname) + free (cli_req.volname);//malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + + return ret; +} + + +char * +glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) +{ + char *saveptr = NULL; + char *brick = NULL; + char *brick_list = NULL; + int ret = 0; + glusterd_brickinfo_t *brickinfo = NULL; + uint32_t i = 0; + char *str = NULL; + char msg[2048] = {0,}; + + brick_list = gf_strdup (bricks); + if (!brick_list) { + gf_log ("glusterd", GF_LOG_ERROR, + "Out of memory"); + ret = -1; + goto out; + } + + if (count) + brick = strtok_r (brick_list+1, " \n", &saveptr); + + + while ( i < count) { + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) { + snprintf (msg, sizeof(msg), "Unable to" + " get brickinfo"); + gf_log ("", GF_LOG_ERROR, "%s", msg); + ret = -1; + goto out; + } + + if (glusterd_is_replace_running (volinfo, brickinfo)) { + snprintf (msg, sizeof(msg), "Volume %s: replace brick is running" + " and the brick %s:%s you are trying to add is the destination brick" + " for replace brick", volinfo->volname, brickinfo->hostname, brickinfo->path); + ret = -1; + goto out; + } + + glusterd_brickinfo_delete (brickinfo); + brickinfo = NULL; + brick = strtok_r (NULL, " \n", &saveptr); + i++; + } + +out: + if (brick_list) + GF_FREE(brick_list); + if (brickinfo) + glusterd_brickinfo_delete (brickinfo); + if (ret) + str = gf_strdup (msg); + return str; +} + +static int +glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t **brickinfo) +{ + int32_t ret = -1; + + if (!volinfo || !brickinfo) + goto out; + + *brickinfo = volinfo->dst_brick; + + ret = 0; + +out: + return ret; +} + +int +glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int ret = 0; + char *src_brick = NULL; + char *dst_brick = NULL; + char *volname = NULL; + int replace_op = 0; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *src_brickinfo = NULL; + char *host = NULL; + char *path = NULL; + char msg[2048] = {0}; + char *dup_dstbrick = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_brickinfo_t *dst_brickinfo = NULL; + gf_boolean_t is_run = _gf_false; + + ret = dict_get_str (dict, "src-brick", &src_brick); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); + + ret = dict_get_str (dict, "dst-brick", &dst_brick); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "dict get on replace-brick operation failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "volume: %s does not exist", + volname); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + ret = -1; + snprintf (msg, sizeof (msg), "volume: %s is not started", + volname); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (!glusterd_store_is_valid_brickpath (volname, dst_brick) || + !glusterd_is_valid_volfpath (volname, dst_brick)) { + snprintf (msg, sizeof (msg), "brick path %s is too " + "long.", dst_brick); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + + ret = -1; + goto out; + } + + ret = glusterd_check_gsync_running (volinfo, &is_run); + if (ret && (is_run == _gf_false)) + gf_log ("", GF_LOG_WARNING, "Unable to get the status" + " of active "GEOREP" session"); + if (is_run) { + gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" + "for the volume %s ", volname); + snprintf (msg, sizeof(msg), GEOREP" sessions are active " + "for the volume %s.\nStop "GEOREP "sessions " + "involved in this volume. Use 'volume "GEOREP + " status' command for more info.", + volname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + if (glusterd_is_defrag_on(volinfo)) { + snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " + "progress. Please retry after completion", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + switch (replace_op) { + case GF_REPLACE_OP_START: + if (glusterd_is_rb_started (volinfo)) { + gf_log ("", GF_LOG_ERROR, "Replace brick is already " + "started for volume "); + ret = -1; + goto out; + } + break; + case GF_REPLACE_OP_PAUSE: + if (glusterd_is_rb_paused (volinfo)) { + gf_log ("", GF_LOG_ERROR, "Replace brick is already " + "paused for volume "); + ret = -1; + goto out; + } else if (!glusterd_is_rb_started(volinfo)) { + gf_log ("", GF_LOG_ERROR, "Replace brick is not" + " started for volume "); + ret = -1; + goto out; + } + break; + + case GF_REPLACE_OP_ABORT: + if ((!glusterd_is_rb_paused (volinfo)) && + (!glusterd_is_rb_started (volinfo))) { + gf_log ("", GF_LOG_ERROR, "Replace brick is not" + " started or paused for volume "); + ret = -1; + goto out; + } + break; + + case GF_REPLACE_OP_COMMIT: + if (!glusterd_is_rb_started (volinfo)) { + gf_log ("", GF_LOG_ERROR, "Replace brick is not " + "started for volume "); + ret = -1; + goto out; + } + break; + + case GF_REPLACE_OP_COMMIT_FORCE: break; + case GF_REPLACE_OP_STATUS: + break; + default: + ret = -1; + goto out; + } + + ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, + &src_brickinfo); + if (ret) { + snprintf (msg, sizeof (msg), "brick: %s does not exist in " + "volume: %s", src_brick, volname); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + gf_log ("", GF_LOG_DEBUG, + "I AM THE SOURCE HOST"); + if (src_brickinfo->port && rsp_dict) { + ret = dict_set_int32 (rsp_dict, "src-brick-port", + src_brickinfo->port); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not set src-brick-port=%d", + src_brickinfo->port); + } + } + + } + + dup_dstbrick = gf_strdup (dst_brick); + if (!dup_dstbrick) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); + goto out; + } + host = strtok (dup_dstbrick, ":"); + path = strtok (NULL, ":"); + + if (!host || !path) { + gf_log ("", GF_LOG_ERROR, + "dst brick %s is not of form :", + dst_brick); + ret = -1; + goto out; + } + if (!glusterd_brickinfo_get (NULL, host, path, NULL)) { + snprintf(msg, sizeof(msg), "Brick: %s:%s already in use", + host, path); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && + (replace_op == GF_REPLACE_OP_START)) { + ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); + volinfo->src_brick = src_brickinfo; + volinfo->dst_brick = dst_brickinfo; + } else { + ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); + } + + if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { + gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" + " destination bricks specified"); + ret = -1; + goto out; + } + if (!glusterd_is_local_addr (host)) { + ret = glusterd_brick_create_path (host, path, + volinfo->volume_id, 0777, + op_errstr); + if (ret) + goto out; + } else { + ret = glusterd_friend_find (NULL, host, &peerinfo); + if (ret) { + snprintf (msg, sizeof (msg), "%s, is not a friend", + host); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (!peerinfo->connected) { + snprintf (msg, sizeof (msg), "%s, is not connected at " + "the moment", host); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) { + snprintf (msg, sizeof (msg), "%s, is not befriended " + "at the moment", host); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + } + ret = 0; + +out: + if (dup_dstbrick) + GF_FREE (dup_dstbrick); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int +rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + int32_t pump_needed) +{ + dict_t *dict = NULL; + int ret = 0; + + dict = volinfo->dict; + + gf_log ("", GF_LOG_DEBUG, + "attempting to set pump value=%d", pump_needed); + + ret = dict_set_int32 (dict, "enable-pump", pump_needed); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "could not dict_set enable-pump"); + goto out; + } + + ret = glusterd_create_rb_volfiles (volinfo, brickinfo); + +out: + return ret; +} + +static int +rb_src_brick_restart (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + int activate_pump) +{ + int ret = 0; + + gf_log ("", GF_LOG_DEBUG, + "Attempting to kill src"); + + ret = glusterd_nfs_server_stop (); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to stop nfs, ret: %d", + ret); + } + + ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to stop " + "glusterfs, ret: %d", ret); + goto out; + } + + glusterd_delete_volfile (volinfo, src_brickinfo); + + if (activate_pump) { + ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 1); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not regenerate volfiles with pump"); + goto out; + } + } else { + ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 0); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not regenerate volfiles without pump"); + goto out; + } + + } + + sleep (2); + ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to start " + "glusterfs, ret: %d", ret); + goto out; + } + +out: + ret = glusterd_nfs_server_start (); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to start nfs, ret: %d", + ret); + } + return ret; +} + +static int +rb_send_xattr_command (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo, + const char *xattr_key, + const char *value) +{ + glusterd_conf_t *priv = NULL; + char mount_point_path[PATH_MAX] = {0,}; + struct stat buf; + int ret = -1; + + priv = THIS->private; + + snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = stat (mount_point_path, &buf); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "stat failed. Could not send " + " %s command", xattr_key); + goto out; + } + + ret = sys_lsetxattr (mount_point_path, xattr_key, + value, + strlen (value) + 1, + 0); + + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "setxattr failed"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static int +rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo) +{ + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + int ret = -1; + int32_t port = 0; + + priv = THIS->private; + + port = pmap_registry_alloc (THIS); + brickinfo->port = port; + + GF_ASSERT (port); + + runinit (&runner); + runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); + runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_DSTBRICKVOL_FILENAME, + priv->workdir, volinfo->volname); + runner_argprintf (&runner, "-p" "%s/vols/%s/"RB_DSTBRICK_PIDFILE, + priv->workdir, volinfo->volname); + runner_add_arg (&runner, "--xlator-option"); + runner_argprintf (&runner, "src-server.listen-port=%d", port); + + ret = runner_run (&runner); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not start glusterfs"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "Successfully started glusterfs: brick=%s:%s", + brickinfo->hostname, brickinfo->path); + + ret = 0; + +out: + return ret; +} + +static int +rb_spawn_glusterfs_client (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo) +{ + glusterd_conf_t *priv = NULL; + char cmd_str[8192] = {0,}; + runner_t runner = {0,}; + struct stat buf; + int ret = -1; + + priv = THIS->private; + + runinit (&runner); + runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); + runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_CLIENTVOL_FILENAME, + priv->workdir, volinfo->volname); + runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, + priv->workdir, volinfo->volname); + + ret = runner_run (&runner); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not start glusterfs"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "Successfully started glusterfs: brick=%s:%s", + brickinfo->hostname, brickinfo->path); + + memset (cmd_str, 0, sizeof (cmd_str)); + + snprintf (cmd_str, 4096, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = stat (cmd_str, &buf); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "stat on mountpoint failed"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "stat on mountpoint succeeded"); + + ret = 0; + +out: + return ret; +} + +static const char *client_volfile_str = "volume mnt-client\n" + " type protocol/client\n" + " option remote-host %s\n" + " option remote-subvolume %s\n" + " option remote-port %d\n" + " option transport-type %s\n" + "end-volume\n" + "volume mnt-wb\n" + " type performance/write-behind\n" + " subvolumes mnt-client\n" + "end-volume\n"; + +static int +rb_generate_client_volfile (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo) +{ + glusterd_conf_t *priv = NULL; + FILE *file = NULL; + char filename[PATH_MAX] = {0, }; + int ret = -1; + char *ttype = NULL; + + priv = THIS->private; + + gf_log ("", GF_LOG_DEBUG, + "Creating volfile"); + + snprintf (filename, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENTVOL_FILENAME); + + file = fopen (filename, "w+"); + if (!file) { + gf_log ("", GF_LOG_DEBUG, + "Open of volfile failed"); + ret = -1; + goto out; + } + + GF_ASSERT (src_brickinfo->port); + + ttype = glusterd_get_trans_type_rb (volinfo->transport_type); + if (NULL == ttype){ + ret = -1; + goto out; + } + + fprintf (file, client_volfile_str, src_brickinfo->hostname, + src_brickinfo->path, src_brickinfo->port, ttype); + + fclose (file); + GF_FREE (ttype); + + ret = 0; + +out: + return ret; +} + +static const char *dst_brick_volfile_str = "volume src-posix\n" + " type storage/posix\n" + " option directory %s\n" + "end-volume\n" + "volume %s\n" + " type features/locks\n" + " subvolumes src-posix\n" + "end-volume\n" + "volume src-server\n" + " type protocol/server\n" + " option auth.addr.%s.allow *\n" + " option transport-type %s\n" + " subvolumes %s\n" + "end-volume\n"; + +static int +rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + glusterd_conf_t *priv = NULL; + FILE *file = NULL; + char filename[PATH_MAX] = {0, }; + int ret = -1; + char *trans_type = NULL; + + priv = THIS->private; + + gf_log ("", GF_LOG_DEBUG, + "Creating volfile"); + + snprintf (filename, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_DSTBRICKVOL_FILENAME); + + file = fopen (filename, "w+"); + if (!file) { + gf_log ("", GF_LOG_DEBUG, + "Open of volfile failed"); + ret = -1; + goto out; + } + + trans_type = glusterd_get_trans_type_rb (volinfo->transport_type); + if (NULL == trans_type){ + ret = -1; + goto out; + } + + fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, + dst_brickinfo->path, dst_brickinfo->path, + trans_type, dst_brickinfo->path); + + GF_FREE (trans_type); + + fclose (file); + + ret = 0; + +out: + return ret; +} + + +static int +rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo) +{ + glusterd_conf_t *priv = NULL; + char mount_point_path[PATH_MAX] = {0,}; + int ret = -1; + + priv = THIS->private; + + snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = mkdir (mount_point_path, 0777); + if (ret && (errno != EEXIST)) { + gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", + errno); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static int +rb_mountpoint_rmdir (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo) +{ + glusterd_conf_t *priv = NULL; + char mount_point_path[PATH_MAX] = {0,}; + int ret = -1; + + priv = THIS->private; + + snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = rmdir (mount_point_path); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "rmdir failed"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static int +rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo) +{ + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + char filename[PATH_MAX] = {0,}; + struct stat buf; + char mount_point_path[PATH_MAX] = {0,}; + int ret = -1; + + priv = THIS->private; + + snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = stat (mount_point_path, &buf); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "stat failed. Cannot destroy maintenance " + "client"); + goto out; + } + + runinit (&runner); + runner_add_args (&runner, "/bin/umount", "-f", NULL); + runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, + priv->workdir, volinfo->volname); + + ret = runner_run (&runner); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "umount failed on maintenance client"); + goto out; + } + + ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "rmdir of mountpoint failed"); + goto out; + } + + snprintf (filename, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENTVOL_FILENAME); + + ret = unlink (filename); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "unlink failed"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static int +rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo) +{ + int ret = -1; + + ret = rb_generate_client_volfile (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to generate client " + "volfile"); + goto out; + } + + ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " + "mountpoint"); + goto out; + } + + ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); + goto out; + } + + ret = 0; +out: + return ret; +} + +static int +rb_spawn_destination_brick (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *dst_brickinfo) + +{ + int ret = -1; + + ret = rb_generate_dst_brick_volfile (volinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to generate client " + "volfile"); + goto out; + } + + ret = rb_spawn_dst_brick (volinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); + goto out; + } + + ret = 0; +out: + return ret; +} + +static int +rb_do_operation_start (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + char start_value[8192] = {0,}; + int ret = -1; + + + gf_log ("", GF_LOG_DEBUG, + "replace-brick sending start xattr"); + + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not spawn maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "mounted the replace brick client"); + + snprintf (start_value, 8192, "%s:%s:%d", + dst_brickinfo->hostname, + dst_brickinfo->path, + dst_brickinfo->port); + + + ret = rb_send_xattr_command (volinfo, src_brickinfo, + dst_brickinfo, RB_PUMP_START_CMD, + start_value); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to send command to pump"); + } + + ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to destroy maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "unmounted the replace brick client"); + ret = 0; + +out: + return ret; +} + +static int +rb_do_operation_pause (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + int ret = -1; + + gf_log ("", GF_LOG_INFO, + "replace-brick send pause xattr"); + + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not spawn maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "mounted the replace brick client"); + + ret = rb_send_xattr_command (volinfo, src_brickinfo, + dst_brickinfo, RB_PUMP_PAUSE_CMD, + "jargon"); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to send command to pump"); + + } + + ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to destroy maintenance " + "client"); + goto out; + } + + + gf_log ("", GF_LOG_DEBUG, + "unmounted the replace brick client"); + + ret = 0; + +out: + if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + ret = rb_src_brick_restart (volinfo, src_brickinfo, + 0); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not restart src-brick"); + } + } + return ret; +} + +static int +rb_kill_destination_brick (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + glusterd_conf_t *priv = NULL; + char pidfile[PATH_MAX] = {0,}; + + priv = THIS->private; + + snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_DSTBRICK_PIDFILE); + + return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); +} + +static int +rb_do_operation_commit (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + int ret = -1; + int cmd_ret = -1; + + gf_log ("", GF_LOG_DEBUG, + "replace-brick sending commit xattr"); + + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not spawn maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "mounted the replace brick client"); + + cmd_ret = rb_send_xattr_command (volinfo, src_brickinfo, + dst_brickinfo, RB_PUMP_COMMIT_CMD, + "jargon"); + if (cmd_ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to send command to pump"); + } + + ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to destroy maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "unmounted the replace brick client"); + + ret = 0; + +out: + return cmd_ret || ret; +} + +static int +rb_do_operation_abort (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + int ret = -1; + + gf_log ("", GF_LOG_DEBUG, + "replace-brick sending abort xattr"); + + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not spawn maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "mounted the replace brick client"); + + ret = rb_send_xattr_command (volinfo, src_brickinfo, + dst_brickinfo, RB_PUMP_ABORT_CMD, + "jargon"); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to send command to pump"); + } + + ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to destroy maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "unmounted the replace brick client"); + + ret = 0; + +out: + if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + ret = rb_src_brick_restart (volinfo, src_brickinfo, + 0); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not restart src-brick"); + } + } + return ret; +} + + +static int +rb_get_xattr_command (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo, + const char *xattr_key, + char *value) +{ + glusterd_conf_t *priv = NULL; + char mount_point_path[PATH_MAX] = {0,}; + struct stat buf; + int ret = -1; + + priv = THIS->private; + + snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", + priv->workdir, volinfo->volname, + RB_CLIENT_MOUNTPOINT); + + ret = stat (mount_point_path, &buf); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "stat failed. Could not send " + " %s command", xattr_key); + goto out; + } + + ret = sys_lgetxattr (mount_point_path, xattr_key, value, 8192); + + if (ret < 0) { + gf_log ("", GF_LOG_DEBUG, + "getxattr failed"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static int +rb_do_operation_status (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo) +{ + char status[8192] = {0,}; + char *status_reply = NULL; + dict_t *ctx = NULL; + int ret = 0; + gf_boolean_t origin = _gf_false; + + ctx = glusterd_op_get_ctx (); + if (!ctx) { + gf_log ("", GF_LOG_ERROR, + "Operation Context is not present"); + goto out; + } + + origin = _gf_true; + + if (origin) { + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not spawn maintenance " + "client"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "mounted the replace brick client"); + + ret = rb_get_xattr_command (volinfo, src_brickinfo, + dst_brickinfo, RB_PUMP_STATUS_CMD, + status); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to get status from pump"); + goto umount; + } + + gf_log ("", GF_LOG_DEBUG, + "pump status is %s", status); + + status_reply = gf_strdup (status); + if (!status_reply) { + gf_log ("", GF_LOG_ERROR, "Out of memory"); + ret = -1; + goto umount; + } + + ret = dict_set_dynstr (ctx, "status-reply", + status_reply); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "failed to set pump status in ctx"); + + } + + umount: + ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to destroy maintenance " + "client"); + goto out; + } + } + + gf_log ("", GF_LOG_DEBUG, + "unmounted the replace brick client"); +out: + return ret; +} + +/* Set src-brick's port number to be used in the maintainance mount + * after all commit acks are received. + */ +static int +rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, + dict_t *req_dict, int32_t replace_op) +{ + xlator_t *this = NULL; + dict_t *ctx = NULL; + int ret = 0; + int dict_ret = 0; + int src_port = 0; + + this = THIS; + + ctx = glusterd_op_get_ctx (); + if (ctx) { + dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); + if (src_port) + src_brickinfo->port = src_port; + } + + if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + gf_log ("", GF_LOG_INFO, + "adding src-brick port no"); + + src_brickinfo->port = pmap_registry_search (this, + src_brickinfo->path, GF_PMAP_PORT_BRICKSERVER); + if (!src_brickinfo->port && + replace_op != GF_REPLACE_OP_COMMIT_FORCE ) { + gf_log ("", GF_LOG_ERROR, + "Src brick port not available"); + ret = -1; + goto out; + } + + if (rsp_dict) { + ret = dict_set_int32 (rsp_dict, "src-brick-port", src_brickinfo->port); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not set src-brick port no"); + goto out; + } + } + + ctx = glusterd_op_get_ctx (); + if (ctx) { + ret = dict_set_int32 (ctx, "src-brick-port", src_brickinfo->port); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not set src-brick port no"); + goto out; + } + } + + } + +out: + return ret; + +} + +static int +rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, + dict_t *req_dict, int32_t replace_op) +{ + dict_t *ctx = NULL; + int ret = 0; + int dict_ret = 0; + int dst_port = 0; + + ctx = glusterd_op_get_ctx (); + if (ctx) { + dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); + if (dst_port) + dst_brickinfo->port = dst_port; + + } + + if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { + gf_log ("", GF_LOG_INFO, + "adding dst-brick port no"); + + if (rsp_dict) { + ret = dict_set_int32 (rsp_dict, "dst-brick-port", + dst_brickinfo->port); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not set dst-brick port no in rsp dict"); + goto out; + } + } + + ctx = glusterd_op_get_ctx (); + if (ctx) { + ret = dict_set_int32 (ctx, "dst-brick-port", + dst_brickinfo->port); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not set dst-brick port no"); + goto out; + } + } + } +out: + return ret; +} + +static int +glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, + char *old_brick, char *new_brick) +{ + glusterd_brickinfo_t *old_brickinfo = NULL; + glusterd_brickinfo_t *new_brickinfo = NULL; + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + + GF_ASSERT (volinfo); + + ret = glusterd_brickinfo_from_brick (new_brick, + &new_brickinfo); + if (ret) + goto out; + + ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, + &old_brickinfo); + if (ret) + goto out; + + ret = glusterd_resolve_brick (new_brickinfo); + if (ret) + goto out; + + list_add_tail (&new_brickinfo->brick_list, + &old_brickinfo->brick_list); + + volinfo->brick_count++; + + ret = glusterd_op_perform_remove_brick (volinfo, old_brick); + if (ret) + goto out; + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_brick_start (volinfo, new_brickinfo); + if (ret) + goto out; + } + + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) +{ + int ret = 0; + dict_t *ctx = NULL; + int replace_op = 0; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char *src_brick = NULL; + char *dst_brick = NULL; + glusterd_brickinfo_t *src_brickinfo = NULL; + glusterd_brickinfo_t *dst_brickinfo = NULL; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "src-brick", &src_brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + goto out; + } + + gf_log (this->name, GF_LOG_DEBUG, + "src brick=%s", src_brick); + + ret = dict_get_str (dict, "dst-brick", &dst_brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); + goto out; + } + + gf_log (this->name, GF_LOG_DEBUG, + "dst brick=%s", dst_brick); + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "dict_get on operation failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); + goto out; + } + + + ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get " + "replace brick destination brickinfo"); + goto out; + } + + ret = glusterd_resolve_brick (dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); + goto out; + } + + ret = rb_update_srcbrick_port (src_brickinfo, rsp_dict, + dict, replace_op); + if (ret) + goto out; + + if ((GF_REPLACE_OP_START != replace_op)) { + ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, + dict, replace_op); + if (ret) + goto out; + } + + switch (replace_op) { + case GF_REPLACE_OP_START: + { + if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { + gf_log ("", GF_LOG_INFO, + "I AM THE DESTINATION HOST"); + if (!glusterd_is_rb_paused (volinfo)) { + ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to spawn destination brick"); + goto out; + } + } else { + gf_log ("", GF_LOG_ERROR, "Replace brick is already " + "started=> no need to restart dst brick "); + } + } + + + if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + ret = rb_src_brick_restart (volinfo, src_brickinfo, + 1); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Could not restart src-brick"); + goto out; + } + } + + if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { + gf_log ("", GF_LOG_INFO, + "adding dst-brick port no"); + + ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, + dict, replace_op); + if (ret) + goto out; + } + + glusterd_set_rb_status (volinfo, GF_RB_STATUS_STARTED); + break; + } + + case GF_REPLACE_OP_COMMIT: + case GF_REPLACE_OP_COMMIT_FORCE: + { + ctx = glusterd_op_get_ctx (); + if (ctx) { + ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Commit operation failed"); + goto out; + } + } + + ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); + gf_log ("", GF_LOG_DEBUG, + "Received commit - will be adding dst brick and " + "removing src brick"); + + if (!glusterd_is_local_addr (dst_brickinfo->hostname) && + replace_op != GF_REPLACE_OP_COMMIT_FORCE) { + gf_log ("", GF_LOG_INFO, + "I AM THE DESTINATION HOST"); + ret = rb_kill_destination_brick (volinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to kill destination brick"); + goto out; + } + } + + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "Unable to cleanup dst brick"); + goto out; + } + + + ret = glusterd_nfs_server_stop (); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Unable to stop nfs server, ret: %d", ret); + } + + ret = glusterd_op_perform_replace_brick (volinfo, src_brick, + dst_brick); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, "Unable to add " + "dst-brick: %s to volume: %s", + dst_brick, volinfo->volname); + (void) glusterd_check_generate_start_nfs (); + goto out; + } + + volinfo->defrag_status = 0; + + ret = glusterd_check_generate_start_nfs (); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "Failed to generate nfs volume file"); + } + + + ret = glusterd_fetchspec_notify (THIS); + glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); + glusterd_brickinfo_delete (volinfo->dst_brick); + volinfo->src_brick = volinfo->dst_brick = NULL; + } + break; + + case GF_REPLACE_OP_PAUSE: + { + gf_log ("", GF_LOG_DEBUG, + "Received pause - doing nothing"); + ctx = glusterd_op_get_ctx (); + if (ctx) { + ret = rb_do_operation_pause (volinfo, src_brickinfo, + dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Pause operation failed"); + goto out; + } + } + + glusterd_set_rb_status (volinfo, GF_RB_STATUS_PAUSED); + } + break; + + case GF_REPLACE_OP_ABORT: + { + + ctx = glusterd_op_get_ctx (); + if (ctx) { + ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Abort operation failed"); + goto out; + } + } + + ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); + if (ret) { + gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to disable pump"); + } + + + if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { + gf_log (THIS->name, GF_LOG_INFO, + "I AM THE DESTINATION HOST"); + ret = rb_kill_destination_brick (volinfo, dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "Failed to kill destination brick"); + goto out; + } + } + glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); + glusterd_brickinfo_delete (volinfo->dst_brick); + volinfo->src_brick = volinfo->dst_brick = NULL; + } + break; + + case GF_REPLACE_OP_STATUS: + { + gf_log ("", GF_LOG_DEBUG, + "received status - doing nothing"); + ctx = glusterd_op_get_ctx (); + if (ctx) { + if (glusterd_is_rb_paused (volinfo)) { + ret = dict_set_str (ctx, "status-reply", + "replace brick has been paused"); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, + "failed to set pump status" + "in ctx"); + goto out; + } + + ret = rb_do_operation_status (volinfo, src_brickinfo, + dst_brickinfo); + if (ret) + goto out; + } + + } + break; + + default: + ret = -1; + goto out; + } + if (!ret && replace_op != GF_REPLACE_OP_STATUS) + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, "Couldn't store" + " replace brick operation's state"); + +out: + return ret; +} + +void +glusterd_do_replace_brick (void *data) +{ + glusterd_volinfo_t *volinfo = NULL; + int32_t op = 0; + int32_t src_port = 0; + int32_t dst_port = 0; + dict_t *dict = NULL; + char *src_brick = NULL; + char *dst_brick = NULL; + char *volname = NULL; + glusterd_brickinfo_t *src_brickinfo = NULL; + glusterd_brickinfo_t *dst_brickinfo = NULL; + glusterd_conf_t *priv = NULL; + + int ret = 0; + + dict = data; + + GF_ASSERT (THIS); + + priv = THIS->private; + + if (priv->timer) { + gf_timer_call_cancel (THIS->ctx, priv->timer); + priv->timer = NULL; + gf_log ("", GF_LOG_DEBUG, + "Cancelled timer thread"); + } + + gf_log ("", GF_LOG_DEBUG, + "Replace brick operation detected"); + + ret = dict_get_int32 (dict, "operation", &op); + if (ret) { + gf_log ("", GF_LOG_DEBUG, + "dict_get on operation failed"); + goto out; + } + ret = dict_get_str (dict, "src-brick", &src_brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "src brick=%s", src_brick); + + ret = dict_get_str (dict, "dst-brick", &dst_brick); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); + goto out; + } + + gf_log ("", GF_LOG_DEBUG, + "dst brick=%s", dst_brick); + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); + goto out; + } + + ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); + if (!dst_brickinfo) { + gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); + goto out; + } + + ret = glusterd_resolve_brick (dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); + goto out; + } + + ret = dict_get_int32 (dict, "src-brick-port", &src_port); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); + goto out; + } + + ret = dict_get_int32 (dict, "dst-brick-port", &dst_port); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get dst-brick port"); + } + + dst_brickinfo->port = dst_port; + src_brickinfo->port = src_port; + + switch (op) { + case GF_REPLACE_OP_START: + if (!dst_port) { + ret = -1; + goto out; + } + + ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); + if (ret) { + glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); + goto out; + } + break; + case GF_REPLACE_OP_PAUSE: + case GF_REPLACE_OP_ABORT: + case GF_REPLACE_OP_COMMIT: + case GF_REPLACE_OP_COMMIT_FORCE: + case GF_REPLACE_OP_STATUS: + break; + default: + ret = -1; + goto out; + } + +out: + if (ret) + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); + else + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); + + if (dict) + dict_unref (dict); + + glusterd_op_sm (); +} diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c new file mode 100644 index 000000000..1e4670304 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -0,0 +1,1038 @@ +/* + Copyright (c) 2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#define glusterd_op_start_volume_args_get(dict, volname, flags) \ + glusterd_op_stop_volume_args_get (dict, volname, flags) + +int +glusterd_handle_create_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_create_vol_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; + char *brick_list = NULL; + void *cli_rsp = NULL; + char err_str[2048] = {0,}; + gf1_cli_create_vol_rsp rsp = {0,}; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + char *free_ptr = NULL; + char *trans_type = NULL; + uuid_t volume_id = {0,}; + glusterd_brickinfo_t *tmpbrkinfo = NULL; + glusterd_volinfo_t tmpvolinfo = {{0},}; + + GF_ASSERT (req); + + INIT_LIST_HEAD (&tmpvolinfo.bricks); + + this = THIS; + GF_ASSERT(this); + + priv = this->private; + + ret = -1; + if (!gf_xdr_to_cli_create_vol_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + snprintf (err_str, sizeof (err_str), "Garbage args received"); + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received create volume req"); + + if (cli_req.bricks.bricks_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (cli_req.bricks.bricks_val, + cli_req.bricks.bricks_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, + "failed to " + "unserialize req-buffer to dictionary"); + snprintf (err_str, sizeof (err_str), "Unable to decode " + "the buffer"); + goto out; + } else { + dict->extra_stdfree = cli_req.bricks.bricks_val; + } + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "name"); + goto out; + } + gf_cmd_log ("Volume create", "on volname: %s attempted", volname); + + if ((ret = glusterd_check_volume_exists (volname))) { + snprintf(err_str, 2048, "Volume %s already exists", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); + goto out; + } + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "brick count"); + goto out; + } + + ret = dict_get_str (dict, "transport", &trans_type); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get transport-type"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "transport-type"); + goto out; + } + ret = dict_get_str (dict, "bricks", &bricks); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + snprintf (err_str, sizeof (err_str), "Unable to get volume " + "bricks"); + goto out; + } + + uuid_generate (volume_id); + free_ptr = gf_strdup (uuid_utoa (volume_id)); + ret = dict_set_dynstr (dict, "volume-id", free_ptr); + if (ret) { + gf_log ("", GF_LOG_ERROR, "unable to set volume-id"); + snprintf (err_str, sizeof (err_str), "Unable to set volume " + "id"); + goto out; + } + free_ptr = NULL; + + if (bricks) { + brick_list = gf_strdup (bricks); + free_ptr = brick_list; + } + + gf_cmd_log ("Volume create", "on volname: %s type:%s count:%d bricks:%s", + cli_req.volname, ((cli_req.type == 0)? "DEFAULT": + ((cli_req.type == 1)? "STRIPE":"REPLICATE")), cli_req.count, + 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) { + snprintf (err_str, sizeof (err_str), "Unable to get " + "brick info from brick %s", brick); + goto out; + } + + ret = glusterd_new_brick_validate (brick, brickinfo, err_str, + sizeof (err_str)); + if (ret) + goto out; + ret = glusterd_volume_brickinfo_get (brickinfo->uuid, + brickinfo->hostname, + brickinfo->path, + &tmpvolinfo, &tmpbrkinfo); + if (!ret) { + ret = -1; + snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" + " one of the arguments contain the other", + tmpbrkinfo->hostname, tmpbrkinfo->path, brick); + goto out; + } + list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); + brickinfo = NULL; + } + + ret = glusterd_op_begin (req, GD_OP_CREATE_VOLUME, dict); + gf_cmd_log ("Volume create", "on volname: %s %s", volname, + (ret != 0) ? "FAILED": "SUCCESS"); + +out: + if (ret) { + if (dict) + dict_unref (dict); + rsp.op_ret = -1; + rsp.op_errno = 0; + rsp.volname = ""; + if (err_str[0] == '\0') + snprintf (err_str, sizeof (err_str), "Operation failed"); + rsp.op_errstr = err_str; + cli_rsp = &rsp; + glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, + gf_xdr_serialize_cli_create_vol_rsp, + (xdrproc_t)xdr_gf1_cli_create_vol_rsp); + + ret = 0; //Client response sent, prevent second response + } + + if (free_ptr) + GF_FREE(free_ptr); + + glusterd_volume_brickinfos_delete (&tmpvolinfo); + if (brickinfo) + glusterd_brickinfo_delete (brickinfo); + if (cli_req.volname) + free (cli_req.volname); // its a malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + return ret; +} + +int +glusterd_handle_cli_start_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_start_vol_req cli_req = {0,}; + char *dup_volname = NULL; + dict_t *dict = NULL; + glusterd_op_t cli_op = GD_OP_START_VOLUME; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_start_vol_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received start vol req" + "for volume %s", cli_req.volname); + + dict = dict_new (); + + if (!dict) + goto out; + + dup_volname = gf_strdup (cli_req.volname); + if (!dup_volname) + goto out; + + ret = dict_set_dynstr (dict, "volname", dup_volname); + if (ret) + goto out; + + ret = dict_set_int32 (dict, "flags", cli_req.flags); + if (ret) + goto out; + ret = glusterd_op_begin (req, GD_OP_START_VOLUME, dict); + + gf_cmd_log ("volume start","on volname: %s %s", cli_req.volname, + ((ret == 0) ? "SUCCESS": "FAILED")); + +out: + if (ret && dict) + dict_unref (dict); + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + + return ret; +} + + +int +glusterd_handle_cli_stop_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_stop_vol_req cli_req = {0,}; + char *dup_volname = NULL; + dict_t *dict = NULL; + glusterd_op_t cli_op = GD_OP_STOP_VOLUME; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_stop_vol_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_INFO, "Received stop vol req" + "for volume %s", cli_req.volname); + + dict = dict_new (); + + if (!dict) + goto out; + + dup_volname = gf_strdup (cli_req.volname); + if (!dup_volname) + goto out; + + ret = dict_set_dynstr (dict, "volname", dup_volname); + if (ret) + goto out; + + ret = dict_set_int32 (dict, "flags", cli_req.flags); + if (ret) + goto out; + + ret = glusterd_op_begin (req, GD_OP_STOP_VOLUME, dict); + gf_cmd_log ("Volume stop","on volname: %s %s", cli_req.volname, + ((ret)?"FAILED":"SUCCESS")); + +out: + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) { + if (dict) + dict_unref (dict); + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + } + + return ret; +} + +int +glusterd_handle_cli_delete_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_delete_vol_req cli_req = {0,}; + glusterd_op_delete_volume_ctx_t *ctx = NULL; + glusterd_op_t cli_op = GD_OP_DELETE_VOLUME; + + GF_ASSERT (req); + + if (!gf_xdr_to_cli_delete_vol_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + gf_cmd_log ("Volume delete","on volname: %s attempted", cli_req.volname); + + gf_log ("glusterd", GF_LOG_INFO, "Received delete vol req" + "for volume %s", cli_req.volname); + + + ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_delete_volume_ctx_t); + if (!ctx) + goto out; + + strncpy (ctx->volume_name, cli_req.volname, GD_VOLUME_NAME_MAX); + + ret = glusterd_op_begin (req, GD_OP_DELETE_VOLUME, ctx); + gf_cmd_log ("Volume delete", "on volname: %s %s", cli_req.volname, + ((ret) ? "FAILED" : "SUCCESS")); + +out: + if (cli_req.volname) + free (cli_req.volname); //its malloced by xdr + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) { + if (ctx) + GF_FREE (ctx); + + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + } + + return ret; +} + +/* op-sm */ +int +glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + char *bricks = NULL; + char *brick_list = NULL; + char *free_ptr = NULL; + glusterd_brickinfo_t *brick_info = NULL; + int32_t brick_count = 0; + int32_t i = 0; + char *brick = NULL; + char *tmpptr = NULL; + char cmd_str[1024]; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char msg[2048] = {0}; + uuid_t volume_uuid; + char *volume_uuid_str; + + this = THIS; + if (!this) { + gf_log ("glusterd", GF_LOG_ERROR, + "this is NULL"); + goto out; + } + + priv = this->private; + if (!priv) { + gf_log ("glusterd", GF_LOG_ERROR, + "priv is NULL"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + + if (exists) { + snprintf (msg, sizeof (msg), "Volume %s already exists", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } else { + ret = 0; + } + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + ret = dict_get_str (dict, "volume-id", &volume_uuid_str); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume id"); + goto out; + } + ret = uuid_parse (volume_uuid_str, volume_uuid); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to parse volume id"); + goto out; + } + + 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); + if (!brick_list) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Out of memory"); + goto out; + } else { + free_ptr = brick_list; + } + } + + while ( i < brick_count) { + i++; + brick= strtok_r (brick_list, " \n", &tmpptr); + brick_list = tmpptr; + + if (!glusterd_store_is_valid_brickpath (volname, brick) || + !glusterd_is_valid_volfpath (volname, brick)) { + snprintf (msg, sizeof (msg), "brick path %s is too " + "long.", brick); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + + ret = -1; + goto out; + } + + ret = glusterd_brickinfo_from_brick (brick, &brick_info); + if (ret) + goto out; + snprintf (cmd_str, 1024, "%s", brick_info->path); + ret = glusterd_resolve_brick (brick_info); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " + "brick: %s:%s", brick_info->hostname, + brick_info->path); + goto out; + } + + if (!uuid_compare (brick_info->uuid, priv->uuid)) { + ret = glusterd_brick_create_path (brick_info->hostname, + brick_info->path, + volume_uuid, + 0777, op_errstr); + if (ret) + goto out; + brick_list = tmpptr; + } + glusterd_brickinfo_delete (brick_info); + brick_info = NULL; + } +out: + if (free_ptr) + GF_FREE (free_ptr); + if (brick_info) + glusterd_brickinfo_delete (brick_info); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags) +{ + int ret = -1; + + if (!dict || !volname || !flags) + goto out; + + ret = dict_get_str (dict, "volname", volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = dict_get_int32 (dict, "flags", flags); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get flags"); + goto out; + } +out: + return ret; +} + +int +glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + int flags = 0; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char msg[2048]; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + if (!priv) { + gf_log ("glusterd", GF_LOG_ERROR, + "priv is NULL"); + ret = -1; + goto out; + } + + ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); + if (ret) + goto out; + + exists = glusterd_check_volume_exists (volname); + + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); + gf_log ("", GF_LOG_ERROR, "%s", + msg); + *op_errstr = gf_strdup (msg); + ret = -1; + } else { + ret = 0; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_resolve_brick (brickinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Unable to resolve brick %s:%s", + brickinfo->hostname, brickinfo->path); + goto out; + } + + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + ret = glusterd_brick_create_path (brickinfo->hostname, + brickinfo->path, + volinfo->volume_id, + 0777, op_errstr); + if (ret) + goto out; + } + + if (!(flags & GF_CLI_FLAG_OP_FORCE)) { + if (glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "Volume %s already" + " started", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + } + } + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + int flags = 0; + gf_boolean_t exists = _gf_false; + gf_boolean_t is_run = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + char msg[2048] = {0}; + + + ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); + if (ret) + goto out; + + exists = glusterd_check_volume_exists (volname); + + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } else { + ret = 0; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + + if (!(flags & GF_CLI_FLAG_OP_FORCE)) { + if (_gf_false == glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof(msg), "Volume %s " + "is not in the started state", volname); + gf_log ("", GF_LOG_ERROR, "Volume %s " + "has not been started", volname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + ret = glusterd_check_gsync_running (volinfo, &is_run); + if (ret && (is_run == _gf_false)) + gf_log ("", GF_LOG_WARNING, "Unable to get the status" + " of active "GEOREP" session"); + if (is_run) { + gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" + "for the volume %s ", volname); + snprintf (msg, sizeof(msg), GEOREP" sessions are active " + "for the volume '%s'.\nUse 'volume "GEOREP" " + "status' command for more info. Use 'force'" + "option to ignore and stop stop the volume", + volname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + } + + +out: + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + char msg[2048] = {0}; + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } else { + ret = 0; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + + if (glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "Volume %s has been started." + "Volume needs to be stopped before deletion.", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + ret = 0; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int +glusterd_op_create_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + gf_boolean_t vol_added = _gf_false; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + char *brick = NULL; + int32_t count = 0; + int32_t i = 1; + char *bricks = NULL; + char *brick_list = NULL; + char *free_ptr = NULL; + char *saveptr = NULL; + int32_t sub_count = 0; + char *trans_type = NULL; + char *str = NULL; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + ret = glusterd_volinfo_new (&volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); + GF_ASSERT (volinfo->volname); + + ret = dict_get_int32 (dict, "type", &volinfo->type); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get type"); + goto out; + } + + ret = dict_get_int32 (dict, "count", &volinfo->brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + ret = dict_get_int32 (dict, "port", &volinfo->port); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get port"); + goto out; + } + + count = volinfo->brick_count; + + ret = dict_get_str (dict, "bricks", &bricks); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + goto out; + } + + if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { + ret = dict_get_int32 (dict, "replica-count", + &sub_count); + if (ret) + goto out; + } else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) { + ret = dict_get_int32 (dict, "stripe-count", + &sub_count); + if (ret) + goto out; + } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { + ret = dict_get_int32 (dict, "stripe-count", + &volinfo->stripe_count); + if (ret) + goto out; + ret = dict_get_int32 (dict, "replica-count", + &volinfo->replica_count); + if (ret) + goto out; + + sub_count = volinfo->stripe_count * volinfo->replica_count; + } + + ret = dict_get_str (dict, "transport", &trans_type); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get transport"); + goto out; + } + + ret = dict_get_str (dict, "volume-id", &str); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume-id"); + goto out; + } + ret = uuid_parse (str, volinfo->volume_id); + if (ret) { + gf_log ("", GF_LOG_ERROR, "unable to parse uuid %s", str); + goto out; + } + + if (strcasecmp (trans_type, "rdma") == 0) { + volinfo->transport_type = GF_TRANSPORT_RDMA; + volinfo->nfs_transport_type = GF_TRANSPORT_RDMA; + } else if (strcasecmp (trans_type, "tcp") == 0) { + volinfo->transport_type = GF_TRANSPORT_TCP; + volinfo->nfs_transport_type = GF_TRANSPORT_TCP; + } else { + volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; + volinfo->nfs_transport_type = GF_DEFAULT_NFS_TRANSPORT; + } + + volinfo->sub_count = sub_count; + + if (bricks) { + brick_list = gf_strdup (bricks); + free_ptr = brick_list; + } + + if (count) + brick = strtok_r (brick_list+1, " \n", &saveptr); + + while ( i <= count) { + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) + goto out; + + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; + list_add_tail (&brickinfo->brick_list, &volinfo->bricks); + brick = strtok_r (NULL, " \n", &saveptr); + i++; + } + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + glusterd_store_delete_volume (volinfo); + *op_errstr = gf_strdup ("Failed to store the Volume information"); + goto out; + } + + ret = glusterd_create_volfiles_and_notify_services (volinfo); + if (ret) { + *op_errstr = gf_strdup ("Failed to create volume files"); + goto out; + } + + ret = glusterd_volume_compute_cksum (volinfo); + if (ret) { + *op_errstr = gf_strdup ("Failed to compute checksum of volume"); + goto out; + } + + volinfo->defrag_status = 0; + list_add_tail (&volinfo->vol_list, &priv->volumes); + vol_added = _gf_true; +out: + if (free_ptr) + GF_FREE(free_ptr); + if (!vol_added && volinfo) + glusterd_volinfo_delete (volinfo); + return ret; +} + +int +glusterd_op_start_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + char *volname = NULL; + int flags = 0; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_brick_start (volinfo, brickinfo); + if (ret) + goto out; + } + + glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + ret = glusterd_check_generate_start_nfs (); + +out: + gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); + return ret; +} + + +int +glusterd_op_stop_volume (dict_t *dict) +{ + int ret = 0; + int flags = 0; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_brick_stop (volinfo, brickinfo); + if (ret) + goto out; + } + + glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; + + if (glusterd_are_all_volumes_stopped ()) { + if (glusterd_is_nfs_started ()) { + ret = glusterd_nfs_server_stop (); + if (ret) + goto out; + } + } else { + ret = glusterd_check_generate_start_nfs (); + } + +out: + return ret; +} + +int +glusterd_op_delete_volume (dict_t *dict) +{ + int ret = 0; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + goto out; + + ret = glusterd_delete_volume (volinfo); +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index e16d6209b..5a39c3089 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -526,4 +526,57 @@ glusterd_rpc_create (struct rpc_clnt **rpc, dict_t *options, int glusterd_handle_log_level (rpcsvc_request_t *req); + +/* handler functions */ +int32_t glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx); + +int glusterd_handle_gsync_set (rpcsvc_request_t *req); +int glusterd_handle_quota (rpcsvc_request_t *req); +int glusterd_handle_replace_brick (rpcsvc_request_t *req); +int glusterd_handle_log_filename (rpcsvc_request_t *req); +int glusterd_handle_log_locate (rpcsvc_request_t *req); +int glusterd_handle_log_level (rpcsvc_request_t *req); +int glusterd_handle_log_rotate (rpcsvc_request_t *req); +int glusterd_handle_create_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_start_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_stop_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_delete_volume (rpcsvc_request_t *req); + + +/* op-sm functions */ +int glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr); +int glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict); +int glusterd_op_quota (dict_t *dict, char **op_errstr); +int glusterd_op_stage_quota (dict_t *dict, char **op_errstr); +int glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, + dict_t *rsp_dict); +int glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict); +int glusterd_op_log_level (dict_t *dict); +int glusterd_op_log_filename (dict_t *dict); +int glusterd_op_log_rotate (dict_t *dict); +int glusterd_op_stage_log_level (dict_t *dict, char **op_errstr); +int glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr); +int glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr); +int glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr); +int glusterd_op_create_volume (dict_t *dict, char **op_errstr); +int glusterd_op_start_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stop_volume (dict_t *dict); +int glusterd_op_delete_volume (dict_t *dict); + +int glusterd_op_add_brick (dict_t *dict, char **op_errstr); +int glusterd_op_remove_brick (dict_t *dict); +int glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr); +int glusterd_op_stage_remove_brick (dict_t *dict); + + + +/* misc */ +void glusterd_do_replace_brick (void *data); +int glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick); +int glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags); + + #endif -- cgit