#!/usr/bin/env bash
# vim:foldmarker={,}
# vim:foldmethod=marker
# vim: ts=4 sw=4 et

# set -o errexit
# set -o nounset
# set -o pipefail
if [[ -n "${TRACE-}" ]]; then
    set -o xtrace
fi

#
# ClusterControl is a management and monitoring application for your database infrastructure.
# The installation script installs the frontend, backend and a LAMP stack.
#

ask() {
    if [[ ! -z $PROMPT_USER ]]; then
        read -p "$1" x
        [[ -z "$x" ]] || [[ "$x" == ["$2${2^^}"] ]] && return 0

        return 1
    else
        # always return true when prompt user is off
        return 0
    fi
}

ask_p() {
    [[ ! -z $S9S_CMON_PASSWORD ]] && return 0
    read -p "$1" x
    [[ -z "$x" ]] || [[ "$x" == ["$2${2^^}"] ]] && return 0

    return 1
}

confirm() {
    read -p "$1" x
    [[ -z "$x" ]] || [[ "$x" == ["$2${2^^}"] ]] && return 0

    return 1
}

ask_generic_distro() {
    PS3="Please select a generic distribution or exit the installation: "
    options=("redhat" "suse" "debian" "exit")
    select opt in "${options[@]}"
    do
        case $opt in
            "redhat")
                dist="redhat"
                break
                ;;
            "suse")
                    dist="suse"
                    break
                    ;;
            "debian")
                dist="debian"
                break
                ;;
            "exit")
                exit 1
                ;;
            *) echo invalid option;;
        esac
    done
}

do_lsb() {
    os_codename=$(lsb_release -sc)
    os_release=$(lsb_release -rs)
    if [[ -f /etc/centos-release || -f /etc/redhat-release ]]; then
        $(echo $os_release | grep -q "7.")
        [[ $? -eq 0 ]] && rhel_version=7
        $(echo $os_release | grep -q "8.*")
        [[ $? -eq 0 ]] && rhel_version=8
        $(echo $os_release | grep -q "9.*")
        [[ $? -eq 0 ]] && rhel_version=9

        [[ -f /etc/centos-release ]] && CENTOS=1
        [[ -f /etc/oracle-release ]] && ORACLE=1 && yum install -y oraclelinux-release-el${rhel_version}
    fi

    lsb=$(lsb_release -d)
    [[ $lsb =~ $regex_lsb ]] && dist=${BASH_REMATCH[1]} ; return 0
    return 1
}

do_release_file() {
    etc_files=$(ls /etc/*[-_]{release,version} 2>/dev/null)
    for file in $etc_files; do
        # /etc/SuSE-release is deprecated and will be removed in the future, use /etc/os-release instead
        if [[ $file == "/etc/os-release" ]]; then
            if grep SLE $file >/dev/null 2>/dev/null; then
                detect_suse_version
                break
            elif grep opensuse $file >/dev/null 2>/dev/null; then
                detect_suse_version
                break
            fi
        fi
        if [[ $file =~ $regex_etc ]]; then
            dist=${BASH_REMATCH[1]}
            # tolower. bash subs only in bash 4.x
            #dist=${dist,,}
            dist=$(echo $dist | tr '[:upper:]' '[:lower:]')
            if [[ $dist == "redhat" || $dist == "red" || $dist == "fedora" ]]; then
                $(grep -q " 7." $file)
                [[ $? -eq 0 ]] && rhel_version=7 && break
                $(grep -q " 8.*" $file)
                [[ $? -eq 0 ]] && rhel_version=8 && break
                $(grep -q " 9.*" $file)
                [[ $? -eq 0 ]] && rhel_version=9 && break
                break
            else
                # AlmaLinux/RockyLinux.. etc other RedHat compatible ones
                $(grep -q "platform:el7" $file)
                [[ $? -eq 0 ]] && dist="redhat" && rhel_version=7 && break
                $(grep -q "platform:el8" $file)
                [[ $? -eq 0 ]] && dist="redhat" && rhel_version=8 && break
                $(grep -q "platform:el9*" $file)
                [[ $? -eq 0 ]] && dist="redhat" && rhel_version=9 && break
            fi
        fi
    done
    [[ -f /etc/centos-release ]] && CENTOS=1
    [[ -f /etc/oracle-release ]] && ORACLE=1 && yum install -y oraclelinux-release-el${rhel_version}
}

detect_suse_version() {
    dist="suse"
    # we only build for 15.3, 15.4 and tumbleweed for now
    distversion="15.3" # as a fallback
    if grep '15\.4' /etc/os-release >/dev/null 2>/dev/null; then
        distversion="15.4"
    elif grep tumbleweed /etc/os-release >/dev/null 2>/dev/null; then
        distversion="tumbleweed"
    fi
}

add_s9s_apt () {
    repo="deb [arch=amd64] ${repo_http_protocol}://repo.severalnines.com/deb ubuntu main"
    repo_source_file=/etc/apt/sources.list.d/s9s-repo.list
    if [[ ! -e $repo_source_file ]]; then
        wget ${repo_http_protocol}://repo.severalnines.com/severalnines-repos.asc -O- | apt-key add - && echo "$repo" | tee -a $repo_source_file
        log_msg "Added ${repo_source_file}"
        log_msg "Updating repo ..."
        waitForLocks
        apt-get update
    else
        log_msg "Repo file $repo_source_file already exists"
        waitForLocks
        apt-get update
    fi
}

start_cmon_services() {
    if [[ $systemd == 1 ]]; then
        pidof -s cmon-events &>/dev/null || systemctl start cmon-events
        systemctl enable cmon-events
        pidof -s cmon-ssh &>/dev/null || systemctl start cmon-ssh
        systemctl enable cmon-ssh
        pidof -s cmon-cloud &>/dev/null || systemctl start cmon-cloud
        systemctl enable cmon-cloud
    else
        pidof -s cmon-events &>/dev/null || service cmon-events start
        pidof -s cmon-ssh &>/dev/null || service cmon-ssh start
        pidof -s cmon-cloud &>/dev/null || service cmon-cloud start

        if [[ "$dist" == "debian" ]]; then
            update-rc.d cmon-events defaults
            update-rc.d cmon-ssh defaults
            update-rc.d cmon-cloud defaults
        else
            chkconfig --levels 235 cmon-ssh on
            chkconfig --levels 235 cmon-events on
            chkconfig --levels 235 cmon-cloud on
        fi
    fi
}

add_s9s_commandline_apt() {
    # Available distros: wheezy, jessie, precise, trusty, xenial, yakkety, zesty
    repo_source_file=/etc/apt/sources.list.d/s9s-tools.list
    if [[ ! -e $repo_source_file ]]; then
        wget -qO - ${repo_http_protocol}://repo.severalnines.com/s9s-tools/${os_codename}/Release.key | apt-key add -
        echo "deb ${repo_http_protocol}://repo.severalnines.com/s9s-tools/${os_codename}/ ./" | tee /etc/apt/sources.list.d/s9s-tools.list
    else
        log_msg "Repo file $repo_source_file already exists"
    fi
}

add_s9s_yum () {
    repo_source_file=/etc/yum.repos.d/s9s-repo.repo
    if [[ ! -e $repo_source_file ]]; then
        cat > $repo_source_file << EOF
[s9s-repo]
name=Severalnines Repository
baseurl = ${repo_http_protocol}://repo.severalnines.com/rpm/os/x86_64
enabled = 1
gpgkey = ${repo_http_protocol}://repo.severalnines.com/severalnines-repos.asc
gpgcheck = 1
EOF
    log_msg "Added ${repo_source_file}"
    else
        log_msg "Repo file $repo_source_file already exists"
    fi
}

add_s9s_commandline_yum() {
    repo_source_file=/etc/yum.repos.d/s9s-tools.repo
    if [[ ! -e $repo_source_file ]]; then
        if [[ -z $CENTOS ]]; then
            REPO="RHEL_7"
            [[ $rhel_version == "8" ]] && REPO="RHEL_8"
            [[ $rhel_version == "9" ]] && REPO="RHEL_9"
        else
            REPO="CentOS_7"
            [[ $rhel_version == "8" ]] && REPO="CentOS_8"
            [[ $rhel_version == "9" ]] && REPO="CentOS_9"
        fi
        cat > $repo_source_file << EOF
[s9s-tools]
name=s9s-tools (${REPO})
type=rpm-md
baseurl=${repo_http_protocol}://repo.severalnines.com/s9s-tools/${REPO}
gpgcheck=1
gpgkey=${repo_http_protocol}://repo.severalnines.com/s9s-tools/${REPO}/repodata/repomd.xml.key
enabled=1
EOF
    log_msg "Added ${repo_source_file}"
    else
        log_msg "Repo file $repo_source_file already exists"
    fi
}

add_s9s_zypper () {
    repo_source_file=/etc/zypp/repos.d/s9s-repo.repo
    if [[ ! -e $repo_source_file ]]; then
        # make sure curl or wget is available
        command -v curl || zypper -n install --no-confirm curl || command -v wget || zypper -n install --no-confirm wget
        if command -v curl; then
            curl "http://repo.severalnines.com/severalnines-repos.asc" -o/tmp/s9s.asc
            rpm --import /tmp/s9s.asc
        elif command -v wget; then
            wget "http://repo.severalnines.com/severalnines-repos.asc" -O/tmp/s9s.asc
            rpm --import /tmp/s9s.asc
        else
            rpm --import "http://repo.severalnines.com/severalnines-repos.asc"
        fi

        cat > $repo_source_file << EOF
[s9s-repo]
name=Severalnines Repository
baseurl = ${repo_http_protocol}://repo.severalnines.com/rpm/os/x86_64
enabled = 1
gpgkey = ${repo_http_protocol}://repo.severalnines.com/severalnines-repos.asc
gpgcheck = 1
EOF

        zypper refresh
        log_msg "Added ${repo_source_file}"
    else
        log_msg "Repo file $repo_source_file already exists"
    fi
}

add_s9s_commandline_zypper() {
    repo_source_file=/etc/zypp/repos.d/s9s-tools.repo
    if [[ ! -e $repo_source_file ]]; then
        # make sure curl or wget is available
        command -v curl || zypper -n install --no-confirm curl || command -v wget || zypper -n install --no-confirm wget
        if command -v curl; then
            curl "http://repo.severalnines.com/s9s-tools/${distversion}/repodata/repomd.xml.key" -o/tmp/s9s-tools.asc
            rpm --import /tmp/s9s-tools.asc
        elif command -v wget; then
            wget "http://repo.severalnines.com/s9s-tools/${distversion}/repodata/repomd.xml.key" -O/tmp/s9s-tools.asc
            rpm --import /tmp/s9s-tools.asc
        else
            rpm --import "http://repo.severalnines.com/s9s-tools/${distversion}/repodata/repomd.xml.key"
        fi

        cat > $repo_source_file << EOF
[s9s-tools]
name=s9s-tools (Suse ${distversion})
type=rpm-md
baseurl=http://repo.severalnines.com/s9s-tools/${distversion}
gpgcheck=1
gpgkey=http://repo.severalnines.com/s9s-tools/${distversion}/repodata/repomd.xml.key
enabled=1
EOF
        zypper refresh
        log_msg "Added ${repo_source_file}"
    else
        log_msg "Repo file $repo_source_file already exists"
    fi
}

add_mysql_zypper () {
    wget https://dev.mysql.com/get/mysql80-community-release-sl${distversion}.noarch.rpm -o/tmp/mysql80-community-release-sl${distversion}.noarch.rpm

    sudo zypper install -n /tmp/mysql80-community-release-sl${distversion}.noarch.rpm
    zypper ref
    log_msg "Added MySQL repo"
}

find_mysql() {
    mysql_bin="/usr/bin/mysql"
    if ! command -v mysql &>/dev/null; then
        log_msg "Cannot find a mysql client in your PATH!"
        log_msg "Provide the full path to your mysql client, for example /opt/mysql/bin/mysql"
        read -p "=> Absolute path to the MySQL client: " x
        [[ ! -z $x ]] && mysql_bin="$x"
        [[ ! -f $mysql_bin ]] && { log_msg "Cannot find ${mysql_bin}. ..."; exit 1; }
    fi
}

install_frontend() {
    clustercontrol_build=${CLUSTERCONTROL_BUILD:-"clustercontrol"}
    if [[ ${cc_version} == "1" ]]; then
        clustercontrol_build="${clustercontrol_build} clustercontrol2"
    elif [[ ${cc_version} == "2" ]]; then
        clustercontrol_build=${CLUSTERCONTROL_BUILD:-"clustercontrol2"}
    fi
    log_msg "Installing the ClusterControl package ..."
    if [[ $dist == "debian" ]]; then
        waitForLocks
        if [[ -z ${OFFLINE+x} ]]; then
            add_s9s_commandline_apt
            add_s9s_apt
        fi
        waitForLocks
        LC_ALL=en_US.utf8 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true  apt-get -yq install ${clustercontrol_build} || { log_msg "Failed to install clustercontrol packages. (apt-get -yq install ${clustercontrol_build})"; exit 1; }
    elif [[ $dist == "redhat" ]]; then
        if [[ -z ${OFFLINE+x} ]]; then
            add_s9s_commandline_yum
            add_s9s_yum
        fi
        yum -yq install ${clustercontrol_build} || { log_msg "Failed to install clustercontrol packages. (yum -yq install ${clustercontrol_build})"; exit 1; }
    elif [[ $dist == "suse" ]]; then
        if [[ -z ${OFFLINE+x} ]]; then
            add_s9s_commandline_zypper
            add_s9s_zypper
            # add_mysql_zypper
        fi
        zypper install -n --no-confirm ${clustercontrol_build} || { log_msg "Failed to install clustercontrol packages. (zypper -y install ${clustercontrol_build})"; exit 1; }
    fi

    if [[ ${cc_version} != "0" ]]; then
        # change registration form
        [[ -f /var/www/html/clustercontrol2/config.js ]] && sed -i "s|^[ \t]*USER_REGISTRATION:.*|  USER_REGISTRATION: 0,|g" /var/www/html/clustercontrol2/config.js
        # check edition
        local cc_edition="${CC_EDITION:-##__CC_EDITION__##}"
        if [[ "${cc_edition}" == "1" ]]; then
            [[ -f /var/www/html/clustercontrol2/config.js ]] && sed -i "/^[ \t]*USER_REGISTRATION:.*/a\  COMMUNITY_EDITION: 1," /var/www/html/clustercontrol2/config.js
        fi
    fi
}

install_ui_packages_debian() {
    apache_conf=/etc/apache2/sites-available/default
    apache_conf_ssl=/etc/apache2/sites-available/default-ssl
    www_user=www-data
    install_packages="apt-get -y install mysql-server mysql-client apache2 php-mysql php-gd libapache2-mod-php php-curl php-ldap php-xml wget"
    [[ -n $use_existing_mysql ]] && install_packages="apt-get -y install apache2 php-mysql php-gd libapache2-mod-php php-curl php-ldap php-xml wget"
    enable_mods="ssl rewrite headers"
    cert_file="/etc/ssl/certs/s9server.crt"
    key_file="/etc/ssl/private/s9server.key"
    restart_apache="service apache2 restart"
    stop_mysql="service mysql stop"
    start_mysql="service mysql start"
    update_repo="apt-get update"
    mysql_basedir=/usr
    mysql_datadir=/var/lib/mysql
    my_cnf=/etc/mysql/my.cnf
    mysql_socket="/var/run/mysqld/mysqld.sock"

    if [[ -z ${OFFLINE+x} ]]; then
        if ask "=> Do $update_repo? (Y/n): " "y"; then
            $update_repo
        fi
    fi

    case "${os_codename}" in
        'jammy'|'noble')
            setup_php7_debian
            install_packages="apt-get -y install mysql-server mysql-client apache2 php7.4-mysql php7.4-gd libapache2-mod-php7.4 php7.4-curl php7.4-ldap php7.4-xml wget"
            [[ -n $use_existing_mysql ]] && install_packages="apt-get -y install apache2 php7.4-mysql php7.4-gd libapache2-mod-php7.4 php7.4-curl php7.4-ldap php7.4-xml wget"
            ;;
        'buster')
            install_packages="`echo $install_packages | sed 's/mysql-/default-mysql-/g'`"
            ;;
        'bullseye'|'bookworm')
            install_packages="`echo $install_packages | sed 's/mysql-/mariadb-/g'`"
            ;;
    esac

    if [[ -n $install_packages ]]; then
        waitForLocks
        LC_ALL=en_US.utf8 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true $install_packages
        [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
    fi

    if [[ ! -z $use_apache24 ]]; then
        # default web root for clustercontrol is /var/www. apache 2.2 legacy
        if [[ -d /var/www/html ]] && [[ -d /var/www/clustercontrol ]]; then
            ln -sfn /var/www/clustercontrol /var/www/html
        fi
        apache_sites_available_dir="/etc/apache2/sites-available"
        apache_sites_enabled_dir="/etc/apache2/sites-enabled"
        apache_conf="${apache_sites_available_dir}/s9s.conf"
        apache_conf_ssl="${apache_sites_available_dir}/s9s-ssl.conf"
        apache_conf_orig="000-default.conf"
        apache_conf_ssl_orig="default-ssl.conf"

        if [[ -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ]]; then
            servername="${S9S_WEB_SERVER_HOST:-localhost}"
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s.conf
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf
            cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ${apache_sites_available_dir}/
            cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf ${apache_sites_available_dir}/
        else
            # create our configs
            create_apache24_configs
        fi

        rm -f $apache_sites_enabled_dir/$apache_conf_orig
        # just in case
        rm -f $apache_sites_enabled_dir/$apache_conf_ssl_orig
        rm -f $apache_sites_enabled_dir/001-$apache_conf_ssl_orig

        ln -sfn $apache_conf $apache_sites_enabled_dir/001-s9s.conf
        ln -sfn $apache_conf_ssl $apache_sites_enabled_dir/001-s9s-ssl.conf

        # enable sameorigin header
        if [[ -f /etc/apache2/conf-available/security.conf ]]; then
            # enable for header
            sed -ibak "s|^#Header set X-Frame-Options: \"sameorigin\"|Header set X-Frame-Options: \"sameorigin\"|g" /etc/apache2/conf-available/security.conf
            ln -sfn /etc/apache2/conf-available/security.conf /etc/apache2/conf-enabled/security.conf
            a2enmod headers &>/dev/null || log_msg "Failed to enable apache headers module!"
        fi
    fi
}

