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