qnetd: Add support for IPC list command

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
This commit is contained in:
Jan Friesse 2016-05-17 17:22:10 +02:00
parent d3059b855d
commit 4e79df8f84
12 changed files with 307 additions and 29 deletions

View File

@ -311,20 +311,3 @@ qdevice_net_algorithm_register_all(void)
return (0);
}
const char *
qdevice_net_algorithm_type_to_str(enum tlv_decision_algorithm_type algo_type)
{
switch (algo_type) {
case TLV_DECISION_ALGORITHM_TYPE_TEST: return ("Test"); break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT: return ("Fifty-Fifty split"); break;
case TLV_DECISION_ALGORITHM_TYPE_2NODELMS: return ("2 Node LMS"); break;
case TLV_DECISION_ALGORITHM_TYPE_LMS: return ("LMS"); break;
/*
* Default is not defined intentionally. Compiler shows warning when new model is added
*/
}
return ("Unknown algorithm");
}

View File

@ -126,9 +126,6 @@ extern int qdevice_net_algorithm_register(
extern int qdevice_net_algorithm_register_all(void);
extern const char *qdevice_net_algorithm_type_to_str(
enum tlv_decision_algorithm_type algo_type);
#ifdef __cplusplus
}
#endif

View File

@ -60,6 +60,7 @@ qdevice_net_cast_vote_timer_callback(void *data1, void *data2)
case TLV_VOTE_ASK_LATER:
case TLV_VOTE_WAIT_FOR_REPLY:
case TLV_VOTE_NO_CHANGE:
case TLV_VOTE_UNDEFINED:
/*
* Shouldn't happen
*/
@ -98,6 +99,8 @@ qdevice_net_cast_vote_timer_update(struct qdevice_net_instance *instance, enum t
case_processed = 0;
switch (vote) {
case TLV_VOTE_UNDEFINED:
break;
case TLV_VOTE_ACK:
case TLV_VOTE_NACK:
case_processed = 1;

View File

@ -115,7 +115,7 @@ qdevice_net_ipc_cmd_status_add_basic_info(struct qdevice_net_instance *instance,
}
if (dynar_str_catf(outbuf, "Algorithm:\t\t%s\n",
qdevice_net_algorithm_type_to_str(instance->decision_algorithm)) == -1) {
tlv_decision_algorithm_type_to_str(instance->decision_algorithm)) == -1) {
return (0);
}

View File

@ -784,6 +784,9 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
return (-1);
}
client->config_version_set = msg->config_version_set;
client->config_version = msg->config_version;
break;
case TLV_NODE_LIST_TYPE_MEMBERSHIP:
case_processed = 1;
@ -818,6 +821,14 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
exit(1);
}
/*
* Store result vote
*/
client->last_sent_vote = result_vote;
if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
client->last_sent_ack_nack_vote = result_vote;
}
send_buffer = send_buffer_list_get_new(&client->send_buffer_list);
if (send_buffer == NULL) {
qnetd_log(LOG_ERR, "Can't alloc node list reply msg from list. "
@ -888,6 +899,14 @@ qnetd_client_msg_received_ask_for_vote(struct qnetd_instance *instance, struct q
return (0);
}
/*
* Store result vote
*/
client->last_sent_vote = result_vote;
if (result_vote == TLV_VOTE_ACK || result_vote == TLV_VOTE_NACK) {
client->last_sent_ack_nack_vote = result_vote;
}
qnetd_log_debug_ask_for_vote_received(client, msg->seq_number);
reply_error_code = qnetd_algorithm_ask_for_vote_received(client, msg->seq_number,

View File

@ -75,6 +75,14 @@ qnetd_client_send_vote_info(struct qnetd_client *client, uint32_t msg_seq_number
{
struct send_buffer_list_entry *send_buffer;
/*
* Store result vote
*/
client->last_sent_vote = vote;
if (vote == TLV_VOTE_ACK || vote == TLV_VOTE_NACK) {
client->last_sent_ack_nack_vote = vote;
}
qnetd_log_debug_send_vote_info(client, msg_seq_number, vote);
send_buffer = send_buffer_list_get_new(&client->send_buffer_list);

View File

@ -72,6 +72,8 @@ struct qnetd_client {
enum tlv_reply_error_code skipping_msg_reason;
void *algorithm_data;
struct node_list configuration_node_list;
uint8_t config_version_set;
uint64_t config_version;
struct node_list last_membership_node_list;
struct node_list last_quorum_node_list;
struct tlv_ring_id last_ring_id;
@ -83,6 +85,8 @@ struct qnetd_client {
int schedule_disconnect;
uint32_t dpd_time_since_last_check;
uint32_t dpd_msg_received_since_last_check;
enum tlv_vote last_sent_vote;
enum tlv_vote last_sent_ack_nack_vote;
TAILQ_ENTRY(qnetd_client) entries;
TAILQ_ENTRY(qnetd_client) cluster_entries;
};

View File

@ -81,3 +81,207 @@ qnetd_ipc_cmd_status(struct qnetd_instance *instance, struct dynar *outbuf, int
return (0);
}
static int
qnetd_ipc_cmd_add_tie_breaker(const struct qnetd_client *client,
struct dynar *outbuf)
{
if (dynar_str_catf(outbuf, " Tie-breaker:\t") == -1) {
return (0);
}
switch (client->tie_breaker.mode) {
case TLV_TIE_BREAKER_MODE_LOWEST:
if (dynar_str_catf(outbuf, "Node with lowest node ID") == -1) {
return (0);
}
break;
case TLV_TIE_BREAKER_MODE_HIGHEST:
if (dynar_str_catf(outbuf, "Node with highest node ID") == -1) {
return (0);
}
break;
case TLV_TIE_BREAKER_MODE_NODE_ID:
if (dynar_str_catf(outbuf, "Node with node ID "UTILS_PRI_NODE_ID,
client->tie_breaker.node_id) == -1) {
return (0);
}
break;
}
return (dynar_str_catf(outbuf, "\n") != -1);
}
static int
qnetd_ipc_cmd_list_add_node_list(struct dynar *outbuf, int verbose, const struct node_list *nlist)
{
struct node_list_entry *node_info;
int i;
i = 0;
TAILQ_FOREACH(node_info, nlist, entries) {
if (i != 0) {
if (dynar_str_catf(outbuf, ", ") == -1) {
return (-1);
}
}
if (dynar_str_catf(outbuf, UTILS_PRI_NODE_ID, node_info->node_id) == -1) {
return (-1);
}
if (node_info->data_center_id != 0) {
if (dynar_str_catf(outbuf, " (" UTILS_PRI_DATACENTER_ID ")",
node_info->data_center_id) == -1) {
return (-1);
}
}
i++;
}
return (0);
}
static int
qnetd_ipc_cmd_list_add_client_info(const struct qnetd_client *client, struct dynar *outbuf,
int verbose, size_t client_no)
{
if (dynar_str_catf(outbuf, " Node ID "UTILS_PRI_NODE_ID":\n",
client->node_id) == -1) {
return (-1);
}
if (dynar_str_catf(outbuf, " Client address:\t\t%s\n",
client->addr_str) == -1) {
return (-1);
}
if (verbose) {
if (dynar_str_catf(outbuf, " HB interval:\t\t%"PRIu32"ms\n",
client->heartbeat_interval) == -1) {
return (-1);
}
}
if (client->config_version_set) {
if (dynar_str_catf(outbuf, " Configuration version:\t"
UTILS_PRI_CONFIG_VERSION"\n", client->config_version) == -1) {
return (-1);
}
}
if (!node_list_is_empty(&client->configuration_node_list)) {
if ((dynar_str_catf(outbuf, " Configured node list:\t") == -1) ||
(qnetd_ipc_cmd_list_add_node_list(outbuf, verbose,
&client->configuration_node_list) == -1) ||
(dynar_str_catf(outbuf, "\n") == -1)) {
return (-1);
}
}
if (verbose) {
if (dynar_str_catf(outbuf, " Ring ID:\t\t"UTILS_PRI_RING_ID"\n",
client->last_ring_id.node_id, client->last_ring_id.seq) == -1) {
return (-1);
}
}
if (!node_list_is_empty(&client->last_membership_node_list)) {
if ((dynar_str_catf(outbuf, " Membership node list:\t") == -1) ||
(qnetd_ipc_cmd_list_add_node_list(outbuf, verbose,
&client->last_membership_node_list) == -1) ||
(dynar_str_catf(outbuf, "\n") == -1)) {
return (-1);
}
}
if (verbose) {
if (dynar_str_catf(outbuf, " TLS active:\t\t%s",
(client->tls_started ? "Yes" : "No")) == -1) {
return (-1);
}
if (client->tls_started && client->tls_peer_certificate_verified) {
if (dynar_str_catf(outbuf, " (client certificate verified)") == -1) {
return (-1);
}
}
if (dynar_str_catf(outbuf, "\n") == -1) {
return (-1);
}
}
if (client->last_sent_vote != TLV_VOTE_UNDEFINED) {
if (dynar_str_catf(outbuf, " Vote:\t\t\t%s",
tlv_vote_to_str(client->last_sent_vote)) == -1) {
return (-1);
}
if (client->last_sent_ack_nack_vote != TLV_VOTE_UNDEFINED) {
if (dynar_str_catf(outbuf, " (%s)",
tlv_vote_to_str(client->last_sent_ack_nack_vote)) == -1) {
return (-1);
}
}
if (dynar_str_catf(outbuf, "\n") == -1) {
return (-1);
}
}
return (0);
}
int
qnetd_ipc_cmd_list(struct qnetd_instance *instance, struct dynar *outbuf, int verbose,
const char *cluster_name)
{
struct qnetd_cluster *cluster;
struct qnetd_client *client;
size_t cluster_no, client_no;
cluster_no = 0;
TAILQ_FOREACH(cluster, &instance->clusters, entries) {
if (cluster_name != NULL && strcmp(cluster_name, "") != 0 &&
strcmp(cluster_name, cluster->cluster_name) != 0) {
continue ;
}
if (dynar_str_catf(outbuf, "Cluster \"%s\":\n", cluster->cluster_name) == -1) {
return (-1);
}
client_no = 0;
TAILQ_FOREACH(client, &cluster->client_list, cluster_entries) {
if (client_no == 0) {
if (dynar_str_catf(outbuf, " Algorithm:\t\t%s\n",
tlv_decision_algorithm_type_to_str(
client->decision_algorithm)) == -1) {
return (-1);
}
if (!qnetd_ipc_cmd_add_tie_breaker(client, outbuf)) {
return (-1);
}
}
if (qnetd_ipc_cmd_list_add_client_info(client, outbuf, verbose,
client_no) == -1) {
return (-1);
}
client_no++;
}
cluster_no++;
}
return (0);
}

View File

@ -45,6 +45,9 @@ extern "C" {
extern int qnetd_ipc_cmd_status(struct qnetd_instance *instance,
struct dynar *outbuf, int verbose);
extern int qnetd_ipc_cmd_list(struct qnetd_instance *instance,
struct dynar *outbuf, int verbose, const char *cluster_name);
#ifdef __cplusplus
}
#endif

View File

@ -223,6 +223,7 @@ qnetd_ipc_parse_line(struct qnetd_instance *instance, struct unix_socket_client
char *str;
struct qnetd_ipc_user_data *ipc_user_data;
int verbose;
char *cluster_name;
ipc_user_data = (struct qnetd_ipc_user_data *)client->user_data;
@ -230,15 +231,10 @@ qnetd_ipc_parse_line(struct qnetd_instance *instance, struct unix_socket_client
token = dynar_simple_lex_token_next(&lex);
verbose = 0;
cluster_name = NULL;
if (token == NULL) {
qnetd_log(LOG_ERR, "Can't alloc memory for simple lex");
if (qnetd_ipc_send_error(instance, client, "Command too long") != 0) {
client->schedule_disconnect = 1;
}
return;
goto exit_err_low_mem;
}
str = dynar_data(token);
@ -257,6 +253,10 @@ qnetd_ipc_parse_line(struct qnetd_instance *instance, struct unix_socket_client
}
} else if (strcasecmp(str, "status") == 0) {
token = dynar_simple_lex_token_next(&lex);
if (token == NULL) {
goto exit_err_low_mem;
}
str = dynar_data(token);
if (token != NULL && strcmp(str, "") != 0) {
@ -274,6 +274,35 @@ qnetd_ipc_parse_line(struct qnetd_instance *instance, struct unix_socket_client
client->schedule_disconnect = 1;
}
}
} else if (strcasecmp(str, "list") == 0) {
while (((token = dynar_simple_lex_token_next(&lex)) != NULL) &&
(str = dynar_data(token), strcmp(str, "") != 0)) {
if (strcasecmp(str, "verbose") == 0) {
verbose = 1;
} else if (strcasecmp(str, "cluster") == 0) {
token = dynar_simple_lex_token_next(&lex);
if (token == NULL) {
goto exit_err_low_mem;
}
if ((cluster_name = strdup(dynar_data(token))) == NULL) {
goto exit_err_low_mem;
}
} else {
break;
}
}
if (qnetd_ipc_cmd_list(instance, &client->send_buffer, verbose, cluster_name) != 0) {
if (qnetd_ipc_send_error(instance, client, "Can't get QNetd cluster list") != 0) {
client->schedule_disconnect = 1;
}
} else {
if (qnetd_ipc_send_buffer(instance, client) != 0) {
client->schedule_disconnect = 1;
}
}
free(cluster_name); cluster_name = NULL;
} else {
qnetd_log(LOG_DEBUG, "IPC client sent unknown command");
if (qnetd_ipc_send_error(instance, client, "Unknown command '%s'", str) != 0) {
@ -282,6 +311,15 @@ qnetd_ipc_parse_line(struct qnetd_instance *instance, struct unix_socket_client
}
dynar_simple_lex_destroy(&lex);
return ;
exit_err_low_mem:
qnetd_log(LOG_ERR, "Can't alloc memory for simple lex");
if (qnetd_ipc_send_error(instance, client, "Command too long") != 0) {
client->schedule_disconnect = 1;
}
}
void

View File

@ -985,6 +985,7 @@ tlv_vote_to_str(enum tlv_vote vote)
{
switch (vote) {
case TLV_VOTE_UNDEFINED: break;
case TLV_VOTE_ACK: return ("ACK"); break;
case TLV_VOTE_NACK: return ("NACK"); break;
case TLV_VOTE_ASK_LATER: return ("Ask later"); break;
@ -1009,7 +1010,7 @@ tlv_node_state_to_str(enum tlv_node_state state)
return ("Unhandled node state");
}
extern const char *
const char *
tlv_tls_supported_to_str(enum tlv_tls_supported tls_supported)
{
@ -1021,3 +1022,17 @@ tlv_tls_supported_to_str(enum tlv_tls_supported tls_supported)
return ("Unhandled tls supported state");
}
const char *
tlv_decision_algorithm_type_to_str(enum tlv_decision_algorithm_type algorithm)
{
switch (algorithm) {
case TLV_DECISION_ALGORITHM_TYPE_TEST: return ("Test"); break;
case TLV_DECISION_ALGORITHM_TYPE_FFSPLIT: return ("Fifty-Fifty split"); break;
case TLV_DECISION_ALGORITHM_TYPE_2NODELMS: return ("2 Node LMS"); break;
case TLV_DECISION_ALGORITHM_TYPE_LMS: return ("LMS"); break;
}
return ("Unknown algorithm");
}

View File

@ -123,6 +123,7 @@ enum tlv_node_list_type {
};
enum tlv_vote {
TLV_VOTE_UNDEFINED = 0,
TLV_VOTE_ACK = 1,
TLV_VOTE_NACK = 2,
TLV_VOTE_ASK_LATER = 3,
@ -327,6 +328,9 @@ extern const char * tlv_node_state_to_str(enum tlv_node_state state);
extern const char * tlv_tls_supported_to_str(enum tlv_tls_supported tls_supported);
extern const char * tlv_decision_algorithm_type_to_str(
enum tlv_decision_algorithm_type algorithm);
#ifdef __cplusplus
}
#endif