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