[IMP] add --resume-from option
to resume the migration process from a step wehre the database and filestore are correct.
This commit is contained in:
50
README.md
50
README.md
@@ -9,6 +9,7 @@ A tool for migrating Odoo databases between major versions, using [OpenUpgrade](
|
||||
- [Project Structure](#project-structure)
|
||||
- [How It Works](#how-it-works)
|
||||
- [Usage](#usage)
|
||||
- [Resuming a Failed Migration](#resuming-a-failed-migration)
|
||||
- [Customization](#customization)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
@@ -158,7 +159,7 @@ The script performs a **step-by-step migration** between each major version. For
|
||||
### Running the Migration
|
||||
|
||||
```bash
|
||||
./upgrade.sh <source_version> <target_version> <database_name> <source_service>
|
||||
./upgrade.sh <source_version> <target_version> <database_name> <source_service> [--resume-from|-r <version>]
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
@@ -169,6 +170,11 @@ The script performs a **step-by-step migration** between each major version. For
|
||||
| `database_name` | Database name | `my_prod_db` |
|
||||
| `source_service` | Source Docker Compose service | `odoo14` |
|
||||
|
||||
**Options:**
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--resume-from <version>`, `-r <version>` | Resume from an intermediate checkpoint (see [Resuming a Failed Migration](#resuming-a-failed-migration)) |
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
./upgrade.sh 14 17 elabore_20241208 odoo14
|
||||
@@ -239,6 +245,48 @@ compose run odoo17 shell -d ou17 --no-http --stop-after-init < lib/python/valida
|
||||
- **JSON report** written to `/tmp/validation_views_<db>_<timestamp>.json`
|
||||
- **Exit code**: `0` = success, `1` = errors found
|
||||
|
||||
## Resuming a Failed Migration
|
||||
|
||||
Each version hop copies the database before modifying it (`ou14` → `ou15` → `ou16` → …). If a migration crashes mid-way, the intermediate databases from completed hops are still intact and can be used as a restart point.
|
||||
|
||||
### How It Works
|
||||
|
||||
Use `--resume-from <version>` (or `-r <version>`) to restart from an intermediate checkpoint:
|
||||
|
||||
```bash
|
||||
./upgrade.sh <source_version> <target_version> <database_name> <source_service> --resume-from <checkpoint_version>
|
||||
```
|
||||
|
||||
When a checkpoint is specified, the script:
|
||||
- **Skips** the initial database and filestore copy
|
||||
- **Skips** `prepare_db.sh` (already done before the crash)
|
||||
- **Starts the migration loop** from `checkpoint_version + 1`
|
||||
|
||||
### Example
|
||||
|
||||
A migration from 14 to 18 crashes during the 16→17 hop. The database `ou15` was successfully created. Resume from there:
|
||||
|
||||
```bash
|
||||
./upgrade.sh 14 18 my_database odoo14 --resume-from 15
|
||||
```
|
||||
|
||||
This runs: `16.0 → 17.0 → 18.0`, starting from `ou15`.
|
||||
|
||||
### Constraints
|
||||
|
||||
- The checkpoint version must be strictly between the source and target versions.
|
||||
- The intermediate database (`ou<version>`) and its filestore must exist before resuming.
|
||||
|
||||
### Restarting From Scratch
|
||||
|
||||
To restart a full migration from the beginning (ignoring all intermediate databases):
|
||||
|
||||
```bash
|
||||
./upgrade.sh 14 18 my_database odoo14
|
||||
```
|
||||
|
||||
The script automatically drops and recreates the final target database (`ou18`) if it already exists.
|
||||
|
||||
## Customization
|
||||
|
||||
### Version Scripts
|
||||
|
||||
140
upgrade.sh
140
upgrade.sh
@@ -10,7 +10,7 @@ source "${SCRIPT_DIR}/lib/common.sh"
|
||||
|
||||
usage() {
|
||||
cat <<EOF >&2
|
||||
Usage: $0 <origin_version> <final_version> <db_name> <service_name>
|
||||
Usage: $0 <origin_version> <final_version> <db_name> <service_name> [--resume-from|-r <version>]
|
||||
|
||||
Arguments:
|
||||
origin_version Origin Odoo version number (e.g., 12 for version 12.0)
|
||||
@@ -18,14 +18,22 @@ Arguments:
|
||||
db_name Name of the database to migrate
|
||||
service_name Name of the origin Odoo service (docker compose service)
|
||||
|
||||
Example:
|
||||
$0 14 16 elabore_20241208 odoo14
|
||||
Options:
|
||||
--resume-from, -r <version>
|
||||
Resume migration from an already-migrated intermediate
|
||||
database (e.g., ou15). Skips the initial DB copy and
|
||||
prepare_db.sh phases. The intermediate DB must exist.
|
||||
|
||||
Examples:
|
||||
$0 14 18 elabore_20241208 odoo14
|
||||
$0 14 18 elabore_20241208 odoo14 --resume-from 15
|
||||
$0 14 18 elabore_20241208 odoo14 -r 15
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ $# -lt 4 ]]; then
|
||||
log_error "Missing arguments. Expected 4, got $#."
|
||||
log_error "Missing arguments. Expected at least 4, got $#."
|
||||
usage
|
||||
fi
|
||||
|
||||
@@ -38,11 +46,50 @@ readonly FINAL_VERSION
|
||||
readonly ORIGIN_DB_NAME="$3"
|
||||
readonly ORIGIN_SERVICE_NAME="$4"
|
||||
|
||||
# Parse optional --resume-from / -r flag
|
||||
RESUME_FROM_VERSION=""
|
||||
shift 4
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--resume-from|-r)
|
||||
if [[ $# -lt 2 ]]; then
|
||||
log_error "Option '$1' requires a version number argument."
|
||||
usage
|
||||
fi
|
||||
RESUME_FROM_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: '$1'"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
readonly RESUME_FROM_VERSION
|
||||
|
||||
readonly COPY_DB_NAME="ou${ORIGIN_VERSION}"
|
||||
export FINALE_DB_NAME="ou${FINAL_VERSION}"
|
||||
readonly FINALE_DB_NAME
|
||||
readonly FINALE_SERVICE_NAME="${FINALE_DB_NAME}"
|
||||
|
||||
# Validate --resume-from value if provided
|
||||
if [[ -n "$RESUME_FROM_VERSION" ]]; then
|
||||
if ! [[ "$RESUME_FROM_VERSION" =~ ^[0-9]+$ ]]; then
|
||||
log_error "--resume-from value must be a numeric version number (got: '$RESUME_FROM_VERSION')."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$RESUME_FROM_VERSION" -le "$ORIGIN_VERSION" ]]; then
|
||||
log_error "--resume-from ($RESUME_FROM_VERSION) must be strictly greater than origin version ($ORIGIN_VERSION)."
|
||||
log_error "To start a fresh migration, run without --resume-from."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$RESUME_FROM_VERSION" -ge "$FINAL_VERSION" ]]; then
|
||||
log_error "--resume-from ($RESUME_FROM_VERSION) must be strictly less than final version ($FINAL_VERSION)."
|
||||
log_error "Nothing to migrate: checkpoint is at or beyond the target version."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
readarray -t postgres_containers < <(docker ps --format '{{.Names}}' | grep postgres || true)
|
||||
|
||||
if [[ ${#postgres_containers[@]} -eq 0 ]]; then
|
||||
@@ -61,8 +108,13 @@ readonly POSTGRES_SERVICE_NAME
|
||||
log_step "INPUT PARAMETERS"
|
||||
log_info "Origin version .......... $ORIGIN_VERSION"
|
||||
log_info "Final version ........... $FINAL_VERSION"
|
||||
log_info "Origin DB name ........... $ORIGIN_DB_NAME"
|
||||
log_info "Origin DB name .......... $ORIGIN_DB_NAME"
|
||||
log_info "Origin service name ..... $ORIGIN_SERVICE_NAME"
|
||||
if [[ -n "$RESUME_FROM_VERSION" ]]; then
|
||||
log_info "Resume from version ..... $RESUME_FROM_VERSION (ou${RESUME_FROM_VERSION})"
|
||||
else
|
||||
log_info "Resume from version ..... none (full migration)"
|
||||
fi
|
||||
|
||||
log_step "COMPUTED GLOBAL VARIABLES"
|
||||
log_info "Copy DB name ............. $COPY_DB_NAME"
|
||||
@@ -74,20 +126,42 @@ log_info "Postgres service name .... $POSTGRES_SERVICE_NAME"
|
||||
|
||||
log_step "CHECKS ALL NEEDED COMPONENTS ARE AVAILABLE"
|
||||
|
||||
db_exists=$(docker exec -it -u 70 "$POSTGRES_SERVICE_NAME" psql -tc "SELECT 1 FROM pg_database WHERE datname = '$ORIGIN_DB_NAME'" | tr -d '[:space:]')
|
||||
if [[ "$db_exists" ]]; then
|
||||
log_info "Database '$ORIGIN_DB_NAME' found."
|
||||
else
|
||||
log_error "Database '$ORIGIN_DB_NAME' not found in the local postgres service. Please add it and restart the upgrade process."
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$RESUME_FROM_VERSION" ]]; then
|
||||
readonly RESUME_DB_NAME="ou${RESUME_FROM_VERSION}"
|
||||
|
||||
filestore_path="${DATASTORE_PATH}/${ORIGIN_SERVICE_NAME}/${FILESTORE_SUBPATH}/${ORIGIN_DB_NAME}"
|
||||
if [[ -d "$filestore_path" ]]; then
|
||||
log_info "Filestore '$filestore_path' found."
|
||||
resume_db_exists=$(docker exec -u 70 "$POSTGRES_SERVICE_NAME" psql -tc "SELECT 1 FROM pg_database WHERE datname = '${RESUME_DB_NAME}'" | tr -d '[:space:]')
|
||||
if [[ "$resume_db_exists" ]]; then
|
||||
log_info "Checkpoint database '${RESUME_DB_NAME}' found."
|
||||
else
|
||||
log_error "Checkpoint database '${RESUME_DB_NAME}' not found in the local postgres service."
|
||||
log_error "Ensure the migration up to version ${RESUME_FROM_VERSION} completed successfully before resuming."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
resume_filestore_path="${DATASTORE_PATH}/${RESUME_DB_NAME}/${FILESTORE_SUBPATH}/${RESUME_DB_NAME}"
|
||||
if [[ -d "$resume_filestore_path" ]]; then
|
||||
log_info "Checkpoint filestore '${resume_filestore_path}' found."
|
||||
else
|
||||
log_error "Checkpoint filestore '${resume_filestore_path}' not found."
|
||||
log_error "Ensure the filestore for '${RESUME_DB_NAME}' is intact before resuming."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_error "Filestore '$filestore_path' not found, please add it and restart the upgrade process."
|
||||
exit 1
|
||||
db_exists=$(docker exec -u 70 "$POSTGRES_SERVICE_NAME" psql -tc "SELECT 1 FROM pg_database WHERE datname = '$ORIGIN_DB_NAME'" | tr -d '[:space:]')
|
||||
if [[ "$db_exists" ]]; then
|
||||
log_info "Database '$ORIGIN_DB_NAME' found."
|
||||
else
|
||||
log_error "Database '$ORIGIN_DB_NAME' not found in the local postgres service. Please add it and restart the upgrade process."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
filestore_path="${DATASTORE_PATH}/${ORIGIN_SERVICE_NAME}/${FILESTORE_SUBPATH}/${ORIGIN_DB_NAME}"
|
||||
if [[ -d "$filestore_path" ]]; then
|
||||
log_info "Filestore '$filestore_path' found."
|
||||
else
|
||||
log_error "Filestore '$filestore_path' not found, please add it and restart the upgrade process."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log_step "LAUNCH VIRGIN ODOO IN FINAL VERSION"
|
||||
@@ -102,24 +176,36 @@ run_compose --debug run "$FINALE_SERVICE_NAME" -i base --stop-after-init --no-ht
|
||||
|
||||
log_info "Model database in final Odoo version created."
|
||||
|
||||
log_step "COPY ORIGINAL COMPONENTS"
|
||||
if [[ -z "$RESUME_FROM_VERSION" ]]; then
|
||||
log_step "COPY ORIGINAL COMPONENTS"
|
||||
|
||||
copy_database "$ORIGIN_DB_NAME" "$COPY_DB_NAME" "$COPY_DB_NAME"
|
||||
log_info "Original database copied to ${COPY_DB_NAME}@${COPY_DB_NAME}."
|
||||
copy_database "$ORIGIN_DB_NAME" "$COPY_DB_NAME" "$COPY_DB_NAME"
|
||||
log_info "Original database copied to ${COPY_DB_NAME}@${COPY_DB_NAME}."
|
||||
|
||||
copy_filestore "$ORIGIN_SERVICE_NAME" "$ORIGIN_DB_NAME" "$COPY_DB_NAME" "$COPY_DB_NAME"
|
||||
log_info "Original filestore copied."
|
||||
copy_filestore "$ORIGIN_SERVICE_NAME" "$ORIGIN_DB_NAME" "$COPY_DB_NAME" "$COPY_DB_NAME"
|
||||
log_info "Original filestore copied."
|
||||
else
|
||||
log_step "COPY ORIGINAL COMPONENTS — SKIPPED (resuming from checkpoint ou${RESUME_FROM_VERSION})"
|
||||
fi
|
||||
|
||||
|
||||
log_step "PATH OF MIGRATION"
|
||||
|
||||
readarray -t versions < <(seq $((ORIGIN_VERSION + 1)) "$FINAL_VERSION")
|
||||
log_info "Migration path is ${versions[*]}"
|
||||
if [[ -n "$RESUME_FROM_VERSION" ]]; then
|
||||
readarray -t versions < <(seq $((RESUME_FROM_VERSION + 1)) "$FINAL_VERSION")
|
||||
log_info "Resuming migration from ou${RESUME_FROM_VERSION} — path is ${versions[*]}"
|
||||
else
|
||||
readarray -t versions < <(seq $((ORIGIN_VERSION + 1)) "$FINAL_VERSION")
|
||||
log_info "Migration path is ${versions[*]}"
|
||||
fi
|
||||
|
||||
|
||||
log_step "DATABASE PREPARATION"
|
||||
|
||||
"${SCRIPT_DIR}/scripts/prepare_db.sh" "$COPY_DB_NAME" "$COPY_DB_NAME" "$FINALE_DB_NAME" "$FINALE_SERVICE_NAME"
|
||||
if [[ -z "$RESUME_FROM_VERSION" ]]; then
|
||||
log_step "DATABASE PREPARATION"
|
||||
"${SCRIPT_DIR}/scripts/prepare_db.sh" "$COPY_DB_NAME" "$COPY_DB_NAME" "$FINALE_DB_NAME" "$FINALE_SERVICE_NAME"
|
||||
else
|
||||
log_step "DATABASE PREPARATION — SKIPPED (resuming from checkpoint ou${RESUME_FROM_VERSION})"
|
||||
fi
|
||||
|
||||
|
||||
log_step "UPGRADE PROCESS"
|
||||
|
||||
Reference in New Issue
Block a user