summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPranith K <pranithk@gluster.com>2010-09-28 02:47:08 +0000
committerVijay Bellur <vijay@dev.gluster.com>2010-09-28 04:50:21 -0700
commit65a84c9d0d691ac4f7a5f33374140e50746a96af (patch)
tree3ae88729a1f8789d0df531331132180d3faed6c2
parentdbbec1261eae8440726b001df8fe4c06837d6f3d (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.c26
-rw-r--r--rpc/rpc-lib/src/protocol-common.h7
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c126
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c17
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c182
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h16
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h3
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);