From 782eb6c9978a282ba9daa9516b8a484e89445ffe Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Tue, 3 Dec 2024 22:27:51 +0100 Subject: [PATCH] fix: [vps] retry in ``odoo dump`` if dump zip's integrity failed --- bin/vps | 132 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 110 insertions(+), 22 deletions(-) diff --git a/bin/vps b/bin/vps index 7e04150..0e35a93 100755 --- a/bin/vps +++ b/bin/vps @@ -1684,7 +1684,8 @@ cmdline.spec:odoo:cmd:restore:run() { local out - depends zip + unzip:require "6.0" || return 1 + odoo_service="${opt_service:-odoo}" if [[ "$ZIP_DUMP_LOCATION" == "http://"* ]] || @@ -1710,16 +1711,6 @@ cmdline.spec:odoo:cmd:restore:run() { exit 1 } - if ! out=$(zip -T "$ZIP_DUMP_LOCATION" 2>&1); then - err "Dump file to restore is an invalid zip file." - if [ "$opt_debug" ]; then - printf "%s" "$out" | prefix " ${GRAY}|${NORMAL} " >&2 - else - echo " Use \`\`--debug\`\` (or \`\`-d\`\`) to get more information." >&2 - fi - exit 1 - fi - opts_compose=() [ -t 1 ] && opts_compose+=("--color") [ "$opt_debug" ] && { @@ -1729,6 +1720,13 @@ cmdline.spec:odoo:cmd:restore:run() { opts_load=() [ "$opt_neutralize" ] && opts_load+=("--neutralize") + unzip:check-integrity "$ZIP_DUMP_LOCATION" || { + if [ -z "$opt_debug" ]; then + echo " Use \`\`--debug\`\` (or \`\`-d\`\`) to get more information." >&2 + fi + return 1 + } + project_name=$(compose:project_name) || exit 1 container_name=$(compose:service:container:get "${project_name}" "${odoo_service}") || exit 1 info "Found container ${CYAN}${container_name}${NORMAL} for service ${DARKYELLOW}$odoo_service${NORMAL}." @@ -1776,10 +1774,11 @@ cmdline.spec:odoo:cmd:dump:run() { : :optval: --database,-D 'Target database (default if not specified)' : :optval: --service,-s "The service (defaults to 'odoo')" : :optfla: --debug,-d "Display debugging information" + : :optfla: --force,-f "Force the dump even if the file already exists" odoo_service="${opt_service:-odoo}" - depends zip + unzip:require "6.0" || return 1 msg_dbname=default [ -n "$opt_database" ] && msg_dbname="'$opt_database'" @@ -1791,19 +1790,45 @@ cmdline.spec:odoo:cmd:dump:run() { opts_compose+=("--debug") } - compose --no-hooks "${opts_compose[@]}" save "$odoo_service" $opt_database > "$DUMP_ZIPFILE" || { - err "Failed dumping ${DARKYELLOW}$odoo_service${NORMAL}'s $msg_dbname database to '$DUMP_ZIPFILE'." - exit 1 - } + if [ -e "$DUMP_ZIPFILE" ]; then + if [ -z "$opt_force" ]; then + err "File '$DUMP_ZIPFILE' already exists." + echo " Use \`\`--force\`\` (or \`\`-f\`\`) to overwrite it." >&2 + exit 1 + else + info "Removing previous file '$DUMP_ZIPFILE'." + rm -f "$DUMP_ZIPFILE" || return 1 + fi + fi + + max_retry=5 + retry=1 + success= + while [ "$retry" -le "$max_retry" ]; do + if [ "$retry" -gt 1 ]; then + info "Retry $retry/$max_retry to dump ${DARKYELLOW}$odoo_service${NORMAL}'s $msg_dbname database." + fi + compose --no-hooks "${opts_compose[@]}" save "$odoo_service" $opt_database > "$DUMP_ZIPFILE" || { + err "Failed dumping ${DARKYELLOW}$odoo_service${NORMAL}'s $msg_dbname database to '$DUMP_ZIPFILE'." + return 1 + } - if ! zip -T "$DUMP_ZIPFILE" >/dev/null; then - err "Dump produced an invalid zip file '$DUMP_ZIPFILE'. Deleting it." - echo " Note: if the database is too big, you may want to check that the" >&2 - echo " \`limit-time-*' parameters are not set to low." >&2 - rm -f "$DUMP_ZIPFILE" + unzip:check-integrity "$DUMP_ZIPFILE" || { + err "Dump produced an invalid zip file '$DUMP_ZIPFILE'. Deleting it." + if [ -z "$opt_debug" ]; then + echo " Use \`\`--debug\`\` (or \`\`-d\`\`) to get more information." >&2 + fi + rm -f "$DUMP_ZIPFILE" + ((retry++)) + continue + } + success=1 + break + done + if [ -z "$success" ]; then + err "Failed to dump ${DARKYELLOW}$odoo_service${NORMAL}'s $msg_dbname database to '$DUMP_ZIPFILE'." exit 1 fi - info "Successfully dumped ${DARKYELLOW}$odoo_service${NORMAL}'s $msg_dbname database to '$DUMP_ZIPFILE'." } @@ -2215,6 +2240,69 @@ awk:require() { done } + +unzip:require() { + local require_at_least="$1" version already_installed + while true; do + if ! version=$(unzip -v 2>/dev/null); then + version="" + else + ## Version is in the first line, here's an example: + ## + ## UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP. + + version=${version##UnZip } + version=${version%% of*} + fi + if [ -z "$version" ] || version_gt "$require_at_least" "$version"; then + if [ -z "$already_installed" ]; then + if [ -z "$version" ]; then + info "No 'unzip' available, probably using a clone. Installing 'unzip'..." + else + info "Found unzip version '$version'. Updating 'unzip'..." + fi + apt-get install unzip -y &1); then + ## remove OK files + out=$(printf "%s\n" "$out" | egrep -v "^\s+testing: .*\s+OK$") + ## if last line is not "No errors detected in compressed data of $file." + ## then it's an error + last_line=${out##*$'\n'} + if [ "$last_line" == "No errors detected in compressed data of $file." ]; then + return 0 + fi + err "Zip file '$file' failed integrity check." + if [ -n "$VERBOSE" ]; then + printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " >&2 + fi + return 1 + fi + return 0 +} + + resource:list() { declare -F | egrep -- '-fx? stats:[a-zA-Z0-9_.-]+$' | cut -f 3- -d " " | cut -f 2- -d ":" }