sunetdrive/templates/mariadb/quorum.erb.sh

100 lines
3.3 KiB
Bash
Raw Permalink Normal View History

2023-02-13 09:44:56 +00:00
#!/usr/bin/env bash
# A bash implementation of http://code.openark.org/blog/mysql/leader-election-using-mysql
# Defaults
quorum_alive_command='/bin/true'
quorum_config='/etc/quorum.conf'
quorum_db='quorum'
quorum_db_command='/usr/bin/mysql'
quorum_host='localhost'
quorum_id=$(hostname -f)
quorum_interval='20'
quorum_notify_command='/usr/bin/echo alive status:${QUORUM_ALIVE_STATUS}, leader: ${QUORUM_LEADER}, my leader status: ${QUORUM_LEADER_STATUS}'
quorum_password='quorum'
quorum_table='service_election'
quorum_user='quorum'
# Override default config path from env
if [[ "x${QUORUM_CONFIG}" != "x" ]]; then
quorum_config="${QUORUM_CONFIG}"
fi
# Override default config with settings from config file
if [[ -f "${quorum_config}" ]]; then
. "${quorum_config}"
fi
# Override with env
if [[ "x${QUORUM_ALIVE_COMMAND}" != "x" ]]; then
quorum_alive_command=${QUORUM_ALIVE_COMMAND}
fi
if [[ "x${QUORUM_DB}" != "x" ]]; then
quorum_db=${QUORUM_DB}
fi
if [[ "x${QUORUM_DB_COMMAND}" != "x" ]]; then
quorum_db_command=${QUORUM_DB_COMMAND}
fi
if [[ "x${QUORUM_HOST}" != "x" ]]; then
quorum_host=${QUORUM_HOST}
fi
if [[ "x${QUORUM_ID}" != "x" ]]; then
quorum_id=${QUORUM_ID}
fi
if [[ "x${QUORUM_INTERVAL}" != "x" ]]; then
quorum_interval=${QUORUM_INTERVAL}
fi
if [[ "x${QUORUM_NOTIFY_COMMAND}" != "x" ]]; then
quorum_notify_command=${QUORUM_NOTIFY_COMMAND}
fi
if [[ "x${QUORUM_PASSWORD}" != "x" ]]; then
quorum_password=${QUORUM_PASSWORD}
fi
if [[ "x${QUORUM_TABLE}" != "x" ]]; then
quorum_table=${QUORUM_TABLE}
fi
if [[ "x${QUORUM_USER}" != "x" ]]; then
quorum_user=${QUORUM_USER}
fi
# MySQL command
quorum_db_command="${quorum_db_command} --database=${quorum_db} --user ${quorum_user} --password ${quorum_password}"
# Queries
create_table_query='CREATE TABLE ${quorum_table} (
anchor tinyint(3) unsigned NOT NULL,
service_id varchar(128) NOT NULL,
last_seen_active timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (anchor)
) ENGINE=InnoDB'
table_exists_query="SELECT *
FROM information_schema.tables
WHERE table_schema = '${quorum_db}'
AND table_name = '${quorum_table}'
LIMIT 1"
election_query="insert ignore into ${quorum_table} ( anchor, service_id, last_seen_active ) values ( 1, '${quorum_id}', now() ) on duplicate key update service_id = if(last_seen_active < now() - interval ${quorum_interval} second, values(service_id), service_id), last_seen_active = if(service_id = values(service_id), values(last_seen_active), last_seen_active)"
is_leader_query="select count(*) as is_leader from ${quorum_table} where anchor=1 and service_id='${quorum_id}'"
who_is_leader_query="select max(service_id) as leader from ${quorum_table} where anchor=1"
# Set up table if it does not exist
${quorum_db_command} -e "${table_exists_query}" >/dev/null 2>&1
if [[ ${?} -ne 0 ]]; then
${quorum_db_command} -e "${create_table_query}" >/dev/null 2>&1
fi
# Run the algorithm
${quorum_alive_command} >/dev/null 2>&1
alive_status=${?}
if [[ ${alive_status} -eq 0 ]]; then
${quorum_db_command} -e "${election_query}" >/dev/null 2>&1
fi
leader_status=$(${quorum_db_command} -e "${is_leader_query}")
leader=$(${quorum_db_command} -e "${who_is_leader_query}")
QUORUM_ALIVE_STATUS=${alive_status} QUORUM_LEADER=${leader} QUORUM_LEADER_STATUS=${leader_status} eval ${quorum_notify_command}
exit ${alive_status}