setup_php7_debian() {
    if [[ -z ${OFFLINE+x} ]]; then
        log_msg "NOTE: PHP 8 is currently not supported!"
        log_msg "NOTE: On this operating system we need to downgrade to PHP 7..."
        sleep 3
        log_msg "Setting up PHP 7 ..."
        apt update -y
        apt install -y software-properties-common apt-transport-https
        add-apt-repository -y ppa:ondrej/php
        apt update
        log_msg "Using PHP 7 repository ..."
    fi
}

setup_php7_redhat() {
    yum install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
    yum module reset php
    yum module enable php:remi-7.4 -y
}

install_ui_packages_redhat() {
    apache_conf=/etc/httpd/conf/httpd.conf
    apache_conf_ssl=/etc/httpd/conf.d/ssl.conf
    www_user=apache
    install_apache="yum -y install httpd"
    install_packages="yum -y install mysql-server mysql php php-mysql php-gd mod_ssl php-curl php-ldap php-xml wget"
    enable_mods=""
    cert_file="/etc/pki/tls/certs/s9server.crt"
    key_file="/etc/pki/tls/private/s9server.key"
    restart_apache="service httpd restart"
    update_repo="yum update"
    mysql_basedir=/usr
    mysql_datadir=/var/lib/mysql
    my_cnf=/etc/my.cnf
    mysql_socket="/var/run/mysqld/mysqld.sock"
    stop_mysql=""
    start_mysql="service mysqld start"
    chkconfig="chkconfig --levels 235 mysqld on"
    chkconfig_apache="chkconfig --levels 235 httpd on"
    mysql_socket="/var/lib/mysql/mysql.sock"

    if [[ ! -z $rhel_version ]]; then
        case "$rhel_version" in
            7)
                install_packages="yum -y install mariadb-server php php-mysql php-gd mod_ssl php-curl php-ldap php-xml wget"
                [[ -n $use_existing_mysql ]] && install_packages="yum -y install php php-mysql php-gd mod_ssl php-curl php-ldap php-xml wget"
                ;;
            8|9)
                [[ ${rhel_version} == "9" ]] && setup_php7_redhat
                install_packages="yum -y install mariadb-server php php-mysqlnd php-gd mod_ssl php-curl php-ldap php-xml php-json wget"
                [[ -n $use_existing_mysql ]] && install_packages="yum -y install php php-mysqlnd php-gd mod_ssl php-curl php-ldap php-xml php-json wget"
                if [[ ! -z ${ORACLE+x} ]]; then
                    install_packages="${install_packages} php-fpm"
                    restart_apache="systemctl restart httpd && systemctl restart php-fpm"
                fi
                ;;
            *)
                log_msg "Unknown/Unsupported Centos/Red Hat version $rhel_version"
                exit 1
                ;;
        esac
    fi

    if [[ -z ${OFFLINE+x} ]]; then
        if ! ask "=> Do $update_repo? (y/N): " "n"; then
            $update_repo
        fi
    fi

    if [[ -n $install_packages ]]; then
        $install_apache &>/dev/null
        $install_packages
        [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
    fi

    if [[ ! -z $rhel_version ]]; then
        case "$rhel_version" in
            7|8|9)
                yum list installed | grep -q mariadb-server
                if [[ $? -eq 0 ]]; then
                    start_mysql="service mariadb start"
                    chkconfig="chkconfig --levels 235 mariadb on"
                fi
                ;;
        esac
    fi
    # workaround for mysql 8, not safe
    $(yum list installed | grep mysql | grep -q mysql80)
    if [[ $? -eq 0 ]]; then
        mysqld8="mysqld --initialize-insecure --user=mysql --basedir=/usr --datadir=/var/lib/mysql"
    fi
    $chkconfig_apache

    apache_version=$(apachectl -v | grep -i "server version" | cut -d' ' -f3)
    [[ "${apache_version%.*}" == "Apache/2.4"  ]] && use_apache24=1

    if [[ ! -z $use_apache24 ]]; then
        # default web root for clustercontrol is /var/www. apache 2.2 legacy
        if [[ -d /var/www/html ]] && [[ -d /var/www/clustercontrol ]]; then
            ln -sfn /var/www/clustercontrol /var/www/html
        fi
        apache_sites_enabled_dir="/etc/httpd/conf.d"
        apache_conf="${apache_sites_enabled_dir}/s9s.conf"
        apache_conf_ssl="${apache_sites_enabled_dir}/ssl.conf"
        apache_conf_orig="default.conf"
        apache_conf_ssl_orig="ssl.conf"

        rm -f $apache_sites_enabled_dir/$apache_conf_orig
        # just in case
        rm -f $apache_sites_enabled_dir/$apache_conf_ssl_orig
        rm -f $apache_sites_enabled_dir/001-$apache_conf_ssl_orig
        if [[ -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ]]; then
            servername="${S9S_WEB_SERVER_HOST:-localhost}"
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s.conf
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf
        fi
        cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ${apache_sites_enabled_dir}/
        cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf ${apache_sites_enabled_dir}/${apache_conf_ssl_orig}

        if [[ -d /var/lib/php ]]; then
            [[ ! -d /var/lib/php/session ]] && mkdir -p /var/lib/php/session && chmod og=+wxt /var/lib/php/session
        fi
        grep -q "Listen 443" /etc/httpd/conf/httpd.conf
        [[ $? -eq 1 ]] && sed -i '1s/^/Listen 443\n/' /etc/httpd/conf/httpd.conf &>/dev/null
        grep -q "ServerName 127.0.0.1" /etc/httpd/conf/httpd.conf
        [[ $? -eq 1 ]] && sed -i '1s/^/ServerName 127.0.0.1\n/' /etc/httpd/conf/httpd.conf &>/dev/null

        # enable sameorigin header
        if [[ ! -f /etc/httpd/conf.d/security.conf ]]; then
            # enable for header
            cat > /etc/httpd/conf.d/security.conf << EOF
