setterm -cursor off

stty -echoctl # hide ^C

# function called by trap
ct_on_exit() {
    setterm -cursor on
    echo
    exit $1
}

trap 'ct_on_exit' EXIT HUP INT TERM

# Init list of OSDs Down
ceph osd tree down |grep "osd\."| awk '{print $1}'|sort -n -o /tmp/OSDs_Down

CT_SCRIPT_NAME=$0
CT_MAX_REMAPPED=64
CT_MAX_TEMP=1000
CT_OSD_DOWN=0
CT_HELP_MSG="""
  -h, --help        show this help message and exit
  -M MAX_REMAPPED, --CT_MAX_REMAPPED CT_MAX_REMAPPED            
                    Increasing PG_NUM waits until there is less 'MAX_REMAPPED' in progress to resume,
                          default: $CT_MAX_REMAPPED
  -d, --osd_down    Suspend operation when an OSD is down
  -w WAIT, --wait_for_nobackfill WAIT
                    Wait to start until the cluster has no more backfill
  -t MAX_TEMP, --max_temp MAX_TEMP
                    Suspend operation if serveur Temp (°) >= MAX_TEMP
  -S SCHEDULE, --schedule SCHEDULE
                    Schedule, eg : 21-07 for 21h to 07h or 08-16 for 8h to 16h
"""


CT_HELP_EXAMPLE="-M 100 -d -w -t 45 -S 21-07"

CT_HELP_DESCR="[-m|--CT_MAX_REMAPPED CT_MAX_REMAPPED] [-w|--wait_for_nobackfill WAIT] [-d|osd-down]"

ct_help_min () {
    if [ $1 -lt $2 ]
    then
        help_msg
        ct_on_exit 1
    fi
}

ct_help () {
    _shift=0
    ARGS=$#
    while [ $# -ge 1 ]; do
        _key="$1"
        case $_key in
            -h|--help)
                help_msg
                ct_on_exit 0
                shift 1
                ;;
            -M|--MAX_REMAPPED)
                CT_MAX_REMAPPED=$2
                ((_shift = _shift + 2))
                shift 2
                ;;
            -d|--osd_down)
                CT_OSD_DOWN=1
                ((_shift = _shift + 1))
                shift 1
                ;;
            -t|--max_temp)
                CT_MAX_TEMP=$2
                 ((_shift = _shift + 2))
                 shift 2
                 ;;
            -w|--wait_for_nobackfill)
                CT_WAIT=1
                ((_shift = _shift + 1))
                shift 1
                ;;
            -S|--schedule)
                CT_SCHEDULE=$2
                 ((_shift = _shift + 2))
                 shift 2
                 ;;
        esac
        if [ "$#" == "$ARGS" ]; then
            return $_shift
        fi
    done
    return $_shift
}

_ct_get_current_remapped() {
  # Get Current Remapped
  ceph -s -f json | jq '.["osdmap"]["osdmap"]["num_remapped_pgs"]'
}

_ct_test_osd_down() {
  if [ $CT_OSD_DOWN -eq 1 ]; then
    ceph osd tree down |grep "osd\."| awk '{print $1}'|sort -n -o /tmp/OSDs_Down_now
    if ! diff -q /tmp/OSDs_Down /tmp/OSDs_Down_now > /dev/null; then
      echo "OSDs down, operation paused"
      echo "For resume,"
      echo "You can reinit OSDs Down list by execute"
      echo "'ceph osd tree down |grep \"osd\\.\"| awk '{print \$1}'|sort -n -o /tmp/OSDs_Down'"
      while ! diff -q /tmp/OSDs_Down /tmp/OSDs_Down_now > /dev/null; do
        sleep 60
        ceph osd tree down |grep "osd\."| awk '{print $1}'|sort -n -o /tmp/OSDs_Down_now
      done
      echo "OSDs down OK"
    fi
  fi
  return 1
}

_ct_test_temp () {
  if [ -f '/sys/class/thermal/thermal_zone0/temp' ]; then
    _CT_TEMP=$(($(cat /sys/class/thermal/thermal_zone0/temp) / 1000))
    return [[ $_CT_TEMP -ge $CT_MAX_TEMP ]]
  fi
  return 1
}

_ct_test_schedule () {
  if [ ! -z $CT_PLANNING ]; then
    _CT_T=$(date "+%H")
    _CT_D=$(echo $CT_SCHEDULE | cut -d '-' -f 1)
    _CT_F=$(echo $CT_SCHEDULE | cut -d '-' -f 2)
    if [[ "$F" > "$D" ]]; then
            [[ ("$_CT_T" = "$_CT_D") || (("$_CT_T" > "$_CT_D") && ("$_CT_T" < "$_CT_F")) ]] && return 0 || return 1
    else
            [[ ("$_CT_T" = "$_CT_D") || (("$_CT_T" > "$_CT_D") || ("$_CT_T" < "$_CT_F")) ]] && return 0 || return 1
    fi
  fi
  return 1
}

_ct_sp="/-\|"
_ct_sc=0
_ct_progress() {
  # Display Progress Bar
  _ct_step=$((${2:-64} / 64))
  _ct_max=$2
  ((_ct_max = _ct_max - 1))
  _ct_current=$1
  printf '%.0s#' $(seq 0 $_ct_step $_ct_current)  
  printf "\b${_ct_sp:_ct_sc:1}"
  printf '%.0s_' $(seq $_ct_current $_ct_step $_ct_max)  
  ((_ct_sc = _ct_sc + 1))
  ((_ct_sc==${#_ct_sp})) && _ct_sc=0
}


ct_healthy_wait() {
# Wait for Remapped <= MAX_REMAPPED
  _ct_mr=$CT_MAX_REMAPPED
  if [ -z "$1" ]; then
    _ct_max=$((CT_MAX_REMAPPED * 2))
  elif [[ $1 -eq 0 ]]; then
    _ct_mr=0
  else
    _ct_max=$1
  fi
  while true; do
    _ct_cbf=$(_ct_get_current_remapped)
    if  [[ $_ct_cbf -gt $CT_MAX_REMAPPED ]]; then
      _ct_cu=$((CT_MAX_REMAPPED - (_ct_cbf - _ct_mr)))
      if [ $_ct_cu -lt 0 ]
      then
        _ct_cu=0
      fi
      echo -ne "\r[$(_ct_progress ${_ct_cu} ${_ct_max})] ==> Current remapped > Max remapped (${_ct_cbf}>${_ct_mr})      "
    elif _ct_test_osd_down; then
      echo -ne "\rOSD Down !"
    elif _ct_test_temp; then
      echo -ne "\rHigh temperature !"
    elif _ct_test_schedule; then
      echo -ne "\rHours outside Time planning !"
    else
      echo
      return 0
    fi
    sleep 10
  done
}

if [ ! -z $CT_WAIT ]
then
  ct_healthy_wait 0
fi
