#!/bin/bash



#Preupgrade Assistant performs system upgradability assessment
#and gathers information required for successful operating system upgrade.
#Copyright (C) 2013 Red Hat Inc.
#Honza Horak <hhorak@redhat.com>, Petr Stodulka <pstodulk@redhat.com>
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.
. /usr/share/preupgrade/common.sh
check_rpm_to "" ""
#END GENERATED SECTION

# This check can be used only if you need root privileges
check_root

export POSTMIGRATE_D="$VALUE_TMP_PREUPGRADE/postmigrate.d"
export my_libs=1
export my55_libs=1
export my_serv=1
export my55_serv=1

# original mysql include mysql-libs files on RHEL 5
is_pkg_installed "mysql" \
  && is_dist_native "mysql" \
  && my_libs=0
is_pkg_installed "mysql55-mysql-libs" \
  && is_dist_native "mysql55-mysql-libs" \
  && my55_libs=0
is_pkg_installed "mysql-server" \
  && is_dist_native "mysql-server" \
  && my_serv=0
is_pkg_installed "mysql55-mysql-server" \
  && is_dist_native "mysql55-mysql-server" \
  && my55_serv=0

[ $my_libs -eq 1 ] && [ $my55_libs -eq 1 ] && {
  # there is not anything we can do
  exit_not_applicable
}

# MariaDB packages are in obsoleted group and these are not installed now
# atuomatically. Install the main packages for now.
add_pkg_to_kickstart "mariadb-libs"

[ $my_serv -eq 0 ] || [ $my55_serv -eq 0 ] && {
  add_pkg_to_kickstart "mariadb-server"
}


source ../mysql-common.sh

# filters comments that has # in the beggining of the line from stdin
filter_comments() {
    grep -v -e '^[[:space:]]*$' -e '^[[:space:]]*#' | sed 's|[[:space:]]*#.*||'
}

export OPTION_NOT_OK_FILE=option_not_ok
export OPTION_FIXED_FILE=option_fixed
export CONFIG_LIST=config_list
export tmp_file=$(mktemp /tmp/.mysqlconfigXXX)
rm -f $OPTION_NOT_OK_FILE
rm -f $OPTION_FIXED_FILE
rm -f $CONFIG_LIST

[ -f "$tmp_file" ] || {
  log_error "The $tmp_file file was not created."
  exit_error
}

medium_unsup_plug=0
high_unsup_innodb=0
high_depre_lang=0

get_mysqld_ports() {
    conf_get_section "$1" "mysqld" \
      | filter_comments \
      | grep "^[[:space:]]*port[[:space:]]*=[[:space:]]*[0-9][0-9]*" \
      | sed -e "s/^[[:space:]]*port[[:space:]]*=[[:space:]]*\([0-9][0-9]*\).*$/\1/"
}