Header set X-Frame-Options: "sameorigin"
EOF
        fi

        service httpd restart
    fi
}

install_ui_packages_suse() {
    apache_conf=/etc/apache2/httpd.conf
    apache_conf_ssl=/etc/apache2/ssl.conf
    www_user=wwwrun
    install_packages="zypper install -n --no-confirm mariadb apache2 php7 php7-mysql apache2-mod_php7 php7-gd php7-curl php7-ldap php7-xmlreader php7-ctype php7-json wget insserv-compat sysvinit-tools ca-certificates"
    restart_mysql="systemctl restart mysql.service"
    chkconfig="systemctl enable mysql.service"
    enable_mods=""
    cert_file="/etc/ssl/certs/s9server.crt"
    key_file="/etc/ssl/private/s9server.key"
    restart_apache="systemctl restart apache2"
    update_repo="zypper refresh"
    mysql_basedir=/usr
    mysql_datadir=/var/lib/mysql
    my_cnf=/etc/my.cnf
    mysql_socket="/var/lib/mysql/mysql.sock"
    stop_mysql="systemctl stop mariadb"
    start_mysql="systemctl start mariadb"

    [[ -n $use_existing_mysql ]] && install_packages="zypper install -n --no-confirm apache2 php7 php7-mysql apache2-mod_php7 php7-gd php7-curl php7-ldap php7-xmlreader php7-ctype php7-json wget insserv-compat sysvinit-tools ca-certificates"

    if [[ -z ${OFFLINE+x} ]]; then
        if ! ask "=> Do $update_repo? (y/N): " "n"; then
            $update_repo
        fi
    fi

    if [[ -n $install_packages ]]; then
        $install_packages
        [[ $? -ne 0 ]] && log_msg "Installing packages failed" && exit 1
    fi
    systemctl enable apache2.service
    apache_version=$(apache2ctl -v | grep -i "server version" | cut -d' ' -f3)
    [[ "${apache_version%.*}" == "Apache/2.4"  ]] && use_apache24=1

    if [[ ! -z $use_apache24 ]]; then
        # default web root for clustercontrol is /var/www. apache 2.2 legacy
        if [[ -d /var/www/html ]] && [[ -d /var/www/clustercontrol ]]; then
            ln -sfn /var/www/clustercontrol /var/www/html
        fi
        apache_sites_enabled_dir="/etc/apache2/vhosts.d"
        apache_conf="${apache_sites_enabled_dir}/s9s.conf"
        apache_conf_ssl="${apache_sites_enabled_dir}/ssl.conf"
        apache_conf_orig="vhost.conf"
        apache_conf_ssl_orig="ssl.conf"

        rm -f $apache_sites_enabled_dir/$apache_conf_orig
        # just in case
        rm -f $apache_sites_enabled_dir/$apache_conf_ssl_orig
        rm -f $apache_sites_enabled_dir/001-$apache_conf_ssl_orig
        if [[ -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ]]; then
            servername="${S9S_WEB_SERVER_HOST:-localhost}"
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s.conf
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf
        fi
        cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s.conf ${apache_sites_enabled_dir}/
        cp -f $wwwroot/clustercontrol/app/tools/apache2/s9s-ssl.conf ${apache_sites_enabled_dir}/${apache_conf_ssl_orig}

        # enable mods
        a2enmod rewrite
        a2enmod headers
        a2enmod php7
        a2enmod proxy
        a2enmod proxy_http
        a2enmod proxy_wstunnel
        echo "AddType application/x-httpd-php .php" >> /etc/apache2/mod_mime-defaults.conf
        cat >> /etc/apache2/loadmodule.conf << EOF
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
EOF
        echo "APACHE_SERVER_FLAGS=\"SSL\"" >> /etc/sysconfig/apache2
        ln -sfn /var/www/html /srv/www/vhosts
    fi

    log_msg "Starting mariadb ..."
    systemctl start mariadb
}

install_ui_packages() {
    case $dist in
        debian) install_ui_packages_debian;;
        redhat) install_ui_packages_redhat;;
        suse) install_ui_packages_suse;;
        *) log_msg "Unknown $dist. "; exit 1
    esac

    sed -ibak "s|AllowOverride None|AllowOverride All|g" $apache_conf
    sed -ibak "s|AllowOverride None|AllowOverride All|g" $apache_conf_ssl

    # Apache's default cert's lifespan is  1-10y depending on distro
    sed -ibak "s|^[ \t]*SSLCertificateFile.*|           SSLCertificateFile ${cert_file}|g" $apache_conf_ssl
    sed -ibak "s|^[ \t]*SSLCertificateKeyFile.*|            SSLCertificateKeyFile ${key_file}|g" $apache_conf_ssl
    [[ -n ${rhel_version} && ${rhel_version} == "7" ]] && sed -ibak "s|^[ \t]*#SSLCertificateChainFile.*|           SSLCertificateChainFile ${cert_file}|g" $apache_conf_ssl

    for m in $enable_mods; do
        a2enmod $m
        # Enable Web SSH
        [[ ! -z $use_apache24 ]] && a2enmod proxy proxy_http proxy_wstunnel
    done

    [[ $dist == "debian" ]] && [[ -z $need_apache24 ]] &&  ln -sf $apache_conf_ssl /etc/apache2/sites-enabled/001-${apache_conf_ssl##*/}

    mkdir -p $wwwroot/cmon/upload/schema
    cat > $wwwroot/cmon/.htaccess << EOF
Options -Indexes
EOF
    chmod -R 770 $wwwroot/clustercontrol/app/tmp $wwwroot/clustercontrol/app/upload $wwwroot/cmon
    if [[ $dist == "suse" ]]; then
        chown -R $www_user $wwwroot/clustercontrol/app/tmp $wwwroot/clustercontrol/app/upload $wwwroot/cmon
    else
        chown -R $www_user.$www_user $wwwroot/clustercontrol/app/tmp $wwwroot/clustercontrol/app/upload $wwwroot/cmon
    fi
    if [[ -d $wwwroot/clustercontrol/ssl ]]; then
        # generate new cert
        if command -v openssl &>/dev/null; then
            cd $wwwroot/clustercontrol/ssl
            create_cert
        fi
        # copy the files from the clustercontrol package
        cp -f $wwwroot/clustercontrol/ssl/server.crt ${cert_file} &>/dev/null
        cp -f $wwwroot/clustercontrol/ssl/server.key ${key_file} &>/dev/null
        rm -rf $wwwroot/clustercontrol/ssl &>/dev/null
    fi

    $restart_apache

    if [[ -z $use_existing_mysql ]]; then
        log_msg "Stoppping MySQL Server before updating configuration ..."
        #killall -15 mysqld mysqld_safe &>/dev/null
        $stop_mysql
        [[ $? -ne 0 ]] && [[ $stop_mysql != "" ]] && log_msg "Failed to stop the MySQL Server. ..." && exit 1

        create_my_cnf /tmp/my.cnf
        if [[ "${os_codename}" == "bookworm"  || "${os_codename}" == "bullseye" ]]; then
            cp -f /tmp/my.cnf /etc/mysql/mariadb.conf.d/55-s9s-server.cnf || exit 1
        else
            cp -f /tmp/my.cnf $my_cnf || exit 1
            rm -rf $mysql_datadir/ib_log* $mysql_datadir/mysqld.pid $mysql_datadir/cmon $mysql_datadir/dcps
        fi
        rm -f /tmp/my.cnf

        echo -e "\n=> Starting database. This may take a couple of minutes. Do NOT press any key."
        if [[ ! -z $mysqld8 ]]; then
            # initialize-insecure for centos/rhel
            $mysqld8
        fi

        if [[ ! -z $rhel_version ]]; then
            case "$rhel_version" in
                7|8|9)
                    yum list installed | grep -q mariadb-server
                    if [[ $? -eq 0 ]]; then
                        start_mysql="service mariadb start"
                        chkconfig="chkconfig --levels 235 mariadb on"
                    fi
                    ;;
            esac
        fi

        $start_mysql
        [[ $? -ne 0 ]] && log_msg "Failed to start the MySQL Server. ..." && exit 1

        log_msg "Securing the MySQL Server ..."
        log_msg "!! In order to complete the installation you need to set a MySQL root password !!"
        log_msg "Supported special password characters: ~!@#$%^&*()_+{}<>?"
        [[ -z $S9S_ROOT_PASSWORD ]] && read -n 1 -s -r -p "=> Press any key to proceed ..."
        echo ""

        case "${os_codename}" in
            'focal' | 'disco' | 'bionic' | 'xenial' | 'jammy' | 'noble')
                $mysql_basedir/bin/mysql -uroot -P${db_port} -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY ''"
                ;;
        esac

        if [[ -z ${S9S_CMON_PASSWORD} ]]; then
            [[ -e /var/lib/mysql/mysql.sock ]] && mysql_secure_installation --socket="/var/lib/mysql/mysql.sock" || mysql_secure_installation
            [[ $? -ne 0 ]] && log_msg "Unable to secure the MySQL server running mysql_secure_installation, exiting ..." && exit 1
            echo -e "\n=> Please enter the MySQL root password that was set to continue!"
            until set_root_password; do
                log_msg ""
                log_msg "Password mismatch! Try again."
                sleep 1
            done
        else
            log_msg "!! Setting MySQL root user password !!"
            [[ -e /var/lib/mysql/mysql.sock ]] && $mysql_basedir/bin/mysqladmin --socket="/var/lib/mysql/mysql.sock" -uroot password "${S9S_ROOT_PASSWORD}" || $mysql_basedir/bin/mysqladmin -uroot password "${S9S_ROOT_PASSWORD}"
            log_msg "!! Please run mysql_secure_installation after the setup !!"
        fi
    fi

    if [[ $dist = "redhat" ]]; then
        [[ -z $use_existing_mysql ]] && $chkconfig
        setenforce 0
        sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config &>/dev/null
        cat << EOF
