diff options
author | Ronnie Sahlberg <ronniesahlberg@gmail.com> | 2010-09-15 14:56:57 +1000 |
---|---|---|
committer | Ronnie Sahlberg <ronniesahlberg@gmail.com> | 2010-09-15 14:58:11 +1000 |
commit | 22ea35f17ddb7c21bc2e3df5a1f7f7c4a0743ca2 (patch) | |
tree | a96c7593d8c0a65d665a96c3b7021962a01bc560 | |
parent | 0b5bd411ca3c4ce9ff8f8e4224bc9b63319f0ffc (diff) | |
download | samba-22ea35f17ddb7c21bc2e3df5a1f7f7c4a0743ca2.tar.gz samba-22ea35f17ddb7c21bc2e3df5a1f7f7c4a0743ca2.tar.xz samba-22ea35f17ddb7c21bc2e3df5a1f7f7c4a0743ca2.zip |
adda GETPUBLICIPS control to libctdb and use this in the test example
enhance the test example to show the new releaseip/takeip messages
(This used to be ctdb commit 21cc57883e6c02b0e037211b26d1d866d5d7f03d)
-rw-r--r-- | ctdb/include/ctdb.h | 72 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 8 | ||||
-rw-r--r-- | ctdb/include/ctdb_protocol.h | 16 | ||||
-rw-r--r-- | ctdb/libctdb/control.c | 48 | ||||
-rw-r--r-- | ctdb/libctdb/messages.c | 2 | ||||
-rw-r--r-- | ctdb/libctdb/sync.c | 19 | ||||
-rw-r--r-- | ctdb/libctdb/tst.c | 110 |
7 files changed, 250 insertions, 25 deletions
diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index 92f4626868f..1c6cf353f2e 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -444,6 +444,43 @@ bool ctdb_getnodemap_recv(struct ctdb_connection *ctdb, struct ctdb_request *req, struct ctdb_node_map **nodemap); /** + * ctdb_getpublicips_send - read the public ip list from a node. + * @ctdb: the ctdb_connection from ctdb_connect. + * @destnode: the destination node (see below) + * @callback: the callback when ctdb replies to our message (typesafe) + * @cbdata: the argument to callback() + * + * This control returns the list of public ips known to the local node. + * Deamons only know about those ips that are listed in the local + * public addresses file, which means the returned list of ips may + * be only a subset of all ips across the entire cluster. + * + * There are several special values for destnode, detailed in + * ctdb_protocol.h, particularly CTDB_CURRENT_NODE which means the + * local ctdbd. + */ +struct ctdb_request * +ctdb_getpublicips_send(struct ctdb_connection *ctdb, + uint32_t destnode, + ctdb_callback_t callback, + void *cbdata); +/** + * ctdb_getpublicips_recv - read the public ip list from a node + * @ctdb: the ctdb_connection from ctdb_connect. + * @req: the completed request. + * @ips: a pointer to the returned public ip list + * + * This returns false if something went wrong. + * If the command failed, it guarantees to set ips to NULL. + * A non-NULL value for nodemap means the command was successful. + * + * A non-NULL value of the nodemap must be release released/freed + * by ctdb_free_publicips(). + */ +bool ctdb_getpublicips_recv(struct ctdb_connection *ctdb, + struct ctdb_request *req, struct ctdb_all_public_ips **ips); + +/** * ctdb_getrecmaster_send - read the recovery master of a node * @ctdb: the ctdb_connection from ctdb_connect. * @destnode: the destination node (see below) @@ -612,6 +649,37 @@ bool ctdb_getnodemap(struct ctdb_connection *ctdb, void ctdb_free_nodemap(struct ctdb_node_map *nodemap); +/** + * ctdb_getpublicips - read the public ip list from a node. + * @ctdb: the ctdb_connection from ctdb_connect. + * @destnode: the destination node (see below) + * @ips: a pointer to the returned public ip list + * + * This control returns the list of public ips known to the local node. + * Deamons only know about those ips that are listed in the local + * public addresses file, which means the returned list of ips may + * be only a subset of all ips across the entire cluster. + * + * There are several special values for destnode, detailed in + * ctdb_protocol.h, particularly CTDB_CURRENT_NODE which means the + * local ctdbd. + * + * This returns false if something went wrong. + * If the command failed, it guarantees to set ips to NULL. + * A non-NULL value for nodemap means the command was successful. + * + * A non-NULL value of the nodemap must be release released/freed + * by ctdb_free_publicips(). + */ +bool ctdb_getpublicips(struct ctdb_connection *ctdb, + uint32_t destnode, struct ctdb_all_public_ips **ips); + +/* + * This function is used to release/free the public ip structure returned + * by ctdb_getpublicips() and ctdb_getpublicips_recv() + */ +void ctdb_free_publicips(struct ctdb_all_public_ips *ips); + /* These ugly macro wrappers make the callbacks typesafe. */ #include <ctdb_typesafe_cb.h> @@ -669,4 +737,8 @@ void ctdb_free_nodemap(struct ctdb_node_map *nodemap); ctdb_getnodemap_send((ctdb), (destnode), \ ctdb_sendcb((cb), (cbdata)), (cbdata)) +#define ctdb_getpublicips_send(ctdb, destnode, cb, cbdata) \ + ctdb_getpublicips_send((ctdb), (destnode), \ + ctdb_sendcb((cb), (cbdata)), (cbdata)) + #endif diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 89b8f08b6f7..8ceae204d61 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -991,10 +991,6 @@ struct ctdb_public_ipv4 { struct sockaddr_in sin; }; -struct ctdb_public_ip { - uint32_t pnn; - ctdb_sock_addr addr; -}; int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_public_ip *ip); int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout, @@ -1005,10 +1001,6 @@ struct ctdb_all_public_ipsv4 { struct ctdb_public_ipv4 ips[1]; }; -struct ctdb_all_public_ips { - uint32_t num; - struct ctdb_public_ip ips[1]; -}; int32_t ctdb_control_get_public_ipsv4(struct ctdb_context *ctdb, struct ctdb_req_control *c, TDB_DATA *outdata); int32_t ctdb_control_get_public_ips(struct ctdb_context *ctdb, struct ctdb_req_control *c, TDB_DATA *outdata); int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb, diff --git a/ctdb/include/ctdb_protocol.h b/ctdb/include/ctdb_protocol.h index a9f6249d617..f04b3f39fbd 100644 --- a/ctdb/include/ctdb_protocol.h +++ b/ctdb/include/ctdb_protocol.h @@ -155,6 +155,12 @@ struct ctdb_call_info { */ #define CTDB_SRVID_ISCSID_RANGE 0xFE02000000000000LL +/* A range of ports reserved for testing (top 32 bits) + * All ports matching the 32 top bits are reserved for exclusive use by + * test applications + */ +#define CTDB_SRVID_TEST_RANGE 0xFE03000000000000LL + /* used on the domain socket, send a pdu to the local daemon */ #define CTDB_CURRENT_NODE 0xF0000001 /* send a broadcast to all nodes in the cluster, active or not */ @@ -518,4 +524,14 @@ struct ctdb_node_map { #define NODE_FLAGS_INACTIVE (NODE_FLAGS_DELETED|NODE_FLAGS_DISCONNECTED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED) +struct ctdb_public_ip { + uint32_t pnn; + ctdb_sock_addr addr; +}; + +struct ctdb_all_public_ips { + uint32_t num; + struct ctdb_public_ip ips[1]; +}; + #endif diff --git a/ctdb/libctdb/control.c b/ctdb/libctdb/control.c index d1934008d29..07185dbb41b 100644 --- a/ctdb/libctdb/control.c +++ b/ctdb/libctdb/control.c @@ -25,6 +25,7 @@ #undef ctdb_getrecmaster_send #undef ctdb_getpnn_send #undef ctdb_getnodemap_send +#undef ctdb_getpublicips_send bool ctdb_getrecmaster_recv(struct ctdb_connection *ctdb, struct ctdb_request *req, uint32_t *recmaster) @@ -124,3 +125,50 @@ void ctdb_free_nodemap(struct ctdb_node_map *nodemap) } free(nodemap); } + +bool ctdb_getpublicips_recv(struct ctdb_connection *ctdb, + struct ctdb_request *req, + struct ctdb_all_public_ips **ips) +{ + struct ctdb_reply_control *reply; + + *ips = NULL; + reply = unpack_reply_control(ctdb, req, CTDB_CONTROL_GET_PUBLIC_IPS); + if (!reply) { + return false; + } + if (reply->status == -1) { + DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: status -1"); + return false; + } + if (reply->datalen == 0) { + DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: returned data is 0 bytes"); + return false; + } + + *ips = malloc(reply->datalen); + if (*ips == NULL) { + DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: failed to malloc buffer"); + return false; + } + memcpy(*ips, reply->data, reply->datalen); + + return true; +} +struct ctdb_request *ctdb_getpublicips_send(struct ctdb_connection *ctdb, + uint32_t destnode, + ctdb_callback_t callback, + void *private_data) +{ + return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_PUBLIC_IPS, + destnode, + NULL, 0, callback, private_data); +} + +void ctdb_free_publicips(struct ctdb_all_public_ips *ips) +{ + if (ips == NULL) { + return; + } + free(ips); +} diff --git a/ctdb/libctdb/messages.c b/ctdb/libctdb/messages.c index b79857c52ff..d61d29e16f5 100644 --- a/ctdb/libctdb/messages.c +++ b/ctdb/libctdb/messages.c @@ -119,7 +119,7 @@ ctdb_set_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid, info->handler_data = handler_data; DEBUG(ctdb, LOG_DEBUG, - "ctdb_set_message_handler_send: sending request %u for id %llu", + "ctdb_set_message_handler_send: sending request %u for id %llx", req->hdr.hdr->reqid, srvid); return req; } diff --git a/ctdb/libctdb/sync.c b/ctdb/libctdb/sync.c index d0aa86ac180..a1be3be9fad 100644 --- a/ctdb/libctdb/sync.c +++ b/ctdb/libctdb/sync.c @@ -138,6 +138,25 @@ bool ctdb_getnodemap(struct ctdb_connection *ctdb, return ret; } +bool ctdb_getpublicips(struct ctdb_connection *ctdb, + uint32_t destnode, struct ctdb_all_public_ips **ips) +{ + struct ctdb_request *req; + bool done = false; + bool ret = false; + + *ips = NULL; + + req = synchronous(ctdb, + ctdb_getpublicips_send(ctdb, destnode, set, &done), + &done); + if (req != NULL) { + ret = ctdb_getpublicips_recv(ctdb, req, ips); + ctdb_request_free(ctdb, req); + } + return ret; +} + bool ctdb_set_message_handler(struct ctdb_connection *ctdb, uint64_t srvid, ctdb_message_fn_t handler, void *cbdata) { diff --git a/ctdb/libctdb/tst.c b/ctdb/libctdb/tst.c index b423a48ccff..e61561fc77c 100644 --- a/ctdb/libctdb/tst.c +++ b/ctdb/libctdb/tst.c @@ -41,25 +41,33 @@ TDB_DATA key; +char *ctdb_addr_to_str(ctdb_sock_addr *addr) +{ + static char cip[128] = ""; + + switch (addr->sa.sa_family) { + case AF_INET: + inet_ntop(addr->ip.sin_family, &addr->ip.sin_addr, cip, sizeof(cip)); + break; + case AF_INET6: + inet_ntop(addr->ip6.sin6_family, &addr->ip6.sin6_addr, cip, sizeof(cip)); + break; + default: + printf("ERROR, unknown family %u\n", addr->sa.sa_family); + } + + return cip; +} + void print_nodemap(struct ctdb_node_map *nodemap) { int i; - char cip[128]; printf("number of nodes:%d\n", nodemap->num); for (i=0;i<nodemap->num;i++) { - switch(nodemap->nodes[i].addr.sa.sa_family) { - case AF_INET: - inet_ntop(nodemap->nodes[i].addr.ip.sin_family, &nodemap->nodes[i].addr.ip.sin_addr, cip, sizeof(cip)); - break; - case AF_INET6: - inet_ntop(nodemap->nodes[i].addr.ip6.sin6_family, &nodemap->nodes[i].addr.ip6.sin6_addr, cip, sizeof(cip)); - break; - } - printf("Node:%d Address:%s Flags:%s%s%s%s%s%s\n", nodemap->nodes[i].pnn, - cip, + ctdb_addr_to_str(&nodemap->nodes[i].addr), nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED?"DISCONNECTED ":"", nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY?"UNHEALTHY ":"", nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED?"ADMIN DISABLED ":"", @@ -71,7 +79,17 @@ void print_nodemap(struct ctdb_node_map *nodemap) void msg_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data) { - printf("Message received on port %d : %s\n", (int)srvid, data.dptr); + printf("Message received on port %llx : %s\n", srvid, data.dptr); +} + +void rip_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data) +{ + printf("RELEASE IP message for %s\n", data.dptr); +} + +void tip_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data) +{ + printf("TAKE IP message for %s\n", data.dptr); } static void gnm_cb(struct ctdb_connection *ctdb, @@ -91,6 +109,35 @@ static void gnm_cb(struct ctdb_connection *ctdb, ctdb_free_nodemap(nodemap); } +void print_ips(struct ctdb_all_public_ips *ips) +{ + int i; + + printf("Num public ips:%d\n", ips->num); + for (i=0; i<ips->num;i++) { + printf("%s hosted on node %d\n", + ctdb_addr_to_str(&ips->ips[i].addr), + ips->ips[i].pnn); + } +} + +static void ips_cb(struct ctdb_connection *ctdb, + struct ctdb_request *req, void *private) +{ + bool status; + struct ctdb_all_public_ips *ips; + + status = ctdb_getpublicips_recv(ctdb, req, &ips); + ctdb_request_free(ctdb, req); + if (!status) { + printf("Error reading PUBLIC IPS\n"); + return; + } + printf("ASYNC response to getpublicips:\n"); + print_ips(ips); + ctdb_free_publicips(ips); +} + static void pnn_cb(struct ctdb_connection *ctdb, struct ctdb_request *req, void *private) { @@ -186,6 +233,7 @@ int main(int argc, char *argv[]) uint32_t recmaster; TDB_DATA msg; bool rrl_cb_called = false; + uint64_t srvid; ctdb_log_level = LOG_DEBUG; ctdb_connection = ctdb_connect("/tmp/ctdb.socket", @@ -195,23 +243,43 @@ int main(int argc, char *argv[]) pfd.fd = ctdb_get_fd(ctdb_connection); - handle = ctdb_set_message_handler_send(ctdb_connection, 55, + srvid = CTDB_SRVID_TEST_RANGE|55; + handle = ctdb_set_message_handler_send(ctdb_connection, srvid, msg_h, NULL, - message_handler_cb, NULL); + message_handler_cb, &srvid); if (handle == NULL) { printf("Failed to register message port\n"); exit(10); } - /* Hack for testing: this makes sure registration goes out. */ + /* Hack for testing: this makes sure registrations went out. */ while (!registered) { ctdb_service(ctdb_connection, POLLIN|POLLOUT); } + handle = ctdb_set_message_handler_send(ctdb_connection, + CTDB_SRVID_RELEASE_IP, + rip_h, NULL, + message_handler_cb, NULL); + if (handle == NULL) { + printf("Failed to register message port for RELEASE IP\n"); + exit(10); + } + + handle = ctdb_set_message_handler_send(ctdb_connection, + CTDB_SRVID_TAKE_IP, + tip_h, NULL, + message_handler_cb, NULL); + if (handle == NULL) { + printf("Failed to register message port for TAKE IP\n"); + exit(10); + } + msg.dptr="HelloWorld"; msg.dsize = strlen(msg.dptr); - if (!ctdb_send_message(ctdb_connection, 0, 55, msg)) { + srvid = CTDB_SRVID_TEST_RANGE|55; + if (!ctdb_send_message(ctdb_connection, 0, srvid, msg)) { printf("Failed to send message. Aborting\n"); exit(10); } @@ -277,6 +345,16 @@ int main(int argc, char *argv[]) } /* + * Read the list of public ips from a node (async) + */ + handle = ctdb_getpublicips_send(ctdb_connection, CTDB_CURRENT_NODE, + ips_cb, NULL); + if (handle == NULL) { + printf("Failed to send getpublicips control\n"); + exit(10); + } + + /* * Read the nodemap from a node (sync) */ if (!ctdb_getnodemap(ctdb_connection, CTDB_CURRENT_NODE, |