#!/bin/bash

# Переменная для режима
zvirt_mode='None'
# Конфигурирование Keycloak
keycloak_configure='False'
# Дополнительные переменные
var_update_version=4.2
var_minimum_version=4.0
var_pg_update_version=16
# Лог
file_log="/var/log/zvirt-update-$(date +%Y%m%d%H%M).log"
# Имя метапакета
var_meta_package="None"

# Функция проверки успешности операций
function check_operation_result {
    local val=$?
    if [ $val -ne 0 ]; then
      echo "Ошибка!" >&2
      exit 1
    else
      echo "Операция успешно выполнена!" | tee -a $file_log
    fi
}

# Функция проверки сервиса
function is_service_exists() {
    local status is_active
    status=$(systemctl is-enabled "$1" 2>/dev/null)
    is_active=$(systemctl is-active "$1")
    if [[ -n $status ]] && [[ $status == "enabled" ]] && [[ $is_active == "active" ]]; then
        echo 1
    else
        echo 0
    fi
}

# Функция подтверждения действия
function is_confirm() {
    local no_val="$1"
    local yes_val="$2"
    select number in y n;
    do
      case $REPLY in
      "n")
          $no_val
          ;;
      "y")
          $yes_val 2>/dev/null
          break
          ;;
      esac
    done
}

# Проверка наличия мета-пакета в системе
function install_or_update() {
  local meta_package="$1"
  if [[ -z "$(rpm -qa | grep "$meta_package")" ]]; then
    dnf install -y "$meta_package" --allowerasing
  else
    dnf update -y "$meta_package" --allowerasing
  fi
}