=> NOTE: Stopping and disabling firewall...manually re-enable and add rules if required.
Required ports to be opened, http://support.severalnines.com/entries/22654676-Firewall-ports-
EOF
        if [[ $systemd == 1 ]]; then
            systemctl stop firewalld
            systemctl disable firewalld
        else
            service iptables stop
            chkconfig iptables off
        fi
    fi
}

create_my_cnf() {

    cat > $1 << EOF
[mysqld]
user = mysql
#basedir = $mysql_basedir
datadir = $mysql_datadir
pid_file = $mysql_datadir/mysqld.pid
socket = $mysql_socket
port = ${db_port}
#log_error = error.log
max_allowed_packet = 128M
#event_scheduler = 1
innodb_buffer_pool_size = ${INNODB_BUFFER_POOL_SIZE}M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
#innodb_data_file_path = ibdata1:100M:autoextend
innodb_log_file_size = 512M
innodb_log_files_in_group = 2
#innodb_buffer_pool_instances = 4
innodb_thread_concurrency = 0
innodb_flush_method = O_DIRECT
sysdate_is_now = 1
max_connections = 512
thread_cache_size = 128
#table_open_cache=512
lower_case_table_names = 0
#skip_name_resolve
skip-log-bin
EOF

    case "${os_codename}" in
        'disco' |'bionic'|'xenial'|'jammy'|'noble'|'stretch'|'buster'|'bullseye')
            cat >> $1 << EOF
plugin-load-add = auth_socket.so
EOF
        ;;
    esac

    cat >> $1 << EOF
[mysql]
socket=$mysql_socket

[client]
socket=$mysql_socket

[mysqld_safe]
pid-file=$mysql_datadir/mysqld.pid
#log-error=error.log
basedir=$mysql_basedir
datadir=$mysql_datadir
EOF

}

install_web_server() {
    case "${dist}" in
        'debian')
            www_user=www-data
            install_packages="apt-get -y install apache2"
            enable_mods="ssl rewrite headers proxy proxy_http proxy_wstunnel"
            cert_file="/etc/ssl/certs/s9server.crt"
            key_file="/etc/ssl/private/s9server.key"
            restart_apache="service apache2 restart"
            update_repo="apt-get update"

            if [[ -z ${OFFLINE+x} ]]; then
                if ask "=> Do $update_repo? (Y/n): " "y"; then
                    $update_repo
                fi
            fi

            if [[ -n $install_packages ]]; then
                waitForLocks
                LC_ALL=en_US.utf8 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true $install_packages
                [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
            fi

            for m in $enable_mods; do
                log_msg "Enabling apache module ${m} ..."
                a2enmod $m
            done

            # enable sameorigin header
            if [[ -f /etc/apache2/conf-available/security.conf ]]; then
                # enable for header
                sed -ibak "s|^#Header set X-Frame-Options: \"sameorigin\"|Header set X-Frame-Options: \"sameorigin\"|g" /etc/apache2/conf-available/security.conf
                ln -sfn /etc/apache2/conf-available/security.conf /etc/apache2/conf-enabled/security.conf
            fi

            [[ -e /etc/apache2/sites-enabled/000-default.conf ]] && rm -f /etc/apache2/sites-enabled/000-default.conf

            # restart the web server after the controller has been installed
            ;;
        'redhat')
            apache_conf=/etc/httpd/conf/httpd.conf
            apache_conf_ssl=/etc/httpd/conf.d/ssl.conf
            www_user=apache
            install_packages="yum -y install httpd mod_ssl"
            enable_mods=""
            cert_file="/etc/pki/tls/certs/s9server.crt"
            key_file="/etc/pki/tls/private/s9server.key"
            restart_apache="service httpd restart"
            [[ ! -z $ORACLE ]] && restart_apache="systemctl restart httpd"
            update_repo="yum update"
            chkconfig_apache="chkconfig --levels 235 httpd on"

            if [[ -z ${OFFLINE+x} ]]; then
                if ! ask "=> Do $update_repo? (y/N): " "n"; then
                    $update_repo
                fi
            fi

            if [[ -n $install_packages ]]; then
                $install_packages
                [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
            fi

            $chkconfig_apache

            apache_version=$(apachectl -v | grep -i "server version" | cut -d' ' -f3)
            [[ "${apache_version%.*}" == "Apache/2.4"  ]] && use_apache24=1

            if [[ ! -z $use_apache24 ]]; then
                # enable sameorigin header
                if [[ ! -f /etc/httpd/conf.d/security.conf ]]; then
                    # enable for header
                    cat > /etc/httpd/conf.d/security.conf << EOF
Header set X-Frame-Options: "sameorigin"
EOF
                fi
                # restart the web server after the controller has been installed
            fi
            ;;
        'suse')
            install_packages="zypper install -n --no-confirm apache2"
            restart_apache="systemctl restart apache2"
            cert_file="/etc/ssl/certs/s9server.crt"
            key_file="/etc/ssl/private/s9server.key"
            update_repo="zypper refresh"

            if [[ -z ${OFFLINE+x} ]]; then
                if ! ask "=> Do $update_repo? (y/N): " "n"; then
                    $update_repo
                fi
            fi

            if [[ -n $install_packages ]]; then
                $install_packages
                [[ $? -ne 0 ]] && log_msg "Installing packages failed" && exit 1
            fi
            systemctl enable apache2.service

            # enable mods
            a2enmod rewrite
            a2enmod headers
            a2enmod proxy
            a2enmod proxy_http
            a2enmod proxy_wstunnel
            echo "AddType application/x-httpd-php .php" >> /etc/apache2/mod_mime-defaults.conf
            cat >> /etc/apache2/loadmodule.conf << EOF
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
EOF

            # restart the web server after the controller has been installed

            # echo "Listen 443" >> ${apache_conf_ssl}
            # ln -sfn /var/www/html /srv/www/vhosts
            ;;
    esac
    # generate new cert
    if command -v openssl &>/dev/null; then
        mkdir -p /tmp/ssl && cd /tmp/ssl
        create_cert
        # copy the files from the clustercontrol package
        cp -f /tmp/ssl/server.crt ${cert_file} &>/dev/null
        cp -f /tmp/ssl/server.key ${key_file} &>/dev/null
        rm -rf /tmp/ssl &>/dev/null
    fi
}

