diff options
author | Pranith K <pranithk@gluster.com> | 2010-09-28 02:47:08 +0000 |
---|---|---|
committer | Vijay Bellur <vijay@dev.gluster.com> | 2010-09-28 04:50:21 -0700 |
commit | 65a84c9d0d691ac4f7a5f33374140e50746a96af (patch) | |
tree | 3ae88729a1f8789d0df531331132180d3faed6c2 | |
parent | dbbec1261eae8440726b001df8fe4c06837d6f3d (diff) |
mgmt/glusterd: prevent detach of peer with its bricks existing in cluster
Signed-off-by: Pranith Kumar K <pranithk@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 1681 ()
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1681
-rw-r--r-- | cli/src/cli3_1-cops.c | 26 | ||||
-rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 7 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 126 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 17 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 182 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 16 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 3 |
7 files changed, 266 insertions, 111 deletions
diff --git a/cli/src/cli3_1-cops.c b/cli/src/cli3_1-cops.c index d92da29138e..0984a793694 100644 --- a/cli/src/cli3_1-cops.c +++ b/cli/src/cli3_1-cops.c @@ -155,7 +155,31 @@ gf_cli3_1_deprobe_cbk (struct rpc_req *req, struct iovec *iov, } gf_log ("cli", GF_LOG_NORMAL, "Received resp to deprobe"); - cli_out ("Detach %s", (rsp.op_ret) ? "unsuccessful": "successful"); + if (rsp.op_ret) { + switch (rsp.op_errno) { + case GF_DEPROBE_LOCALHOST: + cli_out ("%s is localhost", + rsp.hostname); + break; + case GF_DEPROBE_NOT_FRIEND: + cli_out ("%s is not part of cluster", + rsp.hostname); + break; + case GF_DEPROBE_BRICK_EXIST: + cli_out ("Brick(s) with the peer %s exist in " + "cluster", rsp.hostname); + break; + default: + cli_out ("Detach returned with unknown errno %d", + rsp.op_errno); + break; + } + cli_out ("Detach unsuccessful"); + gf_log ("glusterd",GF_LOG_ERROR,"Detach failed with op_ret %d" + " and op_errno %d", rsp.op_ret, rsp.op_errno); + } else { + cli_out ("Detach successful"); + } ret = rsp.op_ret; diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index b46f3b9883f..a84c1eb7831 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -162,6 +162,13 @@ enum gf_probe_resp { GF_PROBE_VOLUME_CONFLICT }; +enum gf_deprobe_resp { + GF_DEPROBE_SUCCESS, + GF_DEPROBE_LOCALHOST, + GF_DEPROBE_NOT_FRIEND, + GF_DEPROBE_BRICK_EXIST +}; + enum gf_cbk_procnum { GF_CBK_NULL = 0, GF_CBK_FETCHSPEC, diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index af4b3130648..5de695300fc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -55,94 +55,6 @@ #include "common-utils.h" static int -glusterd_friend_find_by_hostname (const char *hoststr, - glusterd_peerinfo_t **peerinfo) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_peerinfo_t *entry = NULL; - glusterd_peer_hostname_t *name = NULL; - struct addrinfo *addr = NULL; - struct addrinfo *p = NULL; - char *host = NULL; - struct sockaddr_in6 *s6 = NULL; - struct sockaddr_in *s4 = NULL; - struct in_addr *in_addr = NULL; - char hname[1024] = {0,}; - - GF_ASSERT (hoststr); - GF_ASSERT (peerinfo); - - *peerinfo = NULL; - priv = THIS->private; - - GF_ASSERT (priv); - - list_for_each_entry (entry, &priv->peers, uuid_list) { - list_for_each_entry (name, &entry->hostnames, hostname_list) { - if (!strncmp (name->hostname, hoststr, - 1024)) { - - gf_log ("glusterd", GF_LOG_NORMAL, - "Friend %s found.. state: %d", hoststr, - entry->state.state); - *peerinfo = entry; - return 0; - } - } - } - - ret = getaddrinfo(hoststr, NULL, NULL, &addr); - if (ret != 0) { - gf_log ("", GF_LOG_ERROR, "error in getaddrinfo: %s\n", - gai_strerror(ret)); - goto out; - } - - for (p = addr; p != NULL; p = p->ai_next) { - switch (p->ai_family) { - case AF_INET: - s4 = (struct sockaddr_in *) p->ai_addr; - in_addr = &s4->sin_addr; - break; - case AF_INET6: - s6 = (struct sockaddr_in6 *) p->ai_addr; - in_addr =(struct in_addr *) &s6->sin6_addr; - break; - default: ret = -1; - goto out; - } - host = inet_ntoa(*in_addr); - - ret = getnameinfo (p->ai_addr, p->ai_addrlen, hname, - 1024, NULL, 0, 0); - if (ret) - goto out; - - list_for_each_entry (entry, &priv->peers, uuid_list) { - list_for_each_entry (name, &entry->hostnames, - hostname_list) { - if (!strncmp (name->hostname, host, - 1024) || !strncmp (name->hostname,hname, - 1024)) { - gf_log ("glusterd", GF_LOG_NORMAL, - "Friend %s found.. state: %d", - hoststr, entry->state.state); - *peerinfo = entry; - freeaddrinfo (addr); - return 0; - } - } - } - } - -out: - if (addr) - freeaddrinfo (addr); - return -1; -} - -static int glusterd_friend_find_by_uuid (uuid_t uuid, glusterd_peerinfo_t **peerinfo) { @@ -642,7 +554,15 @@ glusterd_handle_cli_deprobe (rpcsvc_request_t *req) { int32_t ret = -1; gf1_cli_probe_req cli_req = {0,}; + uuid_t uuid = {0}; + int op_errno = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); GF_ASSERT (req); if (!gf_xdr_to_cli_probe_req (req->msg[0], &cli_req)) { @@ -653,12 +573,35 @@ glusterd_handle_cli_deprobe (rpcsvc_request_t *req) gf_log ("glusterd", GF_LOG_NORMAL, "Received CLI deprobe req"); + ret = glusterd_hostname_to_uuid (cli_req.hostname, uuid); + if (ret) { + op_errno = GF_DEPROBE_NOT_FRIEND; + goto out; + } - ret = glusterd_deprobe_begin (req, cli_req.hostname, cli_req.port); + if (!uuid_compare (uuid, priv->uuid)) { + op_errno = GF_DEPROBE_LOCALHOST; + ret = -1; + goto out; + } + + ret = glusterd_all_volume_cond_check (glusterd_friend_brick_belongs, + -1, &uuid); + if (ret) { + op_errno = GF_DEPROBE_BRICK_EXIST; + goto out; + } + + ret = glusterd_deprobe_begin (req, cli_req.hostname, + cli_req.port, uuid); gf_cmd_log ("peer deprobe", "on host %s:%d %s", cli_req.hostname, cli_req.port, (ret) ? "FAILED" : "SUCCESS"); out: + if (ret) { + ret = glusterd_xfer_cli_deprobe_resp (req, ret, op_errno, + cli_req.hostname); + } if (cli_req.hostname) free (cli_req.hostname);//malloced by xdr return ret; @@ -2784,7 +2727,8 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port) } int -glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port) +glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, + uuid_t uuid) { int ret = -1; glusterd_peerinfo_t *peerinfo = NULL; @@ -2794,7 +2738,7 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port) GF_ASSERT (hoststr); GF_ASSERT (req); - ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo); + ret = glusterd_friend_find (uuid, (char *)hoststr, &peerinfo); if (ret) { gf_log ("glusterd", GF_LOG_NORMAL, "Unable to find peerinfo" diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 9c337328235..3f01dc5da6b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1220,6 +1220,9 @@ glusterd_op_perform_add_bricks (glusterd_volinfo_t *volinfo, int32_t count, 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++; @@ -1558,6 +1561,9 @@ glusterd_op_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) 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++; @@ -2521,6 +2527,11 @@ glusterd_op_replace_brick (gd1_mgmt_stage_op_req *req, dict_t *rsp_dict) goto out; } + ret = glusterd_resolve_brick (dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); + goto out; + } /* Set src-brick's port number to be used in the maintainance mount * after all commit acks are received. */ @@ -3755,6 +3766,12 @@ glusterd_do_replace_brick (void *data) 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"); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index f99ddde9c92..71f23a8f139 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -588,26 +588,10 @@ int32_t glusterd_resolve_brick (glusterd_brickinfo_t *brickinfo) { int32_t ret = -1; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - GF_ASSERT (priv); GF_ASSERT (brickinfo); - ret = glusterd_friend_find (NULL, brickinfo->hostname, &peerinfo); - - if (!ret) { - uuid_copy (brickinfo->uuid, peerinfo->uuid); - } - - if (ret) { - ret = glusterd_is_local_addr (brickinfo->hostname); - if (!ret) - uuid_copy (brickinfo->uuid, priv->uuid); - } - + ret = glusterd_hostname_to_uuid (brickinfo->hostname, brickinfo->uuid); gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -1853,8 +1837,170 @@ glusterd_set_brick_status (glusterd_brickinfo_t *brickinfo, int glusterd_is_brick_started (glusterd_brickinfo_t *brickinfo) -{ +{ GF_ASSERT (brickinfo); return (!(brickinfo->status == GF_BRICK_STARTED)); } +int +glusterd_friend_brick_belongs (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, void* uuid) +{ + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + GF_ASSERT (uuid); + + if (!uuid_compare (brickinfo->uuid, *((uuid_t *)uuid))) + return 0; + + return -1; +} + +int +glusterd_all_volume_cond_check (glusterd_condition_func func, int status, + void *ctx) +{ + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + priv = this->private; + + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + list_for_each_entry (brickinfo, &volinfo->bricks, + brick_list) { + ret = func (volinfo, brickinfo, ctx); + if (ret != status) { + ret = -1; + goto out; + } + } + } + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} + +int +glusterd_friend_find_by_hostname (const char *hoststr, + glusterd_peerinfo_t **peerinfo) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *entry = NULL; + glusterd_peer_hostname_t *name = NULL; + struct addrinfo *addr = NULL; + struct addrinfo *p = NULL; + char *host = NULL; + struct sockaddr_in6 *s6 = NULL; + struct sockaddr_in *s4 = NULL; + struct in_addr *in_addr = NULL; + char hname[1024] = {0,}; + + GF_ASSERT (hoststr); + GF_ASSERT (peerinfo); + + *peerinfo = NULL; + priv = THIS->private; + + GF_ASSERT (priv); + + list_for_each_entry (entry, &priv->peers, uuid_list) { + list_for_each_entry (name, &entry->hostnames, hostname_list) { + if (!strncmp (name->hostname, hoststr, + 1024)) { + + gf_log ("glusterd", GF_LOG_NORMAL, + "Friend %s found.. state: %d", hoststr, + entry->state.state); + *peerinfo = entry; + return 0; + } + } + } + + ret = getaddrinfo(hoststr, NULL, NULL, &addr); + if (ret != 0) { + gf_log ("", GF_LOG_ERROR, "error in getaddrinfo: %s\n", + gai_strerror(ret)); + goto out; + } + + for (p = addr; p != NULL; p = p->ai_next) { + switch (p->ai_family) { + case AF_INET: + s4 = (struct sockaddr_in *) p->ai_addr; + in_addr = &s4->sin_addr; + break; + case AF_INET6: + s6 = (struct sockaddr_in6 *) p->ai_addr; + in_addr =(struct in_addr *) &s6->sin6_addr; + break; + default: ret = -1; + goto out; + } + host = inet_ntoa(*in_addr); + + ret = getnameinfo (p->ai_addr, p->ai_addrlen, hname, + 1024, NULL, 0, 0); + if (ret) + goto out; + + list_for_each_entry (entry, &priv->peers, uuid_list) { + list_for_each_entry (name, &entry->hostnames, + hostname_list) { + if (!strncmp (name->hostname, host, + 1024) || !strncmp (name->hostname,hname, + 1024)) { + gf_log ("glusterd", GF_LOG_NORMAL, + "Friend %s found.. state: %d", + hoststr, entry->state.state); + *peerinfo = entry; + freeaddrinfo (addr); + return 0; + } + } + } + } + +out: + if (addr) + freeaddrinfo (addr); + return -1; +} + +int +glusterd_hostname_to_uuid (char *hostname, uuid_t uuid) +{ + GF_ASSERT (hostname); + GF_ASSERT (uuid); + + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_conf_t *priv = NULL; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = glusterd_friend_find_by_hostname (hostname, &peerinfo); + if (ret) { + ret = glusterd_is_local_addr (hostname); + if (ret) + goto out; + else + uuid_copy (uuid, priv->uuid); + } else { + uuid_copy (uuid, peerinfo->uuid); + } + +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 3f49acfda43..9fa272a69f3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -43,6 +43,10 @@ struct glusterd_lock_ { time_t timestamp; }; +typedef int (*glusterd_condition_func) (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + void *ctx); + typedef struct glusterd_lock_ glusterd_lock_t; int32_t @@ -173,4 +177,16 @@ glusterd_set_brick_status (glusterd_brickinfo_t *brickinfo, int glusterd_is_brick_started (glusterd_brickinfo_t *brickinfo); +int +glusterd_friend_find_by_hostname (const char *hoststr, + glusterd_peerinfo_t **peerinfo); +int +glusterd_hostname_to_uuid (char *hostname, uuid_t uuid); + +int +glusterd_friend_brick_belongs (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, void *uuid); +int +glusterd_all_volume_cond_check (glusterd_condition_func func, int status, + void *ctx); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 2eb430f2798..ac30d3e5c38 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -311,7 +311,8 @@ int glusterd_xfer_friend_remove_resp (rpcsvc_request_t *req, char *hostname, int port); int -glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port); +glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, + uuid_t uuid); int glusterd_handle_cli_deprobe (rpcsvc_request_t *req); |