#!/bin/bash

#######
## Description: Plugin checks the available disk space, it sets and removes downtimes for icinga checks, depending on free disk space on the server.
## Author: Sebastian Klee
## E-Mail: s.klee@timmehosting.de
## Version: 1.4
## Date: 14.10.2025
#######

## Variables
# Determination of the available Disk Space.
free_space=$(df -m | grep -e '/$' | awk '{print $4}')

# Start and end time of the downtimes, when set.
start_time_downtime=$(date +%s -d "+0 hour")
end_time_downtime=$(date +%s -d "+10 hour")

# Condition for the first if query, the variable gets it's value from our monitoring.
condition_free_space=$1

# Destintation for the API requests(should be the first master of the monitoring), the variable gets it's value from our monitoring.
monitoring_master=$2

# Server for the API requests: For which server do we need to set, check or remove downtimes.
hostname_server=$3
##

# IF query to check if the server's free disk space falls below a certain value.
if [[ $free_space -lt $condition_free_space ]]; then

  # We need this empty file for a later check to decide if certain API Requests are necessary
  touch /usr/local/lib/nagios/plugins/disk_full.txt

  # API request to check if there are downtimes from author `Speicherplatz`, if that is the case, write the Date of the downtime end in the variable `downtime_actual_end`.
  downtime_actual_end=$(curl -k -s --netrc-file /etc/icinga2/scripts/api_u/downtime.cnf -H 'Accept: application/json' -X GET https://"${monitoring_master}":5665/v1/objects/downtimes -d   '{ "type": "Downtime", "filter": "host.name==\"'"$hostname_server"'\" && downtime.author==\"Speicherplatz\"", "attrs" : ["end_time"], "pretty": true}' | awk '$1 ~ "end_time" {print$2}' | tail -1)
  # Determine the Difference between the actual date and the date of the downtime end.
  rest_downtime=$((downtime_actual_end-start_time_downtime))
  # Determine the Size of the variable `downtime_actual_end`. The Variable `size` gets the value 0, if the previous API request couldn't find any Downtime form author `Speicherplatz`.
  size=${#downtime_actual_end}

  # This IF-Statement is true, if the value of variable `size` is 0(the previous API request didn't find any downtimes from the author `Speicherplatz`).
  # The IF-Statement is also true, if the previous API Request found a Downtime from the author `speicherplatz` with less than 600 seconds remaining time.
  if [[ $size = "0" ]] || [[ $rest_downtime -lt 600 ]]; then
    # API request to set downtimes.
    curl -k -s --netrc-file /etc/icinga2/scripts/api_u/downtime.cnf -H 'Accept: application/json' -X POST https://"${monitoring_master}":5665/v1/actions/schedule-downtime -d \
    '{ "type": "Service", "filter": "host.name==\"'"$hostname_server"'\"", "author": "Speicherplatz", "start_time": '"$start_time_downtime"', "end_time": '"$end_time_downtime"', "comment": "Datentraeger voll, '"$free_space"' MB Frei", "pretty": true }' > /dev/null 2>&1

    # For security reasons the script stops the database aerver through this block , to avoid a crash and corruption of the database, if not enough space is left. 
    service_bin="/usr/bin/systemctl"
    if [[ -f $service_bin ]]; then
      /usr/bin/systemctl stop mysql.service > /dev/null 2>&1
    else
      /usr/bin/monit unmonitor mysql
      /etc/init.d/mysql stop > /dev/null 2>&1
    fi
  fi
  # Output of the check together with the status code 2 (critical).
  echo "Critical: Disk space full/almost full, downtimes for the services are active, Database Server stopped to avoid database corruption, ${free_space} MB free"
  exit 2

# Downtimes that were set up by this script are removed in this else block, if they exist.
else

  disk_full="/usr/local/lib/nagios/plugins/disk_full.txt"
  # If the file in the variable disk_full exists, which is only the case if the disk was nearly full, go to the if block to look for downtimes to removed. 
  if [[ -f $disk_full ]]; then
    # The file in the variable disk_full must be removed with the downtimes the script had set up.
    rm $disk_full
    # API request to check if there are downtimes from author `Speicherplatz` for the checked Server, if that is the case the Variable `status` gets the value `0`, if not it gets the value `1`.
    curl -k -s --netrc-file /etc/icinga2/scripts/api_u/downtime.cnf -H 'Accept: application/json' -X GET https://"${monitoring_master}":5665/v1/objects/downtimes -d \
    '{ "type": "Downtime", "filter": "host.name==\"'"$hostname_server"'\" && downtime.author==\"Speicherplatz\"", "attrs" : ["author"], "pretty": true}' | grep 'author' > /dev/null 2>&1

    status=$?
    service_bin="/usr/bin/systemctl"
    # This IF checks the value of the variable `status`, if the previous API request did find any downtimes, the condition of the if is true.
    if [[ $status = "0" ]]; then
      # API request to remove downtimes.
      curl -k -s --netrc-file /etc/icinga2/scripts/api_u/downtime.cnf -H 'Accept: application/json' -X POST https://"${monitoring_master}":5665/v1/actions/remove-downtime -d \
      '{ "type": "Downtime", "filter": "host.name==\"'"$hostname_server"'\" && downtime.author==\"Speicherplatz\"", "pretty": true }' > /dev/null 2>&1

      # This Block starts the Database Server, if enough space is left.
      if [[ -f $service_bin ]]; then
        /usr/bin/systemctl start mysql.service > /dev/null 2>&1
        /usr/bin/systemctl restart prometheus.service > /dev/null 2>&1
      else
        /etc/init.d/mysql start > /dev/null 2>&1
        /usr/bin/monit monitor mysql
      fi
    # Check the status of the database server, in the case that the downtimes were not removed by this script, rather through other means.
    else
      if [[ -f $service_bin ]]; then
        /usr/bin/systemctl status mysql.service > /dev/null 2>&1
        status_mysql=$?
        if [[ $status_mysql -gt 0 ]]; then
          /usr/bin/systemctl start mysql.service > /dev/null 2>&1
          /usr/bin/systemctl restart prometheus.service > /dev/null 2>&1
        fi
      else
        /etc/init.d/mysql status > /dev/null 2>&1
        status_mysql=$?
        if [[ $status_mysql -gt 0 ]]; then
          /etc/init.d/mysql start > /dev/null 2>&1
          /usr/bin/monit monitor mysql
        fi
      fi
    fi
  fi

  # Output of the check together with the status code 0 (ok).
  echo "OK: Disk Space is not fully used yet, ${free_space} MB free"
  exit 0

fi