configure_ccv2_web() {
    # change default port 9443 to 443
    # ask to set the servername
    servername="${S9S_WEB_SERVER_HOST:-$host}"
    if [[ -z ${S9S_WEB_SERVER_HOST} ]]; then
        if ! ask_p "=> The Apache web 'ServerName' will be set to ${servername}. Do you want to change it? (y/N): " "n"; then
            read -p "=> Enter the 'ServerName': " x
            [[ ! -z $x ]] && servername="$x"
        fi
    fi
    log_msg "The Apache 'ServerName' will be set to ${servername} ..."

    case "${dist}" in
        'debian')
            # sed -i "s|^[ \t]*CMON_API_URL.*|  CMON_API_URL: 'https://${servername}:19501/v2',|g" /var/www/html/clustercontrol2/config.js
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" /etc/apache2/sites-available/cc-frontend.conf
            if [[ ${cc_version} == "1" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/apache2/sites-available/cc-frontend.conf
            elif [[ ${cc_version} == "2" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/apache2/sites-available/cc-frontend.conf
                sed -i "s|Listen 9443|#Listen 443|g" /etc/apache2/sites-available/cc-frontend.conf
                sed -i "s|9443|443|g" /etc/apache2/sites-available/cc-frontend.conf
            fi
            ;;
        'redhat')
            if [[ ! -e /etc/httpd/conf.d/cc-frontend.conf ]]; then
                [[ -e /usr/share/cmon/apache/cc-frontend.conf ]] && cp /usr/share/cmon/apache/cc-frontend.conf /etc/httpd/conf.d/
            fi
            # sed -i "s|^[ \t]*CMON_API_URL.*|  CMON_API_URL: 'https://${servername}:19501/v2',|g" /var/www/html/clustercontrol2/config.js
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" /etc/httpd/conf.d/cc-frontend.conf
            if [[ ${cc_version} == "1" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/httpd/conf.d/cc-frontend.conf
            elif [[ ${cc_version} == "2" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/httpd/conf.d/cc-frontend.conf
                sed -i "s|Listen 9443|#Listen 443|g" /etc/httpd/conf.d/cc-frontend.conf
                sed -i "s|9443|443|g" /etc/httpd/conf.d/cc-frontend.conf
            fi
            ;;
        'suse')
            [[ ! -e /etc/apache2/vhosts.d/cc-frontend.conf ]] && cp -f /etc/httpd/conf.d/cc-frontend.conf /etc/apache2/vhosts.d/
            # sed -i "s|^[ \t]*CMON_API_URL.*|  CMON_API_URL: 'https://${servername}:19501/v2',|g" /var/www/html/clustercontrol2/config.js
            sed -i "s|^[ \t]*ServerName.*|        ServerName ${servername}|g" /etc/apache2/vhosts.d/cc-frontend.conf
            if [[ ${cc_version} == "1" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/apache2/vhosts.d/cc-frontend.conf
            elif [[ ${cc_version} == "2" ]]; then
                sed -i "s|https://cc2.severalnines.local:9443.*|https://${servername}\/|g" /etc/apache2/vhosts.d/cc-frontend.conf
                sed -i "s|Listen 9443|#Listen 443|g" /etc/apache2/vhosts.d/cc-frontend.conf
                sed -i "s|9443|443|g" /etc/apache2/vhosts.d/cc-frontend.conf
            fi
            ;;
    esac
}

install_database_server() {
    case "${dist}" in
        'debian')
            install_packages="apt install -y mysql-server mysql-client"
            [[ -n $use_existing_mysql ]] && install_packages=""
            stop_mysql="service mysql stop"
            start_mysql="service mysql start"
            update_repo="apt-get update"
            mysql_basedir=/usr
            mysql_datadir=/var/lib/mysql
            my_cnf=/etc/mysql/my.cnf
            mysql_socket="/var/run/mysqld/mysqld.sock"

            case "${os_codename}" in
                'jammy'|'noble')
                    setup_php7_debian
                    install_packages="apt-get -y install mysql-server mysql-client apache2 php7.4-mysql php7.4-gd libapache2-mod-php7.4 php7.4-curl php7.4-ldap php7.4-xml wget"
                    [[ -n $use_existing_mysql ]] && install_packages="apt-get -y install apache2 php7.4-mysql php7.4-gd libapache2-mod-php7.4 php7.4-curl php7.4-ldap php7.4-xml wget"
                    ;;
                'buster')
                    install_packages="`echo $install_packages | sed 's/mysql-/default-mysql-/g'`"
                    ;;
                'bullseye'|'bookworm')
                    install_packages="`echo $install_packages | sed 's/mysql-/mariadb-/g'`"
                    ;;
            esac

            if [[ -z ${OFFLINE+x} ]]; then
                if ask "=> Do $update_repo? (Y/n): " "y"; then
                    $update_repo
                fi
            fi

            if [[ -n $install_packages ]]; then
                waitForLocks
                LC_ALL=en_US.utf8 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true $install_packages
                [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
            fi
            if [[ -z $use_existing_mysql ]]; then
                log_msg "Stoppping MySQL Server before updating configuration ..."
                #killall -15 mysqld mysqld_safe &>/dev/null
                $stop_mysql
                [[ $? -ne 0 ]] && [[ $stop_mysql != "" ]] && log_msg "Failed to stop the MySQL Server. ..." && exit 1

                create_my_cnf /tmp/my.cnf
                if [[ "${os_codename}" == "bookworm"  || "${os_codename}" == "bullseye" ]]; then
                    cp -f /tmp/my.cnf /etc/mysql/mariadb.conf.d/55-s9s-server.cnf || exit 1
                else
                    cp -f /tmp/my.cnf $my_cnf || exit 1
                    rm -rf $mysql_datadir/ib_log* $mysql_datadir/mysqld.pid $mysql_datadir/cmon $mysql_datadir/dcps
                fi
                rm -f /tmp/my.cnf
            fi
            ;;
        'redhat')
            install_packages="yum -y install mysql-server mysql"
            update_repo="yum update"
            mysql_basedir=/usr
            mysql_datadir=/var/lib/mysql
            stop_mysql=""
            start_mysql="service mysqld start"
            chkconfig="chkconfig --levels 235 mysqld on"
            mysql_socket="/var/lib/mysql/mysql.sock"

            if [[ ! -z $rhel_version ]]; then
                case "$rhel_version" in
                    7|8|9)
                        install_packages="yum -y install mariadb-server"
                        [[ -n $use_existing_mysql ]] && install_packages=""
                        ;;
                    *)
                        log_msg "Unknown/Unsupported Centos/Red Hat version $rhel_version"
                        exit 1
                        ;;
                esac
            fi

            if [[ -z ${OFFLINE+x} ]]; then
                if ! ask "=> Do $update_repo? (y/N): " "n"; then
                    $update_repo
                fi
            fi
            if [[ -n $install_packages ]]; then
                $install_packages
                [[ $? -ne 0 ]] && log_msg "Installing packages ${install_packages}, failed" && exit 1
            fi

            if [[ ! -z $rhel_version ]]; then
                case "$rhel_version" in
                    7|8|9)
                        yum list installed | grep -q mariadb-server
                        if [[ $? -eq 0 ]]; then
                            start_mysql="service mariadb start"
                            [[ ! -z $ORACLE ]] && start_mysql="systemctl start mariadb"
                            chkconfig="chkconfig --levels 235 mariadb on"
                        fi
                        ;;
                esac
            fi
            # workaround for mysql 8, not safe
            $(yum list installed | grep mysql | grep -q mysql80)
            if [[ $? -eq 0 ]]; then
                mysqld8="mysqld --initialize-insecure --user=mysql --basedir=/usr --datadir=/var/lib/mysql"
                $mysqld8
            fi
            $chkconfig
            ;;
            'suse')
                install_packages="zypper install -n --no-confirm mariadb"
                restart_mysql="systemctl restart mysql.service"
                chkconfig="systemctl enable mysql.service"
                update_repo="zypper refresh"
                mysql_basedir=/usr
                mysql_datadir=/var/lib/mysql
                my_cnf=/etc/my.cnf
                mysql_socket="/var/lib/mysql/mysql.sock"
                stop_mysql="systemctl stop mariadb"
                start_mysql="systemctl start mariadb"

                [[ -n $use_existing_mysql ]] && install_packages=""

                if [[ -z ${OFFLINE+x} ]]; then
                    if ! ask "=> Do $update_repo? (y/N): " "n"; then
                        $update_repo
                    fi
                fi

                if [[ -n $install_packages ]]; then
                    $install_packages
                    [[ $? -ne 0 ]] && log_msg "Installing packages failed" && exit 1
                fi
                ;;
    esac
    echo -e "\n=> Starting database. This may take a couple of minutes. Do NOT press any key."
    $start_mysql
    [[ $? -ne 0 ]] && log_msg "Failed to start the database server. ..." && exit 1

    log_msg "Securing the MySQL Server ..."
    log_msg "!! In order to complete the installation you need to set a MySQL root password !!"
    log_msg "Supported special password characters: ~!@#$%^&*()_+{}<>?"
    [[ -z $S9S_ROOT_PASSWORD ]] && read -n 1 -s -r -p "=> Press any key to proceed ..."
    echo ""

    case "${os_codename}" in
        'focal'|'disco'|'bionic'|'xenial'|'jammy'|'noble')
            $mysql_basedir/bin/mysql -uroot -P${db_port} -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY ''"
            ;;
    esac

    if [[ -z ${S9S_CMON_PASSWORD} ]]; then
        [[ -e /var/lib/mysql/mysql.sock ]] && mysql_secure_installation --socket="/var/lib/mysql/mysql.sock" || mysql_secure_installation
        [[ $? -ne 0 ]] && log_msg "Unable to secure the MySQL server running mysql_secure_installation, exiting ..." && exit 1
        echo -e "\n=> Please enter the MySQL root password that was set to continue!"
        until set_root_password; do
            log_msg ""
            log_msg "Password mismatch! Try again."
            sleep 1
        done
    else
        log_msg "!! Setting MySQL root user password !!"
        [[ -e /var/lib/mysql/mysql.sock ]] && $mysql_basedir/bin/mysqladmin --socket="/var/lib/mysql/mysql.sock" -uroot password "${S9S_ROOT_PASSWORD}" || $mysql_basedir/bin/mysqladmin -uroot password "${S9S_ROOT_PASSWORD}"
        log_msg "!! Please run mysql_secure_installation after the setup !!"
    fi
}

configure_database_server() {
    find_mysql

    if [[ $root_password == "" ]] || [[ -z $root_password ]]; then
        IFS="" read -s -p "=> Enter your MySQL root user's password: " x
        [[ ! -z $x ]] && root_password="$x"
    fi

    $mysql_bin -uroot -p''"${root_password}"'' -P${db_port} -e "SELECT USER();" &>/dev/null
    if [[ $? -ne 0 ]]; then
        log_msg "Cannot Connect! Try again."
        IFS="" read -s -p "=> Enter your MySQL root user's password: " x
        [[ ! -z $x ]] && root_password="$x"
        log_msg ""
    fi

    log_msg "Set a password for ClusterControl's MySQL user (cmon) [${cmon_password}]"
    log_msg "Supported special characters: ~!@#$%^&*()_+{}<>?"
    until set_cmon_password; do
        log_msg ""
        log_msg "Password mismatch! Try again."
        sleep 1
    done

    cat > /tmp/ui.sql << EOF
BEGIN;
CREATE USER 'cmon'@'localhost' identified by '${cmon_password}';
GRANT ALL PRIVILEGES ON *.* to 'cmon'@'localhost' WITH GRANT OPTION;
CREATE USER 'cmon'@'127.0.0.1' identified by '${cmon_password}';
GRANT ALL PRIVILEGES ON *.* to 'cmon'@'127.0.0.1' WITH GRANT OPTION;
CREATE USER 'cmon'@'${host}' identified by '${cmon_password}';
GRANT ALL PRIVILEGES ON *.* to 'cmon'@'${host}' WITH GRANT OPTION;
COMMIT;
EOF

    log_msg "Creating the MySQL cmon user ..."
    if [[ -z $use_existing_mysql ]]; then
        $mysql_bin -uroot -P${db_port} -p''"${root_password}"'' < /tmp/ui.sql
    else
        cat > /tmp/drop.sql << EOF
DROP USER 'cmon'@'localhost';
DROP USER 'cmon'@'127.0.0.1';
DROP USER 'cmon'@'${host}';
EOF
        $mysql_bin -f -uroot -P${db_port} -p''"${root_password}"'' < /tmp/drop.sql &>/dev/null
        [[ $? -ne 0 ]] && log_msg "Failed to drop cmon user! ..." && exit 1
        rm -f /tmp/drop.sql
        $mysql_bin -f -uroot -P${db_port} -p''"${root_password}"'' < /tmp/ui.sql &>/dev/null
    fi
    [[ $? -ne 0 ]] && log_msg "Failed to add cmon user! ..." && exit 1
    rm -f /tmp/ui.sql

    if [[ ${cc_version} != "2" ]]; then
        install_ui_database
    fi
}

