diff --git a/app/sbin/ODOO_19/ODOO_19.lib b/app/sbin/ODOO_19/ODOO_19.lib index 7a63bba..bd56f9e 100644 --- a/app/sbin/ODOO_19/ODOO_19.lib +++ b/app/sbin/ODOO_19/ODOO_19.lib @@ -38,10 +38,39 @@ echo "==================================================" # Function: Create PostgreSQL user # ----------------------------- +# Run a query as postgres admin. Returns psql's exit status so callers can tell +# "query returned nothing" apart from "could not connect". +pg_admin() { + PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql -h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres -tAc "$1" +} + +# Wait until Postgres accepts connections (default: up to 60s). +wait_for_postgres() { + local tries="${1:-30}" + local i + for ((i = 1; i <= tries; i++)); do + if pg_admin "SELECT 1;" >/dev/null 2>&1; then + return 0 + fi + echo "Postgres not reachable yet ($i/$tries), retrying..." + sleep 2 + done + return 1 +} + check_and_create_db() { echo "check and create" echo "Connecting as $POSTGRES_ADMIN_USER to $POSTGRES_HOST:$POSTGRES_PORT" +# ----------------------------- +# Never guess: if Postgres cannot be queried we must NOT assume the DB is +# missing, because a restore wipes the filestore. +# ----------------------------- +if ! wait_for_postgres; then + echo "ERROR: cannot connect to Postgres at $POSTGRES_HOST:$POSTGRES_PORT - skipping DB check, NO restore performed" + return 1 +fi + # ----------------------------- # Check if user exists # ----------------------------- @@ -54,10 +83,26 @@ fi # ----------------------------- # Check if database exists # ----------------------------- -DB_EXISTS=$(PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql -h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$UUID';" | grep -q 1 && echo "yes" || echo "no") +DB_RESULT=$(pg_admin "SELECT 1 FROM pg_database WHERE datname='$UUID';") +DB_RC=$? +if [ $DB_RC -ne 0 ]; then + echo "ERROR: DB existence query failed (rc=$DB_RC) - NO restore performed" + return 1 +fi + +if [ "$DB_RESULT" = "1" ]; then + DB_EXISTS="yes" +else + DB_EXISTS="no" +fi if [ "$DB_EXISTS" = "no" ]; then - /4server/sbin/ODOO_19/restore $UUID default.zip + FILESTORE_HOST="/4server/data/$UUID/odoo/odoo-web-data/filestore" + if [ -d "$FILESTORE_HOST" ] && [ -n "$(ls -A "$FILESTORE_HOST" 2>/dev/null)" ]; then + echo "ERROR: database $UUID not found but a filestore exists at $FILESTORE_HOST - refusing automatic restore of default.zip (would delete the filestore). Restore manually if intended." + return 1 + fi + /4server/sbin/ODOO_19/restore $UUID default.zip fi } diff --git a/app/sbin/ODOO_19/restore b/app/sbin/ODOO_19/restore index 5e55637..f4b74da 100755 --- a/app/sbin/ODOO_19/restore +++ b/app/sbin/ODOO_19/restore @@ -35,6 +35,14 @@ else fi +source /4server/sbin/ODOO_19/ODOO_19.lib + +# Abort BEFORE touching anything if Postgres is not reachable +if ! wait_for_postgres; then + echo "ERROR: cannot connect to Postgres at $POSTGRES_HOST:$POSTGRES_PORT - restore aborted, nothing was changed" + exit 1 +fi + ### DELETE AND CREATE DATABASE PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql -h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -d postgres -c " SELECT pg_terminate_backend(pid) FROM pg_stat_activity @@ -49,10 +57,21 @@ PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \ -c "ALTER ROLE \"$UUID\" CREATEDB;" -doas docker exec "$UUID" rm -rf /home/odoo/.local/share/Odoo/filestore +# Move the old filestore aside instead of deleting it; it is only removed after a successful load +OLD_FS="/home/odoo/.local/share/Odoo/.filestore.pre-restore" +doas docker exec "$UUID" rm -rf "$OLD_FS" +doas docker exec "$UUID" sh -c "[ -d /home/odoo/.local/share/Odoo/filestore ] && mv /home/odoo/.local/share/Odoo/filestore $OLD_FS; true" doas docker exec "$UUID" rm -rf /root/.local/share/Odoo/filestore -doas docker exec "$UUID" odoo db --db_host beedb -w "$ODOO_DB_PASSWORD" -r "$UUID" load "$UUID" $FILENAME -f +if ! doas docker exec "$UUID" odoo db --db_host beedb -w "$ODOO_DB_PASSWORD" -r "$UUID" load "$UUID" $FILENAME -f; then + echo "ERROR: odoo db load failed - putting the old filestore back" + doas docker exec "$UUID" sh -c "[ -d $OLD_FS ] && rm -rf /home/odoo/.local/share/Odoo/filestore && mv $OLD_FS /home/odoo/.local/share/Odoo/filestore; true" + PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \ + -h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \ + -c "ALTER ROLE \"$UUID\" NOCREATEDB;" + exit 1 +fi +doas docker exec "$UUID" rm -rf "$OLD_FS" PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" psql \ -h "$POSTGRES_HOST" -U "$POSTGRES_ADMIN_USER" -p "$POSTGRES_PORT" -d postgres \ diff --git a/app/templates/postgresql.conf b/app/templates/postgresql.conf index dc451b4..5755d50 100644 --- a/app/templates/postgresql.conf +++ b/app/templates/postgresql.conf @@ -1,5 +1,5 @@ listen_addresses = '*' -max_connections = 150 +max_connections = 300 dynamic_shared_memory_type = posix max_wal_size = 1GB min_wal_size = 80MB