#!/bin/bash # # Cluster init ! # #function ProgressBar { # # Process data # let _progress=(${1}*100/${2}*100)/100 # let _done=(${_progress}*4)/10 # let _left=40-$_done # # Build progressbar string lengths # _fill=$(printf "%${_done}s") # _empty=$(printf "%${_left}s") # # # 1.2 Build progressbar strings and print the ProgressBar line # # 1.2.1 Output example: # # 1.2.1.1 Progress : [########################################] 100% # printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%" #} function redisRun() { cmd="redis-cli" host=$1 shift port=$1 shift #pass=$1 #shift #opt="-h ${host} -p ${port} -a ${pass}" opt="-h ${host} -p ${port}" act=${@} ${cmd} ${opt} ${act} return ${?} } # # Get Node ID with IP Adress and Port Number # Params : # - $1 => Leader IP # - $2 => Leader Port # - $3 => Cluster Password # - $4 => Node IP Adress # - $5 => Node Port # function getNodeID() { if [[ ${1} == ${3} ]] then searchCmd="awk '/myself,master/ { print \$1 }'" else searchCmd="awk '/${3}:${4}@/ { print \$1 }'" fi result=$(redisRun $1 $2 cluster nodes | eval ${searchCmd}) rcode=${?} if [[ -z ${result} ]] then searchCmd="awk '/${3}:${4}@/ { print \$1 }'" result=$(redisRun $1 $2 cluster nodes | eval ${searchCmd}) rcode=${?} fi echo ${result} return ${rcode} } function redisClusterForgetAll() { local res=0 for node in $(redisRun ${1} ${2} ${3} cluster nodes | awk '!/myself,master/ {print $1}') do redisRun ${1} ${2} ${3} "cluster forget ${node}" res=$((res+${?})) done return ${res} } # # Assing redis slots to master Node # Params : # - $1 => Node IP # - $2 => Node Port # - $3 => Cluster Password # - $4 => First slot # - $5 => Last slot # function redisSlotAssign() { res=0 for slot in $(seq ${3} ${4}) do OUT=$(redisRun ${1} ${2} "cluster ADDSLOTS $slot") res=$((res+${?})) if [[ ${OUT} =~ ERR ]] then OUT=$(redisRun ${1} ${2} "cluster ADDSLOTS $slot") fi done return ${res} } function redisAddReplica() { redisRun ${1} ${2} "cluster replicate ${3}" return ${?} } function redisClusterIsOK() { out=$(redis-cli -h ${1} -p ${2} cluster info | grep "cluster_state:ok") return $? } CONF="/etc/redis/cluster.conf" INITFLAG="/usr/share/eole/redisinit.flg" sysConf=$(grep "vm.overcommit_memory" /etc/sysctl.conf 2>&1 > /dev/null) if [[ ${?} -ne 0 ]] then echo "vm.overcommit_memory=1" >> /etc/sysctl.conf sysctl -p /etc/sysctl.conf fi [[ ! -e ${CONF} ]] && exit 0 declare -A IPADDRS declare -A PORTS declare -A ROLES declare -A MASTERS declare -A NIDS declare LeaderIP declare LeaderPort index=0 while read line do [[ ${line} =~ ^# ]] && continue line=${line//::/:none:} li=(${line//:/ }) name=${li[0]} ip=${li[1]} port=${li[2]} role=${li[3]} master=${li[4]} ntype=${li[5]} if [[ ${ntype} == "Leader" ]] then LeaderIP=${ip} LeaderPort=${port} fi NAMES+=(${name}) IPADDRS+=([${name}]=${ip}) PORTS+=([${name}]=${port}) ROLES+=([${name}]=${role}) MASTERS+=([${name}]=${master}) done < ${CONF} # Disable Transparent Huge Page support on kernel echo never > /sys/kernel/mm/transparent_hugepage/enabled if [[ ${1} == "forget" ]] then redisClusterForgetAll ${LeaderIP} ${LeaderPort} exit ${?} fi # If the cluster is "ok" don't do anything st=$(redisClusterIsOK ${LeaderIP} ${LeaderPort}) [[ ${?} -eq 0 ]] && exit 0 if [[ -e ${INITFLAG} ]] then echo "Init allready done ... nothing to do" exit 0 fi echo " * Organise Cluster Meeting." for node in ${NAMES[@]} do act="cluster meet ${IPADDRS[${node}]} ${PORTS[${node}]}" echo " - ${node} - ${IPADDRS[${node}]}:${PORTS[${node}]} meeting with :" for oth in ${NAMES[@]} do [[ ${oth} == ${node} ]] && continue echo -en " -> ${oth} - ${IPADDRS[${oth}]} ${PORTS[${oth}]} " redisRun ${IPADDRS[${oth}]} ${PORTS[${oth}]} "${act}" done done echo " * Waiting for all members ." for node in ${NAMES[@]} do try=3 scmd="awk '/${IPADDRS[$node]}:${PORTS[${node}]}/ {print \$8}'" while [[ $(redisRun ${LeaderIP} ${LeaderPort} "cluster nodes" | eval ${scmd}) != "connected" ]] do sleep 1 try=$((try-1)) [[ ${try} -eq 0 ]] break done done nbMaster=$(grep -c ":master" ${CONF}) totalslots=16384 perNodeSlots=$((totalslots/nbMaster)) startSlot=0 echo " * Assign Slots to the nodes." for node in ${NAMES[@]} do if [[ ${ROLES[$node]} == "master" ]] then if [[ ${startSlot} -eq 0 ]] then lastSlot=$(((perNodeSlots+startSlot)-1)) else lastSlot=$((perNodeSlots+startSlot)) fi [[ ${lastSlot} -ge ${totalslots} ]] && lastSlot=$((totalslots-1)) echo " - Slots ${startSlot} to ${lastSlot} => ${node} - ${IPADDRS[${node}]} ${PORTS[${node}]}" redisSlotAssign ${IPADDRS[${node}]} ${PORTS[${node}]} ${startSlot} ${lastSlot} startSlot=$((lastSlot+1)) fi done echo " * Configuring replication." NIDS+=() for node in ${NAMES[@]} do NIDS+=([${node}]=$(getNodeID ${LeaderIP} ${LeaderPort} ${IPADDRS[${node}]} ${PORTS[${node}]})) done for node in ${NAMES[@]} do [[ ${ROLES[$node]} == "master" ]] && continue echo -ne " - Replicate ${MASTERS[${node}]} to ${node}\t\t" redisAddReplica ${IPADDRS[${node}]} ${PORTS[${node}]} ${NIDS[${MASTERS[${node}]}]} done sleep 5 echo echo "Cluster status :" echo redisRun ${LeaderIP} ${LeaderPort} cluster info echo touch ${INITFLAG} exit 0