summaryrefslogtreecommitdiffstats
path: root/cli/src
diff options
context:
space:
mode:
authorCsaba Henk <csaba@gluster.com>2011-07-30 17:50:22 +0200
committerVijay Bellur <vijay@gluster.com>2011-09-12 06:23:11 -0700
commit37ac355cbbd36497f914905615bffb3e35805f0a (patch)
treea3a2b14739d9955e797927b5327b617738a00a3d /cli/src
parent78170472e6c7f0bce95ab035cc4ed86ec662e80d (diff)
glusterd / cli: mount-broker service
Mountbroker is configured in glusterd volfile through a DSL which is restriced enough to be able to appear in the role of the value of a volfile knob. Basically the DSL describes set-theorical requirements against the option set which is sent by the cli (in the hope of getting a mount with these options). If the requirements meet and the volume id and the uid who is to "own" the mount can be unambigously deduced from the given request, glusterd does the mount with the given parameters. The use case of geo-replication is sugared by means of volume options which then generate a complete mount-broker option set. Demo: - add the following option to your glusterd volfile: option mountbroker-root /tmp/mbr option mountbroker.fool EQL(volfile-id=pop*|user-map-root=*|volfile-server=localhost)&MEET(user-map-root=john|user-map-root=jane) - before starting glusterd, create /tmp/mbr owned by root with mode 0755 - with cli, do $ gluster system:: mount fool volfile-id=pop33 user-map-root=jane volfile-server=localhost - on succesful completion (volume pop33 exists and is started, jane is a valid username), the mount path will be echoed to you - you can get rid of the mount by $ gluster system:: umount <mount-path> Change-Id: I629cf64add0a45500d05becc3316f67cdb5b42ff BUG: 3482 Reviewed-on: http://review.gluster.com/128 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vijay@gluster.com>
Diffstat (limited to 'cli/src')
-rw-r--r--cli/src/cli-cmd-system.c118
-rw-r--r--cli/src/cli-rpc-ops.c131
2 files changed, 249 insertions, 0 deletions
diff --git a/cli/src/cli-cmd-system.c b/cli/src/cli-cmd-system.c
index 061cf4e83a7..25938b8974b 100644
--- a/cli/src/cli-cmd-system.c
+++ b/cli/src/cli-cmd-system.c
@@ -178,6 +178,116 @@ out:
return ret;
}
+static dict_t *
+make_seq_dict (int argc, char **argv)
+{
+ char index[] = "4294967296"; // 1<<32
+ int i = 0;
+ int ret = 0;
+ dict_t *dict = dict_new ();
+
+ if (!dict)
+ return NULL;
+
+ for (i = 0; i < argc; i++) {
+ snprintf(index, sizeof(index), "%d", i);
+ ret = dict_set_str (dict, index, argv[i]);
+ if (ret == -1)
+ break;
+ }
+
+ if (ret) {
+ dict_destroy (dict);
+ dict = NULL;
+ }
+
+ return dict;
+}
+
+int
+cli_cmd_mount_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
+{
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ int ret = -1;
+ dict_t *dict = NULL;
+ void *dataa[] = {NULL, NULL};
+
+ if (wordcount < 4) {
+ cli_usage_out (word->pattern);
+ goto out;
+ }
+
+ dict = make_seq_dict (wordcount - 3, (char **)words + 3);
+ if (!dict)
+ goto out;
+
+ dataa[0] = (void *)words[2];
+ dataa[1] = dict;
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_MOUNT];
+ if (proc && proc->fn) {
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+ ret = proc->fn (frame, THIS, dataa);
+ }
+
+ out:
+ if (dict)
+ dict_unref (dict);
+
+ if (!proc && ret)
+ cli_out ("Mount command failed");
+
+ return ret;
+}
+
+int
+cli_cmd_umount_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
+{
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ int ret = -1;
+ dict_t *dict = NULL;
+
+ if (!(wordcount == 3 ||
+ (wordcount == 4 && strcmp (words[3], "lazy") == 0))) {
+ cli_usage_out (word->pattern);
+ goto out;
+ }
+
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
+ ret = dict_set_str (dict, "path", (char *)words[2]);
+ if (ret != 0)
+ goto out;
+ ret = dict_set_int32 (dict, "lazy", wordcount == 4);
+ if (ret != 0)
+ goto out;
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_UMOUNT];
+ if (proc && proc->fn) {
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+ ret = proc->fn (frame, THIS, dict);
+ }
+
+ out:
+ if (dict)
+ dict_unref (dict);
+
+ if (!proc && ret)
+ cli_out ("Umount command failed");
+
+ return ret;
+}
+
struct cli_cmd cli_system_cmds[] = {
{ "system:: getspec <VOLID>",
cli_cmd_getspec_cbk,
@@ -195,6 +305,14 @@ struct cli_cmd cli_system_cmds[] = {
cli_cmd_getwd_cbk,
"query glusterd work directory"},
+ { "system:: mount <label> <args...>",
+ cli_cmd_mount_cbk,
+ "request a mount"},
+
+ { "system:: umount <path> [lazy]",
+ cli_cmd_umount_cbk,
+ "request an umount"},
+
{ "system:: help",
cli_cmd_system_help_cbk,
"display help for system commands"},
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 31ede5007fd..3d6ce25ef1b 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -3665,6 +3665,135 @@ gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this,
return ret;
}
+static int
+gf_cli3_1_mount_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ gf1_cli_mount_rsp rsp = {0,};
+ int ret = 0;
+
+ if (-1 == req->rpc_status) {
+ goto out;
+ }
+
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_mount_rsp);
+ if (ret < 0) {
+ gf_log ("", GF_LOG_ERROR, "error");
+ goto out;
+ }
+
+ gf_log ("cli", GF_LOG_INFO, "Received resp to mount");
+
+ if (rsp.op_ret == 0) {
+ ret = 0;
+ cli_out ("%s", rsp.path);
+ } else {
+ /* weird sounding but easy to parse... */
+ cli_out ("%d : failed with this errno (%s)",
+ rsp.op_errno, strerror (rsp.op_errno));
+ ret = 1;
+ }
+
+out:
+ cli_cmd_broadcast_response (ret);
+ return ret;
+}
+
+int32_t
+gf_cli3_1_mount (call_frame_t *frame, xlator_t *this, void *data)
+{
+ gf1_cli_mount_req req = {0,};
+ int ret = -1;
+ void **dataa = data;
+ char *label = NULL;
+ dict_t *dict = NULL;
+
+ if (!frame || !this || !data)
+ goto out;
+
+ label = dataa[0];
+ dict = dataa[1];
+
+ req.label = label;
+ ret = dict_allocate_and_serialize (dict, &req.dict.dict_val,
+ (size_t *)&req.dict.dict_len);
+ if (ret) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ GLUSTER_CLI_MOUNT, NULL,
+ this, gf_cli3_1_mount_cbk,
+ (xdrproc_t)xdr_gf1_cli_mount_req);
+
+out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
+static int
+gf_cli3_1_umount_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ gf1_cli_umount_rsp rsp = {0,};
+ int ret = 0;
+
+ if (-1 == req->rpc_status) {
+ goto out;
+ }
+
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_umount_rsp);
+ if (ret < 0) {
+ gf_log ("", GF_LOG_ERROR, "error");
+ goto out;
+ }
+
+ gf_log ("cli", GF_LOG_INFO, "Received resp to mount");
+
+ if (rsp.op_ret == 0)
+ ret = 0;
+ else {
+ cli_out ("umount failed");
+ ret = 1;
+ }
+
+out:
+ cli_cmd_broadcast_response (ret);
+ return ret;
+}
+
+int32_t
+gf_cli3_1_umount (call_frame_t *frame, xlator_t *this, void *data)
+{
+ gf1_cli_umount_req req = {0,};
+ int ret = -1;
+ dict_t *dict = NULL;
+
+ if (!frame || !this || !data)
+ goto out;
+
+ dict = data;
+
+ ret = dict_get_str (dict, "path", &req.path);
+ if (ret == 0)
+ ret = dict_get_int32 (dict, "lazy", &req.lazy);
+
+ if (ret) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ GLUSTER_CLI_UMOUNT, NULL,
+ this, gf_cli3_1_umount_cbk,
+ (xdrproc_t)xdr_gf1_cli_umount_req);
+
+ out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_NULL] = {"NULL", NULL },
[GLUSTER_CLI_PROBE] = {"PROBE_QUERY", gf_cli3_1_probe},
@@ -3697,6 +3826,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_LOG_LEVEL] = {"VOLUME_LOGLEVEL", gf_cli3_1_log_level},
[GLUSTER_CLI_GETWD] = {"GETWD", gf_cli3_1_getwd},
[GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli3_1_status_volume},
+ [GLUSTER_CLI_MOUNT] = {"MOUNT", gf_cli3_1_mount},
+ [GLUSTER_CLI_UMOUNT] = {"UMOUNT", gf_cli3_1_umount}
};
struct rpc_clnt_program cli_prog = {