mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
Add two new controls to add/delete public ip address from a node at runtime.
The controls only modify the runtime setting of which public addresses a node can server and does not modify /etc/ctdb/public_addresses. To make the change permanent you also need to edit /etc/ctdb/public_addresses manually. After ip addresses have been added/deleted you need to invoke a recovery for the ip addresses to be redistributed. (This used to be ctdb commit f8294d103fdd8a720d0b0c337d3973c7fdf76b5c)
This commit is contained in:
parent
26ec64a571
commit
0d7b34c9e5
@ -2290,6 +2290,55 @@ int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
add a public address to a node
|
||||
*/
|
||||
int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
|
||||
struct timeval timeout,
|
||||
uint32_t destnode,
|
||||
struct ctdb_control_ip_iface *pub)
|
||||
{
|
||||
TDB_DATA data;
|
||||
int32_t res;
|
||||
int ret;
|
||||
|
||||
data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
|
||||
data.dptr = (unsigned char *)pub;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
|
||||
NULL, &res, &timeout, NULL);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
delete a public address from a node
|
||||
*/
|
||||
int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
|
||||
struct timeval timeout,
|
||||
uint32_t destnode,
|
||||
struct ctdb_control_ip_iface *pub)
|
||||
{
|
||||
TDB_DATA data;
|
||||
int32_t res;
|
||||
int ret;
|
||||
|
||||
data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
|
||||
data.dptr = (unsigned char *)pub;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
|
||||
NULL, &res, &timeout, NULL);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
kill a tcp connection
|
||||
@ -2328,13 +2377,13 @@ int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
|
||||
TDB_DATA data;
|
||||
int32_t res;
|
||||
int ret, len;
|
||||
struct ctdb_control_gratious_arp *gratious_arp;
|
||||
struct ctdb_control_ip_iface *gratious_arp;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
|
||||
|
||||
|
||||
len = strlen(ifname)+1;
|
||||
gratious_arp = talloc_size(tmp_ctx,
|
||||
offsetof(struct ctdb_control_gratious_arp, iface) + len);
|
||||
offsetof(struct ctdb_control_ip_iface, iface) + len);
|
||||
CTDB_NO_MEMORY(ctdb, gratious_arp);
|
||||
|
||||
gratious_arp->sin = *sin;
|
||||
@ -2342,7 +2391,7 @@ int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
|
||||
memcpy(&gratious_arp->iface[0], ifname, len);
|
||||
|
||||
|
||||
data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
|
||||
data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + len;
|
||||
data.dptr = (unsigned char *)gratious_arp;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define CTDB_NULL_FUNC 0xFF000001
|
||||
#define CTDB_FETCH_FUNC 0xFF000002
|
||||
|
||||
|
||||
/*
|
||||
a tcp connection description
|
||||
*/
|
||||
@ -499,6 +500,8 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
|
||||
CTDB_CONTROL_TRY_DELETE_RECORDS = 74,
|
||||
CTDB_CONTROL_ENABLE_MONITOR = 75,
|
||||
CTDB_CONTROL_DISABLE_MONITOR = 76,
|
||||
CTDB_CONTROL_ADD_PUBLIC_IP = 77,
|
||||
CTDB_CONTROL_DEL_PUBLIC_IP = 78,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -527,10 +530,13 @@ struct ctdb_control_killtcp {
|
||||
};
|
||||
|
||||
/*
|
||||
struct for send_gratious_arp
|
||||
struct holding a sockaddr_in and an interface name,
|
||||
used for send_gratious_arp and also add/remove public addresses
|
||||
*/
|
||||
struct ctdb_control_gratious_arp {
|
||||
//struct ctdb_control_gratious_arp {
|
||||
struct ctdb_control_ip_iface {
|
||||
struct sockaddr_in sin;
|
||||
uint32_t mask;
|
||||
uint32_t len;
|
||||
char iface[1];
|
||||
};
|
||||
@ -1165,6 +1171,8 @@ int32_t ctdb_control_set_tunable(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
int32_t ctdb_control_list_tunables(struct ctdb_context *ctdb, TDB_DATA *outdata);
|
||||
int32_t ctdb_control_get_reclock_file(struct ctdb_context *ctdb, TDB_DATA *outdata);
|
||||
int32_t ctdb_control_try_delete_records(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata);
|
||||
int32_t ctdb_control_add_public_address(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
|
||||
void ctdb_tunables_set_defaults(struct ctdb_context *ctdb);
|
||||
|
||||
@ -1190,6 +1198,16 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
|
||||
uint32_t destnode,
|
||||
struct ctdb_control_killtcp *killtcp);
|
||||
|
||||
int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
|
||||
struct timeval timeout,
|
||||
uint32_t destnode,
|
||||
struct ctdb_control_ip_iface *pub);
|
||||
|
||||
int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
|
||||
struct timeval timeout,
|
||||
uint32_t destnode,
|
||||
struct ctdb_control_ip_iface *pub);
|
||||
|
||||
int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
|
||||
struct timeval timeout,
|
||||
uint32_t destnode,
|
||||
|
@ -380,6 +380,12 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
case CTDB_CONTROL_TRY_DELETE_RECORDS:
|
||||
return ctdb_control_try_delete_records(ctdb, indata, outdata);
|
||||
|
||||
case CTDB_CONTROL_ADD_PUBLIC_IP:
|
||||
return ctdb_control_add_public_address(ctdb, indata);
|
||||
|
||||
case CTDB_CONTROL_DEL_PUBLIC_IP:
|
||||
return ctdb_control_del_public_address(ctdb, indata);
|
||||
|
||||
default:
|
||||
DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
|
||||
return -1;
|
||||
|
@ -391,7 +391,7 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
|
||||
|
||||
|
||||
|
||||
static int add_public_address(struct ctdb_context *ctdb, struct sockaddr_in addr, unsigned mask, const char *iface)
|
||||
static int ctdb_add_public_address(struct ctdb_context *ctdb, struct sockaddr_in addr, unsigned mask, const char *iface)
|
||||
{
|
||||
struct ctdb_vnn *vnn;
|
||||
|
||||
@ -400,7 +400,7 @@ static int add_public_address(struct ctdb_context *ctdb, struct sockaddr_in addr
|
||||
if (ctdb_same_sockaddr(&addr, &vnn->public_address)) {
|
||||
DEBUG(DEBUG_CRIT,("Same ip '%s' specified multiple times in the public address list \n",
|
||||
inet_ntoa(addr.sin_addr)));
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,7 +471,7 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist)
|
||||
iface = tok;
|
||||
}
|
||||
|
||||
if (add_public_address(ctdb, addr, mask, iface)) {
|
||||
if (ctdb_add_public_address(ctdb, addr, mask, iface)) {
|
||||
DEBUG(DEBUG_CRIT,("Failed to add line %u to the public address list\n", i+1));
|
||||
talloc_free(lines);
|
||||
return -1;
|
||||
@ -1781,23 +1781,23 @@ static void send_gratious_arp(struct event_context *ev, struct timed_event *te,
|
||||
*/
|
||||
int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_gratious_arp *gratious_arp = (struct ctdb_control_gratious_arp *)indata.dptr;
|
||||
struct ctdb_control_ip_iface *gratious_arp = (struct ctdb_control_ip_iface *)indata.dptr;
|
||||
struct control_gratious_arp *arp;
|
||||
|
||||
|
||||
/* verify the size of indata */
|
||||
if (indata.dsize < offsetof(struct ctdb_control_gratious_arp, iface)) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_gratious_arp structure\n"));
|
||||
if (indata.dsize < offsetof(struct ctdb_control_ip_iface, iface)) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_ip_iface structure\n"));
|
||||
return -1;
|
||||
}
|
||||
if (indata.dsize !=
|
||||
( offsetof(struct ctdb_control_gratious_arp, iface)
|
||||
( offsetof(struct ctdb_control_ip_iface, iface)
|
||||
+ gratious_arp->len ) ){
|
||||
|
||||
DEBUG(DEBUG_ERR,(__location__ " Wrong size of indata. Was %u bytes "
|
||||
"but should be %u bytes\n",
|
||||
(unsigned)indata.dsize,
|
||||
(unsigned)(offsetof(struct ctdb_control_gratious_arp, iface)+gratious_arp->len)));
|
||||
(unsigned)(offsetof(struct ctdb_control_ip_iface, iface)+gratious_arp->len)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1817,3 +1817,83 @@ int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indat
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ctdb_control_add_public_address(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_ip_iface *pub = (struct ctdb_control_ip_iface *)indata.dptr;
|
||||
|
||||
|
||||
/* verify the size of indata */
|
||||
if (indata.dsize < offsetof(struct ctdb_control_ip_iface, iface)) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_ip_iface structure\n"));
|
||||
return -1;
|
||||
}
|
||||
if (indata.dsize !=
|
||||
( offsetof(struct ctdb_control_ip_iface, iface)
|
||||
+ pub->len ) ){
|
||||
|
||||
DEBUG(DEBUG_ERR,(__location__ " Wrong size of indata. Was %u bytes "
|
||||
"but should be %u bytes\n",
|
||||
(unsigned)indata.dsize,
|
||||
(unsigned)(offsetof(struct ctdb_control_ip_iface, iface)+pub->len)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ctdb_add_public_address(ctdb, pub->sin, pub->mask, &pub->iface[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
called when releaseip event finishes for del_public_address
|
||||
*/
|
||||
static void delete_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
void *private_data)
|
||||
{
|
||||
talloc_free(private_data);
|
||||
}
|
||||
|
||||
int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_ip_iface *pub = (struct ctdb_control_ip_iface *)indata.dptr;
|
||||
struct ctdb_vnn *vnn;
|
||||
int ret;
|
||||
|
||||
/* verify the size of indata */
|
||||
if (indata.dsize < offsetof(struct ctdb_control_ip_iface, iface)) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_ip_iface structure\n"));
|
||||
return -1;
|
||||
}
|
||||
if (indata.dsize !=
|
||||
( offsetof(struct ctdb_control_ip_iface, iface)
|
||||
+ pub->len ) ){
|
||||
|
||||
DEBUG(DEBUG_ERR,(__location__ " Wrong size of indata. Was %u bytes "
|
||||
"but should be %u bytes\n",
|
||||
(unsigned)indata.dsize,
|
||||
(unsigned)(offsetof(struct ctdb_control_ip_iface, iface)+pub->len)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* walk over all public addresses until we find a match */
|
||||
for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
|
||||
if (ctdb_same_ip(&vnn->public_address, &pub->sin)) {
|
||||
TALLOC_CTX *mem_ctx = talloc_new(ctdb);
|
||||
|
||||
DLIST_REMOVE(ctdb->vnn, vnn);
|
||||
|
||||
ret = ctdb_event_script_callback(ctdb,
|
||||
timeval_current_ofs(ctdb->tunable.script_timeout, 0),
|
||||
mem_ctx, delete_ip_callback, mem_ctx,
|
||||
"releaseip %s %s %u",
|
||||
vnn->iface,
|
||||
inet_ntoa(vnn->public_address.sin_addr),
|
||||
vnn->public_netmask_bits);
|
||||
talloc_free(vnn);
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -504,6 +504,76 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv
|
||||
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 len;
|
||||
unsigned mask;
|
||||
struct sockaddr_in addr;
|
||||
struct ctdb_control_ip_iface *pub;
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!parse_ip_mask(argv[0], &addr, &mask)) {
|
||||
DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]);
|
||||
pub = talloc_size(ctdb, len);
|
||||
CTDB_NO_MEMORY(ctdb, pub);
|
||||
|
||||
pub->sin = addr;
|
||||
pub->mask = mask;
|
||||
pub->len = strlen(argv[1]);
|
||||
memcpy(&pub->iface[0], argv[1], strlen(argv[1]));
|
||||
|
||||
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));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
delete a public ip address from a node
|
||||
*/
|
||||
static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
int ret;
|
||||
struct sockaddr_in addr;
|
||||
struct ctdb_control_ip_iface pub;
|
||||
|
||||
if (argc != 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
if (inet_aton(argv[0], &addr.sin_addr) == 0) {
|
||||
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pub.sin = addr;
|
||||
pub.mask = 0;
|
||||
pub.len = 0;
|
||||
|
||||
ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
|
||||
if (ret != 0) {
|
||||
DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
kill a tcp connection
|
||||
*/
|
||||
@ -1454,6 +1524,8 @@ 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>"},
|
||||
{ "delip", control_delip, false, "delete an ip address from a node", "<ip>"},
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user