Skip to Content

Odoo 14 → 18 Migration Scripts

This folder contains automation to migrate an Odoo database sequentially through major versions using OpenUpgrade and per‑version local instances.

Primary script: - migrate_14-18.sh — migrates an Odoo 14 database through 15 → 16 → 17 → 18.

The script follows the PMIverse multi‑version layout and safety conventions described in the global guidelines.

Prerequisites

  • OS: Arch Linux (workstation)

  • PostgreSQL available locally; your user can run psql, createdb, dropdb, pg_dump, pg_restore.

  • Instance folders present (one per Odoo version):

  • /srv/pmiverse/_pmisuite14/
  • /srv/pmiverse/_pmisuite15/
  • /srv/pmiverse/_pmisuite16/
  • /srv/pmiverse/_pmisuite17/
  • /srv/pmiverse/_pmisuite18/

  • Each instance must include:

  • Python venv at <instance>/venv (script sources <instance>/venv/bin/activate)
  • OCB repo with odoo-bin at <instance>/repos/OCB/odoo-bin
  • OpenUpgrade repos per version (for 15+) at <instance>/repos/OCB-openupgrade/<ver>-openupgrade/openupgrade_scripts/scripts
  • Odoo config file at <instance>/config/pmisuite<ver>.conf with correct addons_path (including OpenUpgrade addons if needed)

  • A local PostgreSQL database containing your Odoo 14 data (e.g., mydb14).

What the migration script does

migrate_14-18.sh performs a safe, sequential migration. High‑level steps:

  1. Validates required CLI tools and files: psql, createdb, dropdb, pg_dump, pg_restore, per‑version odoo-bin, venvs, configs.
  2. Verifies the source 14.0 DB exists.
  3. Normalizes the source DB name by replacing dashes with underscores for derived names.
  4. Performs the migration pipeline: - Step 0: Create 14 baseline clone <src>_14. Uninstall obsolete modules (like pmis_stock_analytics) using Odoo 14 shell; backup baseline. - Step 1 (14 → 15): Clone to <src>_15, apply 15.0 pre-migration fixes (e.g., account modules, warehouse mismatches), run OpenUpgrade with 15 env; backup. - Step 2 (15 → 16): Clone to <src>_16, run OpenUpgrade with 16 env; backup. - Step 3 (16 → 17): Clone to <src>_17, apply 17.0 pre-migration fixes (e.g., HR user partner detachment), run OpenUpgrade with 17 env; backup. - Step 4 (17 → 18): Clone to <src>_18, run OpenUpgrade with 18 env; backup.
  5. Writes migration logs to /srv/pmiverse/logs/openupgrade_<ver>.log and backups (pg_dump -Fc) to /srv/pmiverse/backups after each step (unless --skip-backups is used).

Usage

cd /srv/pmiverse/_pmiconfig/scripts/migrate
./migrate_14-18.sh -d <source_db>
# Optional: overwrite intermediate DBs if they already exist
./migrate_14-18.sh -d <source_db> --force
# Optional: skip backups between versions for speed
./migrate_14-18.sh -d <source_db> --skip-backups
# Help
./migrate_14-18.sh --help

Arguments:

  • -d, --database <source_db>: required. Name of your existing Odoo 14 DB in Postgres.
  • -f, --force: optional. If present, existing target/intermediate DBs (e.g., <src>_15) are dropped and recreated as needed.
  • --skip-backups: optional. Skip database backups (.dump files) after each migration step. Recommended for very large databases.
  • --up15-path, --up16-path, --up17-path, --up18-path: override each version's OpenUpgrade scripts directory.
  • -h, --help: print option help without creating directories or accessing databases.

Derived database names: - The script will create and operate on: <src>_14, <src>_15, <src>_16, <src>_17, <src>_18. - Dashes in <src> are normalized to underscores when deriving these names.

After migration

When the script completes, your final migrated database is <src>_18. To start Odoo 18 locally against it:

# Activate the 18.0 venv
source /srv/pmiverse/_pmisuite18/venv/bin/activate
# Run Odoo 18 with the pinned config
/srv/pmiverse/_pmisuite18/repos/OCB/odoo-bin \
  -c /srv/pmiverse/_pmisuite18/config/pmisuite18.conf \
  -d <src>_18 \
  --logfile=/srv/pmiverse/logs/odoo18_<src>_18.log

Before first app start on a production‑derived dump, neutralize external effects (mail, URLs, crons, integrations). Example (Odoo shell):

params = env["ir.config_parameter"].sudo()
params.set_param("web.base.url", "http://localhost:18069")
params.set_param("mail.smtp_host", "localhost")
params.set_param("mail.smtp_port", 1025)  # mailhog

See the “Safe Handling of Production Dumps (Dev)” section in the global guidelines for a fuller checklist.

Production migration runbook (14 → 18)

This section explains how to migrate a real production database to Odoo 18 using a controlled host to perform the upgrade, then deploy it back to the production server. It complements the local instructions above and follows PMIverse guidelines.

Production-sensitive and destructive: The commands in this section are examples, not verified service names or a complete change plan for every host. Confirm all database names, service units, paths, backups, neutralization controls, and rollback steps for the target environment, then obtain explicit operational approval before execution.

Important principles: - Always back up both DB and filestore together at each stage. - Keep config parity with production (ports, proxy_mode = True, wide addons_path). - Neutralize integrations on restored copies until go‑live. - Execute in an approved change window with a clear rollback plan.

1) Prepare

  • On the migration host (workstation or staging VM), ensure the per‑version instances exist: /srv/pmiverse/_pmisuite{14,15,16,17,18} with venvs, odoo-bin, OpenUpgrade paths, and pinned configs pmisuite{15,16,17,18}.conf.
  • Ensure Postgres CLI tools are available: psql, pg_dump, pg_restore, createdb, dropdb.
  • Choose a working base name <src> for derived DBs. The script will create <src>_14, <src>_15, <src>_16, <src>_17, <src>_18.

2) Back up production (on the production server)

  • Stop Odoo to quiesce writes (unit names may differ):
sudo systemctl stop odoo
# or: sudo systemctl stop odoo14
  • Database backup (custom format):
pg_dump -Fc -d <prod_db> > /srv/pmiverse/backups/<prod_db>_pre_migration_$(date +%Y%m%d_%H%M%S).dump
  • Filestore backup (the path depends on your production data_dir):
rsync -aHAX --info=stats2 /path/to/filestore/<prod_db>/ \
      /srv/pmiverse/backups/filestore_<prod_db>_pre_migration/
  • Optionally start Odoo back if business requires while you transfer copies:
sudo systemctl start odoo

3) Transfer backups to the migration host

rsync -aHAX user@prod:/srv/pmiverse/backups/<prod_db>_pre_migration_*.dump \
      /srv/pmiverse/backups/
rsync -aHAX user@prod:/srv/pmiverse/backups/filestore_<prod_db>_pre_migration/ \
      /srv/pmiverse/backups/filestore_<prod_db>_pre_migration/

4) Restore the production dump on the migration host and neutralize

  • Restore DB into a local database name you will pass to -d (e.g., <src>):
createdb <src>
pg_restore -d <src> /srv/pmiverse/backups/<prod_db>_pre_migration_*.dump
  • If add‑ons require filestore present during upgrade, restore it under the migration host’s data_dir path (per config) so that filestore/<db> aligns with the DB name you restore.

  • Before starting servers for checks, neutralize external effects (Odoo shell):

# Odoo shell connected to <src> (or <src>_14 later)
params = env["ir.config_parameter"].sudo()
params.set_param("web.base.url", "http://localhost:18069")
params.set_param("mail.smtp_host", "localhost")
params.set_param("mail.smtp_port", 1025)  # mailhog
# Review connectors, acquirers, and crons; disable non‑essential ones

5) Run the migration on the migration host

cd /srv/pmiverse/_pmiconfig/scripts/migrate
./migrate_14-18.sh -d <src>
# Add --force if intermediate targets already exist and can be overwritten
  • The script creates <src>_14 (baseline) and upgrades stepwise to <src>_18, producing logs and backups per hop under /srv/pmiverse/logs and /srv/pmiverse/backups.

6) Validate on Odoo 18 locally (UAT smoke test)

  • Start Odoo 18 locally against <src>_18:
source /srv/pmiverse/_pmisuite18/venv/bin/activate
/srv/pmiverse/_pmisuite18/repos/OCB/odoo-bin \
  -c /srv/pmiverse/_pmisuite18/config/pmisuite18.conf \
  -d <src>_18 --logfile=/srv/pmiverse/logs/odoo18_<src>_18.log
  • Validate critical flows, custom modules, and reports. Fix issues, then re‑run with --force if necessary.

7) Prepare the production Odoo 18 stack

  • Ensure the Odoo 18 stack exists on production: repos, venv, pmisuite18.conf, systemd unit, nginx/proxy config, ports, proxy_mode = True, and wide addons_path matching the migration host. Keep paths under /srv/pmiverse for parity.
  • Schedule a change window and stop the old Odoo service before restoring the migrated DB:
