[SCM] CTDB repository - branch master updated - a63825e32658b36e0964584758b9a276c18056b8

Ronnie Sahlberg sahlberg at samba.org
Wed Apr 23 11:09:34 GMT 2008


The branch, master has been updated
       via  a63825e32658b36e0964584758b9a276c18056b8 (commit)
      from  0a4e667f42c6fb23be13651f7b0d0a545a49900b (commit)

http://gitweb.samba.org/?p=sahlberg/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit a63825e32658b36e0964584758b9a276c18056b8
Author: Ronnie Sahlberg <sahlberg at samba.org>
Date:   Wed Apr 23 21:05:36 2008 +1000

    when adding a new public ip address to a running node using the 'ctdb addip' command,
    If no other node is hosting this public ip at the moment, then assign it immediately to the current node.

-----------------------------------------------------------------------

Summary of changes:
 tools/ctdb.c |  255 +++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 153 insertions(+), 102 deletions(-)


Changeset truncated at 500 lines:

diff --git a/tools/ctdb.c b/tools/ctdb.c
index 2a3228b..6e94417 100644
--- a/tools/ctdb.c
+++ b/tools/ctdb.c
@@ -417,6 +417,40 @@ static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char *
 	return 0;
 }
 
+/* send a release ip to all nodes */
+static int control_send_release(struct ctdb_context *ctdb, uint32_t pnn,
+struct sockaddr_in *sin)
+{
+	int ret;
+	struct ctdb_public_ip pip;
+	TDB_DATA data;
+	struct ctdb_node_map *nodemap=NULL;
+
+	ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
+		return ret;
+	}
+
+	/* send a moveip message to the recovery master */
+	pip.pnn = pnn;
+	pip.sin.sin_family = AF_INET;
+	pip.sin.sin_addr   = sin->sin_addr;
+	data.dsize = sizeof(pip);
+	data.dptr = (unsigned char *)&pip;
+
+
+	/* send release ip to all nodes */
+	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
+			list_of_active_nodes(ctdb, nodemap, ctdb, true),
+			TIMELIMIT(), false, data) != 0) {
+		DEBUG(DEBUG_ERR, (__location__ " Unable to send 'ReleaseIP' to all nodes.\n"));
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
   move/failover an ip address to a specific node
  */
@@ -426,9 +460,6 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv
 	struct sockaddr_in ip;
 	uint32_t value;
 	struct ctdb_all_public_ips *ips;
-	struct ctdb_public_ip pip;
-	TDB_DATA data;
-	struct ctdb_node_map *nodemap=NULL;
 	int i, ret;
 
 	if (argc < 2) {
@@ -442,12 +473,6 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv
 	}
 
 
-	ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
-	if (ret != 0) {
-		DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
-		return ret;
-	}
-
 	if (sscanf(argv[1], "%u", &pnn) != 1) {
 		DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
 		return -1;
@@ -496,47 +521,128 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv
 		return -1;
 	}
 
-	/* send a moveip message to the recovery master */
-	pip.pnn = pnn;
-	pip.sin.sin_family = AF_INET;
-	pip.sin.sin_addr   = ips->ips[i].sin.sin_addr;
-	data.dsize = sizeof(pip);
-	data.dptr = (unsigned char *)&pip;
+	ret = control_send_release(ctdb, pnn, &ips->ips[i].sin);
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Failed to send 'change ip' to all nodes\n"));;
+		return -1;
+	}
 
+	return 0;
+}
 
-	/* send release ip to all nodes */
-	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
-			list_of_active_nodes(ctdb, nodemap, ctdb, true),
-			TIMELIMIT(), false, data) != 0) {
-		DEBUG(DEBUG_ERR, (__location__ " Unable to send 'ReleaseIP' to all nodes.\n"));
-		return -1;
+struct node_ip {
+	uint32_t pnn;
+	struct sockaddr_in sin;
+};
+
+void getips_store_callback(void *param, void *data)
+{
+	struct node_ip *node_ip = (struct node_ip *)data;
+	struct ctdb_all_public_ips *ips = param;
+	int i;
+
+	i = ips->num++;
+	ips->ips[i].pnn = node_ip->pnn;
+	ips->ips[i].sin = node_ip->sin;
+}
+
+void getips_count_callback(void *param, void *data)
+{
+	uint32_t *count = param;
+
+	(*count)++;
+}
+
+static int
+control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
+{
+	struct ctdb_all_public_ips *tmp_ips;
+	struct ctdb_node_map *nodemap=NULL;
+	trbt_tree_t *tree;
+	int i, j, len, ret;
+	uint32_t count;
+
+	ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
+		return ret;
+	}
+
+	tree = trbt_create(tmp_ctx, 0);
+
+	for(i=0;i<nodemap->num;i++){
+		if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
+			continue;
+		}
+
+		/* read the public ip list from this node */
+		ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
+		if (ret != 0) {
+			DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
+			return -1;
+		}
+	
+		for (j=0; j<tmp_ips->num;j++) {
+			struct node_ip *node_ip;
+
+			node_ip = talloc(tmp_ctx, struct node_ip);
+			node_ip->pnn = tmp_ips->ips[j].pnn;
+			node_ip->sin = tmp_ips->ips[j].sin;
+
+			trbt_insert32(tree, tmp_ips->ips[j].sin.sin_addr.s_addr, node_ip);
+		}
+		talloc_free(tmp_ips);
 	}
 
