Reverted bashism removals from r228, after discussing this.
[matthijs/upstream/backupninja.git] / handlers / dup.helper
1 HELPERS="$HELPERS dup:incremental_encrypted_remote_filesystem_backup"
2
3 ### Functions
4
5 do_dup_host_includes() {
6    set -o noglob
7    # choose the files to backup
8    REPLY=
9    while [ -z "$REPLY" ]; do
10       formBegin "$dup_title - host system: includes"
11          [ -z "$dup_includes" ] && dup_includes="$dup_default_includes"
12          for i in $dup_includes; do
13             formItem include "$i"
14          done
15          formItem include ""
16          formItem include ""
17          formItem include ""
18          formDisplay
19       [ $? = 0 ] || return 1
20       dup_includes="$REPLY"
21    done
22    set +o noglob
23 }
24
25 do_dup_vserver() {
26    # choose the vservers to backup (into $selected_vservers)
27    choose_one_or_more_vservers "$dup_title"
28    [ $? = 0 ] || return 1
29
30    set -o noglob
31    # choose the files to backup
32    REPLY=
33    while [ -z "$REPLY" ]; do
34       formBegin "$dup_title - vservers: includes"
35          [ -z "$dup_vsincludes" ] && dup_vsincludes="$dup_default_includes"
36          for i in $dup_vsincludes; do
37             formItem include "$i"
38          done
39          formItem include ""
40          formItem include ""
41          formItem include ""
42       formDisplay
43       [ $? = 0 ] || return 1
44       dup_vsincludes="$REPLY"
45    done
46    set +o noglob
47 }
48
49 do_dup_excludes() {
50    set -o noglob
51    formBegin "$dup_title: excludes"
52      [ -z "$dup_excludes" ] && dup_excludes="$dup_default_excludes"
53      for i in $dup_excludes; do
54         formItem exclude "$i"
55      done
56      formItem exclude ""
57      formItem exclude ""
58      formItem exclude ""
59    formDisplay
60    [ $? = 0 ] || return 1
61    dup_excludes="$REPLY"
62    set +o noglob
63 }
64
65 do_dup_src() {
66    choose_host_or_vservers_or_both "$dup_title"
67    [ $? = 0 ] || return 1
68    case $host_or_vservers in
69       'host')
70          do_dup_host_includes
71          [ $? = 0 ] || return 1
72          ;;
73       'vservers')
74          do_dup_vserver
75          [ $? = 0 ] || return 1
76          ;;
77       'both')
78          do_dup_host_includes
79          [ $? = 0 ] || return 1
80          do_dup_vserver
81          [ $? = 0 ] || return 1
82          ;;
83       *)
84          return 1
85          ;;
86    esac
87    do_dup_excludes
88    [ $? = 0 ] || return 1
89    
90    _src_done="(DONE)"
91    setDefault dest
92 }
93
94 do_dup_dest() {
95
96    local replyconverted
97    local thereply
98
99    set -o noglob
100    REPLY=
101    while [ -z "$REPLY" -o -z "$dup_destdir" -o -z "$dup_desthost" -o -z "$dup_destuser" ]; do
102       formBegin "$dup_title - destination: last three items are compulsory"
103         formItem "desthost" "$dup_desthost"
104         formItem "destuser" "$dup_destuser"
105         formItem "destdir" "$dup_destdir"
106         formItem "keep" "$dup_keep"
107         formItem "incremental" "$dup_incremental"
108         formItem "bandwidthlimit" "$dup_bandwidth"
109         formItem "sshoptions" "$dup_sshoptions"
110       formDisplay
111       [ $? = 0 ] || return 1
112
113       IFS=$''
114       replyconverted=`echo $REPLY | tr '\n' :`
115       IFS=$':'
116       thereply=($replyconverted)
117       IFS=$' \t\n'
118       
119       dup_desthost=${thereply[0]}
120       dup_destuser=${thereply[1]}
121       dup_destdir=${thereply[2]}
122       dup_keep=${thereply[3]}
123       dup_incremental=${thereply[4]}
124       dup_bandwidth=${thereply[5]}
125       dup_sshoptions=${thereply[6]}
126
127    done
128    set +o noglob
129
130    _dest_done="(DONE)"
131    setDefault gpg
132 }
133
134 do_dup_gpg() {
135    
136    set -o noglob
137
138    # encryptkey ?
139    REPLY=
140    while [ -z "$REPLY" -o -z "$dup_gpg_encryptkey" ]; do
141       inputBox "$dup_title - GnuPG" "Enter the GnuPG key ID to be used to encrypt the backups:" "$dup_gpg_encryptkey"
142       [ $? = 0 ] || return 1
143       dup_gpg_encryptkey="$REPLY"
144    done
145
146    # passphrase ?
147    REPLY=
148    while [ -z "$REPLY" -o -z "$dup_gpg_password" ]; do
149       passwordBox "$dup_title - GnuPG" "Enter the passphrase needed to unlock the key 0x$dup_gpg_encryptkey"
150       [ $? = 0 ] || return 1
151       dup_gpg_password="$REPLY"
152    done
153
154    # sign ?
155    booleanBox "$dup_title - GnuPG" "Sign the backups?" "$dup_gpg_sign"
156    if [ $? = 0 ]; then
157       dup_gpg_sign=yes
158    else
159       dup_gpg_sign=no
160    fi
161
162    set +o noglob
163    _gpg_done="(DONE)"
164    setDefault adv
165    # TODO: replace the above line by the following when do_dup_conn is written
166    # setDefault conn
167 }
168
169 # TODO: share rdiff.helper code in some lib, and use it here
170 do_dup_conn() {
171    _con_done="(DONE)"
172    setDefault adv
173 }
174
175 do_dup_misc_options() {
176
177    set -o noglob
178    local replyconverted
179    local thereply
180
181    formBegin "$dup_title - misc. options"
182      formItem "nicelevel" "$dup_nicelevel"
183      formItem "testconnect" "$dup_testconnect"
184      formItem "options" "$dup_options"
185    formDisplay
186    [ $? = 0 ] || return 1
187
188    IFS=$''
189    replyconverted=`echo $REPLY | tr '\n' :`
190    IFS=$':'
191    thereply=($replyconverted)
192    IFS=$' \t\n'
193
194    dup_nicelevel=${thereply[0]}
195    dup_testconnect=${thereply[1]}
196    dup_options=${thereply[2]}
197
198    set +o noglob
199 }
200
201 # (rdiff.helper compatible interface... there could be some sode to share, hmmm.)
202 do_dup_adv() {
203    do_dup_misc_options
204    [ $? = 0 ] || return 1
205    _adv_done="(DONE)"
206    setDefault finish
207 }
208
209 do_dup_finish() {
210    get_next_filename $configdirectory/90.dup
211    cat > $next_filename <<EOF
212 # passed directly to duplicity
213 #options = --verbosity 8
214 options = $dup_options
215
216 # default is 0, but set to 19 if you want to lower the priority.
217 nicelevel = $dup_nicelevel
218
219 # default is yes. set to no to skip the test if the remote host is alive
220 testconnect = $dup_testconnect
221
222 ######################################################
223 ## gpg section
224 ## (how to encrypt and optionnally sign the backups)
225
226 [gpg]
227
228 # passphrase needed to unlock the GnuPG key
229 # NB: do not quote it, and it should not contain any quote
230 password = $dup_gpg_password
231
232 # default is no, for backward compatibility with backupninja <= 0.5.
233 # when set to yes, encryptkey option must be set below.
234 sign = $dup_gpg_sign
235
236 # key ID used for data encryption and, optionnally, signing.
237 # if not set, local root's default gpg key is used.
238 encryptkey = $dup_gpg_encryptkey
239
240 ######################################################
241 ## source section
242 ## (where the files to be backed up are coming from)
243
244 [source]
245
246 # files to include in the backup
247 # (supports globbing with '*')
248 # BIG FAT WARNING
249 # Symlinks are not dereferenced. Moreover, an include line whose path
250 # contains, at any level, a symlink to a directory, will only have the
251 # symlink backed-up, not the target directory's content. Yes, you have
252 # to dereference yourself the symlinks, or to use 'mount --bind'
253 # instead.
254 # EXAMPLE
255 # Let's say /home is a symlink to /mnt/crypt/home ; the following line
256 # will only backup a "/home" symlink ; neither /home/user nor
257 # /home/user/Mail will be backed-up :
258 #   include = /home/user/Mail
259 # A workaround is to 'mount --bind /mnt/crypt/home /home' ; another
260 # one is to write :
261 #   include = /mnt/crypt/home/user/Mail
262 EOF
263
264    if [ "$host_or_vservers" == host -o "$host_or_vservers" == both ]; then
265       set -o noglob
266       for i in $dup_includes; do
267          echo "include = $i" >> $next_filename
268       done
269       set +o noglob
270    fi
271
272    cat >> $next_filename <<EOF
273
274 # If vservers = yes in /etc/backupninja.conf then the following variables can
275 # be used:
276 # vsnames = all | <vserver1> <vserver2> ... (default = all)
277 # vsinclude = <path>
278 # Any path specified in vsinclude is added to the include list for each vserver
279 # listed in vsnames (or all if vsnames = all).
280 # E.g. vsinclude = /home will backup the /home partition in every vserver
281 # listed in vsnames. If you have vsnames = "foo bar baz", this vsinclude will
282 # add to the include list /vservers/foo/home, /vservers/bar/home and
283 # /vservers/baz/home.
284 # Vservers paths are derived from $VROOTDIR.
285
286 EOF
287
288    if [ "$host_or_vservers" == vservers -o "$host_or_vservers" == both ]; then
289       set -o noglob
290       echo -e "vsnames = \"$selected_vservers\"\n" >> $next_filename
291       for i in $dup_vsincludes; do
292          echo "vsinclude = $i" >> $next_filename
293       done
294       set +o noglob
295    fi
296
297    # excludes
298    cat >> $next_filename <<EOF
299
300 # rdiff-backup specific comment, TO ADAPT
301 # files to exclude from the backup
302 # (supports globbing with '*')
303 EOF
304     set -o noglob
305     for i in $dup_excludes; do
306         echo "exclude = $i" >> $next_filename
307     done
308     set +o noglob
309
310     cat >> $next_filename <<EOF
311
312 ######################################################
313 ## destination section
314 ## (where the files are copied to)
315
316 [dest]
317
318 # perform an incremental backup? (default = yes)
319 # if incremental = no, perform a full backup in order to start a new backup set
320 incremental = $dup_incremental
321
322 # how many days of data to keep ; default is 60 days.
323 # (you can also use the time format of duplicity)
324 # 'keep = yes' means : do not delete old data, the remote host will take care of this
325 #keep = 60
326 #keep = yes
327 keep = $dup_keep
328
329 # bandwith limit, in kbit/s ; default is 0, i.e. no limit
330 #bandwidthlimit = 128
331 bandwidthlimit = $dup_bandwidth
332
333 # passed directly to ssh and scp
334 #sshoptions = -i /root/.ssh/id_dsa_duplicity
335 sshoptions = $dup_sshoptions
336
337 # put the backups under this directory
338 destdir = $dup_destdir
339
340 # the machine which will receive the backups
341 desthost = $dup_desthost
342
343 # make the files owned by this user
344 # note: you must be able to ssh backupuser@backhost
345 # without specifying a password (if type = remote).
346 destuser = $dup_destuser
347
348 EOF
349
350     chmod 600 $next_filename
351
352 }
353
354 dup_main_menu() {
355
356   while true; do
357      srcitem="choose files to include & exclude $_src_done"
358      destitem="configure backup destination $_dest_done"
359      gpgitem="configure GnuPG encryption/signing $_gpg_done"
360      conitem="set up ssh keys and test remote connection $_con_done"
361      advitem="edit advanced settings $_adv_done"
362      # TODO: add the following to the menu when do_dup_conn is written
363      # conn "$conitem" \
364      menuBox "$dup_title" "choose a step:" \
365         src "$srcitem" \
366         dest "$destitem" \
367         gpg "$gpgitem" \
368         adv "$advitem" \
369         finish "finish and create config file"
370      [ $? = 0 ] || return 1
371      result="$REPLY"
372
373      case "$result" in
374         "src") do_dup_src;;
375         "dest") do_dup_dest;;
376         "gpg") do_dup_gpg;;
377         # TODO: enable the following when do_dup_conn is written
378         # "conn") do_dup_conn;;
379         "adv") do_dup_adv;;
380         "finish")
381            if [[ "$_dest_done$_gpg_done$_src_done" != "(DONE)(DONE)(DONE)" ]]; then
382            # TODO: replace the previous test by the following when do_dup_conn is written
383            # if [[ "$_con_done$_dest_done$_gpg_done$_src_done" != "(DONE)(DONE)(DONE)(DONE)" ]]; then
384               msgBox "$dup_title" "You cannot create the configuration file until the four first steps are completed."
385            else
386               do_dup_finish
387               break
388            fi
389            ;;
390      esac
391
392   done
393 }
394
395 ### Main function
396
397 dup_wizard() {
398    
399    require_packages duplicity
400
401    # Global variables
402    dup_title="Duplicity action wizard"
403    _src_done=
404    _dest_done=
405    _con_done=
406    _gpg_done=
407    _adv_done=
408    dup_includes=
409    dup_excludes=
410    dup_vsincludes=
411    dup_incremental=yes
412    dup_keep=60
413    dup_bandwidth=
414    dup_sshoptions=
415    dup_destdir="/backups/`hostname`"
416    dup_desthost=
417    dup_destuser=
418    dup_gpg_sign="yes"
419    dup_gpg_encryptkey=""
420    dup_gpg_password=""
421    dup_nicelevel=19
422    dup_testconnect=yes
423    dup_options=
424
425    # Global variables whose '*' shall not be expanded
426    set -o noglob
427    dup_default_includes="/var/spool/cron/crontabs /var/backups /etc /root /home /usr/local/*bin /var/lib/dpkg/status*"
428    dup_default_excludes="/home/*/.gnupg"
429    set +o noglob
430
431    dup_main_menu
432 }