1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

server: add a ctdb_do_updateip()

metze

(This used to be ctdb commit eded224368dded2264e53546c196b1b485cb2094)
This commit is contained in:
Stefan Metzmacher 2010-01-16 15:01:17 +01:00
parent aa485b17bb
commit 58d7c44b1c

View File

@ -409,6 +409,124 @@ static int32_t ctdb_do_takeip(struct ctdb_context *ctdb,
return 0;
}
struct ctdb_do_updateip_state {
struct ctdb_req_control *c;
struct ctdb_iface *old;
struct ctdb_vnn *vnn;
};
/*
called when updateip event finishes
*/
static void ctdb_do_updateip_callback(struct ctdb_context *ctdb, int status,
void *private_data)
{
struct ctdb_do_updateip_state *state =
talloc_get_type(private_data, struct ctdb_do_updateip_state);
int32_t ret;
if (status != 0) {
if (status == -ETIME) {
ctdb_ban_self(ctdb);
}
DEBUG(DEBUG_ERR,(__location__ " Failed to move IP %s from interface %s to %s\n",
ctdb_addr_to_str(&state->vnn->public_address),
state->old->name,
ctdb_vnn_iface_string(state->vnn)));
/*
* All we can do is reset the old interface
* and let the next run fix it
*/
ctdb_vnn_unassign_iface(ctdb, state->vnn);
state->vnn->iface = state->old;
state->vnn->iface->references++;
ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
talloc_free(state);
return;
}
ret = ctdb_announce_vnn_iface(ctdb, state->vnn);
if (ret != 0) {
ctdb_request_control_reply(ctdb, state->c, NULL, -1, NULL);
talloc_free(state);
return;
}
/* the control succeeded */
ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL);
talloc_free(state);
return;
}
/*
update (move) an ip address
*/
static int32_t ctdb_do_updateip(struct ctdb_context *ctdb,
struct ctdb_req_control *c,
struct ctdb_vnn *vnn)
{
int ret;
struct ctdb_do_updateip_state *state;
struct ctdb_iface *old = vnn->iface;
ctdb_vnn_unassign_iface(ctdb, vnn);
ret = ctdb_vnn_assign_iface(ctdb, vnn);
if (ret != 0) {
DEBUG(DEBUG_ERR,("update of IP %s/%u failed to "
"assin a usable interface (old iface '%s')\n",
ctdb_addr_to_str(&vnn->public_address),
vnn->public_netmask_bits,
old->name));
return -1;
}
if (vnn->iface == old) {
DEBUG(DEBUG_ERR,("update of IP %s/%u trying to "
"assin a same interface '%s'\n",
ctdb_addr_to_str(&vnn->public_address),
vnn->public_netmask_bits,
old->name));
return -1;
}
state = talloc(vnn, struct ctdb_do_updateip_state);
CTDB_NO_MEMORY(ctdb, state);
state->c = talloc_steal(ctdb, c);
state->old = old;
state->vnn = vnn;
DEBUG(DEBUG_NOTICE,("Update of IP %s/%u from "
"interface %s to %s\n",
ctdb_addr_to_str(&vnn->public_address),
vnn->public_netmask_bits,
old->name,
ctdb_vnn_iface_string(vnn)));
ret = ctdb_event_script_callback(ctdb,
state,
ctdb_do_updateip_callback,
state,
false,
CTDB_EVENT_UPDATE_IP,
"%s %s %s %u",
state->old->name,
ctdb_vnn_iface_string(vnn),
ctdb_addr_to_str(&vnn->public_address),
vnn->public_netmask_bits);
if (ret != 0) {
DEBUG(DEBUG_ERR,(__location__ " Failed update IP %s from interface %s to %s\n",
ctdb_addr_to_str(&vnn->public_address),
old->name, ctdb_vnn_iface_string(vnn)));
talloc_free(state);
return -1;
}
return 0;
}
/*
Find the vnn of the node that has a public ip address
returns -1 if the address is not known as a public address
@ -438,6 +556,7 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
struct ctdb_vnn *vnn;
bool have_ip = false;
bool do_updateip = false;
bool do_takeip = false;
/* update out vnn list */
@ -450,7 +569,25 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
vnn->pnn = pip->pnn;
have_ip = ctdb_sys_have_ip(&pip->addr);
if (vnn->iface) {
if (vnn->iface->link_up) {
struct ctdb_iface *best;
best = ctdb_vnn_best_iface(ctdb, vnn);
/* only move when the rebalance gains something */
if (best && vnn->iface->references > (best->references + 1)) {
do_updateip = true;
}
} else if (vnn->iface != best_iface) {
do_updateip = true;
}
}
if (!have_ip) {
if (do_updateip) {
ctdb_vnn_unassign_iface(ctdb, vnn);
do_updateip = false;
}
do_takeip = true;
}
@ -459,6 +596,11 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
if (ret != 0) {
return -1;
}
} else if (do_updateip) {
ret = ctdb_do_updateip(ctdb, c, vnn);
if (ret != 0) {
return -1;
}
} else {
/*
* The interface is up and the kernel known the ip