awips2/deltaScripts/21.3.1/DR8327/postgresql-11.10-upgrade/_upgrade_postgresql_database.sh
2022-05-05 12:34:50 -05:00

246 lines
7.9 KiB
Bash

#!/bin/bash
# This script performs the PostgreSQL upgrade. This script should only be
# called by upgrade_postgresql_database.sh and not by itself. If the upgrade
# fails, you may rerun the script and it will start from the beginning.
#
# Do not Ctrl+C or otherwise interrupt the script while it is running as this
# may prevent proper cleanup.
#
# Author: tgurney
# $1 is the directory containing this script
here="$1"
source "$here/settings.sh" || exit 1
# directory for temporarily keeping config files from the data dir
temp_config_dir=$(mktemp -d) || exit 1
export LD_LIBRARY_PATH="${postgres_lib}:${psql_dir}/lib:$LD_LIBRARY_PATH"
# roll back as much as possible in the event of an error
cleanup_exit() {
echo "INFO: Cleaning up"
# remove symlinked psql
if [[ -h "${postgres_dir}/bin/psql" ]]; then
rm -vf "${postgres_dir}/bin/psql"
fi
# put back any tablespaces that had been moved
for ts_dir in "${tablespaces[@]}"; do
if [[ -d "${temp_new_data}/${ts_dir}" && ! -e "${postgres_data_dir}/${ts_dir}" ]]; then
mv -fv "${temp_new_data}/${ts_dir}" "${postgres_data_dir}/${ts_dir}"
fi
done
# restore original pg_hba.conf
if [[ -f "${temp_config_dir}/pg_hba.conf" ]]; then
cp -fv "${temp_config_dir}/pg_hba.conf" "${postgres_data_dir}/pg_hba.conf"
fi
# clean up temp directories
rm -rf "${temp_config_dir}"
rm -rf "${temp_old_data}"
rm -rf "${temp_new_data}"
sync
echo -e "\nERROR: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "ERROR: !! UPGRADE FAILED !!"
echo "ERROR: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo -e "\nERROR: One or more errors occurred. See above output."
echo -en "\nAny changes made by this script have been rolled back. You "
echo -en "may run this script again once any issues have been resolved.\n"
exit 1
}
if [[ ! -d "${postgres_data_dir}" ]]; then
echo "ERROR: Specified PostgreSQL data dir ${postgres_data_dir} does not exist."
echo "ERROR: Cannot continue."
cleanup_exit
fi
if [[ -d "${postgres_copy_of_old}_done" ]]; then
echo "INFO: PostgreSQL upgrade has already been completed."
exit 0
fi
if [[ ! -d "${postgres_copy_of_old}" ]]; then
echo -n "ERROR: Did not find the old version of PostgreSQL at "
echo "${postgres_copy_of_old}. Upgrade might already be complete."
echo "ERROR: Cannot continue."
cleanup_exit
fi
if [[ "${postgres_version}" != "${new_ver}" ]]; then
echo -n "ERROR: Currently installed version of PostgreSQL is "
echo "${postgres_version}. Expected ${new_ver}. Cannot continue."
cleanup_exit
fi
if [[ "${psql_version}" != "${new_ver}" ]]; then
echo -n "ERROR: Currently installed version of psql is "
echo "${psql_version}. Expected ${new_ver}. Cannot continue."
cleanup_exit
fi
${postgres_dir}/bin/pg_ctl -D "${postgres_data_dir}" status
if [[ "$?" -eq 0 ]]; then
echo "ERROR: It looks like PostgreSQL is running. Cannot continue."
cleanup_exit
fi
# This doesn't appear to work consistently, so we cannot guarantee proper
# cleanup on Ctrl+C or other interruption.
trap cleanup_exit SIGINT SIGTERM
# Identify any tablespaces that need to be moved after running pg_upgrade
tablespaces=()
for ts_link in "${pg_tblspc}"/* ; do
this_ts=$(readlink "${ts_link}")
if [[ "${this_ts}" == "${postgres_data_dir}"* ]]; then
echo "INFO: ${this_ts} is inside the data dir. It will be moved temporarily"
tablespaces+=("$(basename ${this_ts})")
fi
done
echo -e "\nINFO: Backing up config files"
for conf in "${config_files[@]}"; do
if [[ -f "${postgres_data_dir}/${conf}" ]]; then
cp -v "${postgres_data_dir}/${conf}" "${temp_config_dir}/${conf}" || cleanup_exit
else
echo "INFO: $conf does not exist, skipping this one"
fi
done
echo "INFO: Done backing up config files"
echo -e "\nINFO: Initializing new cluster at ${temp_new_data}"
rm -rf "${temp_new_data}"
"${initdb}" -D "${temp_new_data}" || cleanup_exit
echo -e "\nINFO: Starting new cluster on port ${temp_port}"
"${postgres_dir}/bin/postgres" --port="${temp_port}" -D "${temp_new_data}" 2>&1 &
echo "INFO: Waiting 10 seconds for cluster to start"
sleep 10 || cleanup_exit
"${psql}" --port="${temp_port}" --db=postgres -c 'select 1 test;'
if [[ "$?" != "0" ]]; then
echo "ERROR: Test query failed"
cleanup_exit
fi
if [[ -n "${is_openfire}" ]]; then
echo -e "\nINFO: Setting up awips db user"
"${psql}" --port="${temp_port}" --db=postgres << EOF
begin;
alter role awips with password 'awips';
commit;
EOF
else
echo -e "\nINFO: Setting up $db_admin_user db user"
"${psql}" --port="${temp_port}" --db=postgres -c \
'create role awipstmp with login superuser createdb createrole;'
"${psql}" --port="${temp_port}" --db=postgres --user=awipstmp << EOF
begin;
alter role awips rename to $db_admin_user;
alter role awipstmp with nologin;
commit;
EOF
"${psql}" --port="${temp_port}" --db=postgres --user=$db_admin_user << EOF
begin;
alter role $db_admin_user with password 'awips';
drop role awipstmp;
commit;
EOF
fi
echo -e "\nINFO: Stopping new cluster"
"${postgres_dir}/bin/pg_ctl" -D "${temp_new_data}" stop
sleep 3 || cleanup_exit
# prevent pg_upgrade from prompting for a password for the old cluster
echo -e "\nINFO: Updating old pg_hba.conf to trust local connections"
grep -E "local\s+all\s+all\s+trust" "${postgres_data_dir}/pg_hba.conf" >/dev/null
if [[ "$?" -ne 0 ]]; then
echo -e "local\tall\tall\ttrust" >> "${postgres_data_dir}/pg_hba.conf" || cleanup_exit
fi
# Need to symlink psql,
# because pg_upgrade expects $postgres_dir/bin/psql to exist
echo -e "\nINFO: Creating link to ${psql} at ${postgres_dir}/bin/psql"
if [[ ! -x "${postgres_dir}/bin/psql" ]]; then
ln -fvs "${psql}" "${postgres_dir}/bin/psql" || cleanup_exit
fi
echo -e "\nINFO: Starting upgrade"
# Run pg_upgrade twice, first time is a read-only compatibility check.
for check in yes no; do
if [[ "${check}" == "yes" ]]; then
check="--check"
else
check=""
fi
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${postgres_copy_of_old}/lib" \
"${pg_upgrade}" ${check} --jobs=4 --link \
--old-port="${temp_port}" \
--new-port="${temp_port}" \
--old-bindir="${postgres_copy_of_old}/bin" \
--new-bindir="${postgres_dir}/bin" \
--old-datadir="${postgres_data_dir}" \
--new-datadir="${temp_new_data}" \
--username="${db_admin_user}" \
|| cleanup_exit
done
# Point of no return, no cleanup/rollback is possible.
trap - SIGINT SIGTERM
# These scripts are created by pg_upgrade but are not needed.
# We provide our own script (rebuild_stats_and_hash_indexes.sh) instead.
rm -f analyze_new_cluster.sh
rm -f reindex_hash.sql
echo -e "\nINFO: Copying config files to new data directory"
for conf in "${config_files[@]}"; do
if [[ -f "${temp_config_dir}/${conf}" ]]; then
cp -v "${temp_config_dir}/${conf}" "${temp_new_data}/${conf}"
fi
done
echo -e "\nINFO: Moving tablespaces"
for ts_dir in "${tablespaces[@]}"; do
mv -v "${postgres_data_dir}/${ts_dir}" "${temp_new_data}"
done
echo "INFO: Done moving tablespaces"
echo -e "\nINFO: Moving new data dir to ${postgres_data_dir}"
rm -rf "${temp_old_data}"
mkdir "${temp_old_data}"
mv "${postgres_data_dir}"/* "${temp_old_data}"
mv "${temp_new_data}"/* "${postgres_data_dir}"
echo -e "\nINFO: Deleting temp directories"
rm -rf "${temp_old_data}"
rm -rf "${temp_new_data}"
rm -rf "${temp_config_dir}"
echo -e "\nINFO: Removing symlinked psql"
if [[ -h "${postgres_dir}/bin/psql" ]]; then
rm -f "${postgres_dir}/bin/psql"
fi
echo -e "\nINFO: Syncing disks"
sync
echo -e "\nINFO: Moving old PostgreSQL install to ${postgres_copy_of_old}_done"
mv "${postgres_copy_of_old}" "${postgres_copy_of_old}_done"
echo -e "\nINFO: ****************************************"
echo "INFO: ** UPGRADE COMPLETE **"
echo "INFO: ****************************************"