sudo systemctl stop odoo
# or: sudo systemctl stop odoo14

8) Transfer the migrated DB and filestore back to production

  • On the migration host, back up the final migrated DB:
pg_dump -Fc -d <src>_18 > /srv/pmiverse/backups/<src>_18_migrated_$(date +%Y%m%d_%H%M%S).dump
  • Transfer the DB dump and the (migrated) filestore:
rsync -aHAX /srv/pmiverse/backups/<src>_18_migrated_*.dump \
      user@prod:/srv/pmiverse/backups/
rsync -aHAX /srv/pmiverse/_pmisuite18/data/filestore/<src>_18/ \
      user@prod:/srv/pmiverse/_pmisuite18/data/filestore/<target_db>/

Note: If filestore didn’t change during migration, ensure the prod 18 instance points to the correct filestore location matching <target_db>.

9) Restore on production and reconfigure for go‑live

  • On production, create and restore the target database name (can keep original or use a new one):
createdb <target_db>
pg_restore -d <target_db> /srv/pmiverse/backups/<src>_18_migrated_*.dump
  • Update system parameters for production values (hostnames, mail relays), re‑enable crons and integrations, verify web.base.url. Review dbfilter/nginx/proxy to route traffic correctly.

  • Start Odoo 18 in production and monitor:

sudo systemctl start odoo18
sudo journalctl -u odoo18 -f

10) Post‑go‑live checks and rollback plan

  • Verify: user logins, critical flows, scheduled actions, mail in/out, integrations.
  • Monitor performance, worker health, and logs. Keep backups ready.
  • Rollback plan: stop Odoo 18, restore the last good Odoo 14 DB+filestore backups, start old service.

Checklist summary - [ ] Back up prod DB + filestore; transfer to migration host - [ ] Restore locally; neutralize; run migrate_14-18.sh - [ ] Validate on 18; fix issues - [ ] Prepare prod 18 stack; stop old service for cutover - [ ] Transfer migrated DB + filestore; restore on prod - [ ] Reconfigure; enable crons/integrations; start Odoo 18 - [ ] Post‑go‑live monitoring; rollback plan ready

Logs and backups

  • Logs:
  • /srv/pmiverse/logs/uninstall_pmis_stock_analytics.log (Step 0)
  • /srv/pmiverse/logs/openupgrade_15.log
  • /srv/pmiverse/logs/openupgrade_16.log
  • /srv/pmiverse/logs/openupgrade_17.log
  • /srv/pmiverse/logs/openupgrade_18.log

  • Backups: /srv/pmiverse/backups/<db>_<tag>_<timestamp>.dump (format: custom -Fc).

These locations are created if missing. Keep DB and filestore backups together for safety (filestore per instance under its data_dir).

Safety notes

  • The script never modifies your source DB. It clones and works on derived DBs.
  • Without --force, the script aborts if a target DB already exists.
  • With --force, existing intermediate DBs are dropped before recreation — use carefully.
  • Do not edit the shared per‑instance config files for one‑off local tweaks; prefer CLI overrides in IDE run configs as needed.

Troubleshooting

  • “Source database '' does not exist”
  • Confirm with psql -lqt | cut -d '|' -f 1 | grep -w <name>.

  • “Missing file: …/odoo-bin” or “Missing upgrade path dir: …/openupgrade_scripts/scripts”

  • Ensure the per‑version repos exist and paths match the layout above.

  • Permission errors for createdb/dropdb/pg_restore

  • Ensure your OS user has rights on the local Postgres cluster or connect as a role with sufficient privileges.

  • Encoding or collation mismatches

  • Create the target DBs with the same encoding/locale as your source cluster. The script uses createdb defaults; adjust cluster defaults if required.

  • OpenUpgrade failures at a specific hop

  • Inspect the corresponding openupgrade_<ver>.log and apply OCA/OpenUpgrade recommended fixes (addon availability, pre‑migration data cleanup, etc.). Re‑run with --force once corrected.

Clean up

If you need to reclaim space after a successful migration, you may drop intermediate DBs, e.g.:

dropdb <src>_14
dropdb <src>_15
dropdb <src>_16
dropdb <src>_17

Only do this after verifying <src>_18 is healthy and backed up.

  • Global guidelines: /srv/pmiverse/_pmiguidelines (PMIverse multi‑version development standards)
  • OpenUpgrade project: https://github.com/OCA/OpenUpgrade

License and attribution

  • Copyright (c) 2025. LUXIM d.o.o., Slovenia — Matjaž Mozetič.
  • Internal automation script and docs for PMIverse environment.