Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 729 lines (676 sloc) 24.1 KB
#!/bin/bash
# vim: set ts=4 sw=4 et si:
. ./scripts/volume-common.sh
ETC_CASSANDRA="${ETC_CASSANDRA:-/etc/cassandra}"
CASSANDRA_ENV="${ETC_CASSANDRA}/cassandra-env.sh"
CASSANDRA_YML="${ETC_CASSANDRA}/cassandra.yaml"
CASSANDRA_ACCESS="${ETC_CASSANDRA}/access.properties"
CASSANDRA_PASSWD="${ETC_CASSANDRA}/passwd.properties"
CASSANDRA_RACKDC="${ETC_CASSANDRA}/cassandra-rackdc.properties"
CASSANDRA_TOPOLOGY="${ETC_CASSANDRA}/cassandra-topology.properties"
CASSANDRA_USER="cassandra"
CASSANDRA_GROUP="cassandra"
NAGIOS_EXPORT_DIR="/var/lib/nagios/export"
set -ex
export LANG=en_US.UTF-8
# Comms-less leader determination
# Picks the unit with the lowest id.
am_i_the_leader () {
# FWIW this is race-prone (as not all units have the same 'relation-list'
# view at the same point in time), so am_i_the_leader it's kinda ~best-effort.
# Until juju-core provides facilities for master election, keep this
# nasty workaround.
# Leader is the lowest unit number and won't be in the
# list of relation peers
if [ -z "${JUJU_RELATION_ID}" ]; then
juju-log "${FUNCNAME[1]}: ${FUNCNAME[0]}: not running under relation context"
return 2
fi
local units=$(relation-list)
juju-log "related units seen: ${units}"
local unit_no=${JUJU_UNIT_NAME##*/}
local unit
for unit in ${units}; do
peer_unit_no=${unit##*/}
if [ "${peer_unit_no}" -lt "${unit_no}" ]; then
juju-log "I am not the leader"
return 1
fi
done
juju-log "I am the leader"
return 0
}
bzr_ci () {
local msg=${FUNCNAME[1]}
test -n "$1" && msg="$1"
bzr st ${ETC_CASSANDRA}|egrep -q '^modified|added' || return 1
bzr ci -m "[$(date "+%Y-%m-%d %H:%M:%S")] ${JUJU_UNIT_NAME}: ${msg} auto-commit" ${ETC_CASSANDRA} || return 1
return 0
}
migrate_cassandra_data() {
local from=${1?} to=${2?}
[[ $from = $to ]] && return 0
/etc/init.d/cassandra stop
rsync -vaP "$from/" "$to/"
mv "$from" "$from.migrated_${JUJU_UNIT_NAME//\//-}@$(date +%s)"
}
# When the volume is mounted by another (fresh) unit, getent passwd
# entry *can* get a different UID (depending e.g. on user order
# creation and/or other role accounts present), thus the need
# to fix permissions (ownership) over cassandra data dir.
fix_cassandra_perms() {
local data_dir=${1?}
chown -R cassandra:cassandra ${data_dir}
}
# Install cassandra source and install packages
install_cassandra () {
juju-log "Installing Cassandra"
# Install the repository
APT_REPO_SPEC="$(config-get apt-repo-spec)"
APT_REPO_KEY=$(config-get apt-repo-key)
# Check for configured extra packages to install from config
EXTRA_PACKAGES="$(config-get extra_packages)"
# Get the debian package in the files directory.
DEBIAN_PACKAGE_FILE=($CHARM_DIR/files/cassandra_*.deb)
# Does the debain cassandra package exist in the charm directory?
if [[ -f ${DEBIAN_PACKAGE_FILE} ]]; then
# The apt-get update command is necessary to install java.
apt-get update -qq
# Install the prerequisites for cassandra.
DEBIAN_FRONTEND=noninteractive apt-get -qq install -y openjdk-7-jre-headless libjna-java python-support python-cheetah dnsutils bzr ${EXTRA_PACKAGES}
# Use the debian package manager to install the cassandra package.
dpkg -i ${DEBIAN_PACKAGE_FILE}
else
# Add the key
if [[ -n "${APT_REPO_KEY}" ]]; then
# Use port 80 to get the keyserver key.
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ${APT_REPO_KEY}
fi
if [[ -n "${APT_REPO_SPEC}" ]]; then
echo "${APT_REPO_SPEC}" > /etc/apt/sources.list.d/cassandra.list
fi
# Update the repositories
apt-get update
# Ensure that cassandra does not startup before we have configured it
disable_cassandra_start
# Install the package
DEBIAN_FRONTEND=noninteractive apt-get -qq install -y cassandra python-cheetah python-pip dnsutils bzr ${EXTRA_PACKAGES}
# Install charm-helpers for benchmarking support
pip install charmhelpers
fi
bzr_ci || :
}
# Update the cassandra environment with the appropriate JMX port
configure_jmx_port () {
check_units_to_update || return 0
juju-log "Configuring JMX port"
JMX_PORT=$(config-get jmx-port)
test -n "${JMX_PORT}" || return 1
test ${JMX_PORT} -gt 0 -a ${JMX_PORT} -lt 65535 || return 1
sed -i -e "s/^JMX_PORT=.*/JMX_PORT=\"${JMX_PORT}\"/" ${CASSANDRA_ENV}
# Open port ready for expose
open-port ${JMX_PORT}/TCP
}
get_private_ip () {
# Make sure that we use the resolvable private address
# some dig versions dealxs with both hostnames and ip
# addresses, but don't depend on that.
local address=$(unit-get private-address)
if [[ ${address} =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
# already an IP
echo "${address}"
else
# not an IP (some providers return hostnames), resolve it
dig +short "${address}"
fi
}
relation-get-all() {
# reltype is e.g. 'cluster'
# relkey is e.g. 'seed-nodes'
# default separator is space
local reltype=${1:?} relkey=${2:?} separator="${3:- }"
local rid unit value=
# aggregate all values from every related unit
value=$(
for rid in $(relation-ids ${reltype});do
for unit in $(relation-list -r ${rid});do
relation-get -r ${rid} ${relkey} ${unit}
done
done
)
echo "${value}" | sort -u | paste -d "${separator}" -s
}
write_seed_nodes() {
local seeds="${1?}"
# write to config if non-null seeds, or seed value coming from
if [ -n "${seeds}" ] || [ "$(config-get force-seed-nodes)" != "" ] || \
[ "$(config-get allow-single-node)" = "True" ]; then
local seeds_comma=$(echo "$seeds" | sed -r 's/ +/,/g')
juju-log "Setting seeds node to be '${seeds_comma}'"
sed -i -e "s/\- seeds:.*/\- seeds: \"${seeds_comma}\"/" ${CASSANDRA_YML}
else
# This happens when e.g. the unit relates to a non-leader
juju-log "Skipping seeds node setting (no seeds)"
fi
}
get_seed_nodes() {
local force_seed_nodes="$(config-get force-seed-nodes)"
local allow_single_node="$(config-get allow-single-node)"
local seeds
if [ -n "${force_seed_nodes}" ]; then
seeds="${force_seed_nodes}"
elif [ "${allow_single_node}" == "True" ]; then
seeds="$(get_private_ip)"
# If running under relation context ...
elif [ -n "${JUJU_RELATION_ID}" ]; then
if am_i_the_leader; then
seeds="$(running_nodes)"
# Too early, maybe bootstraping the whole cluster ...
if [ -z "${seeds}" ]; then
seeds=$(get_private_ip)
fi
else
seeds=$(relation-get-all cluster seed-nodes)
fi
fi
juju-log "${FUNCNAME[1]}: ${FUNCNAME[0]}: seeds='$seeds'"
echo "${seeds}"
}
srv_root_get() {
sed -r -n 's,commitlog_directory: *([^ ]+)/commitlog.*,\1,p' ${CASSANDRA_YML}
}
srv_root_from_volid() {
local volid=${1?missing volid}
local mntpoint
if mntpoint=$(volume_mount_point_from_volid "${volid}"); then
echo "${mntpoint}/cassandra"
else
echo "/var/lib/cassandra"
fi
}
srv_root_save() {
local srv_root=${1:?missing srv_root}
sed -i -r -e $'/data_file_directories:/{\nN;s|- /.*|- '"${srv_root}/data"'|}' \
-e "s|^(commitlog_directory):.*|\1: ${srv_root}/commitlog|" \
-e "s|^(saved_caches_directory):.*|\1: ${srv_root}/savedcache_dir|" \
${CASSANDRA_YML}
test -d "${srv_root}" || {
mkdir -p "${srv_root}"
chown -R ${CASSANDRA_USER}:${CASSANDRA_GROUP} "${srv_root}"
}
}
disable_cassandra_start() {
# Ensure that cassandra does not startup before we have configured it
if [ -e /usr/sbin/policy-rc.d ]; then
mv /usr/sbin/policy-rc.d /usr/sbin/policy-rc.d.orig
fi
install -m 755 files/policy-rc.d /usr/sbin/policy-rc.d
}
enable_cassandra_start() {
if [ -e /usr/sbin/policy-rc.d.orig ]; then
mv /usr/sbin/policy-rc.d.orig /usr/sbin/policy-rc.d
else
rm -rf /usr/sbin/policy-rc.d.orig
fi
}
get_initial_token() {
token_map_unitname=$(config-get token-map-by-unitname)
token_map_volid=$(config-get token-map-by-volid)
initial_token=""
if [[ -z ${token_map_unitname} ]] && [[ -z ${token_map_volid} ]]; then
echo $initial_token
return
elif [[ -n ${token_map_unitname} ]] && [[ -n ${token_map_volid} ]]; then
juju-log "ERROR: cannot specify token-map-by-unitname and token-map-by-volid"
exit 1
elif [[ -n ${token_map_unitname} ]]; then
token_map=$token_map_unitname
token_key=${JUJU_UNIT_NAME}
elif [[ -n ${token_map_volid} ]]; then
token_map=$token_map_volid
token_key=$(volume_get_volume_id)
fi
python="import sys;from yaml import load;token_map = load(sys.stdin);print token_map.get(\"${token_key}\")"
initial_token=$(echo $token_map | python -c "${python}")
echo ${initial_token/None/}
}
# Construct the cassandra.yaml file from the appropriate information above
configure_cassandra () {
check_units_to_update || return 0
juju-log "Configuring Cassandra"
local LISTEN_ADDRESS=$(get_private_ip)
local CLUSTER_PORT=$(config-get cluster-port)
local CLIENT_PORT=$(config-get client-port)
local CLUSTER_NAME=$(config-get cluster-name)
local AUTO_MEMORY=$(config-get auto-memory)
local HEAP_SIZE=$(config-get heap-size)
local NEW_GEN_SIZE=$(config-get new-gen-size)
local SRV_ROOT=$(config-get srv-root)
local COMPACTION_THROUGHPUT=$(config-get compaction-throughput)
local STREAM_THROUGHPUT=$(config-get stream-throughput)
local NUM_TOKENS=$(config-get num-tokens)
local INITIAL_TOKEN=$(get_initial_token)
local PARTITIONER=$(config-get partitioner)
local ENDPOINT_SNITCH=$(config-get endpoint_snitch)
local DATACENTER=$(config-get datacenter)
local RACK=$(config-get rack)
local DC_SUFFIX=$(config-get dc_suffix)
local PREFER_LOCAL=$(config-get prefer_local | tr '[:upper:]' '[:lower:]')
# This needs to 'detect' whether its running in ec2
# and use the ec2Snitch instead if it is - or we could
# specify this as a configuration parameter
# non-trivial sed to edit data_file_directories (has its value in the line following it)
sed -i -r -e "s/^cluster_name:.*/cluster_name: \'${CLUSTER_NAME}\'/" \
-e "s/^(storage_port):.*/\1: ${CLUSTER_PORT}/" \
-e "s/^(listen_address):.*/\1: ${LISTEN_ADDRESS}/" \
-e "s/^(rpc_address):.*/\1: ${LISTEN_ADDRESS}/" \
-e "s/^(rpc_port):.*/\1: ${CLIENT_PORT}/" \
-e "s/^(compaction_throughput_mb_per_sec):.*/\1: ${COMPACTION_THROUGHPUT}/" \
-e "s/^(# )?(stream_throughput_outbound_megabits_per_sec):.*/\2: ${STREAM_THROUGHPUT}/" \
-e "s/^(partitioner):.*/\1: ${PARTITIONER}/" \
-e "s/^(endpoint_snitch):.*/\1: ${ENDPOINT_SNITCH}/" \
${CASSANDRA_YML}
## Number of tokens or initial token
if [ $NUM_TOKENS -eq 0 ] && [ -n "$INITIAL_TOKEN" ]; then
sed -i -r -e "s/^(# )?(num_tokens):.*/#\2: ${NUM_TOKENS}/" \
-e "s/^(# )?(initial_token):.*/\2: ${INITIAL_TOKEN}/" \
${CASSANDRA_YML}
elif [ $NUM_TOKENS -gt 0 ] && [ -z "$INITIAL_TOKEN" ]; then
sed -i -r -e "s/^(# )?(num_tokens):.*/\2: ${NUM_TOKENS}/" \
-e "s/^(# )?(initial_token):.*/# \2: ${INITIAL_TOKEN}/" \
${CASSANDRA_YML}
else
juju-log "ERROR: cannot specify num_tokens and initial_token"
exit 1
fi
## Enpoint Snitch configuration
# XXX Handle more endpoint snitch options
if [[ "$ENDPOINT_SNITCH" =~ .*SimpleSnitch ]]; then
rm -f ${CASSANDRA_RACKDC} ${CASSANDRA_TOPOLOGY}
elif [[ "$ENDPOINT_SNITCH" =~ .*GossipingPropertyFileSnitch ]]; then
rm -f ${CASSANDRA_TOPOLOGY}
(
echo "dc=${DATACENTER}"
echo "rack=${RACK}"
if [ -n "$DC_SUFFIX" ]; then
echo "dc_suffix=${DC_SUFFIX}"
fi
if [ "$PREFER_LOCAL" = "true" ]; then
echo "prefer_local=true"
fi
) > ${CASSANDRA_RACKDC}
else
rm -f ${CASSANDRA_RACKDC}
fi
## Storage configuration
local volid
local IO_SCHEDULER=$(config-get io-scheduler)
if volid=$(volume_get_volume_id);then
juju-log "INFO: volid=${volid}"
else
disable_cassandra_start
juju-log "ERROR: invalid storage_config at ${FUNCNAME[0]}"
return 1
fi
local srv_root_curr=$(srv_root_get)
(
set -e
[[ -z "${volid}" ]] && exit 0
if volume_is_permanent "${volid}";then
local srv_root_new=$(srv_root_from_volid ${volid})
if [[ ${srv_root_new} != ${srv_root_curr} ]];then
volume_init_and_mount ${volid}
if [[ -d ${srv_root_curr}/data ]];then
juju-log "WARNING: found already existing cassandra data, migrating ${srv_root_curr} -> ${srv_root_new}"
migrate_cassandra_data ${srv_root_curr} ${srv_root_new}
fi
fix_cassandra_perms ${srv_root_new}
srv_root_save ${srv_root_new}
fi
# Set the kernel block scheduler
if [[ -n "$IO_SCHEDULER" ]]; then
DEV=$(df $srv_root_new | awk '{print $1}' |tail -n 1)
DEV=${DEV#\/dev\/}
DEV=${DEV%[0-9]}
echo "$IO_SCHEDULER" > /sys/block/${DEV}/queue/scheduler
fi
fi
) && enable_cassandra_start || disable_cassandra_start
# Open port ready for expose
open-port ${CLIENT_PORT}/TCP
# Get the architecture from the uname command.
ARCHITECTURE=`uname -m`
if [ "$ARCHITECTURE" == "ppc64le" ]; then
# On the ppc64le architecture requires a higher value for stack size.
sed -i -e "s/-Xss[0-9]*k/-Xss1664k/" ${CASSANDRA_ENV}
else
# Default cassandra-env.sh for some cassandra 1.0.x specifies -Xss128k
# while 160k min is required
sed -i -e "s/-Xss[0-9]*k/-Xss256k/" ${CASSANDRA_ENV}
fi
# OpenJDK does not handle the UseCondCardMark flag.
sed -i -e "s/-XX:+UseCondCardMark//" ${CASSANDRA_ENV}
# Configure memory settings as specified in configuration
if [ "$AUTO_MEMORY" = "False" ]; then
juju-log "Configuring Manual Memory Setttings"
sed -i -e "s/^[#]MAX_HEAP_SIZE=.*/MAX_HEAP_SIZE=\"${HEAP_SIZE}\"/" \
-e "s/^[#]HEAP_NEWSIZE=.*/HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" ${CASSANDRA_ENV}
else
sed -i -e "s/^[#]MAX_HEAP_SIZE=.*/#MAX_HEAP_SIZE=\"${HEAP_SIZE}\"/" \
-e "s/^[#]HEAP_NEWSIZE=.*/#HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" ${CASSANDRA_ENV}
fi
local use_simpleauth=$(config-get use-simpleauth)
if [[ ${use_simpleauth} == True ]];then
local auth_opts
install -o ${CASSANDRA_USER} -m 600 /dev/null ${CASSANDRA_PASSWD}
config-get auth-passwd64|base64 -d > ${CASSANDRA_PASSWD}
config-get auth-access64|base64 -d > ${CASSANDRA_ACCESS}
auth_opts="-Dpasswd.properties=${CASSANDRA_PASSWD} -Daccess.properties=${CASSANDRA_ACCESS}"
add_JVM_OPTS_line "Daccess.properties" "$auth_opts"
replace_YAML_key authenticator org.apache.cassandra.auth.SimpleAuthenticator
else
rm -f ${CASSANDRA_PASSWD} ${CASSANDRA_ACCESS}
del_JVM_OPTS_line "Daccess.properties"
replace_YAML_key authenticator org.apache.cassandra.auth.AllowAllAuthenticator
fi
local extra_jvm_opts=$(config-get extra-jvm-opts)
if [[ ${extra_jvm_opts} != "" ]];then
add_JVM_OPTS_line "JUJU_extra-jvm-opts" "$extra_jvm_opts"
else
del_JVM_OPTS_line "JUJU_extra-jvm-opts"
fi
reconfigure_cluster_seeds
}
# Remove JVM_OPTS line by regex
del_JVM_OPTS_line() {
local regex="${1?}"
juju-log "Deleting from JVM_OPTS: key=${regex}"
sed -ri "\!^JVM_OPTS=.*${regex}!d" ${CASSANDRA_ENV} || true
}
# Add JVM_OPTS line, use regex remove it before, if already present
add_JVM_OPTS_line() {
local regex="${1?}" line="${2?}"
del_JVM_OPTS_line "${regex}"
juju-log "Adding to JVM_OPTS: ${line} (key=${regex})"
echo "JVM_OPTS=\"\$JVM_OPTS ${line}\" ## ${regex} " >> ${CASSANDRA_ENV}
}
# Replace an *existent* YAML key: value
# Note that key will be treated as a regex
replace_YAML_key() {
local key="${1?}" value="${2?}"
juju-log "Replacing YAML: key=${key} value=${value}"
sed -ri -e "s!^(${key}): .*!\1: ${value}!" ${CASSANDRA_YML}
}
# Service Control Commands
cassandra_is_running() {
juju-log "${FUNCNAME[1]}: ${FUNCNAME[0]} $@"
service cassandra status
}
# wait until "$func $*" OK, loop $times sleeping $secs (default: 1)
wait_until() {
local secs=${1:?} times=${2:?} func=${3:?}
shift 3
juju-log "${FUNCNAME[1]}: ${FUNCNAME[0]} $@"
while let times=times-1; do
if ${func} ${*}; then
juju-log "${FUNCNAME[0]} $func $*: OK (times=$times left)"
return 0
fi
juju-log "${FUNCNAME[0]} $func $*: sleep ${secs}, times=$times left"
sleep ${secs}
done
return 1
}
# ditto wait_until, with opposite logic
wait_until_not() {
local secs=${1:?} times=${2:?} func=${3:?}
juju-log "${FUNCNAME[1]}: ${FUNCNAME[0]} $@"
while let times=times-1; do
if ${func} ${*}; then
:
else
juju-log "${FUNCNAME[0]} $func $*: OK (times=$times left)"
return 0
fi
juju-log "${FUNCNAME[0]} $func $*: sleep ${secs}, times=$times left"
sleep ${secs}
done
return 1
}
restart_cassandra () {
juju-log "Restarting Cassandra"
service cassandra restart
wait_until 1 60 cassandra_is_running
}
start_cassandra() {
juju-log "Starting Cassandra"
service cassandra status || service cassandra start
wait_until 1 60 cassandra_is_running
}
stop_cassandra() {
juju-log "Stopping Cassandra"
service cassandra stop || :
wait_until_not 1 60 cassandra_is_running
}
setup_database_interface () {
juju-log "Setup Cassandra database interface"
relation-set port="$(config-get client-port)"
}
setup_jmx_interface () {
juju-log "Setup Cassandra JMX interface"
relation-set port="$(config-get jmx-port)"
}
reconfigure_cluster_seeds() {
juju-log "Reconfiguring cluster seeds"
local seeds=$(get_seed_nodes)
write_seed_nodes "${seeds}"
# If under relation context, and I'm leader => propagate seed-nodes to other units.
if [ -n "${seeds}" -a -n "${JUJU_RELATION_ID}" ] && am_i_the_leader; then
juju-log "Setting relation seed-nodes to ${seeds}"
relation-set seed-nodes="${seeds}"
fi
}
nodestatus_is() {
local ip="${1:?}" wanted_status="${2:?}"
local nodestatus="$(nodestatus ${ip})"
juju-log "nodestatus='${nodestatus}' wanted_status='${wanted_status}'"
[[ ${nodestatus} =~ ${wanted_status} ]]
return $?
}
nodestatus() {
local node_ip=$1
local VER=$(dpkg-query --show --showformat='${Version}' cassandra)
local MAJ=${VER%%.*}
local MIN_REL=${VER#*.}
local MIN=${MIN_REL%%.*}
local RING_COLS='$3$4'
if [ $MAJ == "0" ] || ([ $MAJ == "1" ] && [ $MIN == "0" ]); then
# nodetool ring columns are different in 1.0 and lower
RING_COLS='$4$5'
fi
nodetool -h $node_ip ring 2>/dev/null | \
awk "/^$node_ip / {print $RING_COLS}" | \
tail -n1
}
running_nodes() {
local node_ip=$(get_private_ip)
nodetool -h $node_ip ring 2>/dev/null | \
awk '/Up *Normal/ {print $1}' | \
sort -u | \
paste -d " " -s
}
echo_yml_expression() {
python -c "import yaml,sys;print yaml.load(sys.stdin)$1" < ${CASSANDRA_YML}
}
current_file_seeds() {
echo_yml_expression '["seed_provider"][0]["parameters"][0]["seeds"]'
}
bootstrap () {
local IP
local count status
if am_i_the_leader; then
:
else
local file_seeds=$(current_file_seeds)
case "${file_seeds}" in
""|127.*)
juju-log "Returning soft-fail on not-yet received external seeds"
return 0;;
esac
fi
juju-log "Waiting for this node to join the cluster"
# wait until cassandra is UP ok, 3 retries
# start_cassandra will no-op if already running
count=3
while let count=count-1; do
start_cassandra
if wait_until 60 2 nodestatus_is $(get_private_ip) "Up(Joining|Normal)"; then
return 0
fi
done
juju-log "Timed out waiting for Up Normal/Joining"
exit 2
}
remove_down_nodes () {
reconfigure_cluster_seeds
}
decommission_node () {
juju-log "Decommissioning node - this may take some time..."
nodetool -h $(get_private_ip) decommission
}
run_exec_d_hooks() {
local exec_hook=${1:?}
if [[ -d exec.d ]]; then
shopt -s nullglob
for f in exec.d/*/charm-${exec_hook}; do
[[ -x "$f" ]] || continue
${SHELL} -c "$f"|| {
## bail out if anyone fails
juju-log -l ERROR "$f: returned exit_status=$? "
exit 1
}
done
fi
}
update_nagios_checks() {
if [ -d "/usr/lib/nagios/plugins" ] && [ -d "/etc/nagios/nrpe.d" ]; then
IP=`get_private_ip`
install --owner=root --group=root --mode=0555 files/check_cassandra_heap.sh /usr/lib/nagios/plugins/check_cassandra_heap.sh
export NAGIOS_CONTEXT="$(config-get nagios_context)"
export NAGIOS_HOSTNAME="${NAGIOS_CONTEXT}-${JUJU_UNIT_NAME//\//-}"
export NAGIOS_SERVICEGROUP=${NAGIOS_CONTEXT}
export WARN_PCT="$(config-get nagios_heapchk_warn_pct)"
export CRIT_PCT="$(config-get nagios_heapchk_crit_pct)"
export SERVICE_DESCRIPTION="Cassandra server heap usage"
export NRPE_CMD_NAME="check_${NAGIOS_CONTEXT}_cassandra_heap"
export NRPE_CMD="/usr/lib/nagios/plugins/check_cassandra_heap.sh ${IP} ${WARN_PCT} ${CRIT_PCT}"
if [ ! -d "${NAGIOS_EXPORT_DIR}" ]; then
mkdir -p "${NAGIOS_EXPORT_DIR}"
fi
cheetah fill --env -p templates/nrpe_cmd_file.tmpl > /etc/nagios/nrpe.d/${NRPE_CMD_NAME}.cfg
cheetah fill --env -p templates/nrpe_service_file.tmpl > ${NAGIOS_EXPORT_DIR}/service__${NAGIOS_HOSTNAME}_${NRPE_CMD_NAME}.cfg
fi
}
# Check if units-to-update comma separated list contains my number, or "all",
# returns 0 if this unit should be updated
check_units_to_update() {
local unit
local units_to_update=$(config-get units-to-update)
local unitnum=${JUJU_UNIT_NAME##*/}
[[ $units_to_update == "all" ]] && return 0
(
OLDIFS="$IFS"
IFS=" ,"
for unit in ${units_to_update}; do
if [[ $unit == $unitnum ]];then
juju-log "check_units_to_update: \"${unitnum}\" in \"${units_to_update}\", updating."
exit 0
fi
done
juju-log "check_units_to_update: \"${unitnum}\" not in \"${units_to_update}\", skipping."
exit 1
)
return $?
}
hook_main() {
local COMMAND="$1"
export BZR_HOME=/root
case $COMMAND in
install)
run_exec_d_hooks "pre-install"
# Install cassandra first run only
[[ -d /usr/share/cassandra ]] || install_cassandra
# Initialize /etc/cassandra bzr
bzr whoami "${JUJU_UNIT_NAME} <juju@${HOSTNAME}>"
test -d ${ETC_CASSANDRA}/.bzr || bzr init ${ETC_CASSANDRA} && bzr add ${ETC_CASSANDRA}
bzr_ci "main:${COMMAND}" ${ETC_CASSANDRA} || :
# Update the cassandra environment with the appropriate JMX port
configure_jmx_port
bzr_ci || :
# Construct the cassandra.yaml file from the appropriate information above
configure_cassandra
bzr_ci || :
run_exec_d_hooks "post-install"
;;
config-changed)
needs_restart=
# Update the cassandra environment with the appropriate JMX port
configure_jmx_port
bzr_ci && needs_restart=:
# Construct the cassandra.yaml file from the appropriate information above
configure_cassandra
bzr_ci && needs_restart=:
# be sure to kick a cassandra restart if not
# running yet
cassandra_is_running || needs_restart=:
if [ $needs_restart ]; then
# Restart as required
restart_cassandra
fi
# Fill in nagios checks
update_nagios_checks
;;
upgrade-charm)
check_units_to_update || exit 0
juju-log "Updating this charm - currently no-op"
;;
stop)
stop_cassandra
;;
start)
if [ "$(config-get allow-single-node)" == "True" ]; then
start_cassandra
fi
;;
database-relation-joined)
setup_database_interface
;;
cluster-relation-joined)
juju-log "Joining cassandra cluster..."
am_i_the_leader || sleep $(( 30 + RANDOM%15 ))
;;
cluster-relation-changed)
reconfigure_cluster_seeds
# if there were config changes, restart cassandra
bzr_ci && restart_cassandra
bootstrap
;;
cluster-relation-departed)
reconfigure_cluster_seeds
# if there were config changes, restart cassandra
bzr_ci && restart_cassandra
remove_down_nodes
;;
jmx-relation-joined)
setup_jmx_interface
;;
nrpe-external-master-relation-changed)
update_nagios_checks
;;
*)
juju-log "Command not recognised: $COMMAND"
;;
esac
}
# Actual processing, if not unittesting
test -n "$CASSANDRA_TESTING" || hook_main ${0##*/}