install_ui_database() {
    echo -e "\n=> Importing the Web Application DB schema and creating the cmon user."
    echo -e "\n=> Importing $wwwroot/clustercontrol/sql/dc-schema.sql"
    $mysql_bin -uroot -p''"${root_password}"'' -P${db_port} < $wwwroot/clustercontrol/sql/dc-schema.sql
    [[ $? -ne 0 ]] && log_msg "Failed to import the Web Application DB schema ($wwwroot/clustercontrol/sql/dc-schema.sql) ..." && exit 1
}

create_ui_bootstrap() {
    log_msg "Creating UI configuration ..."
    cp -f $wwwroot/clustercontrol/bootstrap.php.default $wwwroot/clustercontrol/bootstrap.php &>/dev/null
    PASS="${cmon_password}" perl -p -i -e "s|^define\('DB_PASS'.*|define('DB_PASS', '\$ENV{PASS}');|g" $wwwroot/clustercontrol/bootstrap.php
    sed -i "s|^define('DB_PORT'.*|define('DB_PORT', '${db_port}');|g" $wwwroot/clustercontrol/bootstrap.php
    sed -i "s|^define('RPC_TOKEN'.*|define('RPC_TOKEN', '${cc_api_token}');|g" $wwwroot/clustercontrol/bootstrap.php
    # sed -i "s|^define('WEBSOCKET_HOST'.*|define('WEBSOCKET_HOST', 'ws://${host}:1337');|g" $wwwroot/clustercontrol/bootstrap.php
    # Add container env
    echo "define('CONTAINER', '${CONTAINER}');" >> $wwwroot/clustercontrol/bootstrap.php
    echo "define('ENABLE_ONBOARDING_V1', 'true');" >> $wwwroot/clustercontrol/bootstrap.php
}

check_emailaddress() {
    if [[ "$1" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]; then
        return 0
    else
        log_msg "Invalid email address"
        return 1
    fi
}

set_cmon_password() {
    [[ ! -z $S9S_CMON_PASSWORD ]] && return 0
    IFS="" read -s -p "=> Enter a CMON user password: " x
    if [[ -z $x ]]; then
        log_msg "The password cannot be blank. Try again."
        IFS="" read -s -p "=> Enter a CMON user password: " x
    fi
    cmon_password="$x"
    log_msg ""
    IFS="" read -s -p "=> Enter the CMON user password again: " x
    if [[ "$cmon_password" == "$x" ]]; then
        return 0
    else
        return 1
    fi
}

set_root_password() {
    [[ ! -z $S9S_ROOT_PASSWORD ]] && return 0
    IFS="" read -s -p "=> Enter the MySQL root password: " x
    while [[ -z $x ]]; do
        log_msg "The password cannot be blank. Try again."
        IFS="" read -s -p "=> Enter the MySQL root password: " x
    done
    root_password="$x"
    log_msg ""
    IFS="" read -s -p "=> Enter the MySQL root password again: " x
    if [[ "$root_password" == "$x" ]]; then
        return 0
    else
        return 1
    fi
}

install_controller() {
    cmon_controller="clustercontrol-controller"
    cmon_basedir="/usr"
    [[ ! -z ${CONTROLLER_BUILD} ]] && cmon_controller=${CONTROLLER_BUILD}
    if [[ $dist == "redhat" ]]; then
        case "$rhel_version" in
            9)
                if [[ -z ${OFFLINE+x} ]]; then
                    if [[ -f /etc/almalinux-release ]] || [[ -f /etc/rocky-release ]]; then
                        dnf config-manager --set-enabled crb
                        dnf -y install epel-release
                    elif [[ -f /etc/centos-release ]]; then
                        dnf config-manager --set-enabled crb
                        dnf -y install epel-release epel-next-release
                    else
                        # assume RHEL 9 ...
                        subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
                        dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
                        [[ $? -ne 0 ]] && setup_php7_redhat
                    fi
                fi
                ;;
            8)
                if [[ -z ${OFFLINE+x} ]]; then
                    if [[ -f /etc/almalinux-release ]] || [[ -f /etc/rocky-release ]]; then
                        dnf config-manager --set-enabled powertools
                        dnf -y install epel-release
                    elif [[ -f /etc/centos-release ]]; then
                        dnf config-manager --set-enabled powertools
                        dnf -y install epel-release epel-next-release
                    else
                        # assume RHEL 8 ...
                        subscription-manager repos --enable codeready-builder-for-rhel-8-$(arch)-rpms
                        dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
                    fi
                fi
                ;;
            7)
                if [[ -z ${OFFLINE+x} ]]; then
                    if [[ -f /etc/centos-release ]]; then
                        yum -y install epel-release
                    elif [[ -f /etc/redhat-release ]]; then
                        subscription-manager repos --enable rhel-*-optional-rpms \
                            --enable rhel-*-extras-rpms \
                            --enable rhel-ha-for-rhel-*-server-rpms
                        yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
                    fi
                fi
                ;;
            esac
        # fix CMON API port for SELinux
        log_msg "Adding CMON API port 19501 for SELinux ..."
        semanage port -a -t http_port_t -p tcp 19501 &>/dev/null
        log_msg "Adding CMON port 19510 for events ..."
        semanage port -a -t http_port_t -p tcp 19510 &>/dev/null
        log_msg "Adding CMON port 19518 for clouds ..."
        semanage port -a -t http_port_t -p tcp 19518 &>/dev/null
        # enable httpd for network connections just in case it's off by default
        log_msg "Setting httpd_can_network_connect to 'on' for SELinux ..."
        semanage boolean --modify --on httpd_can_network_connect &>/dev/null

        enable_service="chkconfig --levels 235 cmon on"
        yum -y install $cmon_controller
        [[ $? -ne 0 ]] && exit 1
    elif [[ $dist == "debian" ]]; then
        enable_service="update-rc.d cmon defaults"
        waitForLocks
        apt-get -y install $cmon_controller
        [[ $? -ne 0 ]] && exit 1
    elif [[ $dist == "suse" ]]; then
        enable_service="chkconfig --add cmon"
        zypper install -n --no-confirm $cmon_controller
        [[ $? -ne 0 ]] && exit 1
    fi

    cat >> /etc/default/cmon << EOF
# New events client http callback as of v1.4.2!
EVENTS_CLIENT="http://127.0.0.1:${cmon_events_port}"
CLOUD_SERVICE="http://127.0.0.1:${cmon_cloud_port}"
EOF

    # use the cmon token for the global rcp_token
    rpc_key=${cc_api_token}

    # import cmon schema using cmon --init
    # rm /etc/cmon.cnf that came with the package
    rm -f /etc/cmon.cnf
    cmon --init \
        --mysql-hostname="127.0.0.1" \
        --mysql-port="${db_port}" \
        --mysql-username="${cmon_user}" \
        --mysql-password="${cmon_password}" \
        --mysql-database="cmon" \
        --hostname="${host}" \
        --rpc-token="${rpc_key}" \
        --controller-id="clustercontrol"
    [[ $? -ne 0 ]] && log_msg "Unable to init cmon! Exiting ..." && exit 1

    $enable_service
    log_msg "Starting the Controller process."
    if [[ $systemd == 1 ]]; then
        systemctl restart cmon
        systemctl enable cmon
    else
        service cmon restart
    fi

    if [[ $dist == "redhat" ]]; then
        if [[ $rhel_version = "7" ]]; then
            yum install -y ntp ntpdate
            chkconfig ntpd on
            ntpdate pool.ntp.org
            service ntpd start
        fi
    fi
}

install_s9s_commandline() {
    s9s_tools=s9s-tools
    [[ ! -z ${S9S_TOOLS_BUILD} ]] && s9s_tools=${S9S_TOOLS_BUILD}
    if [[ $dist == "redhat" ]]; then
        yum -y install $s9s_tools
    elif [[ $dist == "suse" ]]; then
        zypper install -n --no-confirm s9s-tools
    elif [[ $dist == "debian" ]]; then
        waitForLocks
        apt-get -y install $s9s_tools
    fi
    [[ $? -ne 0 ]] && log_msg "Unable to install s9s-tools"

    echo "=> Waiting 60s until the CMON Controller completes its startup cycle ..."
    sleep 60 # wait for cmon to start on slower systems
    export S9S_USER_CONFIG=$HOME/.s9s/ccrpc.conf
    log_msg "Create ccrpc user ..."
    s9s user --create --generate-key --new-password=${rpc_key} --group=admins --controller="https://localhost:9501" ccrpc
    if [[ $? -ne 0 ]]; then
        log_msg "*** Unable to create a 'ccrpc' user! Please check your s9s command line installation! ***"
        log_msg "*** Please see https://docs.severalnines.com/docs/clustercontrol/troubleshooting/common-issues/#clustercontrol-controller-cmon on how fix a suspended s9s admin user."
        log_msg "*** Re-install the ClusterControl package again after checking the s9s command line installation."
        exit 1
    fi

    s9s user --set --first-name=RPC --last-name=API &>/dev/null
    unset S9S_USER_CONFIG

    if [[ ${cc_version} == "2" ]]; then
        local email="${S9S_ADMIN_EMAIL:-##__EMAIL__##}"
        if [[ "$email" != *"@"* ]]; then
            email=""
        fi
        export S9S_USER_CONFIG=/tmp/ccsetup.conf
        log_msg "Create temporary cc setup user ..."
        s9s user --create --new-password=admin --group=admins --email-address="${email}" --controller="https://localhost:9501" ccsetup
        unset S9S_USER_CONFIG
    fi

    log_msg "*** Restarting the Controller process to generate the CMON API rpc_tls files."
    if [[ $systemd == 1 ]]; then
        systemctl restart cmon
    else
        service cmon restart
    fi
}

create_cc_user() {
    local email="##__EMAIL__##"
    if [[ ! -z ${S9S_ADMIN_EMAIL} ]]; then
        email="${S9S_ADMIN_EMAIL}"
    else
        return 0
    fi

    if [[ "$email" == *"@"* ]]; then
        local username="${email%%@*}"
        echo "=> Your login username is set to ${username} ..."

        cat > /tmp/login.sql << EOF
USE dcps;
BEGIN;
INSERT INTO settings(name, type) VALUES ('email', 'login');
INSERT INTO settings_items(setting_id, item) VALUES (LAST_INSERT_ID(),'${email}');
INSERT INTO settings(name, type) VALUES ('username', 'login');
INSERT INTO settings_items(setting_id, item) VALUES (LAST_INSERT_ID(),'${username}');
COMMIT;
EOF

        $mysql_bin -f -uroot -P${db_port} -p''"${root_password}"'' < /tmp/login.sql &>/dev/null
        rm -f /tmp/login.sql
    fi
}