+	/* traverse */
+	count = 0;
+	trbt_traversearray32(tree, 1, getips_count_callback, &count);
+
+	len = offsetof(struct ctdb_all_public_ips, ips) + 
+		count*sizeof(struct ctdb_public_ip);
+	tmp_ips = talloc_zero_size(tmp_ctx, len);
+	trbt_traversearray32(tree, 1, getips_store_callback, tmp_ips);
+
+	*ips = tmp_ips;
+
 	return 0;
 }
 
+
 /*
   add a public ip address to a node
  */
 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
 {
-	int ret;
+	int i, ret;
 	int len;
 	unsigned mask;
 	struct sockaddr_in addr;
 	struct ctdb_control_ip_iface *pub;
+	TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+	struct ctdb_all_public_ips *ips;
 
 	if (argc != 2) {
+		talloc_free(tmp_ctx);
 		usage();
 	}
 
 	if (!parse_ip_mask(argv[0], &addr, &mask)) {
 		DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
+		talloc_free(tmp_ctx);
 		return -1;
 	}
 
+	ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
+		talloc_free(tmp_ctx);
+		return ret;
+	}
+
+
 	len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
-	pub = talloc_size(ctdb, len); 
+	pub = talloc_size(tmp_ctx, len); 
 	CTDB_NO_MEMORY(ctdb, pub);
 
 	pub->sin   = addr;
@@ -547,9 +653,32 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
 	ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
 	if (ret != 0) {
 		DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
+		talloc_free(tmp_ctx);
 		return ret;
 	}
 
+
+	/* check if some other node is already serving this ip, if not,
+	 * we will claim it
+	 */
+	for (i=0;i<ips->num;i++) {
+		if (ctdb_same_ip(&addr, &ips->ips[i].sin)) {
+			break;
+		}
+	}
+	/* no one has this ip so we claim it */
+	if (i == ips->num) {
+		ret = control_send_release(ctdb, options.pnn, &addr);
+	} else {
+		ret = control_send_release(ctdb, ips->ips[i].pnn, &addr);
+	}
+
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Failed to send 'change ip' to all nodes\n"));
+		return -1;
+	}
+
+	talloc_free(tmp_ctx);
 	return 0;
 }
 
@@ -786,84 +915,6 @@ static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
 }
 
 
-struct node_ip {
-	uint32_t pnn;
-	struct sockaddr_in sin;
-};
-
-void getips_store_callback(void *param, void *data)
-{
-	struct node_ip *node_ip = (struct node_ip *)data;
-	struct ctdb_all_public_ips *ips = param;
-	int i;
-
-	i = ips->num++;
-	ips->ips[i].pnn = node_ip->pnn;
-	ips->ips[i].sin = node_ip->sin;
-}
-
-void getips_count_callback(void *param, void *data)
-{
-	uint32_t *count = param;
-
-	(*count)++;
-}
-
-static int
-control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
-{
-	struct ctdb_all_public_ips *tmp_ips;
-	struct ctdb_node_map *nodemap=NULL;
-	trbt_tree_t *tree;
-	int i, j, len, ret;
-	uint32_t count;
-
-	ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
-	if (ret != 0) {
-		DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
-		return ret;
-	}
-
-	tree = trbt_create(tmp_ctx, 0);
-
-	for(i=0;i<nodemap->num;i++){
-		if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
-			continue;
-		}
-
-		/* read the public ip list from this node */
-		ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
-		if (ret != 0) {
-			DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
-			return -1;
-		}
-	
-		for (j=0; j<tmp_ips->num;j++) {
-			struct node_ip *node_ip;
-
-			node_ip = talloc(tmp_ctx, struct node_ip);
-			node_ip->pnn = tmp_ips->ips[j].pnn;
-			node_ip->sin = tmp_ips->ips[j].sin;
-
-			trbt_insert32(tree, tmp_ips->ips[j].sin.sin_addr.s_addr, node_ip);
-		}
-		talloc_free(tmp_ips);
-	}
-
-	/* traverse */
-	count = 0;
-	trbt_traversearray32(tree, 1, getips_count_callback, &count);
-
-	len = offsetof(struct ctdb_all_public_ips, ips) + 
-		count*sizeof(struct ctdb_public_ip);
-	tmp_ips = talloc_zero_size(tmp_ctx, len);
-	trbt_traversearray32(tree, 1, getips_store_callback, tmp_ips);
-
-	*ips = tmp_ips;
-
-	return 0;
-}
-
 /*
   display public ip status
  */
@@ -1707,7 +1758,7 @@ static const struct {
 	{ "reloadnodes",     control_reload_nodes_file,		false, "reload the nodes file and restart the transport on all nodes"},
 	{ "getreclock",      control_getreclock,        false,  "get the path to the reclock file" },
 	{ "moveip",          control_moveip,		false, "move/failover an ip address to another node", "<ip> <node>"},
-	{ "addip",           control_addip,		false, "add a ip address to a node", "<ip/mask> <iface>"},
+	{ "addip",           control_addip,		true, "add a ip address to a node", "<ip/mask> <iface>"},
 	{ "delip",           control_delip,		false, "delete an ip address from a node", "<ip>"},
 	{ "eventscript",     control_eventscript,	true, "run the eventscript with the given parameters on a node", "<arguments>"},
 };


-- 
CTDB repository


More information about the samba-cvs mailing list