diff --git a/bin/postgresql-setup.in b/bin/postgresql-setup.in index 9626dd9..1b8bcfa 100644 --- a/bin/postgresql-setup.in +++ b/bin/postgresql-setup.in @@ -59,6 +59,16 @@ option_upgradefrom="@NAME_DEFAULT_PREV_SERVICE@" srvsuff= test 0 -eq @WANT_SYSVINIT@ && srvsuff=".service" +if [ @PGMAJORVERSION@ -ge 18 ]; then + checksums_default_line=" + Default behavior when initializing (not upgrading). + To upgrade to PostgreSQL @PGMAJORVERSION@ without + enabling data checksums, add --no-data-checksums + to PGSETUP_INITDB_OPTIONS (will override this flag) + If data checksums are already enabled, there is no + need to specify this flag." +fi + USAGE_STRING=$"\ Usage: $0 MODE_OPTION [--unit=UNIT_NAME] [OPTION...] @@ -97,6 +107,9 @@ Options: --upgrade-from=ID Specify id \"old\" postgresql stack to upgrade from. List of available IDs can be listed by --upgrade-ids. Default is '$option_upgradefrom'. + --data-checksums Enable data checksums for the data directory. + If upgrading, they will be enabled before + performing the upgrade.${checksums_default_line} Other options: --help show this help @@ -161,6 +174,15 @@ perform_initdb() $RESTORECON "$initdb_log" test -w "$initdb_log" || echo "$initdb_log is not writeable by $USER" + # add option to enable data checksums if flag provided + if [ "${option_data_checksums:-0}" -eq 1 ] && [ @PGMAJORVERSION@ -lt 18 ]; then + if [ -n "$PGSETUP_INITDB_OPTIONS" ]; then + export PGSETUP_INITDB_OPTIONS="$PGSETUP_INITDB_OPTIONS --data-checksums" + else + export PGSETUP_INITDB_OPTIONS="--data-checksums" + fi + fi + # Initialize the database initdbcmd+=( "$PGENGINE"/initdb --pgdata="$pgdata" --auth=ident ) eval "initdbcmd+=( $PGSETUP_INITDB_OPTIONS )" @@ -213,6 +235,30 @@ old_data_in_use() } +enable_checksums() +{ + local old_datadir="$1" + local old_bindir="$2" + + if [ "${option_data_checksums:-0}" -eq 1 ] \ + && ! echo "$PGSETUP_INITDB_OPTIONS" | grep -qE -- "--no-data-checksums"; then + debug "enabling data checksums" + local enable_checksums_result + enable_checksums_result=$("$old_bindir"/pg_checksums -e "$old_datadir" 2>&1) + local enable_checksums_code=$? + if [ ! $enable_checksums_code ]; then + error "Could not enable checksums!" + error_q $"$enable_checksums_result" + return 1 + fi + elif [ "${option_data_checksums:-0}" -eq 1 ]; then + warn "Both --data-checksums and --no-data-checksums flags specified," + warn_q "upgrading without enabling data checksums!" + option_data_checksums=0 + fi +} + + upgrade() { local inplace=false @@ -243,6 +289,32 @@ upgrade() exit 5 fi + info "Checking data checksums" + # timeout for large databases, if checksums are disabled, this command will fail fast + checksums_result=$(timeout 1 "$upgradefrom_engine"/pg_checksums "$upgradefrom_data" 2>&1) + checksums_code=$? + # if timed out, the exit code is 124 + if [ $checksums_code -ne 0 ] && [ $checksums_code -ne 124 ]; then + if echo "$checksums_result" | grep -q "not enabled"; then + if [ "${option_data_checksums:-0}" -ne 1 ] \ + && ! echo "$PGSETUP_INITDB_OPTIONS" | grep -qE -- "--no-data-checksums" \ + && [ @PGMAJORVERSION@ -ge 18 ]; then + error "PostgreSQL @PGMAJORVERSION@ has data checksums enabled by default," + error_q "while your current data directory does not. Please either use the" + error_q "--data-checksums flag to enable them before upgrading, or add" + error_q "--no-data-checksums to the PGSETUP_INITDB_OPTIONS environment variable." + exit 1 + else + debug "checksums flags provided" + fi + else + # this means that checksums are enabled but something else failed + error "Checksum check failed! Output from pg_checksums:" + error_q $"$checksums_result" + exit 1 + fi + fi + # Set up log file for pg_upgrade rm -f "$upgrade_log" touch "$upgrade_log" || die "can't write into $upgrade_log file" @@ -275,6 +347,8 @@ upgrade() info $"Upgrading database." + enable_checksums "$pgdataold" "$upgradefrom_engine" + scls_upgrade_hacks= test -n "$upgradefrom_scls" && { debug "scls [$upgradefrom_scls] will be enabled" @@ -642,7 +716,7 @@ long_opts="\ initdb,upgrade,\ new-systemd-unit,upgrade-ids,\ unit:,service:,port:,datadir:,upgrade-from:,upgrade-from-unit:,\ -debug,\ +data-checksums,debug,\ version,help,usage" args=`getopt -o "$short_opts" -l "$long_opts" -n "@NAME_BINARYBASE@-setup" -- "$@"` \ @@ -701,6 +775,11 @@ while true; do exit 0 ;; + --data-checksums) + option_data_checksums=1 + shift + ;; + --version) print_version exit 0 diff --git a/tmt/plans/fedora-checksums.fmf b/tmt/plans/fedora-checksums.fmf new file mode 100644 index 0000000..5659893 --- /dev/null +++ b/tmt/plans/fedora-checksums.fmf @@ -0,0 +1,8 @@ +name: /plans/fedora +summary: Run tests in a fedora virtual machine environment +discover: + how: fmf + directory: tests/ + filter: tag:fedora-checksums +execute: + how: tmt diff --git a/tmt/tests/virtual/checksums/disable-and-enable/main.fmf b/tmt/tests/virtual/checksums/disable-and-enable/main.fmf new file mode 100644 index 0000000..06bee88 --- /dev/null +++ b/tmt/tests/virtual/checksums/disable-and-enable/main.fmf @@ -0,0 +1,2 @@ +summary: Check if upgrading to postgres 18 with contradictory flags works +name: checksums-disable-and-enable diff --git a/tmt/tests/virtual/checksums/disable-and-enable/test.sh b/tmt/tests/virtual/checksums/disable-and-enable/test.sh new file mode 100755 index 0000000..ff5db59 --- /dev/null +++ b/tmt/tests/virtual/checksums/disable-and-enable/test.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "git clone \"$REPO_URL\" repo" + rlRun "pushd repo" + rlRun "git fetch origin \"$PR_HEAD\"" + rlRun "git checkout FETCH_HEAD" + rlRun "cat /etc/fedora-release" + rlRun "dnf -y install postgresql17-server" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + rlRun "./bin/postgresql-setup --init" 0 "Initializing database dir" + rlRun "systemctl start postgresql" 0 "Starting service" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + rlPhaseEnd + + rlPhaseStartTest + rlRun "su - postgres -c \" + createdb testdb; + psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\"; + psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\" + \"" + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > expected.txt" + + echo "Expected:" + cat expected.txt + + rlRun "dnf -y remove postgresql17*" 0 "Removing postgresql 17" + rlRun "dnf -y install postgresql18-upgrade" 0 "Installing postgresql 18" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + + rlRun "./bin/postgresql-setup --upgrade" 1 "Upgrading without checksums flags" + rlRun "PGSETUP_INITDB_OPTIONS='--no-data-checksums' ./bin/postgresql-setup --upgrade --data-checksums" 0 "Upgrading with contradictory flags" + + rlRun "systemctl start postgresql" 0 "Starting service again" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > actual18.txt" + + echo "Actual:" + cat actual18.txt + + rlAssertNotDiffer expected.txt actual18.txt + rlRun "systemctl stop postgresql" 0 "Stop service" + rlRun "pg_checksums /var/lib/pgsql/data" 1 "Verify checksums not enabled" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf repo" + rlRun "systemctl stop postgresql" 0 "Stopping postgresql service" + rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder" + rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tmt/tests/virtual/checksums/disable/main.fmf b/tmt/tests/virtual/checksums/disable/main.fmf new file mode 100644 index 0000000..21ca87d --- /dev/null +++ b/tmt/tests/virtual/checksums/disable/main.fmf @@ -0,0 +1,2 @@ +summary: Check if upgrading to postgres 18 without enabling works +name: checksums-disable diff --git a/tmt/tests/virtual/checksums/disable/test.sh b/tmt/tests/virtual/checksums/disable/test.sh new file mode 100755 index 0000000..3589a10 --- /dev/null +++ b/tmt/tests/virtual/checksums/disable/test.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "git clone \"$REPO_URL\" repo" + rlRun "pushd repo" + rlRun "git fetch origin \"$PR_HEAD\"" + rlRun "git checkout FETCH_HEAD" + rlRun "cat /etc/fedora-release" + rlRun "dnf -y install postgresql17-server" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + rlRun "./bin/postgresql-setup --init" 0 "Initializing database dir" + rlRun "systemctl start postgresql" 0 "Starting service" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + rlPhaseEnd + + rlPhaseStartTest + rlRun "su - postgres -c \" + createdb testdb; + psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\"; + psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\" + \"" + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > expected.txt" + + echo "Expected:" + cat expected.txt + + rlRun "dnf -y remove postgresql17*" 0 "Removing postgresql 17" + rlRun "dnf -y install postgresql18-upgrade" 0 "Installing postgresql 18" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + + rlRun "./bin/postgresql-setup --upgrade" 1 "Upgrading without checksums flags" + rlRun "PGSETUP_INITDB_OPTIONS='--no-data-checksums' ./bin/postgresql-setup --upgrade" 0 "Upgrading with checksums flag" + + rlRun "systemctl start postgresql" 0 "Starting service again" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > actual18.txt" + + echo "Actual:" + cat actual18.txt + + rlAssertNotDiffer expected.txt actual18.txt + rlRun "systemctl stop postgresql" 0 "Stop service" + rlRun "pg_checksums /var/lib/pgsql/data" 1 "Verify checksums disabled" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf repo" + rlRun "systemctl stop postgresql" 0 "Stopping postgresql service" + rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder" + rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tmt/tests/virtual/checksums/enable/main.fmf b/tmt/tests/virtual/checksums/enable/main.fmf new file mode 100644 index 0000000..b96b84a --- /dev/null +++ b/tmt/tests/virtual/checksums/enable/main.fmf @@ -0,0 +1,2 @@ +summary: Check if upgrading to postgres 18 with enabling checksums works +name: checksums-enable diff --git a/tmt/tests/virtual/checksums/enable/test.sh b/tmt/tests/virtual/checksums/enable/test.sh new file mode 100755 index 0000000..7a6e916 --- /dev/null +++ b/tmt/tests/virtual/checksums/enable/test.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "git clone \"$REPO_URL\" repo" + rlRun "pushd repo" + rlRun "git fetch origin \"$PR_HEAD\"" + rlRun "git checkout FETCH_HEAD" + rlRun "cat /etc/fedora-release" + rlRun "dnf -y install postgresql17-server" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + rlRun "./bin/postgresql-setup --init" 0 "Initializing database dir" + rlRun "systemctl start postgresql" 0 "Starting service" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + rlPhaseEnd + + rlPhaseStartTest + rlRun "su - postgres -c \" + createdb testdb; + psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\"; + psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\" + \"" + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > expected.txt" + + echo "Expected:" + cat expected.txt + + rlRun "dnf -y remove postgresql17*" 0 "Removing postgresql 17" + rlRun "dnf -y install postgresql18-upgrade" 0 "Installing postgresql 18" + + ./bin/postgresql-setup --help > pre + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + + ./bin/postgresql-setup --help > post + rlRun "diff pre post" 1 "Verifying help strings differ" + + rlRun "./bin/postgresql-setup --upgrade" 1 "Upgrading without checksums flags" + rlRun "./bin/postgresql-setup --upgrade --data-checksums" 0 "Upgrading with checksums flag" + + rlRun "systemctl start postgresql" 0 "Starting service again" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > actual18.txt" + + echo "Actual:" + cat actual18.txt + + rlAssertNotDiffer expected.txt actual18.txt + rlRun "systemctl stop postgresql" 0 "Stop service" + rlRun "pg_checksums /var/lib/pgsql/data" 0 "Verify checksums enabled" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf repo" + rlRun "systemctl stop postgresql" 0 "Stopping postgresql service" + rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder" + rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tmt/tests/virtual/checksums/main.fmf b/tmt/tests/virtual/checksums/main.fmf new file mode 100644 index 0000000..42c4d8e --- /dev/null +++ b/tmt/tests/virtual/checksums/main.fmf @@ -0,0 +1,16 @@ +require: + - make + - m4 + - docbook-utils + - help2man + - elinks + - coreutils + - autoconf + - automake + - autoconf-archive + - git +framework: beakerlib +contact: pkhartsk@redhat.com +tag: + - fedora-checksums +test: ./test.sh diff --git a/tmt/tests/virtual/checksums/pre-existing/main.fmf b/tmt/tests/virtual/checksums/pre-existing/main.fmf new file mode 100644 index 0000000..ddebf13 --- /dev/null +++ b/tmt/tests/virtual/checksums/pre-existing/main.fmf @@ -0,0 +1,2 @@ +summary: Check if upgrading to postgres 18 with already enabled checksums works +name: checksums-pre-existing diff --git a/tmt/tests/virtual/checksums/pre-existing/test.sh b/tmt/tests/virtual/checksums/pre-existing/test.sh new file mode 100755 index 0000000..0d6d5e0 --- /dev/null +++ b/tmt/tests/virtual/checksums/pre-existing/test.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "git clone \"$REPO_URL\" repo" + rlRun "pushd repo" + rlRun "git fetch origin \"$PR_HEAD\"" + rlRun "git checkout FETCH_HEAD" + rlRun "cat /etc/fedora-release" + rlRun "dnf -y install postgresql17-server" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + rlRun "./bin/postgresql-setup --init --data-checksums" 0 "Initializing database dir" + rlRun "systemctl start postgresql" 0 "Starting service" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + rlPhaseEnd + + rlPhaseStartTest + rlRun "su - postgres -c \" + createdb testdb; + psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\"; + psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\" + \"" + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > expected.txt" + + echo "Expected:" + cat expected.txt + + rlRun "dnf -y remove postgresql17*" 0 "Removing postgresql 17" + rlRun "dnf -y install postgresql18-upgrade" 0 "Installing postgresql 18" + + rlRun "./bin/postgresql-setup --upgrade" 0 "Upgrading" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + + rlRun "systemctl start postgresql" 0 "Starting service again" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > actual18.txt" + + echo "Actual:" + cat actual18.txt + + rlAssertNotDiffer expected.txt actual18.txt + rlRun "systemctl stop postgresql" 0 "Stop service" + rlRun "pg_checksums /var/lib/pgsql/data" 0 "Verify checksums enabled" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf repo" + rlRun "systemctl stop postgresql" 0 "Stopping postgresql service" + rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder" + rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd diff --git a/tmt/tests/virtual/checksums/pre-pg18/main.fmf b/tmt/tests/virtual/checksums/pre-pg18/main.fmf new file mode 100644 index 0000000..ffa8317 --- /dev/null +++ b/tmt/tests/virtual/checksums/pre-pg18/main.fmf @@ -0,0 +1,2 @@ +summary: Check if upgrading to postgres 17 with enabled checksums works +name: checksums-pre-pg18 diff --git a/tmt/tests/virtual/checksums/pre-pg18/test.sh b/tmt/tests/virtual/checksums/pre-pg18/test.sh new file mode 100755 index 0000000..af2cdd6 --- /dev/null +++ b/tmt/tests/virtual/checksums/pre-pg18/test.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k + +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +rlJournalStart + rlPhaseStartSetup + rlRun "git clone \"$REPO_URL\" repo" + rlRun "pushd repo" + rlRun "git fetch origin \"$PR_HEAD\"" + rlRun "git checkout FETCH_HEAD" + rlRun "cat /etc/fedora-release" + rlRun "dnf -y install postgresql16-server" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + rlRun "./bin/postgresql-setup --init" 0 "Initializing database dir" + rlRun "systemctl start postgresql" 0 "Starting service" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + rlPhaseEnd + + rlPhaseStartTest + rlRun "su - postgres -c \" + createdb testdb; + psql -U postgres -d testdb -c \\\"create table users (id serial primary key, name text)\\\"; + psql -U postgres -d testdb -c \\\"insert into users (name) values ('Alice'), ('Bob'), ('Celine')\\\" + \"" + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > expected.txt" + + echo "Expected:" + cat expected.txt + + rlRun "dnf -y remove postgresql16*" 0 "Removing postgresql 16" + rlRun "dnf -y install postgresql17-upgrade" 0 "Installing postgresql 17" + + rlRun "autoreconf -vfi" 0 "Building and installing postgresql-setup" + rlRun "./configure --prefix=/usr" + rlRun "make" + + rlRun "./bin/postgresql-setup --upgrade --data-checksums" 0 "Upgrading with checksums flag" + + rlRun "systemctl start postgresql" 0 "Starting service again" + rlRun "systemctl is-active postgresql" 0 "Verifying service running" + + rlRun "su - postgres -c ' + psql -U postgres -d testdb -c \"select * from users\" + ' > actual17.txt" + + echo "Actual:" + cat actual17.txt + + rlAssertNotDiffer expected.txt actual17.txt + rlRun "systemctl stop postgresql" 0 "Stop service" + rlRun "pg_checksums /var/lib/pgsql/data" 0 "Verify checksums enabled" + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -rf repo" + rlRun "systemctl stop postgresql" 0 "Stopping postgresql service" + rlRun "rm -rf /var/lib/pgsql" 0 "Removing database folder" + rlRun "dnf -y remove postgresql*" 0 "Uninstalling postgresql" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd