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 <[EMAIL PROTECTED]> 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