# Индикатор операций
function spinner() {
    tput civis
    local info="В процессе ... "
    local pid=$!
    local delay=0.75
    local spinstr='|/-\'
    while kill -0 $pid 2> /dev/null; do
        local temp=${spinstr#?}
        printf "$info [%c] " "$spinstr"
        local spinstr=$temp${spinstr%"$temp"}
        sleep $delay
        local reset="\b\b\b\b\b\b"
        for ((i=1; i<=$(echo $info | wc -c); i++)); do
            reset+="\b"
        done
        printf $reset
    done
    printf "    \b\b\b\b"
    tput cnorm
}

# Текущая версия zVirt
version_zvirt=$(cat "/usr/share/ovirt-engine/setup/ovirt_engine_setup/config.py" | grep DISPLAY_ZVIRT_VERSION | awk '{print $NF}' | tr -d '\047')

if awk "BEGIN {exit !($version_zvirt < $var_minimum_version)}"; then
    echo "Версия zVirt $version_zvirt не может быть автоматически обновлена" | tee -a "$file_log"
    echo "Необходимо выполнить ручное обновление до минимально допустимой версии zVirt $var_minimum_version" | tee -a "$file_log"
    exit 1
else
    echo "Текущая версия zVirt: $version_zvirt" | tee -a "$file_log"
fi

var_vd=$(is_service_exists vdsmd.service)
var_en=$(is_service_exists ovirt-engine.service)

# Определение режима установки
if [[ $var_vd == 1 && $var_en == 1 ]]; then
    echo "Обновление Standalone" | tee -a "$file_log"
    echo "Убедитесь, что вы подключили новые репозитории $var_update_version и выключили/мигрировали все виртуальные машины"
    zvirt_mode='SA'
elif [[ $var_vd == 0 && $var_en == 1 ]]; then
    echo "Обновление Hosted Engine" | tee -a "$file_log"
    echo "Убедитесь, что вы подключили новые репозитории $var_update_version и перевели HE в режим глобального обслуживания"
    zvirt_mode='HE'
elif [[ $var_vd ==  1 && $var_en == 0 ]]; then
    echo "Обновление zVirt Node" | tee -a "$file_log"
    echo "Убедитесь, что вы подключили новые репозитории $var_update_version и выключили/мигрировали все виртуальные машины"
    zvirt_mode='Node'
else
    echo "Не удалось определить режим установки, выполните обновление вручную по соответствующей инструкции" | tee -a "$file_log"
    exit 1
fi

is_confirm exit

if  [[ -z "$(dnf repoquery zvirt-repos-stable-4.2.0 2>&1 | grep zvirt-repos-stable)" ]]; then
    echo "Новые репозитории zVirt версии $var_update_version отсутствуют" | tee -a "$file_log"
    echo "Проверьте подключение новых репозиториев и повторите попытку" | tee -a "$file_log"
    exit 1
fi

if [[ $zvirt_mode == 'SA'  || $zvirt_mode == 'Node' ]]; then
  vm_list=$(virsh -c qemu:///system?authfile=/etc/ovirt-hosted-engine/virsh_auth.conf list --name)
  if [[ -n "$vm_list" ]]; then
    echo "Невозможно продолжить обновление режима $zvirt_mode" | tee -a "$file_log"
    echo "Обнаружены активные виртуальные машины: " | tee -a "$file_log"
    echo "$vm_list" | tee -a "$file_log"
    exit 1
  fi
fi

pg_version=$(psql -V | awk '{print $NF}' | cut -d "." -f 1)

if [[ $zvirt_mode == 'SA' || $zvirt_mode == 'HE' ]] && [[ ! -f /var/lib/pgsql/pgdump_file.sql ]] && [[ $pg_version -lt $var_pg_update_version ]]; then
    echo "Создание dump ovirt-engine" | tee -a "$file_log"
    (su - postgres -c "pg_dumpall > ~/pgdump_file.sql") & spinner
    systemctl stop postgresql.service
    mv /var/lib/pgsql/data /var/lib/pgsql/data_old
    check_operation_result
fi

dnf versionlock clear >> "$file_log" 2>&1
dnf clean all >> "$file_log" 2>&1
rm -rf /etc/dnf/modules.d/* >> "$file_log" 2>&1

if [[ $zvirt_mode == 'SA' || $zvirt_mode == 'Node' ]]; then
    rm -rf /etc/dnf/protected.d/*-release-host-node.conf >> "$file_log" 2>&1
fi

if [[ $zvirt_mode == 'SA' ]]; then
    echo "Обновление режима SA" | tee -a "$file_log"
    var_meta_package="zvirt-standalone"
    (install_or_update zvirt-standalone >> "$file_log" 2>&1) & spinner
    dnf downgrade -y python3-blivet >> "$file_log" 2>&1
elif [[ $zvirt_mode == 'HE' ]]; then
    echo "Обновление режима HE" | tee -a "$file_log"
    var_meta_package="zvirt-appliance"
    (install_or_update zvirt-appliance >> "$file_log" 2>&1) & spinner
elif [[ $zvirt_mode == 'Node' ]]; then
    echo "Обновление режима Node" | tee -a "$file_log"
    var_meta_package="zvirt-hosted-engine"
    (install_or_update zvirt-hosted-engine >> "$file_log" 2>&1) & spinner
    dnf downgrade -y python3-blivet >> "$file_log" 2>&1
fi

[[ $(dnf check-update $var_meta_package -q 2>&1 | grep -c ^[a-z0-9]) -gt 0 ]] && { echo "Ошибка! Проверьте журнал обновления $file_log" ; exit 1; }
echo "Операция успешно выполнена!" | tee -a $file_log

echo "Обновление системных пакетов" | tee -a "$file_log"
(dnf update -y --allowerasing >> "$file_log" 2>&1) & spinner
dnf install -y rsyslog-gnutls >> "$file_log" 2>&1

[[ $(dnf check-update -q 2>&1 | grep -c ^[a-z0-9]) -gt 0 ]] && { echo "Ошибка! Проверьте журнал обновления $file_log" ; exit 1; }
echo "Операция успешно выполнена!" | tee -a $file_log

if [[ $zvirt_mode == 'SA'  || $zvirt_mode == 'HE' ]] && [[ -z "$(ls -A /var/lib/pgsql/data)" ]]; then
    echo "Инициализация базы данных" | tee -a "$file_log"
    (postgresql-setup --initdb >> "$file_log" 2>&1) & spinner
    check_operation_result
    cp /var/lib/pgsql/data_old/pg_hba.conf /var/lib/pgsql/data/
    cp /var/lib/pgsql/data_old/pg_ident.conf /var/lib/pgsql/data/
    cp /var/lib/pgsql/data_old/postgresql.conf /var/lib/pgsql/data/
    systemctl start postgresql.service
    echo "Восстановление ovirt-engine из dump" | tee -a "$file_log"
    (su - postgres -c 'psql -f ~/pgdump_file.sql postgres' >> "$file_log" 2>&1) & spinner
    check_operation_result
fi

if [[ $zvirt_mode == 'SA'  || $zvirt_mode == 'HE' ]]; then
    if [[ $(cat /etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf | grep keycloakEnable | cut -d ":" -f2) == 'False' ]]; then
      echo "Сконфигурировать Keycloak?" | tee -a "$file_log"
      is_confirm break "sed -i s/keycloakEnable=bool:False/keycloakEnable=bool:True/g /etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf"
      keycloak_configure=$(cat /etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf | grep keycloakEnable | cut -d ":" -f2)
      echo "Ответ: $keycloak_configure" | tee -a "$file_log"
    fi

    echo "Обновление конфигурации ovirt-engine" | tee -a "$file_log"
    engine-setup --offline --otopi-environment="OVESETUP_SYSTEM/memCheckEnabled=bool:False"
    check_operation_result
fi

echo "Перезапуск сервисов" | tee -a "$file_log"
if [[ $zvirt_mode == 'SA' ]]; then
    (systemctl restart ovirt-engine.service ovirt-provider-ovn zvirt-engine-backend vdsmd.service >> "$file_log" 2>&1) & spinner
elif [[ $zvirt_mode == 'HE' ]]; then
    (systemctl restart ovirt-engine.service ovirt-provider-ovn zvirt-engine-backend >> "$file_log" 2>&1) & spinner
elif [[ $zvirt_mode == 'Node' ]]; then
    (systemctl restart vdsmd.service >> "$file_log" 2>&1) & spinner
else
    echo "Обновление выполнено! Выполните перезапуск сервисов вручную" | tee -a "$file_log"
    exit 1
fi

echo "Обновление выполнено!" | tee -a "$file_log"