# check options in file $1
# recursion level is in $2
check_options() {
    # recursion level limit so we do not cycle for ever
    [ $# -ne 2 ] && log_warning "check_options accepts two arguments" && return 1
    [ $2 -gt 5 ] && log_warning "check_options recursion level exceeded" && return 2
    CONFIG_FILE=$1
    log_debug  "checking the $CONFIG_FILE configuration file"
    backup_config "$CONFIG_FILE"
    #$DIRTYCONF_D is defined inside ../mysql-common.sh
    BACKUPED_CONFIG_FILE="${DIRTYCONF_D}/$CONFIG_FILE"
    echo "$CONFIG_FILE" >> "$CONFIG_LIST"

    # remove comments and empty lines
    filtered_conf="$(cat "$CONFIG_FILE" | filter_comments)"

    # starting from MariaDB/MySQL 5.5, innodb is the default storage engine,
    # so innodb plugin is not possible to be installed any more.
    echo "$filtered_conf" | grep -e '^[[:space:]]*plugin-load=innodb=' >/dev/null
    innodb_plugin_loaded=$?
    echo "$filtered_conf" | grep -e '^[[:space:]]*ignore-builtin-innodb' >/dev/null
    builtin_innodb_ignored=$?
    if [ $innodb_plugin_loaded -eq 0 ] && [ $builtin_innodb_ignored -eq 1 ]; then
        echo "innodb_plugin_loaded" >> "$tmp_file"
        log_medium_risk "${CONFIG_FILE}: the 'plugin-load=innodb=' option is not supported"
        sed -i -e 's/plugin-load=innodb=/#plugin-load=innodb=/g' $BACKUPED_CONFIG_FILE
        [ $? -eq 0 ] \
            && echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_FIXED_FILE" \
            || echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_NOT_OK_FILE"
    fi

    # innodb_file_io_threads changed to innodb_read_io_threads and innodb_write_io_threads
    echo "$filtered_conf" | grep -e '^[[:space:]]*innodb_file_io_threads' >/dev/null
    if [ $? -eq 0 ]; then
        echo "innodb_file_io_threads" >> "$tmp_file"
        log_high_risk "${CONFIG_FILE}: the 'innodb_file_io_threads' option is not supported"
        sed -i -e 's/innodb_file_io_threads/#innodb_file_io_threads/g' $BACKUPED_CONFIG_FILE
        [ $? -eq 0 ] \
            && echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_FIXED_FILE" \
            || echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_NOT_OK_FILE"
    fi

    # table_cache was renamed to table_open_cache
    echo "$filtered_conf" | grep -e '^[[:space:]]*table_cache' >/dev/null
    if [ $? -eq 0 ]; then
        echo "table_cache" >> "$tmp_file"
        log_slight_risk "${CONFIG_FILE}: the 'table_cache' option was renamed to 'table_open_cache'"
        sed -i -e 's/table_cache/table_open_cache/g' $BACKUPED_CONFIG_FILE
        [ $? -eq 0 ] \
            && echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_FIXED_FILE" \
            || echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_NOT_OK_FILE"
    fi

    # language changed to lc_messages_dir and lc_messages
    echo "$filtered_conf" | grep -e '^[[:space:]]*language\s*=' >/dev/null
    if [ $? -eq 0 ]; then
        echo "language" >> "$tmp_file"
        log_high_risk "${CONFIG_FILE}: the 'language' option is deprecated"
        sed -i -e 's/language\s*=/#language=/g' $BACKUPED_CONFIG_FILE
        [ $? -eq 0 ] \
            && echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_FIXED_FILE" \
            || echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_NOT_OK_FILE"
    fi

    for i in log-bin-trust-routine-creators table_lock_wait_timeout bdb bdb-home bdb-lock-detect bdb-logdir bdb-no-recover bdb-no-sync bdb-shared-data bdb-tmpdir sync-bdb-logs enable-pstack federated merge ndbcluster ; do
        echo "$filtered_conf" | grep -e "^[[:space:]]*${i}\W" >/dev/null
        if [ $? -eq 0 ]; then
            echo "obsolete_options_used" >> "$tmp_config"
            log_high_risk "${CONFIG_FILE}: the '$i' option was removed in MariaDB 5.5"
            sed -i -e "s/${i}\s*/#${i}/g" $BACKUPED_CONFIG_FILE
            [ $? -eq 0 ] \
                && echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_FIXED_FILE" \
                || echo "$BACKUPED_CONFIG_FILE" >> "$OPTION_NOT_OK_FILE"
        fi
    done

    # check set ports
    ports="$(get_mysqld_ports "$CONFIG_FILE")"
    [ -n "$ports" ] && echo "port $ports" >> "$tmp_file"


    # directive include includes the specified configuration file
    includefile=
    echo "$filtered_conf" | grep -uhe '!include[[:space:]]' \
                          | sed -e 's/.*!include[[:space:]]*\([^#]*\).*$/\1/' \
                          | while IFS= read includefile || [ -n "$includefile" ]; do
        if [ -f "$includefile" ] ; then
            check_options "$includefile" $(($2 + 1)) \
                || echo "$includefile" >> "$OPTION_NOT_OK_FILE"
        fi
    done

    # directive includedir includes all configuration files *.cnf
    includedir=
    echo "$filtered_conf" | grep -uhe '!includedir[[:space:]]' \
                          | sed -e 's/.*!includedir[[:space:]]*\([^#]*\).*$/\1/' \
                          | while IFS= read includedir || [ -n "$includedir" ]; do
        for includefile in ${includedir}/*.cnf ; do
            if [ -f "$includefile" ] ; then
                check_options "$includefile" $(($2 + 1)) \
                    || echo "$includefile" >> "$OPTION_NOT_OK_FILE"
            fi
        done
    done

}

# we don't check users' configurations, since they don't provide
# server configuration
if [ -f "/etc/my.cnf" ]; then
  check_options "/etc/my.cnf" 1 \
      || echo "/etc/my.cnf" >> "$OPTION_NOT_OK_FILE"
fi
if [ -f "/opt/rh/mysql55/root/etc/my.cnf" ]; then
  check_options "/opt/rh/mysql55/root/etc/my.cnf" 1 \
      || echo "/opt/rh/mysql55/root/etc/my.cnf" >> "$OPTION_NOT_OK_FILE"
fi

result=$RESULT_INFORMATIONAL

grep -q "^innodb_plugin_loaded" "$tmp_file" && {
    result=$RESULT_FAILED
    cat >> $SOLUTION_FILE <<EOF

* The InnoDB plug-in is now a default storage engine in MariaDB 5.5.
This configuration is using the old 'plugin-load=innodb=' configuration option.
Either remove this directive from the configuration files or use
'ignore-builtin-innodb' because the current directives will not work.
EOF
}

grep -q "^innodb_file_io_threads" "$tmp_file" && {
    result=$RESULT_FAILED
    cat >> $SOLUTION_FILE <<EOF

* The configuration option 'innodb_file_io_threads' was removed in MariaDB 5.5
and replaced with 'innodb_read_io_threads' and 'innodb_write_io_threads'.
To ensure proper functionality, change your configuration to use the
new configuration directives.
EOF
}

grep -q "^table_cache" "$tmp_file" && {
    result=$RESULT_FAILED
    cat >> $SOLUTION_FILE <<EOF

* The configuration option 'table_cache' was renamed to 'table_open_cache'
in MariaDB 5.5.
To ensure proper functionality, change your configuration to use the
new configuration directives.
EOF
}

grep -q "^language$" "$tmp_file" && {
    result=$RESULT_FAILED
    cat >> $SOLUTION_FILE <<EOF

* MySQL 5.0 used the 'language' variable for specifying the directory which
included the error message file. This option is now deprecated and has been
replaced by the 'lc_messages_dir' and 'lc_messages' options.
This also applies to options in the configuration files.
EOF
}

grep -q "^obsolete_options_used" "$tmp_file" && {
  result=$RESULT_FAILED
  cat >> $SOLUTION_FILE <<EOF

* The following options specified in your MySQL configuration files are
not supported in MariaDB 5.5: bdb, bdb-home, bdb-lock-detect, bdb-logdir, bdb-no-recover,
bdb-no-sync, bdb-shared-data, bdb-tmpdir, sync-bdb-logs, enable-pstack,
federated, merge, ndbcluster, log-bin-trust-routine-creators, and
table_lock_wait_timeout. They must be removed.
EOF
}

grep "^port " "$tmp_file" | grep -vq "^port 3306$" && {
  result=$RESULT_FAILED
  log_medium_risk "Found a used non-default port for mysqld. SELinux context has to be set for these ports."
  cat >> $SOLUTION_FILE <<EOF
* The mysqld (MySQL 5.0 or MySQL 5.5) has set a different port to use than
the default 3306. The SELinux context must be set for such ports to mysqld_port_t.
You can do that using semanage like that:

EOF

line=
while IFS= read line || [ -n "$line" ]; do
  echo "$line" | grep -q "^port " || continue
  _port=$(echo "$line" | grep -o "[0-9][0-9]*$")
  echo "  # semanage port -a -t mysqld_port_t -p tcp $_port" >> "$SOLUTION_FILE"
done < "$tmp_file"

#TODO: It will be done automatically by the postmigrate script. - not possible now
}

if [ -f "$OPTION_FIXED_FILE" ] ; then
    # this is not fixed really - files still need modification by user if he want to
    # have really "same" behaviour as in old system
    #echo "Some configuration files were fixed" >> solution.txt
    echo -e "\n
To provide at least basic functionality, some options were commented out
in the files listed below.
You should replace them with options suitable for your environment that
provide the same functionality as you have now:" >> "$SOLUTION_FILE"
    if [ -f "$OPTION_NOT_OK_FILE" ]; then
      # print only files which are not inside $OPTIONS_NOT_OK_FILE
      grep -vwF "$(cat "$OPTION_NOT_OK_FILE" | sort | uniq)" "$OPTION_FIXED_FILE" \
        | sort | uniq  >> "$SOLUTION_FILE"
    else
      cat "$OPTION_FIXED_FILE" | sort | uniq >> "$SOLUTION_FILE"
    fi
    result=$RESULT_FAILED
fi

if [ ! -f "$OPTION_NOT_OK_FILE" ]; then
    [ ! -f "$OPTION_FIXED_FILE" ] \
      && log_info "No problems with options were found in the MySQL configuration."
else
    echo "\n
Some options were not commented out in the files listed below and therefore MariaDB 5.5 might crash unexpectedly.
The listed options should be replaced or commented out manually:" >> "$SOLUTION_FILE"
    cat "$OPTION_NOT_OK_FILE" | sort | uniq >> "$SOLUTION_FILE"
    log_medium_risk "Some configuration files have to be modified manually after migration. See the report."
    result=$RESULT_FAILED
fi

log_info "All processed configuration files are stored in the $DIRTYCONF_D directory."

if [ "$result" == "$RESULT_FAILED" ]; then
    echo "
The files mentioned above are backups of your original configuration files
that are modified, and the affected lines are commented out.
" >> "$SOLUTION_FILE"
## Obsoleted text.
#After the migration you should replace the contents of the default
#MariaDB 5.5 configuration (as is appropriate to your environment) manually, with the
#information provided about replaced or deprecated options listed in the
#backups. You must restart MariaDB for these changes to take effect.
#"
#
fi

########## COMMENT OUT - UNPREPARED ################
# TODO: automatic migration and application of the configuration files
#       is problematic. In case of mysql55 we have to modify configuration
#       files more strictly because of the used prefix /opt/rh/mysql55/root/
#FIXME: troubles with logrotate, .... files which are not backed up now.
############ POSTMIGRATE ##################
##
## Well, this is ugly. Probably better would be some control, if the files
## were modified or not and should not be applied when the default config files
## were found. But now will be applied always.
##
#log_info "MySQL configuration files will be automatically applied on target system."
#mkdir "$POSTMIGRATE_D/mysql"
#cp "mysql-conf.sh" "$CONFIG_LIST" "$POSTMIGRATE_D/mysql"
#chmod +x "$POSTMIGRATE_D/mysql/mysql-conf.sh"
#grep "^port " "$tmp_file" | grep -v "^port 3306$" >> "$POSTMIGRATE_D/mysql/ports"
#grep -Ee "^mysql(d|55-mysqld).*:on" "$VALUE_CHKCONFIG" "$POSTMIGRATE_D/mysql/service"
#
#if [ $? -eq 0 ]; then
#    echo "log_info 'Enable mariadb service.'" >> "$POSTMIGRATE_DIR/mysql/mysql-conf.sh"
#    echo "systemctl enable mariadb" >> "$POSTMIGRATE_DIR/mysql/mysql-conf.sh"
#    log_info "The mariadb sesrvice will be enabled on target machine."
#else
#    # This is default, but just to be sure...
#    echo "systemctl disable mariadb" >> "$POSTMIGRATE_DIR/mysql/mysql-conf.sh"
#    log_info "The mariadb service will be disabled on target machine."
#fi
#
#_lines=$(wc -l "$POSTMIGRATE_D/mysql/service")
#[ $_lines -gt 1 ] && {
#  msg="You have enabled mysqld and mysql55-mysqld services."
#  msg+=" See the report for description of migration issue."
#  log_high_risk "$msg"
#  cat >> $SOLUTION_FILE <<EOF
#
#* The mysqld and mysql55-mysqld services are enabled on this system, but only
#one set of configuration files can be applied on target system. In this case
#configuration of newer mysql55-mysqld will be prefered. If you want to specify
#which set of the configuration files should be used, please disable one of
#these services and run preupg again. Th
#EOF
#}

rm -f "$tmp_file"
exit $result
