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
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;
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,
#define CTDB_NULL_FUNC 0xFF000001
#define CTDB_FETCH_FUNC 0xFF000002
+
/*
a tcp connection description
*/
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,
};
/*
};
/*
- 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];
};
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);
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,
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;
-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;
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;
}
}
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;
*/
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;
}
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;
+}
+
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
*/
{ "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>"},
};
/*