diff --git a/qdevices/qdevice-advanced-settings.c b/qdevices/qdevice-advanced-settings.c index 60ee9cc9..d1931f8c 100644 --- a/qdevices/qdevice-advanced-settings.c +++ b/qdevices/qdevice-advanced-settings.c @@ -1,281 +1,273 @@ /* * Copyright (c) 2015-2016 Red Hat, Inc. * * All rights reserved. * * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "dynar.h" #include "dynar-getopt-lex.h" #include "dynar-str.h" #include "qdevice-config.h" #include "qnet-config.h" #include "qdevice-advanced-settings.h" #include "utils.h" int qdevice_advanced_settings_init(struct qdevice_advanced_settings *settings) { memset(settings, 0, sizeof(*settings)); if ((settings->lock_file = strdup(QDEVICE_DEFAULT_LOCK_FILE)) == NULL) { return (-1); } if ((settings->local_socket_file = strdup(QDEVICE_DEFAULT_LOCAL_SOCKET_FILE)) == NULL) { return (-1); } settings->local_socket_backlog = QDEVICE_DEFAULT_LOCAL_SOCKET_BACKLOG; settings->max_cs_try_again = QDEVICE_DEFAULT_MAX_CS_TRY_AGAIN; if ((settings->votequorum_device_name = strdup(QDEVICE_DEFAULT_VOTEQUORUM_DEVICE_NAME)) == NULL) { return (-1); } settings->ipc_max_clients = QDEVICE_DEFAULT_IPC_MAX_CLIENTS; settings->ipc_max_receive_size = QDEVICE_DEFAULT_IPC_MAX_RECEIVE_SIZE; settings->ipc_max_send_size = QDEVICE_DEFAULT_IPC_MAX_SEND_SIZE; if ((settings->net_nss_db_dir = strdup(QDEVICE_NET_DEFAULT_NSS_DB_DIR)) == NULL) { return (-1); } settings->net_initial_msg_receive_size = QDEVICE_NET_DEFAULT_INITIAL_MSG_RECEIVE_SIZE; settings->net_initial_msg_send_size = QDEVICE_NET_DEFAULT_INITIAL_MSG_SEND_SIZE; settings->net_min_msg_send_size = QDEVICE_NET_DEFAULT_MIN_MSG_SEND_SIZE; settings->net_max_msg_receive_size = QDEVICE_NET_DEFAULT_MAX_MSG_RECEIVE_SIZE; settings->net_max_send_buffers = QDEVICE_NET_DEFAULT_MAX_SEND_BUFFERS; if ((settings->net_nss_qnetd_cn = strdup(QDEVICE_NET_DEFAULT_NSS_QNETD_CN)) == NULL) { return (-1); } if ((settings->net_nss_client_cert_nickname = strdup(QDEVICE_NET_DEFAULT_NSS_CLIENT_CERT_NICKNAME)) == NULL) { return (-1); } settings->net_heartbeat_interval_min = QDEVICE_NET_DEFAULT_HEARTBEAT_INTERVAL_MIN; settings->net_heartbeat_interval_max = QDEVICE_NET_DEFAULT_HEARTBEAT_INTERVAL_MAX; settings->net_min_connect_timeout = QDEVICE_NET_DEFAULT_MIN_CONNECT_TIMEOUT; settings->net_max_connect_timeout = QDEVICE_NET_DEFAULT_MAX_CONNECT_TIMEOUT; - settings->net_delay_before_reconnect = QDEVICE_NET_DEFAULT_DELAY_BEFORE_RECONNECT; settings->net_test_algorithm_enabled = QDEVICE_NET_DEFAULT_TEST_ALGORITHM_ENABLED; settings->master_wins = QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_MODEL; return (0); } void qdevice_advanced_settings_destroy(struct qdevice_advanced_settings *settings) { free(settings->local_socket_file); free(settings->lock_file); free(settings->votequorum_device_name); free(settings->net_nss_db_dir); free(settings->net_nss_qnetd_cn); free(settings->net_nss_client_cert_nickname); } /* * 0 - No error * -1 - Unknown option * -2 - Incorrect value */ int qdevice_advanced_settings_set(struct qdevice_advanced_settings *settings, const char *option, const char *value) { long long int tmpll; char *ep; if (strcasecmp(option, "lock_file") == 0) { free(settings->lock_file); if ((settings->lock_file = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "local_socket_file") == 0) { free(settings->local_socket_file); if ((settings->local_socket_file = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "local_socket_backlog") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_MIN_LOCAL_SOCKET_BACKLOG || errno != 0 || *ep != '\0') { return (-2); } settings->local_socket_backlog = (int)tmpll; } else if (strcasecmp(option, "max_cs_try_again") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_MIN_MAX_CS_TRY_AGAIN || errno != 0 || *ep != '\0') { return (-2); } settings->max_cs_try_again = (int)tmpll; } else if (strcasecmp(option, "votequorum_device_name") == 0) { free(settings->votequorum_device_name); if ((settings->votequorum_device_name = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "ipc_max_clients") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_MIN_IPC_MAX_CLIENTS || errno != 0 || *ep != '\0') { return (-2); } settings->ipc_max_clients = (size_t)tmpll; } else if (strcasecmp(option, "ipc_max_receive_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_MIN_IPC_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->ipc_max_receive_size = (size_t)tmpll; } else if (strcasecmp(option, "ipc_max_send_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_MIN_IPC_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->ipc_max_send_size = (size_t)tmpll; } else if (strcasecmp(option, "net_nss_db_dir") == 0) { free(settings->net_nss_db_dir); if ((settings->net_nss_db_dir = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "net_initial_msg_receive_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_MSG_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->net_initial_msg_receive_size = (size_t)tmpll; } else if (strcasecmp(option, "net_initial_msg_send_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_MSG_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->net_initial_msg_send_size = (size_t)tmpll; } else if (strcasecmp(option, "net_min_msg_send_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_MSG_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->net_min_msg_send_size = (size_t)tmpll; } else if (strcasecmp(option, "net_max_msg_receive_size") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_MSG_RECEIVE_SEND_SIZE || errno != 0 || *ep != '\0') { return (-2); } settings->net_max_msg_receive_size = (size_t)tmpll; } else if (strcasecmp(option, "net_max_send_buffers") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_MAX_SEND_BUFFERS || errno != 0 || *ep != '\0') { return (-2); } settings->net_max_send_buffers = (size_t)tmpll; } else if (strcasecmp(option, "net_nss_qnetd_cn") == 0) { free(settings->net_nss_qnetd_cn); if ((settings->net_nss_qnetd_cn = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "net_nss_client_cert_nickname") == 0) { free(settings->net_nss_client_cert_nickname); if ((settings->net_nss_client_cert_nickname = strdup(value)) == NULL) { return (-1); } } else if (strcasecmp(option, "net_heartbeat_interval_min") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_HEARTBEAT_INTERVAL || errno != 0 || *ep != '\0') { return (-2); } settings->net_heartbeat_interval_min = (uint32_t)tmpll; } else if (strcasecmp(option, "net_heartbeat_interval_max") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_HEARTBEAT_INTERVAL || errno != 0 || *ep != '\0') { return (-2); } settings->net_heartbeat_interval_max = (uint32_t)tmpll; } else if (strcasecmp(option, "net_min_connect_timeout") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_CONNECT_TIMEOUT || errno != 0 || *ep != '\0') { return (-2); } settings->net_min_connect_timeout = (uint32_t)tmpll; } else if (strcasecmp(option, "net_max_connect_timeout") == 0) { tmpll = strtoll(value, &ep, 10); if (tmpll < QDEVICE_NET_MIN_CONNECT_TIMEOUT || errno != 0 || *ep != '\0') { return (-2); } settings->net_max_connect_timeout = (uint32_t)tmpll; - } else if (strcasecmp(option, "net_delay_before_reconnect") == 0) { - tmpll = strtoll(value, &ep, 10); - if (tmpll < QDEVICE_NET_MIN_DELAY_BEFORE_RECONNECT || errno != 0 || *ep != '\0') { - return (-2); - } - - settings->net_delay_before_reconnect = (int)tmpll; } else if (strcasecmp(option, "net_test_algorithm_enabled") == 0) { if ((tmpll = utils_parse_bool_str(value)) == -1) { return (-2); } settings->net_test_algorithm_enabled = (uint8_t)tmpll; } else if (strcasecmp(option, "master_wins") == 0) { tmpll = utils_parse_bool_str(value); if (tmpll == 0) { settings->master_wins = QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_FORCE_OFF; } else if (tmpll == 1) { settings->master_wins = QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_FORCE_ON; } else if (strcasecmp(value, "model") == 0) { settings->master_wins = QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_MODEL; } else { return (-2); } } else { return (-1); } return (0); } diff --git a/qdevices/qdevice-advanced-settings.h b/qdevices/qdevice-advanced-settings.h index bcdbb7bb..eb3206b4 100644 --- a/qdevices/qdevice-advanced-settings.h +++ b/qdevices/qdevice-advanced-settings.h @@ -1,89 +1,88 @@ /* * Copyright (c) 2015-2016 Red Hat, Inc. * * All rights reserved. * * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _QDEVICE_ADVANCED_SETTINGS_H_ #define _QDEVICE_ADVANCED_SETTINGS_H_ #ifdef __cplusplus extern "C" { #endif enum qdevice_advanced_settings_master_wins { QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_MODEL, QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_FORCE_ON, QDEVICE_ADVANCED_SETTINGS_MASTER_WINS_FORCE_OFF, }; struct qdevice_advanced_settings { char *lock_file; char *local_socket_file; int local_socket_backlog; int max_cs_try_again; char *votequorum_device_name; size_t ipc_max_clients; size_t ipc_max_send_size; size_t ipc_max_receive_size; enum qdevice_advanced_settings_master_wins master_wins; /* * Related to model NET */ char *net_nss_db_dir; size_t net_initial_msg_receive_size; size_t net_initial_msg_send_size; size_t net_min_msg_send_size; size_t net_max_msg_receive_size; size_t net_max_send_buffers; char *net_nss_qnetd_cn; char *net_nss_client_cert_nickname; uint32_t net_heartbeat_interval_min; uint32_t net_heartbeat_interval_max; uint32_t net_min_connect_timeout; uint32_t net_max_connect_timeout; - int net_delay_before_reconnect; uint8_t net_test_algorithm_enabled; }; extern int qdevice_advanced_settings_init(struct qdevice_advanced_settings *settings); extern int qdevice_advanced_settings_set(struct qdevice_advanced_settings *settings, const char *option, const char *value); extern void qdevice_advanced_settings_destroy(struct qdevice_advanced_settings *settings); #ifdef __cplusplus } #endif #endif /* _QDEVICE_ADVANCED_SETTINGS_H_ */ diff --git a/qdevices/qdevice-model-net.c b/qdevices/qdevice-model-net.c index 2f2fa592..857ed401 100644 --- a/qdevices/qdevice-model-net.c +++ b/qdevices/qdevice-model-net.c @@ -1,553 +1,559 @@ /* * Copyright (c) 2015-2016 Red Hat, Inc. * * All rights reserved. * * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "qdevice-model.h" #include "qdevice-model-net.h" #include "qdevice-log.h" #include "qdevice-net-cast-vote-timer.h" #include "qdevice-net-instance.h" #include "qdevice-net-ipc-cmd.h" #include "qdevice-net-algorithm.h" #include "qdevice-net-poll.h" #include "qdevice-net-send.h" #include "qdevice-net-votequorum.h" #include "qnet-config.h" #include "nss-sock.h" int qdevice_model_net_init(struct qdevice_instance *instance) { struct qdevice_net_instance *net_instance; qdevice_log(LOG_DEBUG, "Initializing qdevice_net_instance"); if (qdevice_net_instance_init_from_cmap(instance) != 0) { return (-1); } net_instance = instance->model_data; qdevice_log(LOG_DEBUG, "Registering algorithms"); if (qdevice_net_algorithm_register_all() != 0) { return (-1); } qdevice_log(LOG_DEBUG, "Initializing NSS"); if (nss_sock_init_nss((net_instance->tls_supported != TLV_TLS_UNSUPPORTED ? instance->advanced_settings->net_nss_db_dir : NULL)) != 0) { qdevice_log_nss(LOG_ERR, "Can't init nss"); return (-1); } if (qdevice_net_cast_vote_timer_update(net_instance, TLV_VOTE_ASK_LATER) != 0) { qdevice_log(LOG_ERR, "Can't update cast vote timer"); return (-1); } if (qdevice_net_algorithm_init(net_instance) != 0) { qdevice_log(LOG_ERR, "Algorithm init failed"); return (-1); } return (0); } int qdevice_model_net_destroy(struct qdevice_instance *instance) { struct qdevice_net_instance *net_instance; net_instance = instance->model_data; qdevice_log(LOG_DEBUG, "Destroying algorithm"); qdevice_net_algorithm_destroy(net_instance); qdevice_log(LOG_DEBUG, "Destroying qdevice_net_instance"); qdevice_net_instance_destroy(net_instance); qdevice_log(LOG_DEBUG, "Shutting down NSS"); SSL_ClearSessionCache(); if (NSS_Shutdown() != SECSuccess) { qdevice_log_nss(LOG_WARNING, "Can't shutdown NSS"); } if (PR_Cleanup() != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Can't shutdown NSPR"); } free(net_instance); return (0); } static int qdevice_model_net_timer_connect_timeout(void *data1, void *data2) { struct qdevice_net_instance *instance; instance = (struct qdevice_net_instance *)data1; qdevice_log(LOG_ERR, "Connect timeout"); instance->schedule_disconnect = 1; instance->connect_timer = NULL; instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_CONNECT_TO_THE_SERVER; return (0); } static PRIntn qdevice_model_net_get_af(const struct qdevice_net_instance *instance) { PRIntn af; af = PR_AF_UNSPEC; if (instance->force_ip_version == 4) { af = PR_AF_INET; } if (instance->force_ip_version == 6) { af = PR_AF_INET6; } return (af); } int qdevice_model_net_run(struct qdevice_instance *instance) { struct qdevice_net_instance *net_instance; int try_connect; int res; enum tlv_vote vote; + int delay_before_reconnect; net_instance = instance->model_data; qdevice_log(LOG_DEBUG, "Executing qdevice-net"); try_connect = 1; while (try_connect) { net_instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_CONNECT; net_instance->socket = NULL; net_instance->connect_timer = timer_list_add(&net_instance->main_timer_list, net_instance->connect_timeout, qdevice_model_net_timer_connect_timeout, (void *)net_instance, NULL); if (net_instance->connect_timer == NULL) { qdevice_log(LOG_CRIT, "Can't schedule connect timer"); try_connect = 0; break; } qdevice_log(LOG_DEBUG, "Trying connect to qnetd server %s:%u (timeout = %ums)", net_instance->host_addr, net_instance->host_port, net_instance->connect_timeout); res = nss_sock_non_blocking_client_init(net_instance->host_addr, net_instance->host_port, qdevice_model_net_get_af(net_instance), &net_instance->non_blocking_client); if (res == -1) { qdevice_log_nss(LOG_ERR, "Can't initialize non blocking client connection"); } res = nss_sock_non_blocking_client_try_next(&net_instance->non_blocking_client); if (res == -1) { qdevice_log_nss(LOG_ERR, "Can't connect to qnetd host"); nss_sock_non_blocking_client_destroy(&net_instance->non_blocking_client); } while (qdevice_net_poll(net_instance) == 0) { }; if (net_instance->connect_timer != NULL) { timer_list_delete(&net_instance->main_timer_list, net_instance->connect_timer); net_instance->connect_timer = NULL; } if (net_instance->echo_request_timer != NULL) { timer_list_delete(&net_instance->main_timer_list, net_instance->echo_request_timer); net_instance->echo_request_timer = NULL; } try_connect = qdevice_net_disconnect_reason_try_reconnect(net_instance->disconnect_reason); vote = TLV_VOTE_NO_CHANGE; if (qdevice_net_algorithm_disconnected(net_instance, net_instance->disconnect_reason, &try_connect, &vote) != 0) { qdevice_log(LOG_ERR, "Algorithm returned error, force exit"); return (-1); } else { qdevice_log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(vote)); } if (qdevice_net_cast_vote_timer_update(net_instance, vote) != 0) { qdevice_log(LOG_ERR, "qdevice_model_net_run fatal error. " " Can't update cast vote timer vote"); } if (qdevice_net_disconnect_reason_force_disconnect(net_instance->disconnect_reason)) { try_connect = 0; } if (net_instance->socket != NULL) { if (PR_Close(net_instance->socket) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to close connection"); } net_instance->socket = NULL; } if (!net_instance->non_blocking_client.destroyed) { nss_sock_non_blocking_client_destroy(&net_instance->non_blocking_client); } if (net_instance->non_blocking_client.socket != NULL) { if (PR_Close(net_instance->non_blocking_client.socket) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to close non-blocking client connection"); } net_instance->non_blocking_client.socket = NULL; } - qdevice_net_instance_clean(net_instance); - - if (try_connect) { + if (try_connect && + net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_CONNECT) { /* * Give qnetd server a little time before reconnect */ - (void)poll(NULL, 0, - random() % instance->advanced_settings->net_delay_before_reconnect); + delay_before_reconnect = random() % + (int)(net_instance->cast_vote_timer_interval * 0.9); + + qdevice_log(LOG_DEBUG, "Sleeping for %u ms before reconnect", + delay_before_reconnect); + (void)poll(NULL, 0, delay_before_reconnect); } + + qdevice_net_instance_clean(net_instance); } return (0); } /* * Called when cmap reload (or nodelist) was requested. * * nlist is node list * config_version is valid only if config_version_set != 0 * * Should return 0 if processing should continue or -1 to call exit */ int qdevice_model_net_config_node_list_changed(struct qdevice_instance *instance, const struct node_list *nlist, int config_version_set, uint64_t config_version) { struct qdevice_net_instance *net_instance; int send_node_list; enum tlv_vote vote; net_instance = instance->model_data; if (net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) { /* * Nodelist changed, but connection to qnetd not initiated yet. */ send_node_list = 0; if (net_instance->cast_vote_timer_vote == TLV_VOTE_ACK) { vote = TLV_VOTE_NACK; } else { vote = TLV_VOTE_NO_CHANGE; } } else { send_node_list = 1; vote = TLV_VOTE_NO_CHANGE; } if (qdevice_net_algorithm_config_node_list_changed(net_instance, nlist, config_version_set, config_version, &send_node_list, &vote) != 0) { qdevice_log(LOG_ERR, "Algorithm returned error, Disconnecting"); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_CONFIG_NODE_LIST_CHANGED_ERR; net_instance->schedule_disconnect = 1; return (0); } else { qdevice_log(LOG_DEBUG, "Algorithm decided to %s node list and result vote is %s", (send_node_list ? "send" : "not send"), tlv_vote_to_str(vote)); } if (qdevice_net_cast_vote_timer_update(net_instance, vote) != 0) { qdevice_log(LOG_CRIT, "qdevice_model_net_config_node_list_changed fatal error. " " Can't update cast vote timer vote"); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER; net_instance->schedule_disconnect = 1; return (0); } if (send_node_list) { if (qdevice_net_send_config_node_list(net_instance, nlist, config_version_set, config_version, 0) != 0) { net_instance->schedule_disconnect = 1; net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER; return (0); } } return (0); } /* * Called when cmap reload (or nodelist) was requested, but it was not possible to * get node list. * * Should return 0 if processing should continue or -1 to call exit */ int qdevice_model_net_get_config_node_list_failed(struct qdevice_instance *instance) { struct qdevice_net_instance *net_instance; net_instance = instance->model_data; net_instance->schedule_disconnect = 1; net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER; return (0); } int qdevice_model_net_votequorum_quorum_notify(struct qdevice_instance *instance, uint32_t quorate, uint32_t node_list_entries, votequorum_node_t node_list[]) { struct qdevice_net_instance *net_instance; int send_node_list; enum tlv_vote vote; net_instance = instance->model_data; if (net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) { /* * Nodelist changed, but connection to qnetd not initiated yet. */ send_node_list = 0; if (net_instance->cast_vote_timer_vote == TLV_VOTE_ACK) { vote = TLV_VOTE_NACK; } else { vote = TLV_VOTE_NO_CHANGE; } } else { send_node_list = 1; vote = TLV_VOTE_NO_CHANGE; } if (qdevice_net_algorithm_votequorum_quorum_notify(net_instance, quorate, node_list_entries, node_list, &send_node_list, &vote) != 0) { qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting."); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTEQUORUM_QUORUM_NOTIFY_ERR; net_instance->schedule_disconnect = 1; return (0); } else { qdevice_log(LOG_DEBUG, "Algorithm decided to %s list and result vote is %s", (send_node_list ? "send" : "not send"), tlv_vote_to_str(vote)); } if (qdevice_net_cast_vote_timer_update(net_instance, vote) != 0) { qdevice_log(LOG_CRIT, "qdevice_model_net_votequorum_quorum_notify fatal error. " " Can't update cast vote timer vote"); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER; net_instance->schedule_disconnect = 1; return (0); } if (send_node_list) { if (qdevice_net_send_quorum_node_list(net_instance, (quorate ? TLV_QUORATE_QUORATE : TLV_QUORATE_INQUORATE), node_list_entries, node_list) != 0) { /* * Fatal error -> schedule disconnect */ net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER; net_instance->schedule_disconnect = 1; return (0); } } return (0); } int qdevice_model_net_votequorum_node_list_notify(struct qdevice_instance *instance, votequorum_ring_id_t votequorum_ring_id, uint32_t node_list_entries, uint32_t node_list[]) { struct qdevice_net_instance *net_instance; struct tlv_ring_id tlv_rid; enum tlv_vote vote; int send_node_list; net_instance = instance->model_data; qdevice_net_votequorum_ring_id_to_tlv(&tlv_rid, &votequorum_ring_id); if (net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS) { /* * Nodelist changed, but connection to qnetd not initiated yet. */ send_node_list = 0; if (net_instance->cast_vote_timer_vote == TLV_VOTE_ACK) { vote = TLV_VOTE_NACK; } else { vote = TLV_VOTE_NO_CHANGE; } } else { send_node_list = 1; vote = TLV_VOTE_WAIT_FOR_REPLY; } if (qdevice_net_algorithm_votequorum_node_list_notify(net_instance, &tlv_rid, node_list_entries, node_list, &send_node_list, &vote) != 0) { qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting."); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTEQUORUM_NODE_LIST_NOTIFY_ERR; net_instance->schedule_disconnect = 1; return (0); } else { qdevice_log(LOG_DEBUG, "Algorithm decided to %s list and result vote is %s", (send_node_list ? "send" : "not send"), tlv_vote_to_str(vote)); } if (send_node_list) { if (qdevice_net_send_membership_node_list(net_instance, &tlv_rid, node_list_entries, node_list) != 0) { /* * Fatal error -> schedule disconnect */ net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_ALLOCATE_MSG_BUFFER; net_instance->schedule_disconnect = 1; return (0); } } if (qdevice_net_cast_vote_timer_update(net_instance, vote) != 0) { qdevice_log(LOG_CRIT, "qdevice_model_net_votequorum_node_list_notify fatal error " "Can't update cast vote timer"); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER; net_instance->schedule_disconnect = 1; return (0); } return (0); } int qdevice_model_net_votequorum_expected_votes_notify(struct qdevice_instance *instance, uint32_t expected_votes) { struct qdevice_net_instance *net_instance; enum tlv_vote vote; net_instance = instance->model_data; qdevice_log(LOG_DEBUG, "qdevice_model_net_votequorum_expected_votes_notify" " (expected votes old=%"PRIu32" / new=%"PRIu32")", net_instance->qdevice_instance_ptr->vq_expected_votes, expected_votes); vote = TLV_VOTE_NO_CHANGE; if (qdevice_net_algorithm_votequorum_expected_votes_notify(net_instance, expected_votes, &vote) != 0) { qdevice_log(LOG_DEBUG, "Algorithm returned error. Disconnecting."); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_ALGO_VOTEQUORUM_EXPECTED_VOTES_NOTIFY_ERR; net_instance->schedule_disconnect = 1; return (0); } else { qdevice_log(LOG_DEBUG, "Algorithm result vote is %s", tlv_vote_to_str(vote)); } if (qdevice_net_cast_vote_timer_update(net_instance, vote) != 0) { qdevice_log(LOG_CRIT, "qdevice_model_net_votequorum_expected_votes_notify fatal error. " " Can't update cast vote timer vote"); net_instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER; net_instance->schedule_disconnect = 1; return (0); } return (0); } int qdevice_model_net_ipc_cmd_status(struct qdevice_instance *instance, struct dynar *outbuf, int verbose) { struct qdevice_net_instance *net_instance; net_instance = instance->model_data; if (!qdevice_net_ipc_cmd_status(net_instance, outbuf, verbose)) { return (-1); } return (0); } static struct qdevice_model qdevice_model_net = { .name = "net", .init = qdevice_model_net_init, .destroy = qdevice_model_net_destroy, .run = qdevice_model_net_run, .get_config_node_list_failed = qdevice_model_net_get_config_node_list_failed, .config_node_list_changed = qdevice_model_net_config_node_list_changed, .votequorum_quorum_notify = qdevice_model_net_votequorum_quorum_notify, .votequorum_node_list_notify = qdevice_model_net_votequorum_node_list_notify, .votequorum_expected_votes_notify = qdevice_model_net_votequorum_expected_votes_notify, .ipc_cmd_status = qdevice_model_net_ipc_cmd_status, }; int qdevice_model_net_register(void) { return (qdevice_model_register(QDEVICE_MODEL_TYPE_NET, &qdevice_model_net)); } diff --git a/qdevices/qdevice-net-instance.c b/qdevices/qdevice-net-instance.c index 13ff4581..e807d1da 100644 --- a/qdevices/qdevice-net-instance.c +++ b/qdevices/qdevice-net-instance.c @@ -1,398 +1,398 @@ /* * Copyright (c) 2015-2016 Red Hat, Inc. * * All rights reserved. * * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "qdevice-config.h" #include "qdevice-log.h" #include "qdevice-net-instance.h" #include "qnet-config.h" #include "utils.h" #include "qdevice-net-poll-array-user-data.h" #include "qdevice-ipc.h" /* * Needed for creating nspr handle from unix fd */ #include int qdevice_net_instance_init(struct qdevice_net_instance *instance, enum tlv_tls_supported tls_supported, enum tlv_decision_algorithm_type decision_algorithm, uint32_t heartbeat_interval, uint32_t sync_heartbeat_interval, uint32_t cast_vote_timer_interval, const char *host_addr, uint16_t host_port, const char *cluster_name, const struct tlv_tie_breaker *tie_breaker, uint32_t connect_timeout, int force_ip_version, int cmap_fd, int votequorum_fd, int local_socket_fd, const struct qdevice_advanced_settings *advanced_settings) { memset(instance, 0, sizeof(*instance)); instance->advanced_settings = advanced_settings; instance->decision_algorithm = decision_algorithm; instance->heartbeat_interval = heartbeat_interval; instance->sync_heartbeat_interval = sync_heartbeat_interval; instance->cast_vote_timer_interval = cast_vote_timer_interval; instance->cast_vote_timer = NULL; instance->host_addr = host_addr; instance->host_port = host_port; instance->cluster_name = cluster_name; instance->connect_timeout = connect_timeout; instance->last_msg_seq_num = 1; instance->echo_request_expected_msg_seq_num = 1; instance->echo_reply_received_msg_seq_num = 1; instance->force_ip_version = force_ip_version; instance->last_echo_reply_received_time = ((time_t) -1); instance->connected_since_time = ((time_t) -1); memcpy(&instance->tie_breaker, tie_breaker, sizeof(*tie_breaker)); dynar_init(&instance->receive_buffer, advanced_settings->net_initial_msg_receive_size); send_buffer_list_init(&instance->send_buffer_list, advanced_settings->net_max_send_buffers, advanced_settings->net_initial_msg_send_size); timer_list_init(&instance->main_timer_list); pr_poll_array_init(&instance->poll_array, sizeof(struct qdevice_net_poll_array_user_data)); instance->tls_supported = tls_supported; if ((instance->cmap_poll_fd = PR_CreateSocketPollFd(cmap_fd)) == NULL) { qdevice_log_nss(LOG_CRIT, "Can't create NSPR cmap poll fd"); return (-1); } if ((instance->votequorum_poll_fd = PR_CreateSocketPollFd(votequorum_fd)) == NULL) { qdevice_log_nss(LOG_CRIT, "Can't create NSPR votequorum poll fd"); return (-1); } if ((instance->ipc_socket_poll_fd = PR_CreateSocketPollFd(local_socket_fd)) == NULL) { qdevice_log_nss(LOG_CRIT, "Can't create NSPR IPC socket poll fd"); return (-1); } return (0); } void qdevice_net_instance_clean(struct qdevice_net_instance *instance) { dynar_clean(&instance->receive_buffer); send_buffer_list_free(&instance->send_buffer_list); instance->skipping_msg = 0; instance->msg_already_received_bytes = 0; - instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_PREINIT_REPLY; instance->echo_request_expected_msg_seq_num = instance->echo_reply_received_msg_seq_num; instance->using_tls = 0; instance->tls_client_cert_sent = 0; + instance->state = QDEVICE_NET_INSTANCE_STATE_WAITING_CONNECT; instance->schedule_disconnect = 0; instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_UNDEFINED; instance->last_echo_reply_received_time = ((time_t) -1); instance->connected_since_time = ((time_t) -1); } int qdevice_net_instance_destroy(struct qdevice_net_instance *instance) { struct unix_socket_client *ipc_client; const struct unix_socket_client_list *ipc_client_list; struct qdevice_ipc_user_data *qdevice_ipc_user_data; PRFileDesc *prfd; ipc_client_list = &instance->qdevice_instance_ptr->local_ipc.clients; TAILQ_FOREACH(ipc_client, ipc_client_list, entries) { qdevice_ipc_user_data = (struct qdevice_ipc_user_data *)ipc_client->user_data; prfd = (PRFileDesc *)qdevice_ipc_user_data->model_data; if (PR_DestroySocketPollFd(prfd) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to destroy client IPC poll socket fd"); } } dynar_destroy(&instance->receive_buffer); send_buffer_list_free(&instance->send_buffer_list); pr_poll_array_destroy(&instance->poll_array); timer_list_free(&instance->main_timer_list); free((void *)instance->cluster_name); free((void *)instance->host_addr); if (PR_DestroySocketPollFd(instance->votequorum_poll_fd) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to close votequorum connection fd"); } if (PR_DestroySocketPollFd(instance->cmap_poll_fd) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to close votequorum connection fd"); } if (PR_DestroySocketPollFd(instance->ipc_socket_poll_fd) != PR_SUCCESS) { qdevice_log_nss(LOG_WARNING, "Unable to close local socket poll fd"); } return (0); } int qdevice_net_instance_init_from_cmap(struct qdevice_instance *instance) { char *str; cmap_handle_t cmap_handle; enum tlv_tls_supported tls_supported; int i; long int li; enum tlv_decision_algorithm_type decision_algorithm; struct tlv_tie_breaker tie_breaker; uint32_t heartbeat_interval; uint32_t sync_heartbeat_interval; uint32_t cast_vote_timer_interval; char *host_addr; int host_port; char *ep; char *cluster_name; uint32_t connect_timeout; struct qdevice_net_instance *net_instance; int force_ip_version; cmap_handle = instance->cmap_handle; net_instance = malloc(sizeof(*net_instance)); if (net_instance == NULL) { qdevice_log(LOG_ERR, "Can't alloc qdevice_net_instance"); return (-1); } /* * Check tls */ tls_supported = QDEVICE_NET_DEFAULT_TLS_SUPPORTED; if (cmap_get_string(cmap_handle, "quorum.device.net.tls", &str) == CS_OK) { if ((i = utils_parse_bool_str(str)) == -1) { if (strcasecmp(str, "required") != 0) { free(str); qdevice_log(LOG_ERR, "quorum.device.net.tls value is not valid."); goto error_free_instance; } else { tls_supported = TLV_TLS_REQUIRED; } } else { if (i == 1) { tls_supported = TLV_TLS_SUPPORTED; } else { tls_supported = TLV_TLS_UNSUPPORTED; } } free(str); } /* * Host */ if (cmap_get_string(cmap_handle, "quorum.device.net.host", &str) != CS_OK) { qdevice_log(LOG_ERR, "Qdevice net daemon address is not defined (quorum.device.net.host)"); goto error_free_instance; } host_addr = str; if (cmap_get_string(cmap_handle, "quorum.device.net.port", &str) == CS_OK) { host_port = strtol(str, &ep, 10); free(str); if (host_port <= 0 || host_port > ((uint16_t)~0) || *ep != '\0') { qdevice_log(LOG_ERR, "quorum.device.net.port must be in range 0-65535"); goto error_free_host_addr; } } else { host_port = QNETD_DEFAULT_HOST_PORT; } /* * Cluster name */ if (cmap_get_string(cmap_handle, "totem.cluster_name", &str) != CS_OK) { qdevice_log(LOG_ERR, "Cluster name (totem.cluster_name) has to be defined."); goto error_free_host_addr; } cluster_name = str; /* * Adjust qdevice timeouts to better suit qnetd */ cast_vote_timer_interval = instance->heartbeat_interval * 0.5; heartbeat_interval = instance->heartbeat_interval * 0.8; if (heartbeat_interval < instance->advanced_settings->net_heartbeat_interval_min) { qdevice_log(LOG_WARNING, "Heartbeat interval too small %"PRIu32". Adjusting to %"PRIu32".", heartbeat_interval, instance->advanced_settings->net_heartbeat_interval_min); heartbeat_interval = instance->advanced_settings->net_heartbeat_interval_min; } if (heartbeat_interval > instance->advanced_settings->net_heartbeat_interval_max) { qdevice_log(LOG_WARNING, "Heartbeat interval too big %"PRIu32". Adjusting to %"PRIu32".", heartbeat_interval, instance->advanced_settings->net_heartbeat_interval_max); heartbeat_interval = instance->advanced_settings->net_heartbeat_interval_max; } sync_heartbeat_interval = instance->sync_heartbeat_interval * 0.8; /* * Choose decision algorithm */ if (cmap_get_string(cmap_handle, "quorum.device.net.algorithm", &str) != CS_OK) { decision_algorithm = QDEVICE_NET_DEFAULT_ALGORITHM; } else { if (strcmp(str, "test") == 0) { decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_TEST; } else if (strcmp(str, "ffsplit") == 0) { decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_FFSPLIT; } else if (strcmp(str, "2nodelms") == 0) { decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_2NODELMS; } else if (strcmp(str, "lms") == 0) { decision_algorithm = TLV_DECISION_ALGORITHM_TYPE_LMS; } else { qdevice_log(LOG_ERR, "Unknown decision algorithm %s", str); free(str); goto error_free_cluster_name; } free(str); } if (decision_algorithm == TLV_DECISION_ALGORITHM_TYPE_TEST && !instance->advanced_settings->net_test_algorithm_enabled) { qdevice_log(LOG_ERR, "Test algorithm is not enabled. You can force enable it by " "passing -S net_test_algorithm_enabled=on to %s command", QDEVICE_PROGRAM_NAME); goto error_free_cluster_name; } /* * Load tie_breaker mode */ memset(&tie_breaker, 0, sizeof(tie_breaker)); if (cmap_get_string(cmap_handle, "quorum.device.net.tie_breaker", &str) != CS_OK) { tie_breaker.mode = QDEVICE_NET_DEFAULT_TIE_BREAKER_MODE; } else { if (strcmp(str, "lowest") == 0) { tie_breaker.mode = TLV_TIE_BREAKER_MODE_LOWEST; } else if (strcmp(str, "highest") == 0) { tie_breaker.mode = TLV_TIE_BREAKER_MODE_HIGHEST; } else { li = strtol(str, &ep, 10); if (li <= 0 || li > ((uint32_t)~0) || *ep != '\0') { qdevice_log(LOG_ERR, "tie_breaker must be lowest|highest|valid_node_id"); free(str); goto error_free_cluster_name; } tie_breaker.mode = TLV_TIE_BREAKER_MODE_NODE_ID; tie_breaker.node_id = li; } free(str); } /* * Get connect timeout */ if (cmap_get_string(cmap_handle, "quorum.device.net.connect_timeout", &str) != CS_OK) { connect_timeout = heartbeat_interval; } else { li = strtol(str, &ep, 10); if (li < instance->advanced_settings->net_min_connect_timeout || li > instance->advanced_settings->net_max_connect_timeout || *ep != '\0') { qdevice_log(LOG_ERR, "connect_timeout must be valid number in " "range <%"PRIu32",%"PRIu32">", instance->advanced_settings->net_min_connect_timeout, instance->advanced_settings->net_max_connect_timeout); free(str); goto error_free_cluster_name; } connect_timeout = li; free(str); } if (cmap_get_string(cmap_handle, "quorum.device.net.force_ip_version", &str) != CS_OK) { force_ip_version = 0; } else { li = strtol(str, &ep, 10); if ((li != 0 && li != 4 && li != 6) || *ep != '\0') { qdevice_log(LOG_ERR, "force_ip_version must be one of 0|4|6"); free(str); goto error_free_cluster_name; } force_ip_version = li; free(str); } /* * Really initialize instance */ if (qdevice_net_instance_init(net_instance, tls_supported, decision_algorithm, heartbeat_interval, sync_heartbeat_interval, cast_vote_timer_interval, host_addr, host_port, cluster_name, &tie_breaker, connect_timeout, force_ip_version, instance->cmap_poll_fd, instance->votequorum_poll_fd, instance->local_ipc.socket, instance->advanced_settings) == -1) { qdevice_log(LOG_ERR, "Can't initialize qdevice-net instance"); goto error_free_instance; } net_instance->qdevice_instance_ptr = instance; instance->model_data = net_instance; return (0); error_free_cluster_name: free(cluster_name); error_free_host_addr: free(host_addr); error_free_instance: free(net_instance); return (-1); } diff --git a/qdevices/qnet-config.h b/qdevices/qnet-config.h index 1e576872..8435b53f 100644 --- a/qdevices/qnet-config.h +++ b/qdevices/qnet-config.h @@ -1,142 +1,139 @@ /* * Copyright (c) 2015-2016 Red Hat, Inc. * * All rights reserved. * * Author: Jan Friesse (jfriesse@redhat.com) * * This software licensed under BSD license, the text of which follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the Red Hat, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _QNET_CONFIG_H_ #define _QNET_CONFIG_H_ #include #include "tlv.h" #ifdef __cplusplus extern "C" { #endif /* * There are "hardcoded" defaults for both qnetd and qdevice-net. It's not so good * idea to change them as long as you are not 100% sure what you are doing. Also * most of them can be changed in CLI via advanced_settings (-S). */ #define QNETD_PROGRAM_NAME "corosync-qnetd" #define QNETD_DEFAULT_HOST_PORT 5403 #define QNETD_DEFAULT_LISTEN_BACKLOG 10 #define QNETD_MIN_LISTEN_BACKLOG 1 #define QNETD_DEFAULT_MAX_CLIENT_SEND_BUFFERS 32 #define QNETD_MIN_CLIENT_SEND_BUFFERS 2 #define QNETD_DEFAULT_MAX_CLIENT_SEND_SIZE (1 << 15) #define QNETD_DEFAULT_MAX_CLIENT_RECEIVE_SIZE (1 << 15) #define QNETD_MIN_CLIENT_RECEIVE_SEND_SIZE 16 #define QNETD_DEFAULT_MAX_CLIENTS 0 #define QNETD_DEFAULT_NSS_DB_DIR COROSYSCONFDIR "/qnetd/nssdb" #define QNETD_DEFAULT_CERT_NICKNAME "QNetd Cert" #define QNETD_DEFAULT_TLS_SUPPORTED TLV_TLS_SUPPORTED #define QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED 1 #define QNETD_DEFAULT_HEARTBEAT_INTERVAL_MIN (1*1000) #define QNETD_DEFAULT_HEARTBEAT_INTERVAL_MAX (2*60*1000) #define QNETD_MIN_HEARTBEAT_INTERVAL 1 #define QNETD_DEFAULT_DPD_ENABLED 1 #define QNETD_DEFAULT_DPD_INTERVAL (10*1000) #define QNETD_MIN_DPD_INTERVAL 1 #define QNETD_DEFAULT_LOCK_FILE LOCALSTATEDIR"/run/corosync-qnetd/corosync-qnetd.pid" #define QNETD_DEFAULT_LOCAL_SOCKET_FILE LOCALSTATEDIR"/run/corosync-qnetd/corosync-qnetd.sock" #define QNETD_DEFAULT_LOCAL_SOCKET_BACKLOG 10 #define QNETD_MIN_LOCAL_SOCKET_BACKLOG 1 #define QNETD_DEFAULT_IPC_MAX_CLIENTS 10 #define QNETD_MIN_IPC_MAX_CLIENTS 0 #define QNETD_DEFAULT_IPC_MAX_RECEIVE_SIZE (4*1024) #define QNETD_DEFAULT_IPC_MAX_SEND_SIZE (10*1024*1024) #define QNETD_MIN_IPC_RECEIVE_SEND_SIZE 1024 #define QNETD_TOOL_PROGRAM_NAME "corosync-qnetd-tool" #define QDEVICE_NET_DEFAULT_NSS_DB_DIR COROSYSCONFDIR "/qdevice/net/nssdb" #define QDEVICE_NET_DEFAULT_INITIAL_MSG_RECEIVE_SIZE (1 << 15) #define QDEVICE_NET_DEFAULT_INITIAL_MSG_SEND_SIZE (1 << 15) #define QDEVICE_NET_DEFAULT_MIN_MSG_SEND_SIZE QDEVICE_NET_DEFAULT_INITIAL_MSG_SEND_SIZE #define QDEVICE_NET_DEFAULT_MAX_MSG_RECEIVE_SIZE (1 << 24) #define QDEVICE_NET_DEFAULT_MAX_SEND_BUFFERS 10 #define QDEVICE_NET_MIN_MAX_SEND_BUFFERS 2 #define QDEVICE_NET_MIN_MSG_RECEIVE_SEND_SIZE 16 #define QDEVICE_NET_DEFAULT_NSS_QNETD_CN "Qnetd Server" #define QDEVICE_NET_DEFAULT_NSS_CLIENT_CERT_NICKNAME "Cluster Cert" #define QDEVICE_NET_DEFAULT_ALGORITHM TLV_DECISION_ALGORITHM_TYPE_FFSPLIT #define QDEVICE_NET_DEFAULT_TLS_SUPPORTED TLV_TLS_SUPPORTED #define QDEVICE_NET_DEFAULT_TIE_BREAKER_MODE TLV_TIE_BREAKER_MODE_LOWEST #define QDEVICE_NET_DEFAULT_HEARTBEAT_INTERVAL_MIN QNETD_DEFAULT_HEARTBEAT_INTERVAL_MIN #define QDEVICE_NET_DEFAULT_HEARTBEAT_INTERVAL_MAX QNETD_DEFAULT_HEARTBEAT_INTERVAL_MAX #define QDEVICE_NET_MIN_HEARTBEAT_INTERVAL 1 #define QDEVICE_NET_DEFAULT_MIN_CONNECT_TIMEOUT (1*1000) #define QDEVICE_NET_DEFAULT_MAX_CONNECT_TIMEOUT (2*60*1000) #define QDEVICE_NET_MIN_CONNECT_TIMEOUT 1 #ifdef DEBUG #define QDEVICE_NET_DEFAULT_TEST_ALGORITHM_ENABLED 1 #else #define QDEVICE_NET_DEFAULT_TEST_ALGORITHM_ENABLED 0 #endif -#define QDEVICE_NET_DEFAULT_DELAY_BEFORE_RECONNECT (1000) -#define QDEVICE_NET_MIN_DELAY_BEFORE_RECONNECT 1 - /* * Decision algorithms supported by qnetd */ #define QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE 4 extern enum tlv_decision_algorithm_type qnetd_static_supported_decision_algorithms[QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE]; #define QDEVICE_NET_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE QNETD_STATIC_SUPPORTED_DECISION_ALGORITHMS_SIZE #ifdef __cplusplus } #endif #endif /* _QNET_CONFIG_H_ */