create_apache24_configs() {
    servername="${S9S_WEB_SERVER_HOST:-localhost}"
    rm -f $apache_conf
    cat > $apache_conf << EOF
<VirtualHost *:80>
    ServerName ${servername}

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    RedirectMatch ^/$ /clustercontrol/

    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined

    <Directory />
            Options +FollowSymLinks
            AllowOverride All
    </Directory>
    <Directory /var/www/html>
            Options +Indexes +FollowSymLinks +MultiViews
            AllowOverride All
            Require all granted
    </Directory>

</VirtualHost>
EOF
    rm -f $apache_conf_ssl
    cat > $apache_conf_ssl << EOF
<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerName ${servername}
                ServerAdmin webmaster@localhost

                DocumentRoot /var/www/html
                RedirectMatch ^/$ /clustercontrol/

                <Directory />
                        Options +FollowSymLinks
                        AllowOverride All
                </Directory>
                <Directory /var/www/html>
                        Options +Indexes +FollowSymLinks +MultiViews
                        AllowOverride All
                        Require all granted
                </Directory>

                ErrorLog \${APACHE_LOG_DIR}/error.log
                CustomLog \${APACHE_LOG_DIR}/access.log combined

                #LogLevel info ssl:warn

                # HTTP Strict Transport Security (mod_headers is required) (63072000 seconds)
                Header always set Strict-Transport-Security "max-age=63072000"

                SSLEngine on
                SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
                SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
                #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
                #SSLCACertificatePath /etc/ssl/certs/
                #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
                #SSLCARevocationPath /etc/apache2/ssl.crl/
                #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
                #SSLVerifyClient require
                #SSLVerifyDepth  10
                #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                </FilesMatch>
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars
                </Directory>

                BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
                # MSIE 7 and newer should be able to use keepalive
                BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
        </VirtualHost>
    # intermediate configuration
    SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder     off
    SSLSessionTickets       off

#    SSLUseStapling On
#    SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
</IfModule>

EOF

}

log_msg() {
    LAST_MSG="$1"
    echo "$(date +'%Y-%m-%d %H:%M:%S %Z') -- ${LAST_MSG}"
}

track_install_init() {
    wget -qO- --no-check-certificate --post-data="container=${CONTAINER}&email=##__EMAIL__##&uuid=${cc_api_token}&version=${VERSION}&os=${OS}&step=1" https://severalnines.com/service/install_log.php &>/dev/null
}

track_install() {
    wget -qO- --no-check-certificate --post-data="uuid=${cc_api_token}&step=${1}" https://severalnines.com/service/install_log.php &>/dev/null
}

checkLock() {
    if command -v fuser >/dev/null 2>/dev/null; then
        fuser $@ 2>/dev/null >/dev/null
        return $?
    fi
    # fuser (psmisc) not installed, go with lsof
    if [ "`lsof $@ 2>/dev/null >/dev/null`x" != "x" ]; then
        return 0
    fi
    return 1
}

waitForLocks() {
    if checkLock /var/lib/dpkg/lock /var/lib/dpkg/lock-frontend /var/lib/apt/lists/lock /var/cache/apt/archives/lock; then
        echo -n "=> Waiting for APT/DPKG locks."
    else
        return
    fi
    while checkLock /var/lib/dpkg/lock /var/lib/dpkg/lock-frontend /var/lib/apt/lists/lock /var/cache/apt/archives/lock; do
        echo -n .
        sleep 1
    done
    echo .
}

cleanup() {

    if [[ ! -z ${SEND_DIAGNOSTICS} && ${SEND_DIAGNOSTICS} == 1 ]]; then
        [[ $(command -v cmon) ]] && VERSION=$(cmon --version | awk '/version/ {print $3}')
        if [[ $CONTAINER != "" ]]; then
            UUID=$(hostname | md5sum | cut -d' ' -f1)
        else
            UUID=$(dmidecode --string system-uuid 2>/dev/null | sed 's#-##g' | sha256sum | awk '{print $1}')
        fi
        OS=$(cat /proc/version)
        MEM=$(free -m | awk '/Mem:/ { print "T:" $2, "F:" $4}')
        if [[ -z $PYTHON3 ]]; then
            OS=$(python -c "import sys,urllib; print urllib.quote('${OS}')")
            MEM=$(python -c "import sys,urllib; print urllib.quote('${MEM}')")
            LAST_MSG=$(python -c "import sys,urllib; print urllib.quote('${LAST_MSG}')")
        else
            OS=$(python -c "import sys,urllib.parse; print(urllib.parse.quote('${OS}'))")
            MEM=$(python -c "import sys,urllib.parse; print(urllib.parse.quote('${MEM}'))")
            LAST_MSG=$(python -c "import sys,urllib.parse; print(urllib.parse.quote('${LAST_MSG}'))")
        fi

        wget -qO- --post-data="version=${VERSION:=NA}&uuid=${UUID}&os=${OS}&mem=${MEM}&rc=${INSTALLATION_STATUS}&msg=${LAST_MSG}&container=${CONTAINER}" https://severalnines.com/service/diag.php &>/dev/null

        [[ ${INSTALLATION_STATUS} == "1" ]] && echo "Please contact Severalnines support at http://support.severalnines.com if you have installation issues that cannot be resolved."
    fi
}

check_os() {
    dist="Unknown"
    regex_lsb="Description:[[:space:]]*([^ ]*)"
    regex_etc="/etc/(.*)[-_]"
    systemd=0
    [[ $(readlink /sbin/init) == *"systemd"* ]] && systemd=1

    # install lsb-release on debian|ubuntu
    if apt-get --version >/dev/null 2>/dev/null; then
        log_msg "Installing lsb-release ..."
        if [[ -z ${OFFLINE+x} ]]; then
            waitForLocks
            apt-get update -qq
        fi
        apt-get install -yq lsb-release
    fi

    if command -v lsb_release &>/dev/null; then
        do_lsb
        [[ $? -ne 0 ]] && do_release_file
    else
        do_release_file
    fi

    dist=$(echo $dist | tr '[:upper:]' '[:lower:]')
    [[ ! -z $CENTOS ]] && dist="centos"
    case $dist in
        debian) dist="debian";;
        ubuntu) dist="debian";;
        red)    dist="redhat";;
        redhat) dist="redhat";;
        centos) dist="redhat";;
        fedora) dist="redhat";;
        oracle) dist="redhat";;
        suse) dist="suse";;
        system)
            dist="redhat" # amazon ami
            log_msg "This distro is not supported! Supported OS, https://severalnines.com/docs/requirements.html#operating-system"
            exit 1
            ;; # amazon ami
        *) log_msg "This script couldn't detect a supported distriution (dists parsed: ''$dist')."; ask_generic_distro
    esac
}

create_cert() {

    local domain=*.severalnines.local
    local commonname=$domain
    local san=dev.severalnines.local
    local country=SE
    local state=Stockholm
    local locality=Stockholm
    local organization='Severalnines AB'
    local organizationalunit=Severalnines
    local email=support@severalnines.com
    local keylength=2048
    local expires=1825
    local keyname=server.key
    local certname=server.crt
    local csrname=server.csr

    cat > /tmp/v3.ext << EOF
basicConstraints = CA:FALSE
#authorityKeyIdentifier=keyid,issuer
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = DNS:${san}
EOF

    echo "==> Generating tls certificate for $domain"
    # ubunutu 18.0x workaround
    touch $HOME/.rnd
    openssl genrsa -out $keyname $keylength

    openssl req -new -key $keyname -out $csrname \
        -addext "subjectAltName = DNS:${san}" \
        -subj "/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalunit/CN=$commonname/emailAddress=$email" &>/dev/null

    if [[ $? -ne 0 ]]; then
        # centos 6 -addtext is not avaiable
        openssl req -new -key $keyname -out $csrname \
            -subj "/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalunit/CN=$commonname/emailAddress=$email"
    fi
    openssl x509 -req -extfile /tmp/v3.ext -days $expires -sha256 -in $csrname -signkey $keyname -out $certname

    rm -f /tmp/v3.ext
    cd - &>/dev/null
}

