diff options
Diffstat (limited to 'xlators/mgmt')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 28 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 172 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 375 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 11 |
4 files changed, 515 insertions, 71 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 664798ca376..7817e1dd653 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -2511,10 +2511,11 @@ int glusterd_handle_status_volume (rpcsvc_request_t *req) { int32_t ret = -1; + uint32_t cmd = 0; + dict_t *dict = NULL; + char *volname = 0; gf_cli_req cli_req = {{0,}}; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_STATUS_VOLUME; - char *volname = 0; + glusterd_op_t cli_op = GD_OP_STATUS_VOLUME; GF_ASSERT (req); @@ -2530,7 +2531,7 @@ glusterd_handle_status_volume (rpcsvc_request_t *req) if (!dict) goto out; ret = dict_unserialize (cli_req.dict.dict_val, - cli_req.dict.dict_len, &dict); + cli_req.dict.dict_len, &dict); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "failed to " "unserialize buffer"); @@ -2539,15 +2540,22 @@ glusterd_handle_status_volume (rpcsvc_request_t *req) } - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname"); + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) goto out; - } - gf_log ("glusterd", GF_LOG_INFO, "Received status volume req " - "for volume %s", volname); + if (!(cmd & GF_CLI_STATUS_ALL)) { + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "failed to get volname"); + goto out; + } + gf_log (THIS->name, GF_LOG_INFO, + "Received status volume req " + "for volume %s", volname); + } ret = glusterd_op_begin (req, GD_OP_STATUS_VOLUME, dict); diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 8f2d55aaf3a..68a98b16b7b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -527,12 +527,16 @@ out: 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,}; + int ret = -1; + uint32_t cmd = 0; + char msg[2048] = {0,}; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_brickinfo_t *tmpbrickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; GF_ASSERT (dict); this = THIS; @@ -540,30 +544,63 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) priv = this->private; GF_ASSERT(priv); + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + if (cmd & GF_CLI_STATUS_ALL) + goto out; ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to get volume name"); goto out; } - exists = glusterd_check_volume_exists (volname); - if (!exists) { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); *op_errstr = gf_strdup(msg); ret = -1; goto out; } + if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) + goto out; + + ret = glusterd_volume_brickinfo_get (NULL, + brickinfo->hostname, + brickinfo->path, + volinfo, + &tmpbrickinfo, + GF_PATH_COMPLETE); + + if (ret) { + snprintf (msg, sizeof(msg), "No brick %s in" + " volume %s", brick, volname); + gf_log (THIS->name, 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); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning: %d", ret); return ret; } @@ -1203,15 +1240,17 @@ static int glusterd_op_status_volume (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { - int ret = -1; - char *volname = NULL; - int count = 0; - int brick_count = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - int32_t brick_index = 0; + int ret = -1; + int brick_count = 0; + int32_t brick_index = 0; + uint32_t cmd = 0; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_brickinfo_t *tmpbrickinfo = NULL; + glusterd_conf_t *priv = NULL; this = THIS; GF_ASSERT (this); @@ -1221,41 +1260,83 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, GF_ASSERT (dict); - - ret = dict_get_str (dict, "volname", &volname); - if (!ret) { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "does not exist", volname); - goto out; - } - } + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; if (!rsp_dict) { //this should happen only on source ret = 0; rsp_dict = glusterd_op_get_ctx (); + + if ((cmd & GF_CLI_STATUS_ALL)) { + ret = glusterd_get_all_volnames (rsp_dict); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, + "failed to get all volume " + "names for status"); + } + } - if (volname) { - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_add_brick_to_dict (volinfo, - brickinfo, - rsp_dict, - brick_index); - count++; - brick_count = count; - } - brick_index++; + ret = dict_set_uint32 (rsp_dict, "cmd", cmd); + if (ret) + goto out; + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Volume with name: %s " + "does not exist", volname); + goto out; + } + + if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + ret = glusterd_brickinfo_from_brick (brick, &tmpbrickinfo); + if (ret) + goto out; + if (uuid_is_null (tmpbrickinfo->uuid) && + glusterd_resolve_brick (tmpbrickinfo)) + goto out; + } + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + + if ((cmd & GF_CLI_STATUS_BRICK) != 0 && + (strcmp (tmpbrickinfo->path, + brickinfo->path) || + uuid_compare (tmpbrickinfo->uuid, + brickinfo->uuid))) + continue; + + glusterd_add_brick_to_dict (volinfo, brickinfo, + rsp_dict, brick_index); + + if (cmd & GF_CLI_STATUS_DETAIL) + glusterd_add_brick_detail_to_dict (volinfo, + brickinfo, + rsp_dict, + brick_index); + brick_count++; } + if (!(cmd & GF_CLI_STATUS_BRICK)) + brick_index++; } ret = dict_set_int32 (rsp_dict, "count", brick_count); out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -2119,7 +2200,7 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) rsp_dict); if (status) { - gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); + gf_log (THIS->name, GF_LOG_ERROR, "Commit failed: %d", status); } ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, @@ -2131,7 +2212,8 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) if (rsp_dict) dict_unref (rsp_dict); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 2eaf4f4a2f4..b2d0bcdd7ad 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -58,6 +58,9 @@ #include <rpc/pmap_clnt.h> #include <unistd.h> #include <fnmatch.h> +#include <sys/statvfs.h> + + #ifdef GF_SOLARIS_HOST_OS #include <sys/sockio.h> #endif @@ -679,11 +682,11 @@ glusterd_brickinfo_from_brick (char *brick, GF_ASSERT (brickinfo); tmp_host = gf_strdup (brick); - if (tmp_host) - get_host_name (tmp_host, &hostname); + if (tmp_host && !get_host_name (tmp_host, &hostname)) + goto out; tmp_path = gf_strdup (brick); - if (tmp_path) - get_path_name (tmp_path, &path); + if (tmp_path && !get_path_name (tmp_path, &path)) + goto out; GF_ASSERT (hostname); GF_ASSERT (path); @@ -3084,21 +3087,331 @@ out: return -1; } +int +glusterd_get_brick_root (char *path, char **mount_point) +{ + char *ptr = NULL; + struct stat brickstat = {0}; + struct stat buf = {0}; + + if (!path) + goto err; + *mount_point = gf_strdup (path); + if (!*mount_point) + goto err; + if (stat (*mount_point, &brickstat)) + goto err; + + while ((ptr = strrchr (*mount_point, '/')) && + ptr != *mount_point) { + + *ptr = '\0'; + if (stat (*mount_point, &buf)) { + gf_log (THIS->name, GF_LOG_ERROR, "error in " + "stat: %s", strerror (errno)); + goto err; + } + + if (brickstat.st_dev != buf.st_dev) { + *ptr = '/'; + break; + } + } + + if (ptr == *mount_point) { + if (stat ("/", &buf)) { + gf_log (THIS->name, GF_LOG_ERROR, "error in " + "stat: %s", strerror (errno)); + goto err; + } + if (brickstat.st_dev == buf.st_dev) + strcpy (*mount_point, "/"); + } + + return 0; + + err: + if (*mount_point) + GF_FREE (*mount_point); + return -1; +} + +static int +glusterd_add_inode_size_to_dict (dict_t *dict, int count) +{ + int ret = -1; + int fd = -1; + char key[1024] = {0}; + char buffer[4096] = {0}; + char cmd_str[4096] = {0}; + char *inode_size = NULL; + char *device = NULL; + char *fs_name = NULL; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.device", count); + ret = dict_get_str (dict, key, &device); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.fs_name", count); + ret = dict_get_str (dict, key, &fs_name); + if (ret) + goto out; + + /* get inode size for xfs or ext2/3/4 */ + if (!strcmp (fs_name, "xfs")) { + + snprintf (cmd_str, sizeof (cmd_str), + "xfs_info %s | " + "grep isize | " + "cut -d ' ' -f 2- | " + "cut -d '=' -f 2 | " + "cut -d ' ' -f 1 " + "> /tmp/gf_status.txt ", + device); + + } else if (IS_EXT_FS(fs_name)) { + + snprintf (cmd_str, sizeof (cmd_str), + "tune2fs -l %s | " + "grep -i 'inode size' | " + "awk '{print $3}' " + "> /tmp/gf_status.txt ", + device); + + } else { + ret = 0; + gf_log (THIS->name, GF_LOG_INFO, "Skipped fetching " + "inode size for %s: FS type not recommended", + fs_name); + goto out; + } + + ret = runcmd ("/bin/sh", "-c", cmd_str, NULL); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "could not get inode " + "size for %s : %s package missing", fs_name, + ((strcmp (fs_name, "xfs")) ? + "e2fsprogs" : "xfsprogs")); + goto out; + } + + fd = open ("/tmp/gf_status.txt", O_RDONLY); + unlink ("/tmp/gf_status.txt"); + if (fd < 0) { + ret = -1; + goto out; + } + memset (buffer, 0, sizeof (buffer)); + ret = read (fd, buffer, sizeof (buffer)); + if (ret < 2) { + ret = -1; + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.inode_size", count); + + inode_size = get_nth_word (buffer, 1); + if (!inode_size) { + ret = -1; + goto out; + } + + ret = dict_set_dynstr (dict, key, inode_size); + + out: + if (fd >= 0) + close (fd); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, "failed to get inode size"); + return ret; +} + +static int +glusterd_add_brick_mount_details (glusterd_brickinfo_t *brickinfo, + dict_t *dict, int count) +{ + int ret = -1; + int fd = -1; + char key[1024] = {0}; + char base_key[1024] = {0}; + char buffer[4096] = {0}; + char cmd_str[1024] = {0}; + char *mnt_pt = NULL; + char *fs_name = NULL; + char *mnt_options = NULL; + char *device = NULL; + runner_t runner = {0}; + + snprintf (base_key, sizeof (base_key), "brick%d", count); + + ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt); + if (ret) + goto out; + + /* get mount details of brick in back-end */ + snprintf (cmd_str, sizeof (cmd_str), " %s ", mnt_pt); + + runinit (&runner); + runner_add_args (&runner, "grep", cmd_str, "/etc/mtab", NULL); + runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); + + ret = runner_start (&runner); + if (ret) + goto out; + + if (!fgets (buffer, sizeof(buffer), + runner_chio (&runner, STDOUT_FILENO))) { + ret = -1; + goto out; + } + + runner_end (&runner); + + /* get device file */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.device", base_key); + + device = get_nth_word (buffer, 1); + if (!device) + goto out; + + ret = dict_set_dynstr (dict, key, device); + if (ret) + goto out; + + /* fs type */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fs_name", base_key); + + fs_name = get_nth_word (buffer, 3); + if (!fs_name) + goto out; + + ret = dict_set_dynstr (dict, key, fs_name); + if (ret) + goto out; + + /* mount options */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.mnt_options", base_key); + + mnt_options = get_nth_word (buffer, 4); + if (!mnt_options) + goto out; + ret = dict_set_dynstr (dict, key, mnt_options); + + out: + if (mnt_pt) + GF_FREE (mnt_pt); + if (fd >= 0) + close (fd); + return ret; +} + +int +glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int count) +{ + int ret = -1; + uint64_t memtotal = 0; + uint64_t memfree = 0; + uint64_t inodes_total = 0; + uint64_t inodes_free = 0; + uint64_t block_size = 0; + char key[1024] = {0}; + char base_key[1024] = {0}; + struct statvfs brickstat = {0}; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + GF_ASSERT (dict); + + snprintf (base_key, sizeof (base_key), "brick%d", count); + + ret = statvfs (brickinfo->path, &brickstat); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "statfs error: %s ", + strerror (errno)); + goto out; + } + + /* file system block size */ + block_size = brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.block_size", base_key); + ret = dict_set_uint64 (dict, key, block_size); + if (ret) + goto out; + + /* free space in brick */ + memfree = brickstat.f_bfree * brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.free", base_key); + ret = dict_set_uint64 (dict, key, memfree); + if (ret) + goto out; + + /* total space of brick */ + memtotal = brickstat.f_blocks * brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.total", base_key); + ret = dict_set_uint64 (dict, key, memtotal); + if (ret) + goto out; + + /* inodes: total and free counts only for ext2/3/4 and xfs */ + inodes_total = brickstat.f_files; + if (inodes_total) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.total_inodes", base_key); + ret = dict_set_uint64 (dict, key, inodes_total); + if (ret) + goto out; + } + + inodes_free = brickstat.f_ffree; + if (inodes_free) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.free_inodes", base_key); + ret = dict_set_uint64 (dict, key, inodes_free); + if (ret) + goto out; + } + + ret = glusterd_add_brick_mount_details (brickinfo, dict, count); + if (ret) + goto out; + + ret = glusterd_add_inode_size_to_dict (dict, count); + + out: + if (ret) + gf_log (THIS->name, GF_LOG_DEBUG, "Error adding brick" + " detail to dict: %s", strerror (errno)); + return ret; +} + int32_t glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, dict_t *dict, int32_t count) { - int ret = -1; - char key[8192] = {0,}; - char base_key[8192] = {0}; - char pidfile[PATH_MAX] = {0}; - char path[PATH_MAX] = {0}; - int32_t pid = -1; - int32_t brick_online = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; + 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}; + char path[PATH_MAX] = {0}; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -3111,6 +3424,7 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, snprintf (base_key, sizeof (base_key), "brick%d", count); snprintf (key, sizeof (key), "%s.hostname", base_key); + ret = dict_set_str (dict, key, brickinfo->hostname); if (ret) goto out; @@ -3142,13 +3456,42 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.status", base_key); ret = dict_set_int32 (dict, key, brick_online); - if (ret) - goto out; out: if (ret) - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int32_t +glusterd_get_all_volnames (dict_t *dict) +{ + int ret = -1; + int32_t vol_count = 0; + char key[256] = {0}; + glusterd_volinfo_t *entry = NULL; + glusterd_conf_t *priv = NULL; + priv = THIS->private; + GF_ASSERT (priv); + + list_for_each_entry (entry, &priv->volumes, vol_list) { + memset (key, sizeof (key), 0); + snprintf (key, sizeof (key), "vol%d", vol_count); + ret = dict_set_str (dict, key, entry->volname); + if (ret) + goto out; + + vol_count++; + } + + ret = dict_set_int32 (dict, "vol_count", vol_count); + + out: + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, "failed to get all " + "volume names for status"); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index a34956b0c4a..0ce17450284 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -347,11 +347,22 @@ glusterd_recreate_bricks (glusterd_conf_t *conf); int32_t glusterd_handle_upgrade_downgrade (dict_t *options, glusterd_conf_t *conf); +int +glusterd_get_brick_root (char *path, char **mount_point); + +int +glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int32_t count); + int32_t glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, dict_t *dict, int32_t count); +int32_t +glusterd_get_all_volnames (dict_t *dict); + gf_boolean_t glusterd_is_fuse_available (); |