diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-tier.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-tier.c | 1409 |
1 files changed, 0 insertions, 1409 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-tier.c b/xlators/mgmt/glusterd/src/glusterd-tier.c deleted file mode 100644 index 5f9a08f1909..00000000000 --- a/xlators/mgmt/glusterd/src/glusterd-tier.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. - */ - -#include "common-utils.h" -#include "cli1-xdr.h" -#include "xdr-generic.h" -#include "glusterd.h" -#include "glusterd-op-sm.h" -#include "glusterd-store.h" -#include "glusterd-geo-rep.h" -#include "glusterd-utils.h" -#include "glusterd-volgen.h" -#include "run.h" -#include "syscall.h" -#include "byte-order.h" -#include "glusterd-svc-helper.h" -#include "compat-errno.h" -#include "glusterd-tierd-svc.h" -#include "glusterd-tierd-svc-helper.h" -#include "glusterd-messages.h" -#include "glusterd-mgmt.h" -#include "glusterd-syncop.h" - -#include <sys/wait.h> -#include <dlfcn.h> - -extern struct rpc_clnt_program gd_brick_prog; - -const char *gd_tier_op_list[GF_DEFRAG_CMD_TYPE_MAX] = { - [GF_DEFRAG_CMD_START_TIER] = "start", - [GF_DEFRAG_CMD_STOP_TIER] = "stop", -}; - -int -__glusterd_handle_tier (rpcsvc_request_t *req) -{ - int32_t ret = -1; - gf_cli_req cli_req = { {0,} }; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_TIER_START_STOP; - char *volname = NULL; - int32_t cmd = 0; - char msg[2048] = {0,}; - xlator_t *this = NULL; - glusterd_conf_t *conf = NULL; - glusterd_volinfo_t *volinfo = NULL; - char err_str[2048] = {0}; - - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, req, out); - - conf = this->private; - GF_VALIDATE_OR_GOTO (this->name, conf, out); - - ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req); - if (ret < 0) { - 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_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_DICT_UNSERIALIZE_FAIL, "failed to " - "unserialize req-buffer to dictionary"); - snprintf (msg, sizeof (msg), "Unable to decode the " - "command"); - goto out; - } else { - dict->extra_stdfree = cli_req.dict.dict_val; - } - } - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - snprintf (msg, sizeof (msg), "Unable to get volume name"); - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get volume name, " - "while handling tier command"); - goto out; - } - - ret = dict_get_int32 (dict, "rebalance-command", &cmd); - if (ret) { - snprintf (msg, sizeof (msg), "Unable to get the command"); - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get the cmd"); - goto out; - } - - if (conf->op_version < GD_OP_VERSION_3_7_0) { - snprintf (msg, sizeof (msg), "Cannot execute command. The " - "cluster is operating at version %d. Tier command " - "%s is unavailable in this version", conf->op_version, - gd_tier_op_list[cmd]); - ret = -1; - goto out; - } - - if (conf->op_version < GD_OP_VERSION_3_10_0) { - gf_msg_debug (this->name, 0, "The cluster is operating at " - "version less than or equal to %d. Falling back " - "to syncop framework.", - GD_OP_VERSION_3_7_5); - switch (cmd) { - case GF_DEFRAG_CMD_DETACH_STOP: - ret = dict_set_int32 (dict, "rebalance-command", - GF_DEFRAG_CMD_STOP_DETACH_TIER); - break; - - case GF_DEFRAG_CMD_DETACH_COMMIT: - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (err_str, sizeof (err_str), "Volume " - "%s does not exist", volname); - gf_msg (this->name, GF_LOG_ERROR, EINVAL, - GD_MSG_VOL_NOT_FOUND, "%s", err_str); - goto out; - } - ret = glusterd_set_detach_bricks (dict, volinfo); - ret = dict_set_int32 (dict, "command", - GF_OP_CMD_DETACH_COMMIT); - break; - case GF_DEFRAG_CMD_DETACH_COMMIT_FORCE: - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (err_str, sizeof (err_str), "Volume " - "%s does not exist", volname); - gf_msg (this->name, GF_LOG_ERROR, EINVAL, - GD_MSG_VOL_NOT_FOUND, "%s", err_str); - goto out; - } - ret = glusterd_set_detach_bricks (dict, volinfo); - ret = dict_set_int32 (dict, "command", - GF_OP_CMD_DETACH_COMMIT_FORCE); - break; - case GF_DEFRAG_CMD_DETACH_START: - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (err_str, sizeof (err_str), "Volume " - "%s does not exist", volname); - gf_msg (this->name, GF_LOG_ERROR, EINVAL, - GD_MSG_VOL_NOT_FOUND, "%s", err_str); - goto out; - } - ret = glusterd_set_detach_bricks (dict, volinfo); - ret = dict_set_int32 (dict, "command", - GF_OP_CMD_DETACH_START); - break; - - default: - break; - - } - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set dict"); - goto out; - } - if ((cmd == GF_DEFRAG_CMD_STATUS_TIER) || - (cmd == GF_DEFRAG_CMD_DETACH_STATUS) || - (cmd == GF_DEFRAG_CMD_START_TIER) || - (cmd == GF_DEFRAG_CMD_DETACH_STOP)) { - ret = glusterd_op_begin (req, GD_OP_DEFRAG_BRICK_VOLUME, - dict, msg, sizeof (msg)); - } else - ret = glusterd_op_begin (req, GD_OP_REMOVE_BRICK, dict, - msg, sizeof (msg)); - - glusterd_friend_sm (); - glusterd_op_sm (); - - } else { - switch (cmd) { - case GF_DEFRAG_CMD_STATUS_TIER: - cli_op = GD_OP_TIER_STATUS; - break; - - case GF_DEFRAG_CMD_DETACH_STATUS: - cli_op = GD_OP_DETACH_TIER_STATUS; - break; - - case GF_DEFRAG_CMD_DETACH_STOP: - cli_op = GD_OP_REMOVE_TIER_BRICK; - break; - - case GF_DEFRAG_CMD_DETACH_COMMIT: - case GF_DEFRAG_CMD_DETACH_COMMIT_FORCE: - case GF_DEFRAG_CMD_DETACH_START: - cli_op = GD_OP_REMOVE_TIER_BRICK; - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (err_str, sizeof (err_str), "Volume " - "%s does not exist", volname); - gf_msg (this->name, GF_LOG_ERROR, EINVAL, - GD_MSG_VOL_NOT_FOUND, "%s", err_str); - goto out; - } - ret = glusterd_set_detach_bricks (dict, volinfo); - break; - - default: - break; - } - if (ret < 0) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_DICT_SET_FAILED, "dict set failed"); - goto out; - } - ret = glusterd_mgmt_v3_initiate_all_phases (req, - cli_op, - dict); - } - -out: - if (ret) { - if (msg[0] == '\0') - snprintf (msg, sizeof (msg), "Tier operation failed"); - ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - dict, msg); - } - - return ret; -} - -int -glusterd_handle_tier (rpcsvc_request_t *req) -{ - return glusterd_big_locked_handler (req, __glusterd_handle_tier); -} - - -static int -glusterd_manage_tier (glusterd_volinfo_t *volinfo, int opcode) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, volinfo, out); - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - switch (opcode) { - case GF_DEFRAG_CMD_START_TIER: - case GF_DEFRAG_CMD_STOP_TIER: - ret = volinfo->tierd.svc.manager (&(volinfo->tierd.svc), - volinfo, PROC_START_NO_WAIT); - break; - default: - ret = 0; - break; - } - -out: - return ret; - -} - -static int -glusterd_tier_enable (glusterd_volinfo_t *volinfo, char **op_errstr) -{ - int32_t ret = -1; - xlator_t *this = NULL; - int32_t tier_online = -1; - char pidfile[PATH_MAX] = {0}; - int32_t pid = -1; - glusterd_conf_t *priv = NULL; - - this = THIS; - - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, volinfo, out); - GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - if (glusterd_is_volume_started (volinfo) == 0) { - *op_errstr = gf_strdup ("Volume is stopped, start volume " - "to enable tier."); - ret = -1; - goto out; - } - - GLUSTERD_GET_TIER_PID_FILE(pidfile, volinfo, priv); - tier_online = gf_is_service_running (pidfile, &pid); - - if (tier_online) { - *op_errstr = gf_strdup ("tier is already enabled"); - ret = -1; - goto out; - } - - volinfo->is_tier_enabled = _gf_true; - - ret = 0; -out: - if (ret && op_errstr && !*op_errstr) - gf_asprintf (op_errstr, "Enabling tier on volume %s has been " - "unsuccessful", volinfo->volname); - return ret; -} - -static int -glusterd_tier_disable (glusterd_volinfo_t *volinfo, char **op_errstr) -{ - int32_t ret = -1; - xlator_t *this = NULL; - int32_t tier_online = -1; - char pidfile[PATH_MAX] = {0}; - int32_t pid = -1; - glusterd_conf_t *priv = NULL; - - this = THIS; - - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, volinfo, out); - GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); - priv = this->private; - - GLUSTERD_GET_TIER_PID_FILE(pidfile, volinfo, priv); - tier_online = gf_is_service_running (pidfile, &pid); - - if (!tier_online) { - *op_errstr = gf_strdup ("tier is already disabled"); - ret = -1; - goto out; - } - - volinfo->is_tier_enabled = _gf_false; - - ret = 0; -out: - if (ret && op_errstr && !*op_errstr) - gf_asprintf (op_errstr, "Disabling tier volume %s has " - "been unsuccessful", volinfo->volname); - return ret; -} - -int -glusterd_op_remove_tier_brick (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - 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,}; - int32_t flag = 0; - char err_str[4096] = {0,}; - int need_rebalance = 0; - int force = 0; - int32_t cmd = 0; - int32_t replica_count = 0; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_brickinfo_t *tmp = NULL; - char *task_id_str = NULL; - dict_t *bricks_dict = NULL; - char *brick_tmpstr = NULL; - uint32_t commit_hash = 0; - int detach_commit = 0; - void *tier_info = NULL; - char *cold_shd_key = NULL; - char *hot_shd_key = NULL; - int delete_key = 1; - glusterd_svc_t *svc = NULL; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, dict, out); - GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, EINVAL, - GD_MSG_VOL_NOT_FOUND, "Unable to get volinfo"); - goto out; - } - - ret = dict_get_int32 (dict, "rebalance-command", &cmd); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, - "cmd not found"); - goto out; - } - - if (is_origin_glusterd (dict) && - (cmd != GF_DEFRAG_CMD_DETACH_START)) { - if (!gf_uuid_is_null (volinfo->rebal.rebalance_id)) { - ret = glusterd_copy_uuid_to_dict - (volinfo->rebal.rebalance_id, dict, - GF_REMOVE_BRICK_TID_KEY); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_REMOVE_BRICK_ID_SET_FAIL, - "Failed to set remove-brick-id"); - goto out; - } - } - } - /*check only if a tierd is supposed to be running - * if no brick in the tierd volume is a local brick - * skip it */ - cds_list_for_each_entry (brickinfo, &volinfo->bricks, - brick_list) { - if (glusterd_is_local_brick (this, volinfo, - brickinfo)) { - flag = _gf_true; - break; - } - } - if (!flag) - goto out; - - - ret = -1; - - switch (cmd) { - case GF_DEFRAG_CMD_DETACH_STOP: - /* Fall back to the old volume file */ - cds_list_for_each_entry_safe (brickinfo, tmp, - &volinfo->bricks, - brick_list) { - if (!brickinfo->decommissioned) - continue; - brickinfo->decommissioned = 0; - } - ret = glusterd_create_volfiles_and_notify_services - (volinfo); - - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_VOLFILE_CREATE_FAIL, - "failed to create volfiles"); - goto out; - } - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_VOLINFO_SET_FAIL, - "failed to store volinfo"); - goto out; - } - ret = glusterd_tierdsvc_restart (); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_TIERD_START_FAIL, - "Couldn't restart tierd for " - "vol: %s", volinfo->volname); - goto out; - } - - volinfo->tier.op = GD_OP_DETACH_NOT_STARTED; - ret = 0; - goto out; - - - - case GF_DEFRAG_CMD_DETACH_START: - ret = dict_get_str (dict, GF_REMOVE_BRICK_TID_KEY, - &task_id_str); - if (ret) { - gf_msg_debug (this->name, errno, - "Missing remove-brick-id"); - ret = 0; - } else { - ret = dict_set_str (rsp_dict, - GF_REMOVE_BRICK_TID_KEY, - task_id_str); - gf_uuid_parse (task_id_str, - volinfo->tier.rebalance_id); - } - force = 0; - - volinfo->tier.op = GD_OP_DETACH_TIER; - volinfo->tier.defrag_status = GF_DEFRAG_STATUS_STARTED; - break; - - case GF_DEFRAG_CMD_DETACH_COMMIT: - if (volinfo->decommission_in_progress) { - gf_asprintf (op_errstr, "use 'force' option as " - "migration is in progress"); - goto out; - } - if (volinfo->rebal.defrag_status == - GF_DEFRAG_STATUS_FAILED) { - gf_asprintf (op_errstr, "use 'force' option as " - "migration has failed"); - goto out; - } - - case GF_DEFRAG_CMD_DETACH_COMMIT_FORCE: - glusterd_op_perform_detach_tier (volinfo); - detach_commit = 1; - - /* Disabling ctr when detaching a tier, since - * currently tier is the only consumer of ctr. - * Revisit this code when this constraint no - * longer exist. - */ - dict_del (volinfo->dict, "features.ctr-enabled"); - dict_del (volinfo->dict, "cluster.tier-mode"); - - hot_shd_key = gd_get_shd_key - (volinfo->tier_info.hot_type); - cold_shd_key = gd_get_shd_key - (volinfo->tier_info.cold_type); - if (hot_shd_key) { - /* - * Since post detach, shd graph will not - * contain hot tier. So we need to clear - * option set for hot tier. For a tiered - * volume there can be different key - * for both hot and cold. If hot tier is - * shd compatible then we need to remove - * the configured value when detaching a tier, - * only if the key's are different or - * cold key is NULL. So we will set - * delete_key first, and if cold key is not - * null and they are equal then we will clear - * the flag. Otherwise we will delete the - * key. - */ - - if (cold_shd_key) - delete_key = strcmp (hot_shd_key, - cold_shd_key); - if (delete_key) - dict_del (volinfo->dict, hot_shd_key); - } - /* fall through */ - - if (volinfo->decommission_in_progress) { - if (volinfo->tier.defrag) { - LOCK (&volinfo->rebal.defrag->lock); - /* Fake 'rebalance-complete' so the - * graph change - * happens right away */ - volinfo->tier.defrag_status = - GF_DEFRAG_STATUS_COMPLETE; - - UNLOCK (&volinfo->tier.defrag->lock); - } - } - - volinfo->tier.op = GD_OP_DETACH_NOT_STARTED; - ret = 0; - force = 1; - break; - default: - gf_asprintf (op_errstr, "tier command failed. Invalid " - "opcode"); - ret = -1; - goto out; - } - - count = glusterd_set_detach_bricks(dict, volinfo); - - if (cmd == GF_DEFRAG_CMD_DETACH_START) { - bricks_dict = dict_new (); - if (!bricks_dict) { - ret = -1; - goto out; - } - ret = dict_set_int32 (bricks_dict, "count", count); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_SET_FAILED, - "Failed to save remove-brick count"); - goto out; - } - } - - while (i <= count) { - snprintf (key, 256, "brick%d", i); - ret = dict_get_str (dict, key, &brick); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get %s", - key); - goto out; - } - - if (cmd == GF_DEFRAG_CMD_DETACH_START) { - brick_tmpstr = gf_strdup (brick); - if (!brick_tmpstr) { - ret = -1; - gf_msg (this->name, GF_LOG_ERROR, ENOMEM, - GD_MSG_NO_MEMORY, - "Failed to duplicate brick name"); - goto out; - } - ret = dict_set_dynstr (bricks_dict, key, brick_tmpstr); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_SET_FAILED, - "Failed to add brick to dict"); - goto out; - } - brick_tmpstr = NULL; - } - - ret = glusterd_op_perform_remove_brick (volinfo, brick, force, - &need_rebalance); - if (ret) - goto out; - i++; - } - - if (detach_commit) { - /* Clear related information from volinfo */ - tier_info = ((void *)(&volinfo->tier_info)); - memset (tier_info, 0, sizeof (volinfo->tier_info)); - } - - if (cmd == GF_DEFRAG_CMD_DETACH_START) - volinfo->tier.dict = dict_ref (bricks_dict); - - ret = dict_get_int32 (dict, "replica-count", &replica_count); - if (!ret) { - gf_msg (this->name, GF_LOG_INFO, errno, - GD_MSG_DICT_GET_FAILED, - "changing replica count %d to %d on volume %s", - volinfo->replica_count, replica_count, - volinfo->volname); - volinfo->replica_count = replica_count; - volinfo->sub_count = replica_count; - volinfo->dist_leaf_count = glusterd_get_dist_leaf_count - (volinfo); - - /* - * volinfo->type and sub_count have already been set for - * volumes undergoing a detach operation, they should not - * be modified here. - */ - if ((replica_count == 1) && (cmd != GF_DEFRAG_CMD_DETACH_COMMIT) - && (cmd != GF_DEFRAG_CMD_DETACH_COMMIT_FORCE)) { - if (volinfo->type == GF_CLUSTER_TYPE_REPLICATE) { - volinfo->type = GF_CLUSTER_TYPE_NONE; - /* backward compatibility */ - volinfo->sub_count = 0; - } else { - volinfo->type = GF_CLUSTER_TYPE_STRIPE; - /* backward compatibility */ - volinfo->sub_count = volinfo->dist_leaf_count; - } - } - } - volinfo->subvol_count = (volinfo->brick_count / - volinfo->dist_leaf_count); - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_VOLFILE_CREATE_FAIL, "failed to create" - "volfiles"); - goto out; - } - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_VOLINFO_STORE_FAIL, "failed to store volinfo"); - goto out; - } - - if (cmd == GF_DEFRAG_CMD_DETACH_START && - volinfo->status == GLUSTERD_STATUS_STARTED) { - - svc = &(volinfo->tierd.svc); - ret = svc->reconfigure (volinfo); - if (ret) - goto out; - - ret = glusterd_svcs_reconfigure (); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_NFS_RECONF_FAIL, - "Unable to reconfigure NFS-Server"); - goto out; - } - } - /* Need to reset the defrag/rebalance status accordingly */ - switch (volinfo->tier.defrag_status) { - case GF_DEFRAG_STATUS_FAILED: - case GF_DEFRAG_STATUS_COMPLETE: - volinfo->tier.defrag_status = 0; - /* FALLTHROUGH */ - default: - break; - } - if (!force && need_rebalance) { - if (dict_get_uint32(dict, "commit-hash", &commit_hash) == 0) { - volinfo->tier.commit_hash = commit_hash; - } - /* perform the rebalance operations */ - ret = glusterd_handle_defrag_start - (volinfo, err_str, sizeof (err_str), - GF_DEFRAG_CMD_START_DETACH_TIER, - /*change this label to GF_DEFRAG_CMD_DETACH_START - * while removing old code - */ - glusterd_remove_brick_migrate_cbk, GD_OP_REMOVE_BRICK); - - if (!ret) - volinfo->decommission_in_progress = 1; - - else if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_REBALANCE_START_FAIL, - "failed to start the rebalance"); - } - } else { - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_svcs_manager (volinfo); - } - -out: - if (ret && err_str[0] && op_errstr) - *op_errstr = gf_strdup (err_str); - - GF_FREE (brick_tmpstr); - if (bricks_dict) - dict_unref (bricks_dict); - - return ret; - -} - -int -glusterd_op_tier_start_stop (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - glusterd_volinfo_t *volinfo = NULL; - int32_t ret = -1; - char *volname = NULL; - int cmd = -1; - xlator_t *this = NULL; - glusterd_brickinfo_t *brick = NULL; - gf_boolean_t retval = _gf_false; - glusterd_conf_t *priv = NULL; - int32_t pid = -1; - char pidfile[PATH_MAX] = {0}; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, dict, out); - GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_asprintf (op_errstr, FMTSTR_CHECK_VOL_EXISTS, volname); - goto out; - } - - ret = dict_get_int32 (dict, "rebalance-command", &cmd); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, "Unable to get cmd from " - "dict"); - goto out; - } - - cds_list_for_each_entry (brick, &volinfo->bricks, brick_list) { - if (gf_uuid_compare (MY_UUID, brick->uuid) == 0) { - retval = _gf_true; - break; - } - } - /*check if this node needs tierd*/ - - if (!retval) - goto out; - - switch (cmd) { - case GF_DEFRAG_CMD_START_TIER: - GLUSTERD_GET_TIER_PID_FILE(pidfile, volinfo, priv); - /* we check if its running and skip so that we dont get a - * failure during force start - */ - if (gf_is_service_running (pidfile, &pid)) - goto out; - ret = glusterd_tier_enable (volinfo, op_errstr); - if (ret < 0) - goto out; - glusterd_store_perform_node_state_store (volinfo); - break; - - case GF_DEFRAG_CMD_STOP_TIER: - ret = glusterd_tier_disable (volinfo, op_errstr); - if (ret < 0) - goto out; - break; - default: - gf_asprintf (op_errstr, "tier command failed. Invalid " - "opcode"); - ret = -1; - goto out; - } - - ret = glusterd_manage_tier (volinfo, cmd); - if (ret) - goto out; - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_VOLINFO_STORE_FAIL, - "Failed to store volinfo for tier"); - goto out; - } - -out: - return ret; -} - -int -glusterd_op_stage_tier (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - char *volname = NULL; - int ret = -1; - int32_t cmd = 0; - char msg[2048] = {0}; - glusterd_volinfo_t *volinfo = NULL; - char *task_id_str = NULL; - xlator_t *this = 0; - int32_t is_force = 0; - char pidfile[PATH_MAX] = {0}; - int32_t tier_online = -1; - int32_t pid = -1; - int32_t brick_count = 0; - gsync_status_param_t param = {0,}; - glusterd_conf_t *priv = NULL; - gf_boolean_t flag = _gf_false; - glusterd_brickinfo_t *brickinfo = NULL; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, dict, out); - GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, - "volname not found"); - goto out; - } - - ret = dict_get_int32 (dict, "rebalance-command", &cmd); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, - "cmd not found"); - goto out; - } - - ret = glusterd_rebalance_cmd_validate (cmd, volname, &volinfo, - msg, sizeof (msg)); - if (ret) { - gf_msg_debug (this->name, 0, "cmd validate failed"); - goto out; - } - - if (volinfo->type != GF_CLUSTER_TYPE_TIER) { - snprintf (msg, sizeof(msg), "volume %s is not a tier " - "volume", volinfo->volname); - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_VOL_NOT_TIER, "volume: %s is not a tier " - "volume", volinfo->volname); - ret = -1; - goto out; - } - /* Check if the connected clients are all of version - * glusterfs-3.6 and higher. This is needed to prevent some data - * loss issues that could occur when older clients are connected - * when rebalance is run. This check can be bypassed by using - * 'force' - */ - ret = glusterd_check_client_op_version_support - (volname, GD_OP_VERSION_3_6_0, NULL); - if (ret) { - ret = gf_asprintf (op_errstr, "Volume %s has one or " - "more connected clients of a version" - " lower than GlusterFS-v3.6.0. " - "Tier operations not supported in" - " below this version", volname); - goto out; - } - /*check only if a tierd is supposed to be running - * if no brick in the tierd volume is a local brick - * skip it */ - cds_list_for_each_entry (brickinfo, &volinfo->bricks, - brick_list) { - if (glusterd_is_local_brick (this, volinfo, - brickinfo)) { - flag = _gf_true; - break; - } - } - if (!flag) - goto out; - - GLUSTERD_GET_TIER_PID_FILE(pidfile, volinfo, priv); - tier_online = gf_is_service_running (pidfile, &pid); - - switch (cmd) { - case GF_DEFRAG_CMD_START_TIER: - ret = dict_get_int32 (dict, "force", &is_force); - if (ret) - is_force = 0; - - if (brickinfo->status != GF_BRICK_STARTED) { - gf_asprintf (op_errstr, "Received" - " tier start on volume " - "with stopped brick %s", - brickinfo->path); - ret = -1; - goto out; - } - if ((!is_force) && tier_online) { - ret = gf_asprintf (op_errstr, "Tier daemon is " - "already running on volume %s", - volname); - ret = -1; - goto out; - } - ret = glusterd_defrag_start_validate (volinfo, msg, - sizeof (msg), - GD_OP_REBALANCE); - if (ret) { - gf_msg (this->name, 0, GF_LOG_ERROR, - GD_MSG_REBALANCE_START_FAIL, - "start validate failed"); - goto out; - } - break; - - case GF_DEFRAG_CMD_STOP_TIER: - - if (!tier_online) { - ret = gf_asprintf (op_errstr, "Tier daemon is " - "not running on volume %s", - volname); - ret = -1; - goto out; - } - break; - - case GF_DEFRAG_CMD_DETACH_START: - - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, - "Unable to get brick count"); - goto out; - } - - if (!tier_online) { - ret = gf_asprintf (op_errstr, "Tier daemon is " - "not running on volume %s", - volname); - ret = -1; - goto out; - } - if (volinfo->tier.op == GD_OP_DETACH_TIER) { - snprintf (msg, sizeof (msg), "An earlier detach tier " - "task exists for volume %s. Either commit it" - " or stop it before starting a new task.", - volinfo->volname); - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_OLD_REMOVE_BRICK_EXISTS, - "Earlier remove-brick" - " task exists for volume %s.", - volinfo->volname); - ret = -1; - goto out; - } - if (glusterd_is_defrag_on(volinfo)) { - snprintf (msg, sizeof (msg), "Migration is in progress." - " Please retry after completion"); - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_OIP_RETRY_LATER, "Migration is" - "in progress"); - goto out; - } - - ret = glusterd_remove_brick_validate_bricks (GF_OP_CMD_NONE, - brick_count, - dict, volinfo, - op_errstr, cmd); - if (ret) - goto out; - - if (is_origin_glusterd (dict)) { - ret = glusterd_generate_and_set_task_id - (dict, GF_REMOVE_BRICK_TID_KEY); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_TASKID_GEN_FAIL, - "Failed to generate task-id"); - goto out; - } - } else { - ret = dict_get_str (dict, GF_REMOVE_BRICK_TID_KEY, - &task_id_str); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, errno, - GD_MSG_DICT_GET_FAILED, - "Missing remove-brick-id"); - ret = 0; - } - } - break; - - case GF_DEFRAG_CMD_DETACH_STOP: - if (volinfo->tier.op != GD_OP_DETACH_TIER) { - snprintf (msg, sizeof(msg), "Detach-tier " - "not started"); - ret = -1; - goto out; - } - ret = 0; - break; - - case GF_DEFRAG_CMD_STATUS_TIER: - - if (!tier_online) { - ret = gf_asprintf (op_errstr, "Tier daemon is " - "not running on volume %s", - volname); - ret = -1; - goto out; - } - break; - - case GF_DEFRAG_CMD_DETACH_COMMIT: - - if (volinfo->tier.op != GD_OP_DETACH_TIER) { - snprintf (msg, sizeof(msg), "Detach-tier " - "not started"); - ret = -1; - goto out; - } - if ((volinfo->rebal.defrag_status == GF_DEFRAG_STATUS_STARTED) - && (volinfo->tier.op == GD_OP_DETACH_TIER)) { - ret = -1; - snprintf (msg, sizeof (msg), "Detach is in progress. " - "Please retry after completion"); - gf_msg (this->name, GF_LOG_WARNING, 0, - GD_MSG_OIP_RETRY_LATER, "Detach is in " - "progress"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - GD_MSG_DICT_GET_FAILED, - "Unable to get brick count"); - goto out; - } - - ret = glusterd_remove_brick_validate_bricks (GF_OP_CMD_NONE, - brick_count, - dict, volinfo, - op_errstr, cmd); - if (ret) - goto out; - - /* If geo-rep is configured, for this volume, it should be - * stopped. - */ - param.volinfo = volinfo; - ret = glusterd_check_geo_rep_running (¶m, op_errstr); - if (ret || param.is_active) { - ret = -1; - goto out; - } - - break; - case GF_DEFRAG_CMD_DETACH_STATUS: - if (volinfo->tier.op != GD_OP_DETACH_TIER) { - snprintf (msg, sizeof(msg), "Detach-tier " - "not started"); - ret = -1; - goto out; - } - break; - - case GF_DEFRAG_CMD_DETACH_COMMIT_FORCE: - default: - break; - - } - - ret = 0; -out: - if (ret && op_errstr && msg[0]) - *op_errstr = gf_strdup (msg); - - return ret; -} - -int32_t -glusterd_add_tierd_to_dict (glusterd_volinfo_t *volinfo, - dict_t *dict, int32_t count) -{ - - int ret = -1; - int32_t pid = -1; - int32_t brick_online = -1; - char key[1024] = {0}; - char base_key[1024] = {0}; - char pidfile[PATH_MAX] = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - - GF_VALIDATE_OR_GOTO (this->name, volinfo, out); - GF_VALIDATE_OR_GOTO (this->name, dict, out); - - snprintf (base_key, sizeof (base_key), "brick%d", count); - snprintf (key, sizeof (key), "%s.hostname", base_key); - ret = dict_set_str (dict, key, "Tier Daemon"); - if (ret) - goto out; - - snprintf (key, sizeof (key), "%s.path", base_key); - ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (MY_UUID))); - if (ret) - goto out; - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.port", base_key); - ret = dict_set_int32 (dict, key, volinfo->tierd.port); - if (ret) - goto out; - - glusterd_svc_build_tierd_pidfile (volinfo, pidfile, sizeof (pidfile)); - - brick_online = gf_is_service_running (pidfile, &pid); - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.pid", base_key); - ret = dict_set_int32 (dict, key, pid); - if (ret) - goto out; - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.status", base_key); - ret = dict_set_int32 (dict, key, brick_online); - -out: - if (ret) - gf_msg (this ? this->name : "glusterd", - GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, - "Returning %d. adding values to dict failed", ret); - - return ret; -} - -int32_t -__glusterd_tier_status_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - gd1_mgmt_brick_op_rsp rsp = {0}; - int ret = -1; - call_frame_t *frame = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - struct syncargs *args = NULL; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, req, out); - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - - frame = myframe; - args = frame->local; - - if (-1 == req->rpc_status) { - args->op_errno = ENOTCONN; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_brick_op_rsp); - if (ret < 0) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_RES_DECODE_FAIL, - "Failed to decode brick op " - "response received"); - goto out; - } - - if (rsp.output.output_len) { - args->dict = dict_new (); - if (!args->dict) { - ret = -1; - args->op_errno = ENOMEM; - goto out; - } - - ret = dict_unserialize (rsp.output.output_val, - rsp.output.output_len, - &args->dict); - if (ret < 0) - goto out; - } - args->op_ret = rsp.op_ret; - args->op_errno = rsp.op_errno; - args->errstr = gf_strdup (rsp.op_errstr); - -out: - if ((rsp.op_errstr) && (strcmp (rsp.op_errstr, "") != 0)) - free (rsp.op_errstr); - free (rsp.output.output_val); - if (req->rpc_status != -1) - GLUSTERD_STACK_DESTROY(frame); - __wake (args); - - return ret; - -} - -int32_t -glusterd_tier_status_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - __glusterd_tier_status_cbk); -} - -int -glusterd_op_tier_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict, - glusterd_op_t op) -{ - int ret = -1; - xlator_t *this = NULL; - struct syncargs args = {0, }; - glusterd_req_ctx_t *data = NULL; - gd1_mgmt_brick_op_req *req = NULL; - glusterd_conf_t *priv = NULL; - int pending_bricks = 0; - glusterd_pending_node_t *pending_node; - glusterd_req_ctx_t *req_ctx = NULL; - struct rpc_clnt *rpc = NULL; - uuid_t *txn_id = NULL; - extern glusterd_op_info_t opinfo; - - this = THIS; - GF_VALIDATE_OR_GOTO (THIS->name, this, out); - GF_VALIDATE_OR_GOTO (this->name, dict, out); - GF_VALIDATE_OR_GOTO (this->name, rsp_dict, out); - - priv = this->private; - GF_VALIDATE_OR_GOTO (this->name, priv, out); - args.op_ret = -1; - args.op_errno = ENOTCONN; - data = GF_CALLOC (1, sizeof (*data), - gf_gld_mt_op_allack_ctx_t); - - gf_uuid_copy (data->uuid, MY_UUID); - - /* we are printing the detach status for issue of detach start - * by then we need the op to be GD_OP_DETACH_TIER_STATUS for it to - * get the status. ad for the rest of the condition it can go as such. - */ - - if (op == GD_OP_REMOVE_TIER_BRICK) - data->op = GD_OP_DETACH_TIER_STATUS; - else - data->op = op; - data->dict = dict; - - txn_id = &priv->global_txn_id; - - req_ctx = data; - GF_VALIDATE_OR_GOTO (this->name, req_ctx, out); - CDS_INIT_LIST_HEAD (&opinfo.pending_bricks); - - ret = dict_get_bin (req_ctx->dict, "transaction_id", (void **)&txn_id); - gf_msg_debug (this->name, 0, "transaction ID = %s", - uuid_utoa (*txn_id)); - - ret = glusterd_op_bricks_select (req_ctx->op, req_ctx->dict, op_errstr, - &opinfo.pending_bricks, NULL); - - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_BRICK_SELECT_FAIL, "Failed to select bricks"); - opinfo.op_errstr = *op_errstr; - goto out; - } - - cds_list_for_each_entry (pending_node, &opinfo.pending_bricks, list) { - ret = glusterd_brick_op_build_payload - (req_ctx->op, pending_node->node, - (gd1_mgmt_brick_op_req **)&req, - req_ctx->dict); - - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_BRICK_OP_PAYLOAD_BUILD_FAIL, - "Failed to build brick op payload during " - "'Volume %s'", gd_op_list[req_ctx->op]); - goto out; - } - - - rpc = glusterd_pending_node_get_rpc (pending_node); - if (!rpc) { - opinfo.brick_pending_count = 0; - ret = 0; - if (req) { - GF_FREE (req); - req = NULL; - } - glusterd_defrag_volume_node_rsp (req_ctx->dict, - NULL, rsp_dict); - - goto out; - } - - GD_SYNCOP (rpc, (&args), NULL, glusterd_tier_status_cbk, req, - &gd_brick_prog, req->op, xdr_gd1_mgmt_brick_op_req); - - if (req) { - GF_FREE (req); - req = NULL; - } - if (!ret) - pending_bricks++; - - glusterd_pending_node_put_rpc (pending_node); - } - glusterd_handle_node_rsp (req_ctx->dict, pending_node->node, - req_ctx->op, args.dict, rsp_dict, op_errstr, - pending_node->type); - gf_msg_trace (this->name, 0, "Sent commit op req for operation " - "'Volume %s' to %d bricks", gd_op_list[req_ctx->op], - pending_bricks); - opinfo.brick_pending_count = pending_bricks; - -out: - - if (ret) - opinfo.op_ret = ret; - - ret = glusterd_set_txn_opinfo (txn_id, &opinfo); - if (ret) - gf_msg (THIS->name, GF_LOG_ERROR, 0, - GD_MSG_TRANS_OPINFO_SET_FAIL, - "Unable to set transaction's opinfo"); - - gf_msg_debug (this ? this->name : "glusterd", 0, - "Returning %d. Failed to get tier status", ret); - return ret; - -} |