main() {
    # check distro
    check_os
    if [[ "${dist}" == "redhat" ]]; then
        command -v chkconfig || dnf -y install chkconfig
    fi

    trap cleanup EXIT
    INSTALLATION_STATUS=1
    LAST_MSG=""
    repo_http_protocol="http"
    [[ ! -z $REPO_USE_TLS ]] && repo_http_protocol="https"
    message="This script will add Severalnines repository server for deb and rpm packages and  \
        \ninstall the ClusterControl Web Applicaiton and Controller. \
        \nAn Apache and MySQL server will also be installed. An existing MySQL Server on this host can be used."

    [[ `whoami` != "root" ]] && echo -e "Do: sudo $(basename $0) or run as root\n" && echo -e "$message" && exit 1

    # Check if the OS is a 64 bit one. If it's a 32 bit, the installation fails
    # with a non'very descriptive message
    if [[ "$(uname -m)" != 'x86_64'  ]]; then
        log_msg "ClusterControl is only compatible with x86_64 systems" && exit 1
    fi

    if [[ ! -z $NO_INET ]]; then
        log_msg ""
        log_msg "Detected NO_INET is set, i.e., OFFLINE install."
        log_msg "Please follow the instructions in the online manual, https://severalnines.com/docs/installation.html#offline-installation"
        exit 0
    fi

    while [[ $# > 0  ]]; do
        arg="$1"
        case "$arg" in
            -v|--verbose)
                PROMPT_USER=1
                shift
                ;;
            -1|--version1)
                # install v1 of the frontend
                CCVERSION=0
                ;;
            -2|--version2)
                # install only v2 of the frontend
                CCVERSION=2
                ;;
            *)
                log_msg "Unknown option $arg"
                exit 1
                ;;
        esac
        shift
    done

    cc_version=${CCVERSION:-2}

    echo "!!"
    log_msg "Only RHEL/RockyLinux/AlmaLinux 8|9, Debian 10|11|12, Ubuntu 20.04|22.04|24.04 LTS versions are supported"

    cc_api_token=$(cat /proc/sys/kernel/random/uuid | sha1sum | cut -f1 -d' ')
    CONTAINER="NA"
    [[ -f /.dockerenv ]] && CONTAINER="docker"
    grep -qa container=lxc /proc/1/environ &>/dev/null
    [[ $? -eq 0 ]] && CONTAINER="lxc"

    running_mysql=1
    if [[ -f /usr/libexec/mysqld || -f /usr/sbin/mysqld ]]; then
        ps -C mysqld &>/dev/null
        running_mysql=$?
    elif [[ -f /usr/sbin/mariadbd ]]; then
        ps -C mariadbd &>/dev/null
        running_mysql=$?
    fi

    if [[ $running_mysql -eq 1 ]]; then
        MEM_TOTAL=$(free -m | awk '/Mem:/ { print $2}')
        MEM_FREE=$(free -m | awk '/Mem:/ { print $ 4}')
        # default 512M
        if (( ${MEM_TOTAL} < 1500 )); then
            log_msg "Minimum system requirements: 2GB+ RAM, 2+ CPU cores"
            log_msg "Server Memory: ${MEM_TOTAL}M total, ${MEM_FREE}M free"
            INNODB_BUFFER_POOL_SIZE=${INNODB_BUFFER_POOL_SIZE:-512}
        else
            SIZE=$((50*${MEM_TOTAL}/100))
            INNODB_BUFFER_POOL_SIZE=${INNODB_BUFFER_POOL_SIZE:-${SIZE}}
            log_msg "System RAM is > 1.5G"
            log_msg "Setting MySQL innodb_buffer_pool_size to 50% of system RAM"
        fi
        log_msg "MySQL innodb_buffer_pool_size set to ${INNODB_BUFFER_POOL_SIZE}M"
        echo ""

        MIN_FREE_MEMORY=${MIN_FREE_MEMORY:-100}
        if (( ${INNODB_BUFFER_POOL_SIZE} + ${MIN_FREE_MEMORY} > ${MEM_FREE} )); then
            log_msg "You do not have enough free memory ${MEM_FREE}M available to set innodb_buffer_pool_size=${INNODB_BUFFER_POOL_SIZE}M"
            log_msg "Need at least 100M or more free memory in addition to what innodb_buffer_pool_size will allocate."
            log_msg "You can set a custom size for example with 'INNODB_BUFFER_POOL_SIZE=512 ./install-cc' and try again."
            if [[ -z $S9S_CMON_PASSWORD ]]; then
                read -p "=> Enter new innodb_buffer_pool_size (in MB, e.g, 512): " x
                [[ ! -z $x ]] && INNODB_BUFFER_POOL_SIZE=$x
                log_msg "Using new innodb_buffer_pool_size ${INNODB_BUFFER_POOL_SIZE}M"
                echo ""
            else
                exit 1
            fi
        fi
    fi

    log_msg "Severalnines would like your help improving our installation process."
    log_msg "Information such as OS, memory and install success helps us improve how we onboard our users."
    log_msg "None of the collected information identifies you personally."
    log_msg "!!"
    if [[ ! -z ${SEND_DIAGNOSTICS} ]] || confirm "=> Would you like to help us by sending diagnostics data for the installation? (Y/n): " "y"; then
        SEND_DIAGNOSTICS=${SEND_DIAGNOSTICS:-1}
    fi
    echo ""

    [[ ! -z $message ]] && echo -e $message
    echo ""

    until set_root_password; do
        log_msg ""
        log_msg "Password mismatch! Try again."
        sleep 1
    done
    [ -z ${root_password+x} ] || S9S_ROOT_PASSWORD="${root_password}"
    echo ""
    until set_cmon_password; do
        log_msg ""
        log_msg "Password mismatch! Try again."
        sleep 1
    done
    [ -z ${cmon_password+x} ] || S9S_CMON_PASSWORD="${cmon_password}"

    if [[ "$dist" == "debian" ]]; then
        waitForLocks
        log_msg "Installing required packages ..."
        apt-get install -yq wget bc gnupg dmidecode
        case "${os_codename}" in
            'focal' | 'bionic' | 'jammy' | 'noble')
                log_msg "Installing python ..."
                apt-get install -yq python3
                update-alternatives --install /usr/bin/python python /usr/bin/python3 1
                ;;
            *)
                log_msg "Installing python ..."
                apt-get install -yq python
                ;;
        esac
        python --version | grep -q 3.
        [[ $? -eq 0 ]] && PYTHON3=1

        if ! command -v add-apt-repository &>/dev/null; then
            case "${os_codename}" in
                'stretch'|'buster'|'bullseye'|'bookworm'|'xenial'|'focal'|'jammy'|'noble')
                    log_msg "Installing software-properties-common ..."
                    apt-get install -yq software-properties-common
                    ;;
                *)
                    log_msg "Installing python-software-properties ..."
                    apt-get install -yq python-software-properties
                    ;;
            esac
        fi
    fi

    if [[ "$dist" == "redhat" ]]; then
        log_msg "Installing required packages ..."
        yum install -yq wget dmidecode hostname
        log_msg "Installing python ..."
        if [[ $rhel_version == "8" ]]; then
            yum install -y python36
            alternatives --set python /usr/bin/python3
        else
            yum install -y python
        fi
        python --version | grep -q 3.
        [[ $? -eq 0 ]] && PYTHON3=1
    fi

    wwwroot="/var/www/html"
    if [[ "$dist" == "debian" ]]; then
        wwwroot="/var/www"

        distro_id=$(lsb_release -s -i)
        distro_release=$(lsb_release -s -r)
        if [[ $? -eq 0 ]]; then
            distro_release=${distro_release%%.*}
            # Apache 2.4 uses new config
            if [[ ${distro_id} == "Ubuntu" ]]; then
                if (( $(echo "$distro_release > 12" | bc) )); then
                    use_apache24=1
                fi
            elif [[ ${distro_id} == "Debian" ]]; then
                if (( $(echo "$distro_release > 7" | bc) )); then
                    use_apache24=1
                fi
            fi
        else
            log_msg "Unable to determine distro release number ..."
            log_msg "Assuming > apache 2.4..."
            use_apache24=1
        fi
        [[ ! -z $use_apache24 ]] && wwwroot="/var/www/html"
    fi

    ip=($(hostname -I)) || ip=($(hostname -i))
    host="${HOST:-${ip[0]}}"

    [[ ${#ip[@]} > 1 && -z ${HOST} ]] && message="$message\nNOTE: Detected more than one IP: ${ip[@]}\nUsing hostname ${host} or do 'export HOST=<hostname>' to explicitly set a host"
    echo -e $message

    if command -v dig &>/dev/null; then
        echo ""
        echo "Determining network interfaces ..."
        ext_ip=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null)
        log_msg "Web application IP => https://${ext_ip}"
    fi

    if [[ -z ${HOST} ]]; then
        echo ""
        if ! ask_p "=> The CMON Controller's hostname will be set to $host. Do you want to change it? (y/N): " "n"; then
            read -p "=> Enter the hostname: " x
            [[ ! -z $x ]] && host="$x"
        fi
    fi
    log_msg "Using hostname $host"

    db_port=${S9S_DB_PORT:-3306}
    cmon_user=${S9S_CMON_USER:-"cmon"}
    cmon_password=${S9S_CMON_PASSWORD:-"cmon"}
    cmon_events_port=${S9S_EVENTS_PORT:-9510}
    cmon_cloud_port=${S9S_CLOUD_PORT:-9518}
    root_password=${S9S_ROOT_PASSWORD:-""}

    echo ""
    log_msg "Using web document root $wwwroot"
    mkdir -p $wwwroot

    install_cmon=0
    if ask "=> Install the ClusterControl Controller? (Y/n): " "y"; then
        install_cmon=1
        if [[ -z ${S9S_CMON_PASSWORD} && -f /etc/cmon.cnf ]]; then
            log_msg "An existing Controller installation detected!"
            log_msg "A re-installation of the Controller will overwrite the /etc/cmon.cnf file"
            if ask_p "=> Install the Controller? (y/N): " "n"; then
                install_cmon=0
            fi
        fi
    fi

    if [[ $running_mysql -eq 0  ]]; then
        if ask_p "=> Detected a running MySQL server. Should I use your existing MySQL server? (Y/n): " "y"; then
            use_existing_mysql=1
        fi
    fi

    if [[ -z $use_existing_mysql ]]; then
        log_msg "Installing the default distro MySQL Server ..."
    fi

    log_msg "Installing the ClusterControl Web Application ..."
    # install web app
    install_frontend

    [[ -f $wwwroot/clustercontrol/bootstrap.php.default ]] && VERSION=$(sed -n "s/^define('CC_UI_VERSION'.*'\(.*\)'.*/\1/p" $wwwroot/clustercontrol/bootstrap.php.default)
    track_install_init

    if [[ ${cc_version} == "0" || ${cc_version} == "1" ]]; then
        # Setup CC v1 UI
        log_msg "Installing MySQL and Apache server ..."
        track_install "2"
        track_install "3"
        install_ui_packages
        log_msg "Configuring the MySQL server ..."
        track_install "4"
        configure_database_server
        create_ui_bootstrap
        # reset permissions
        chmod -R ugo-w ${wwwroot}/clustercontrol &>/dev/null
        chmod -R ug+w ${wwwroot}/clustercontrol/app/tmp &>/dev/null
        chown -R ${www_user}.${www_user} $wwwroot/clustercontrol/
        log_msg "ClusterControl v1 frontend installed ..."
        if [[ ${cc_version} == "1" ]]; then
            configure_ccv2_web
            log_msg "ClusterControl v2 frontend installed ..."
        fi
    elif [[ ${cc_version} == "2" ]]; then
        # Setup CC v2 UI
        log_msg "Installing MySQL server ..."
        install_database_server
        log_msg "Configuring the MySQL server ..."
        configure_database_server
        log_msg "Installing Web / Apache server ..."
        install_web_server
        configure_ccv2_web
        log_msg "ClusterControl v2 frontend installed ..."
    fi

    log_msg "Web application setup completed!"

    # Install Controller
    if [[ $install_cmon -eq 1 ]]; then
        log_msg "Installing ClusterControl Controller ..."
        track_install "5"
        install_controller
        install_s9s_commandline
        if [[ ${cc_version} != "2" ]]; then
            create_cc_user
        fi
    fi

    # start events and ssh services
    start_cmon_services

    # restart the apache server - this is needed for the rpc_tls.crt
    log_msg "Restarting Apache server ..."
    [[ -f /var/lib/cmon/ca/cmon/rpc_tls.crt ]] || sleep 5
    $restart_apache || log_msg "Unable to restart the Apache Server ..."

    # success
    INSTALLATION_STATUS=0
    [[ ! -z ${ext_ip} ]] && host="${ext_ip}"
    log_msg "ClusterControl installation completed!"
    track_install "6"
    echo "Open your web browser to https://${host} and create a default Admin User."
    echo "If you want to uninstall ClusterControl then please follow the instructions here, https://severalnines.com/docs/administration.html#uninstall"
    exit 0
}

main "$@"
