diff options
| -rw-r--r-- | cli/src/cli.c | 56 | ||||
| -rw-r--r-- | cli/src/cli.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 5 | ||||
| -rw-r--r-- | tests/bugs/bug-948729/bug-948729-force.t | 17 | ||||
| -rw-r--r-- | tests/bugs/bug-948729/bug-948729.t | 3 | ||||
| -rwxr-xr-x | tests/cluster.rc | 12 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 21 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 27 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 161 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 1 | 
10 files changed, 265 insertions, 40 deletions
diff --git a/cli/src/cli.c b/cli/src/cli.c index f87038b61..91b315ff1 100644 --- a/cli/src/cli.c +++ b/cli/src/cli.c @@ -353,6 +353,12 @@ cli_opt_parse (char *opt, struct cli_state *state)                  return 0;          } +        oarg = strtail (opt, "glusterd-sock="); +        if (oarg) { +                state->glusterd_sock = oarg; +                return 0; +        } +          return -1;  } @@ -414,7 +420,6 @@ cli_state_init (struct cli_state *state)          int                   ret = 0; -        state->remote_host = "localhost";          state->log_level = -1;          tree = &state->tree; @@ -501,23 +506,46 @@ cli_rpc_init (struct cli_state *state)          if (!options)                  goto out; -        ret = dict_set_str (options, "remote-host", state->remote_host); -        if (ret) -                goto out; +        /* Connect using to glusterd using the specified method, giving +         * preference to unix socket connection. If nothing is specified connect +         * to the default glusterd socket +         */ +        if (state->glusterd_sock) { +                gf_log ("cli", GF_LOG_INFO, "Connecting to glusterd using " +                        "sockfile %s", state->glusterd_sock); +                ret = rpc_transport_unix_options_build (&options, +                                                        state->glusterd_sock, +                                                        0); +                if (ret) +                        goto out; +        } else if (state->remote_host) { +                gf_log ("cli", GF_LOG_INFO, "Connecting to remote glusterd at " +                        "%s", state->remote_host); +                ret = dict_set_str (options, "remote-host", state->remote_host); +                if (ret) +                        goto out; -        if (state->remote_port) -                port = state->remote_port; +                if (state->remote_port) +                        port = state->remote_port; -        ret = dict_set_int32 (options, "remote-port", port); -        if (ret) -                goto out; +                ret = dict_set_int32 (options, "remote-port", port); +                if (ret) +                        goto out; -        ret = dict_set_str (options, "transport.address-family", "inet"); -        if (ret) -                goto out; +                ret = dict_set_str (options, "transport.address-family", +                                    "inet"); +                if (ret) +                        goto out; +        } else { +                gf_log ("cli", GF_LOG_DEBUG, "Connecting to glusterd using " +                        "default socket"); +                ret = rpc_transport_unix_options_build +                        (&options, DEFAULT_GLUSTERD_SOCKFILE, 0); +                if (ret) +                        goto out; +        }          rpc = rpc_clnt_new (options, this->ctx, this->name, 16); -          if (!rpc)                  goto out; @@ -527,7 +555,7 @@ cli_rpc_init (struct cli_state *state)                  goto out;          } -        rpc_clnt_start (rpc); +        ret = rpc_clnt_start (rpc);  out:          if (ret) {                  if (rpc) diff --git a/cli/src/cli.h b/cli/src/cli.h index a36c1606f..d7b64cfbf 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -128,6 +128,8 @@ struct cli_state {          char                 *log_file;          gf_loglevel_t         log_level; + +        char                 *glusterd_sock;  };  struct cli_local { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 93e7385cc..ab571004e 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -157,6 +157,11 @@  #define UUID_CANONICAL_FORM_LEN  36 +/* Adding this here instead of any glusterd*.h files as it is also required by + * cli + */ +#define DEFAULT_GLUSTERD_SOCKFILE             DATADIR "/run/glusterd.socket" +  /* NOTE: add members ONLY at the end (just before _MAXVALUE) */  typedef enum {          GF_FOP_NULL = 0, diff --git a/tests/bugs/bug-948729/bug-948729-force.t b/tests/bugs/bug-948729/bug-948729-force.t index 3a5df7916..d14e94061 100644 --- a/tests/bugs/bug-948729/bug-948729-force.t +++ b/tests/bugs/bug-948729/bug-948729-force.t @@ -16,7 +16,6 @@ V1=patchy1  V2=patchy2  TEST launch_cluster 2; -cli1="gluster --remote-host=$H1"  TEST $CLI_1 peer probe $H2; @@ -59,22 +58,22 @@ TEST mount -t xfs $LD5 $B5/$V0  TEST mount -t xfs $LD6 $B6/$V0  #Case 0: Parent directory of the brick is absent -TEST ! $cli1 volume create $V0 $H1:$B1/$V0/nonexistent/b1 $H2:$B2/$V0/nonexistent/b2 force +TEST ! $CLI1 volume create $V0 $H1:$B1/$V0/nonexistent/b1 $H2:$B2/$V0/nonexistent/b2 force  #Case 1: File system root is being used as brick directory -TEST   $cli1 volume create $V0 $H1:$B5/$V0 $H2:$B6/$V0 force +TEST   $CLI1 volume create $V0 $H1:$B5/$V0 $H2:$B6/$V0 force  #Case 2: Brick directory contains only one component -TEST   $cli1 volume create $V1 $H1:/$uuid1 $H2:/$uuid2 force +TEST   $CLI1 volume create $V1 $H1:/$uuid1 $H2:/$uuid2 force  #Case 3: Sub-directories of the backend FS being used as brick directory -TEST   $cli1 volume create $V2 $H1:$B1/$V0/brick1 $H2:$B2/$V0/brick2 force +TEST   $CLI1 volume create $V2 $H1:$B1/$V0/brick1 $H2:$B2/$V0/brick2 force  #add-brick tests -TEST ! $cli1 volume add-brick $V0 $H1:$B3/$V0/nonexistent/brick3 force -TEST   $cli1 volume add-brick $V0 $H1:$B3/$V0 force -TEST   $cli1 volume add-brick $V1 $H1:/$uuid3 force -TEST   $cli1 volume add-brick $V2 $H1:$B4/$V0/brick3 force +TEST ! $CLI1 volume add-brick $V0 $H1:$B3/$V0/nonexistent/brick3 force +TEST   $CLI1 volume add-brick $V0 $H1:$B3/$V0 force +TEST   $CLI1 volume add-brick $V1 $H1:/$uuid3 force +TEST   $CLI1 volume add-brick $V2 $H1:$B4/$V0/brick3 force  #####replace-brick tests  #FIX-ME: replace-brick does not work with the newly introduced cluster test diff --git a/tests/bugs/bug-948729/bug-948729.t b/tests/bugs/bug-948729/bug-948729.t index 288ae2bef..f94db1ea0 100644 --- a/tests/bugs/bug-948729/bug-948729.t +++ b/tests/bugs/bug-948729/bug-948729.t @@ -14,7 +14,6 @@ uuid2=`uuidgen`;  uuid3=`uuidgen`;  TEST launch_cluster 2; -cli1="gluster --remote-host=$H1"  TEST $CLI_1 peer probe $H2; @@ -42,7 +41,7 @@ TEST mount -t xfs $LD2 $B2/$V0  TEST mount -t xfs $LD3 $B3/$V0  #Tests without --mode=script option - +cli1=$(echo $CLI1 | sed 's/ --mode=script//')  #Case 0: Parent directory of the brick is absent  TEST ! $cli1 volume create $V0 $H1:$B1/$V0/nonexistent/b1 $H2:$B2/$V0/nonexistent/b2 diff --git a/tests/cluster.rc b/tests/cluster.rc index 1c06bca47..1e42426f6 100755 --- a/tests/cluster.rc +++ b/tests/cluster.rc @@ -45,8 +45,10 @@ function define_glusterds() {  	wopt="management.working-directory=${!b}/glusterd";  	bopt="management.transport.socket.bind-address=${!h}";  	popt="--pid-file=${!b}/glusterd.pid"; -	eval "glusterd_$i='glusterd --xlator-option $wopt --xlator-option $bopt $popt'"; -	eval "glusterd$i='glusterd --xlator-option $wopt --xlator-option $bopt $popt'"; +        sopt="management.glusterd-sockfile=${!b}/glusterd/gd.sock" +        lopt="--log-file=${!b}/glusterd.log" +	eval "glusterd_$i='glusterd --xlator-option $wopt --xlator-option $bopt --xlator-option $sopt $lopt $popt'"; +	eval "glusterd$i='glusterd --xlator-option $wopt --xlator-option $bopt --xlator-option $sopt $lopt $popt'";      done  } @@ -98,9 +100,9 @@ function define_clis() {      local h;      for i in `seq 1 $count`; do -	h="H$i"; -	eval "CLI_$i='$CLI --remote-host=${!h}'"; -	eval "CLI$i='$CLI --remote-host=${!h}'"; +	b="B$i"; +	eval "CLI_$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock'"; +	eval "CLI$i='$CLI --glusterd-sock=${!b}/glusterd/gd.sock'";      done  } diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 93c6959f1..a80d8689c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -3953,3 +3953,24 @@ struct rpcsvc_program gd_svc_cli_prog = {          .actors    = gd_svc_cli_actors,  	.synctask  = _gf_true,  }; + +/* This is a minimal RPC prog, which contains only the readonly RPC procs from + * the cli rpcsvc + */ +rpcsvc_actor_t gd_svc_cli_actors_ro[] = { +        [GLUSTER_CLI_LIST_FRIENDS]       = { "LIST_FRIENDS",      GLUSTER_CLI_LIST_FRIENDS,     glusterd_handle_cli_list_friends,      NULL, 0, DRC_NA}, +        [GLUSTER_CLI_UUID_GET]           = { "UUID_GET",          GLUSTER_CLI_UUID_GET,         glusterd_handle_cli_uuid_get,          NULL, 0, DRC_NA}, +        [GLUSTER_CLI_GET_VOLUME]         = { "GET_VOLUME",        GLUSTER_CLI_GET_VOLUME,       glusterd_handle_cli_get_volume,        NULL, 0, DRC_NA}, +        [GLUSTER_CLI_GETWD]              = { "GETWD",             GLUSTER_CLI_GETWD,            glusterd_handle_getwd,                 NULL, 1, DRC_NA}, +        [GLUSTER_CLI_STATUS_VOLUME]      = {"STATUS_VOLUME",      GLUSTER_CLI_STATUS_VOLUME,    glusterd_handle_status_volume,         NULL, 0, DRC_NA}, +        [GLUSTER_CLI_LIST_VOLUME]        = {"LIST_VOLUME",        GLUSTER_CLI_LIST_VOLUME,      glusterd_handle_cli_list_volume,       NULL, 0, DRC_NA}, +}; + +struct rpcsvc_program gd_svc_cli_prog_ro = { +        .progname  = "GlusterD svc cli read-only", +        .prognum   = GLUSTER_CLI_PROGRAM, +        .progver   = GLUSTER_CLI_VERSION, +        .numactors = GLUSTER_CLI_MAXVALUE, +        .actors    = gd_svc_cli_actors_ro, +	.synctask  = _gf_true, +}; diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 2aef32ba1..1420eb692 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -244,16 +244,22 @@ __server_getspec (rpcsvc_request_t *req)          }          trans = req->trans; +        /* addrstr will be empty for cli socket connections */          ret = rpcsvc_transport_peername (trans, (char *)&addrstr,                                           sizeof (addrstr));          if (ret)                  goto fail; -        tmp = strrchr (addrstr, ':'); -        *tmp = '\0'; +        tmp  = strrchr (addrstr, ':'); +        if (tmp) +                *tmp = '\0'; -        /* we trust the local admin */ -        if (gf_is_local_addr (addrstr)) { +        /* The trusted volfiles are given to the glusterd owned process like NFS +         * server, self-heal daemon etc., so that they are not inadvertently +         * blocked by a auth.{allow,reject} setting. The trusted volfile is not +         * meant for external users. +         */ +        if (strlen (addrstr) && gf_is_local_addr (addrstr)) {                  ret = build_volfile_path (volume, filename,                                            sizeof (filename), @@ -600,6 +606,19 @@ struct rpcsvc_program gluster_handshake_prog = {          .numactors = GF_HNDSK_MAXVALUE,  }; +/* A minimal RPC program just for the cli getspec command */ +rpcsvc_actor_t gluster_cli_getspec_actors[] = { +        [GF_HNDSK_GETSPEC]      = {"GETSPEC",     GF_HNDSK_GETSPEC,      server_getspec,      NULL, 0, DRC_NA}, +}; + +struct rpcsvc_program gluster_cli_getspec_prog = { +        .progname  = "Gluster Handshake (CLI Getspec)", +        .prognum   = GLUSTER_HNDSK_PROGRAM, +        .progver   = GLUSTER_HNDSK_VERSION, +        .actors    = gluster_cli_getspec_actors, +        .numactors = GF_HNDSK_MAXVALUE, +}; +  char *glusterd_dump_proc[GF_DUMP_MAXVALUE] = {          [GF_DUMP_NULL] = "NULL", diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index dc35f8bf0..7d38b9295 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -44,11 +44,13 @@  #include "glusterd-mountbroker.h"  extern struct rpcsvc_program gluster_handshake_prog; +extern struct rpcsvc_program gluster_cli_getspec_prog;  extern struct rpcsvc_program gluster_pmap_prog;  extern glusterd_op_info_t opinfo;  extern struct rpcsvc_program gd_svc_mgmt_prog;  extern struct rpcsvc_program gd_svc_peer_prog;  extern struct rpcsvc_program gd_svc_cli_prog; +extern struct rpcsvc_program gd_svc_cli_prog_ro;  extern struct rpc_clnt_program gd_brick_prog;  extern struct rpcsvc_program glusterd_mgmt_hndsk_prog; @@ -58,15 +60,23 @@ rpcsvc_cbk_program_t glusterd_cbk_prog = {          .progver   = GLUSTER_CBK_VERSION,  }; -struct rpcsvc_program *all_programs[] = { +struct rpcsvc_program *gd_inet_programs[] = {          &gd_svc_peer_prog, -        &gd_svc_cli_prog, +        &gd_svc_cli_prog_ro,          &gd_svc_mgmt_prog,          &gluster_pmap_prog,          &gluster_handshake_prog,          &glusterd_mgmt_hndsk_prog,  }; -int rpcsvc_programs_count = (sizeof (all_programs) / sizeof (all_programs[0])); +int gd_inet_programs_count = (sizeof (gd_inet_programs) / +                              sizeof (gd_inet_programs[0])); + +struct rpcsvc_program *gd_uds_programs[] = { +        &gd_svc_cli_prog, +        &gluster_cli_getspec_prog, +}; +int gd_uds_programs_count = (sizeof (gd_uds_programs) / +                             sizeof (gd_uds_programs[0]));  const char *gd_op_list[GD_OP_MAX + 1] = {          [GD_OP_NONE]                    = "Invalid op", @@ -937,6 +947,123 @@ glusterd_launch_synctask (synctask_fn_t fn, void *opaque)                          " and other volume related services");  } +int +glusterd_uds_rpcsvc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, +                            void *data) +{ +        /* glusterd_rpcsvc_notify() does stuff that calls coming in from the +         * unix domain socket don't need. This is just an empty function to be +         * used for the uds listener. This will be used later if required. +         */ +        return 0; +} + +/* The glusterd unix domain socket listener only listens for cli */ +rpcsvc_t * +glusterd_init_uds_listener (xlator_t *this) +{ +        int             ret = -1; +        dict_t          *options = NULL; +        rpcsvc_t        *rpc = NULL; +        data_t          *sock_data = NULL; +        char            sockfile[PATH_MAX+1] = {0,}; +        int             i = 0; + + +        GF_ASSERT (this); + +        sock_data = dict_get (this->options, "glusterd-sockfile"); +        if (!sock_data) { +                strncpy (sockfile, DEFAULT_GLUSTERD_SOCKFILE, PATH_MAX); +        } else { +                strncpy (sockfile, sock_data->data, PATH_MAX); +        } + +        options = dict_new (); +        if (!options) +                goto out; + +        ret = rpcsvc_transport_unix_options_build (&options, sockfile); +        if (ret) +                goto out; + +        rpc = rpcsvc_init (this, this->ctx, options, 8); +        if (rpc == NULL) { +                ret = -1; +                goto out; +        } + +        ret = rpcsvc_register_notify (rpc, glusterd_uds_rpcsvc_notify, +                                      this); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "Failed to register notify function"); +                goto out; +        } + +        ret = rpcsvc_create_listeners (rpc, options, this->name); +        if (ret != 1) { +                gf_log (this->name, GF_LOG_DEBUG, "Failed to create listener"); +                goto out; +        } +        ret = 0; + +        for (i = 0; i < gd_uds_programs_count; i++) { +                ret = glusterd_program_register (this, rpc, gd_uds_programs[i]); +                if (ret) { +                        i--; +                        for (; i >= 0; i--) +                                rpcsvc_program_unregister (rpc, +                                                           gd_uds_programs[i]); + +                        goto out; +                } +        } + +out: +        if (options) +                dict_unref (options); + +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "Failed to start glusterd " +                        "unix domain socket listener."); +                if (rpc) { +                        GF_FREE (rpc); +                        rpc = NULL; +                } +        } +        return rpc; +} + +void +glusterd_stop_uds_listener (xlator_t *this) +{ +        glusterd_conf_t         *conf = NULL; +        rpcsvc_listener_t       *listener = NULL; +        rpcsvc_listener_t       *next = NULL; + +        GF_ASSERT (this); +        conf = this->private; + +        (void) rpcsvc_program_unregister (conf->uds_rpc, &gd_svc_cli_prog); +        (void) rpcsvc_program_unregister (conf->uds_rpc, &gluster_handshake_prog); + +        list_for_each_entry_safe (listener, next, &conf->uds_rpc->listeners, +                                  list) { +                rpcsvc_listener_destroy (listener); +        } + +        (void) rpcsvc_unregister_notify (conf->uds_rpc, glusterd_rpcsvc_notify, +                                         this); + +        unlink (DEFAULT_GLUSTERD_SOCKFILE); + +        GF_FREE (conf->uds_rpc); +        conf->uds_rpc = NULL; + +        return; +} +  /*   * init - called during glusterd initialization   * @@ -948,6 +1075,7 @@ init (xlator_t *this)  {          int32_t            ret               = -1;          rpcsvc_t          *rpc               = NULL; +        rpcsvc_t          *uds_rpc           = NULL;          glusterd_conf_t   *conf              = NULL;          data_t            *dir_data          = NULL;          struct stat        buf               = {0,}; @@ -1099,18 +1227,29 @@ init (xlator_t *this)                  goto out;          } -        for (i = 0; i < rpcsvc_programs_count; i++) { -                ret = glusterd_program_register (this, rpc, all_programs[i]); +        for (i = 0; i < gd_inet_programs_count; i++) { +                ret = glusterd_program_register (this, rpc, +                                                 gd_inet_programs[i]);                  if (ret) {                          i--;                          for (; i >= 0; i--)                                  rpcsvc_program_unregister (rpc, -                                                           all_programs[i]); +                                                           gd_inet_programs[i]);                          goto out;                  }          } +        /* Start a unix domain socket listener just for cli commands +         * This should prevent ports from being wasted by being in TIMED_WAIT +         * when cli commands are done continuously +         */ +        uds_rpc = glusterd_init_uds_listener (this); +        if (uds_rpc == NULL) { +                ret = -1; +                goto out; +        } +          conf = GF_CALLOC (1, sizeof (glusterd_conf_t),                            gf_gld_mt_glusterd_conf_t);          GF_VALIDATE_OR_GOTO(this->name, conf, out); @@ -1125,6 +1264,7 @@ init (xlator_t *this)          INIT_LIST_HEAD (&conf->volumes);          pthread_mutex_init (&conf->mutex, NULL);          conf->rpc = rpc; +        conf->uds_rpc = uds_rpc;          conf->gfs_mgmt = &gd_brick_prog;          strncpy (conf->workdir, workdir, PATH_MAX); @@ -1241,11 +1381,15 @@ fini (xlator_t *this)                  goto out;          conf = this->private; + +        glusterd_stop_uds_listener (this); +          FREE (conf->pmap);          if (conf->handle)                  gf_store_handle_destroy (conf->handle);          glusterd_sm_tr_log_delete (&conf->op_sm_log);          GF_FREE (conf); +          this->private = NULL;  out:          return; @@ -1346,5 +1490,10 @@ struct volume_options options[] = {            .description = "Sets the quorum percentage for the trusted "            "storage pool."          }, +        { .key = {"glusterd-sockfile"}, +          .type = GF_OPTION_TYPE_PATH, +          .description = "The socket file on which glusterd should listen for " +                        "cli requests. Default is "DEFAULT_GLUSTERD_SOCKFILE "." +        },          { .key   = {NULL} },  }; diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 4ca30770a..dd71341dd 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -154,6 +154,7 @@ typedef struct {          dict_t             *opts;          synclock_t      big_lock;          gf_boolean_t    restart_done; +        rpcsvc_t        *uds_rpc; /* RPCSVC for the unix domain socket */  } glusterd_conf_t;  | 
