more verbose and robust btrbk wrappers
[distro-setup] / switch-mail-host
1 #!/bin/bash
2
3 err-bash-trace() {
4 local -i argc_index=0 frame i start=${1:-0} max_indent=8 indent
5 local source
6 local extdebug=false
7 if [[ $(shopt -p extdebug) == *-s* ]]; then
8 extdebug=true
9 fi
10 for ((frame=0; frame < ${#FUNCNAME[@]}-1; frame++)); do
11 argc=${BASH_ARGC[frame]}
12 argc_index+=$argc
13 ((frame < start)) && continue
14 if (( ${#BASH_SOURCE[@]} > 1 )); then
15 source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:"
16 fi
17 indent=$((frame-start + 1))
18 indent=$((indent < max_indent ? indent : max_indent))
19 printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}"
20 if $extdebug; then
21 for ((i=argc_index-1; i >= argc_index-argc; i--)); do
22 printf " %s" "${BASH_ARGV[i]}"
23 done
24 fi
25 echo \'
26 done
27 return 0
28 }
29
30
31 err-catch() {
32 set -E; shopt -s extdebug
33 _err-trap() {
34 err=$?
35 exec >&2
36 set +x
37 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: \`$BASH_COMMAND' returned $err"
38 err-bash-trace 2
39 set -e # err trap does not work within an error trap
40 "${_errcatch_cleanup[@]:-:}" # note :-: is to be compatible with set -u
41 echo "$0: exiting with code $err"
42 exit $err
43 }
44 trap _err-trap ERR
45 set -o pipefail
46 }
47 err-catch
48
49 usage() {
50 cat <<EOF
51 Usage: ${0##*/} OLD_HOST NEW_HOST
52
53 Turn off mail receiving on OLD_HOST, run btrbk to move mail to NEW_HOST,
54 turn on mail receiving on NEW_HOST. Assumes we want to move all
55 filesystems unless passing -o.
56
57 -o Only btrbk /o, instead of all filesystems.
58 -h|--help Print help and exit.
59
60 I used to adjust home network dns so NEW_HOST resolves locally if it is
61 on the local network, but its simpler just not to and just rely
62 on the internet. Email can wait.
63
64 Note: Uses GNU getopt options parsing style
65 EOF
66 exit $1
67 }
68
69 restore_new_btrbk=false
70 restore_old_btrbk=false
71 cleanup() {
72 if $restore_new_btrbk; then
73 $new_shell sudo systemctl start btrbk.timer
74 fi
75 if $restore_old_btrbk; then
76 $old_shell sudo systemctl start btrbk.timer
77 fi
78 }
79 _errcatch_cleanup=cleanup
80
81 pre="${0##*/}:"
82 m() { printf "$pre %s\n" "$*"; "$@"; }
83 e() { printf "$pre %s\n" "$*"; }
84
85 ##### begin command line parsing ########
86
87 temp=$(getopt -l help owh "$@") || usage 1
88 mp_args="-m /o,/q,/a"
89 eval set -- "$temp"
90 while true; do
91 case $1 in
92 -o) mp_args="-m /o"; shift ;;
93 -h|--help) usage ;;
94 --) shift; break ;;
95 *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
96 esac
97 done
98
99
100 (( $# == 2 )) || usage 1
101
102 old_host=$1
103 new_host=$2
104 source /a/bin/bash_unpublished/source-state
105
106 if [[ $old_host != $MAIL_HOST ]]; then
107 read -p "warning: \$old_host != \$MAIL_HOST: $old_host != $MAIL_HOST, proceed? y/N "
108 if [[ $REPLY != [yY] ]]; then
109 exit 1
110 fi
111 fi
112
113 if [[ $new_host == "$HOSTNAME" ]]; then
114 localhost_new=true
115 new_shell=
116 else
117 localhost_new=false
118 new_shell="ssh $new_host"
119 fi
120
121 old_shell="ssh $old_host"
122 if [[ $old_host == "$HOSTNAME" ]]; then
123 old_shell=
124 fi
125
126 if [[ ! $new_host || ! $old_host ]]; then
127 echo "$0: bad args. see script"
128 exit 1
129 fi
130
131
132 source /a/bin/bash_unpublished/source-state
133
134
135 new_hostname=$($new_shell hostname)
136
137 ########### end initial processing, begin actually modifying things ##########
138
139 if $new_shell systemctl is-active btrbk.timer; then
140 m $new_shell sudo systemctl stop btrbk.timer
141 restore_new_btrbk=true
142 fi
143 if $old_shell systemctl is-active btrbk.timer; then
144 m $old_shell sudo systemctl stop btrbk.timer
145 restore_old_btrbk=true
146 fi
147
148 btrbk_test="systemctl is-active btrbk.service"
149 while [[ $($new_shell $btrbk_test) != inactive ]] || [[ $($old_shell $btrbk_test) != inactive ]]; do
150 echo "$0: btrbk is running on new or old host. sleeping for 8 seconds"
151 sleep 6
152 echo "$0: testing for btrbk activity in 2 seconds"
153 sleep 2
154 done
155
156 # ensure these are unused before doing anything
157
158 e "umounting /m and /o via $new_shell"
159 $new_shell bash -xs <<'EOF'
160 set -eE
161 if mountpoint -q /m; then sudo umount /m; fi
162 if mountpoint -q /o; then sudo umount /o; fi
163 EOF
164
165 # previously, I was checking to see if the new mail host
166 # is on my home network, then changing my home dns
167 # to resolve on the local network, so that I didnt
168 # have to send traffic out to the internet or rely
169 # on that. However, that breaks for a laptop that roams.
170 # So, we could have a cronjob that updates that dns,
171 # however, another solution is to just use ipv6,
172 # and I prefer that.
173 #
174 # TODO: enable ipv6 for email. exim config setting disables it.
175 # need to add vpn support. need to add firewall / routing.
176 # I think exim will try ipv6 first, so no need to disable
177 # ipv6 i think.
178
179 m $old_shell /a/exe/primary-setup $new_hostname
180
181 if $localhost_new; then
182 m btrbk-run -v -s $old_host $mp_args
183 else
184 m btrbk-run -v -t $new_host $mp_args
185 fi
186
187 m $new_shell /a/exe/primary-setup $new_hostname