Browse Source

new: [0km] add support of component partial backup restore

Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>
rc1
Valentin Lab 4 years ago
parent
commit
474cb1733e
  1. 15
      README.org
  2. 87
      bin/0km

15
README.org

@ -924,6 +924,21 @@ la source un chemin et possible aussi à la destination.
0km vps-backup recover myadmin@core-06.0k.io:10023#mail.mybackupedvps.com:/mon/chemin mynewvps.com:/ma/dest
#+end_quote
***** Récupération d'un composant
Suivant si le type de backup est reconnu et le supporte, il est
possible de nommer un composant précis en lieu et place d'un
répertoire ou d'un fichier.
Par exemple, les backup de type 'mailcow' supportent les composants
suivants: =mailcow=, =postfix=, =rspamd=, =redis=, =crypt=, =vmail=,
=vmail-attachments=, =mysql=.
#+begin_quote
0km vps-backup recover myadmin@core-06.0k.io:10023#mail.mybackupedvps.com:mailcow,mysql mynewvps.com
0km vps-backup recover myadmin@core-06.0k.io:10023#mail.mybackupedvps.com:postfix mynewvps.com
#+end_quote
** Troubleshooting

87
bin/0km

@ -386,7 +386,7 @@ EOF
stopped_containers=1
fi
if [[ -n "$path" ]]; then
if [[ "$path" == "/"* ]]; then
##
## Additional intelligence to simple file copy
@ -425,9 +425,35 @@ EOF
fi
fi
else
ALL_TARGETS=(mailcow postfix rspamd redis crypt vmail{,-attachments} mysql)
if [[ -n "$path" ]]; then
targets=()
bad_targets=()
for target in ${path//,/ }; do
if [[ " ${ALL_TARGETS[*]} " != *" $target "* ]]; then
bad_targets+=("$target")
fi
targets+=("$target")
done
if [ "${#bad_targets[@]}" -gt 0 ]; then
bad_target_msg=$(printf "%s, " "${bad_targets[@]}")
err "Unknown components: ${bad_target_msg%, }. These are allowed components:"
printf " - %s\n" "${ALL_TARGETS[@]}" >&2
return 1
fi
msg_target="Partial mailcow backup"
else
targets=("${ALL_TARGETS[@]}")
msg_target="Full mailcow backup"
fi
for target in "${targets[@]}"; do
case "$target" in
postfix|rspamd|redis|crypt|vmail|vmail-attachments)
for vol in postfix rspamd redis crypt vmail{,-attachments}; do
volume_name="mailcowdockerized_${vol}-vol-1"
volume_name="mailcowdockerized_${target}-vol-1"
volume_dir="/var/lib/docker/volumes/${volume_name}/_data"
if ! backup:path_exists "${volume_dir}/"; then
warn "No '$volume_name' in backup. This might be expected."
@ -445,8 +471,8 @@ EOF
echo "${WHITE}Downloading of $volume_name${NORMAL}"
backup:rsync "${volume_dir}/" "${volume_dir}" || return 1
done
;;
mailcow)
## Mailcow git base
COMPOSE_FILE=
for mailcow_dir in /opt/{apps/,}mailcow-dockerized; do
@ -458,12 +484,40 @@ EOF
backup:rsync "${mailcow_dir}"/ "${mailcow_dir}" || return 1
break
done
if [ -z "$COMPOSE_FILE" ]; then
err "Can't find mailcow base installation path in backup."
return 1
fi
;;
mysql)
if [ -z "$COMPOSE_FILE" ]; then
## Mailcow git base
compose_files=()
for mailcow_dir in /opt/{apps/,}mailcow-dockerized; do
ssh:run "root@$vps" -- "[ -e \"$mailcow_dir/docker-compose.yml\" ]" || continue
## this possibly change last value
compose_files+=("$mailcow_dir/docker-compose.yml")
done
if [ "${#compose_files[@]}" == 0 ]; then
err "No compose file found for mailcow installation."
return 1
elif [ "${#compose_files[@]}" -gt 1 ]; then
err "Multiple compose files for mailcow found:"
for f in "${compose_files[@]}"; do
echo " - $f" >&2
done
echo "Can't decide which to use for mounting mysql container." >&2
return 1
fi
COMPOSE_FILE="${compose_files[0]}"
ENV_FILE="${COMPOSE_FILE%/*}/.env"
if ! ssh:run "root@$vps" -- "[ -e \"${COMPOSE_FILE%/*}/.env\" ]"; then
err "No env file in '$ENV_FILE' found."
return 1
fi
fi
## Mysql database
echo "${WHITE}Downloading last backup of mysql backups${NORMAL}"
backup:rsync "/var/backups/mysql/" "/var/backups/mysql" || return 1
@ -553,8 +607,14 @@ EOF
echo "${WHITE}Bringing mysql-mailcow down${NORMAL}"
echo "docker-compose -f \"${COMPOSE_FILE}\" --env-file \"${ENV_FILE}\" down" |
ssh:run "root@$vps" -- bash
;;
*)
err "Unknown component '$target'. Bailing out."
return 1
esac
done
ssh:run "root@$vps" -- "rm -rf '$VPS_TMP_DIR'"
msg_target="Full mailcow backup"
fi
if [ -n "$stopped_containers" ]; then
@ -619,7 +679,7 @@ vps_backup_recover() {
## from vps to backup server.
backup:setup-rsync "$admin" "$vps" "$server" "$id" || return 1
if [ -n "$path" ]; then
if [[ "$path" == "/"* ]]; then
if ! backup:path_exists "${path}"; then
err "File or directory '$path' not found in backup."
return 1
@ -640,14 +700,20 @@ vps_backup_recover() {
mailcow:vps_backup_recover "$admin" "$server" "$id" "$path" "$vps" "$vps_path"
;;
*-*)
if [ -n "$path" ]; then
if [[ "$path" == "/"* ]]; then
## For now, will require having $path and $vps_path set, no additional behaviors
file:vps_backup_recover "$admin" "$server" "$id" "$path" "$vps" "$vps_path"
else
if [ -n "$path" ]; then
err "Partial component recover of ${rtype:-unknown} backup type on" \
"${type:-unknown} type VPS is not yet implemented."
return 1
else
err "Full recover of ${rtype:-unknown} backup type on" \
"${type:-unknown} type VPS is not yet implemented."
return 1
fi
fi
;;
esac
@ -1000,7 +1066,8 @@ cmdline.spec:vps-backup:cmd:recover:run() {
: :posarg: BACKUP_ID 'Backup id.
(ie: myadmin@backup.domain.org:10023#mx.myvps.org
myadmin@ark-01.org#myid:/a/path)'
myadmin@ark-01.org#myid:/a/path
admin@ark-02.io#myid:myqsl,mailcow)'
: :posarg: VPS_PATH 'Target host(s) to check.
(ie: myvps.com
myvps.com:/a/path)'

Loading…
Cancel
Save