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 0km vps-backup recover myadmin@core-06.0k.io:10023#mail.mybackupedvps.com:/mon/chemin mynewvps.com:/ma/dest
#+end_quote #+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 ** Troubleshooting

87
bin/0km

@ -386,7 +386,7 @@ EOF
stopped_containers=1 stopped_containers=1
fi fi
if [[ -n "$path" ]]; then
if [[ "$path" == "/"* ]]; then
## ##
## Additional intelligence to simple file copy ## Additional intelligence to simple file copy
@ -425,9 +425,35 @@ EOF
fi fi
fi fi
else 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" volume_dir="/var/lib/docker/volumes/${volume_name}/_data"
if ! backup:path_exists "${volume_dir}/"; then if ! backup:path_exists "${volume_dir}/"; then
warn "No '$volume_name' in backup. This might be expected." warn "No '$volume_name' in backup. This might be expected."
@ -445,8 +471,8 @@ EOF
echo "${WHITE}Downloading of $volume_name${NORMAL}" echo "${WHITE}Downloading of $volume_name${NORMAL}"
backup:rsync "${volume_dir}/" "${volume_dir}" || return 1 backup:rsync "${volume_dir}/" "${volume_dir}" || return 1
done
;;
mailcow)
## Mailcow git base ## Mailcow git base
COMPOSE_FILE= COMPOSE_FILE=
for mailcow_dir in /opt/{apps/,}mailcow-dockerized; do for mailcow_dir in /opt/{apps/,}mailcow-dockerized; do
@ -458,12 +484,40 @@ EOF
backup:rsync "${mailcow_dir}"/ "${mailcow_dir}" || return 1 backup:rsync "${mailcow_dir}"/ "${mailcow_dir}" || return 1
break break
done done
if [ -z "$COMPOSE_FILE" ]; then if [ -z "$COMPOSE_FILE" ]; then
err "Can't find mailcow base installation path in backup." err "Can't find mailcow base installation path in backup."
return 1 return 1
fi 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 ## Mysql database
echo "${WHITE}Downloading last backup of mysql backups${NORMAL}" echo "${WHITE}Downloading last backup of mysql backups${NORMAL}"
backup:rsync "/var/backups/mysql/" "/var/backups/mysql" || return 1 backup:rsync "/var/backups/mysql/" "/var/backups/mysql" || return 1
@ -553,8 +607,14 @@ EOF
echo "${WHITE}Bringing mysql-mailcow down${NORMAL}" echo "${WHITE}Bringing mysql-mailcow down${NORMAL}"
echo "docker-compose -f \"${COMPOSE_FILE}\" --env-file \"${ENV_FILE}\" down" | echo "docker-compose -f \"${COMPOSE_FILE}\" --env-file \"${ENV_FILE}\" down" |
ssh:run "root@$vps" -- bash ssh:run "root@$vps" -- bash
;;
*)
err "Unknown component '$target'. Bailing out."
return 1
esac
done
ssh:run "root@$vps" -- "rm -rf '$VPS_TMP_DIR'" ssh:run "root@$vps" -- "rm -rf '$VPS_TMP_DIR'"
msg_target="Full mailcow backup"
fi fi
if [ -n "$stopped_containers" ]; then if [ -n "$stopped_containers" ]; then
@ -619,7 +679,7 @@ vps_backup_recover() {
## from vps to backup server. ## from vps to backup server.
backup:setup-rsync "$admin" "$vps" "$server" "$id" || return 1 backup:setup-rsync "$admin" "$vps" "$server" "$id" || return 1
if [ -n "$path" ]; then
if [[ "$path" == "/"* ]]; then
if ! backup:path_exists "${path}"; then if ! backup:path_exists "${path}"; then
err "File or directory '$path' not found in backup." err "File or directory '$path' not found in backup."
return 1 return 1
@ -640,14 +700,20 @@ vps_backup_recover() {
mailcow:vps_backup_recover "$admin" "$server" "$id" "$path" "$vps" "$vps_path" 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 ## For now, will require having $path and $vps_path set, no additional behaviors
file:vps_backup_recover "$admin" "$server" "$id" "$path" "$vps" "$vps_path" 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 else
err "Full recover of ${rtype:-unknown} backup type on" \ err "Full recover of ${rtype:-unknown} backup type on" \
"${type:-unknown} type VPS is not yet implemented." "${type:-unknown} type VPS is not yet implemented."
return 1 return 1
fi fi
fi
;; ;;
esac esac
@ -1000,7 +1066,8 @@ cmdline.spec:vps-backup:cmd:recover:run() {
: :posarg: BACKUP_ID 'Backup id. : :posarg: BACKUP_ID 'Backup id.
(ie: myadmin@backup.domain.org:10023#mx.myvps.org (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. : :posarg: VPS_PATH 'Target host(s) to check.
(ie: myvps.com (ie: myvps.com
myvps.com:/a/path)' myvps.com:/a/path)'

Loading…
Cancel
Save