Generic database restore
Database-specific legacy commands live in
_pmiregistry/scripts/restore/.
restore_database.sh restores one PMIVerse Odoo database backup into its
original target name. It supports registry aliases, explicit configuration,
optional neutralization, and neutralization of an existing database without a
restore.
Use --dry-run first. Restore and neutralization are destructive operational
actions and must not be run against a real PostgreSQL database or filestore
without separate authorization and a verified recovery plan.
Common usage
# Inspect registry resolution without changing anything
/srv/pmiverse/_pmiconfig/scripts/restore/restore_database.sh demo --dry-run
# Inspect explicit resolution
/srv/pmiverse/_pmiconfig/scripts/restore/restore_database.sh \
--suite 18 \
--db example \
--source-file /absolute/path/example_latest.zip \
--dest /srv/pmiverse/_pmisuite18/data/dumps/example \
--filestore /srv/pmiverse/_pmisuite18/data/filestore \
--dry-run
# Restore and apply neutralization after publication
/srv/pmiverse/_pmiconfig/scripts/restore/restore_database.sh demo --neutralize
# Neutralize an existing database without reading or publishing a filestore
/srv/pmiverse/_pmiconfig/scripts/restore/restore_database.sh \
--suite 18 --db example --only-neutralize
Aliases, database names, and host mappings are maintained in
/srv/pmiverse/_pmiregistry/config/pmiverse.conf. The examples above use a
synthetic demo alias; substitute an alias from your registry.
See the deployment notes for
installation-specific assets and the linked legacy restore runbook for
per-target behavior.
Host subdirectories exist on the local rsync/restore server. Remote producers
still write to data/backups/; restoring directly there requires an explicit
source override.
Run the script as the ordinary account that owns the suite resources and has
the required PostgreSQL privileges. The script does not invoke sudo.
Important options
NAMEor--target NAMEselects an alias from/srv/pmiverse/_pmiregistry/config/pmiverse.conf.--suite Nselects the suite used for unresolved defaults.--db NAMEsets the effective PostgreSQL target database.--source-file FILEselects exactly one non-symlink ZIP.--source DIRselects the newest readable non-symlink ZIP in a directory.--dest DIRsets the extraction workspace root.--filestore DIRsets the physical filestore root.--neutralizerestores and then applies SQL and ORM neutralization.--only-neutralizemutates only the existing database and requires no backup.--dry-runprints resolved values and exits before lock or target access.
--source and --source-file are mutually exclusive. CLI values take
precedence over legacy target variables, registry values, derived suite paths,
and built-in defaults.
Backup contract
The selected ZIP must contain exactly one supported database dump:
- one non-empty
dump.sqlor other*.sqlfile; or - one valid custom-format
*.dumpor*.backupfile.
An optional filestore may use one of the supported database/filestore layouts. Dump-only archives publish the database and retain the existing live filestore. Absolute entries, traversal components, backslashes, control characters, ZIP symlinks, extracted symlinks, ambiguous dumps, and ambiguous filestores are rejected.
Resource locking
Restore uses two persistent nonblocking advisory resource locks:
- PostgreSQL lock:
/srv/pmiverse/.pmis-restore-locks/.pmis-restore-postgresql-<sha256>.lock, hashingpostgresql-local-default:<effective-database-name>. - Filestore lock:
<physical-filestore-root>/.pmis-restore-filestore-<sha256>.lock, hashingfilestore:<canonical-live-filestore-path>.
PostgreSQL is always acquired before filestore. Failure to acquire or verify a lock releases every acquired descriptor before target inspection or mutation. The locks remain held through restoration, publication, post-restore work, neutralization, rollback, and rollback-artifact cleanup. Lock files persist; closing their descriptors releases the advisory locks.
Invocations contend if either the effective database or canonical live
filestore is shared. Suite values, aliases, source archives, and workspace
paths do not change resource identity. Invocations with different databases
and different live filestores may run concurrently. --only-neutralize
acquires only the PostgreSQL lock and therefore contends with a normal restore
of the same database.
Every restore-capable account must use the same shared PostgreSQL lock root. The script fails closed if that root is unavailable or unsafe. The identity represents the process's local/default PostgreSQL namespace; separate hosts or deliberately different lock roots are not coordinated.
Publication and rollback
The script validates and extracts the source in a unique workspace, restores into a unique temporary database, and stages any incoming filestore before publishing either resource. An existing database and filestore are renamed to unique rollback artifacts and retained until post-restore work and requested neutralization succeed.
On failure or signal, the script reconciles observed database and filesystem state and attempts coordinated rollback. Ambiguous or incomplete rollback preserves uniquely named artifacts and prints recovery guidance instead of guessing. PostgreSQL and filestore publication is coordinated rollback, not a single cross-system atomic transaction.
For the full resolution rules, archive layouts, neutralization behavior, and
troubleshooting guidance, see
/srv/pmiverse/_pmiconfig/docs/scripts/restore_database.md.