cae99097e814b764cacdb20d3ebfa6acb5fa2f46
[matthijs/upstream/backupninja.git] / handlers / dup.in
1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 #
3 # duplicity script for backupninja
4 # requires duplicity
5 #
6
7 getconf options
8 getconf testconnect yes
9 getconf nicelevel 0
10 getconf tmpdir
11
12 setsection gpg
13 getconf password
14 getconf sign no
15 getconf encryptkey
16 getconf signkey
17
18 setsection source
19 getconf include
20 getconf vsnames all
21 getconf vsinclude
22 getconf exclude
23
24 setsection dest
25 getconf incremental yes
26 getconf keep 60
27 getconf desturl
28 getconf sshoptions
29 getconf bandwidthlimit 0
30 getconf desthost
31 getconf destdir
32 getconf destuser
33 destdir=${destdir%/}
34
35 ### SANITY CHECKS ##############################################################
36
37 [ -n "$desturl" -o -n "$destdir" ]  || fatal "The destination directory (destdir) must be set when desturl is not used."
38 [ -n "$include" ]  || fatal "No source includes specified"
39 [ -n "$password" ] || fatal "The password option must be set."
40
41 ### VServers
42 # If vservers are configured, check that the ones listed in $vsnames do exist.
43 local usevserver=no
44 if [ $vservers_are_available = yes ]; then
45    if [ "$vsnames" = all ]; then
46       vsnames="$found_vservers"
47    else
48       if ! vservers_exist "$vsnames" ; then
49             fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist."
50       fi
51    fi
52    if [ -n "$vsinclude" ]; then
53       info "Using vservers '$vsnames'"
54       usevserver=yes
55    fi
56 else
57    [ -z "$vsinclude" ] || warning 'vservers support disabled in backupninja.conf, vsincludes configuration lines will be ignored'
58 fi
59
60 ### See if we can login on $desthost
61 if [ "$testconnect" == "yes" ]; then
62    if [ -n "$desturl" ]; then
63       warning 'testconnect can not be used when desturl is set'
64    else
65       debug "ssh $sshoptions -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'"
66       if [ ! $test ]; then
67          result=`ssh $sshoptions -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'`
68          if [ "$result" != "1" ]; then
69             fatal "Can't connect to $desthost as $destuser."
70          else
71             debug "Connected to $desthost as $destuser successfully"
72          fi
73       fi
74    fi
75 fi
76
77 ### COMMAND-LINE MANGLING ######################################################
78
79 ### initialize $execstr*
80 execstr_command=
81 execstr_options="$options --no-print-statistics"
82 execstr_source=
83 if [ -n "$desturl" ]; then
84    [ -z "$destuser" ] || warning 'the configured destuser is ignored since desturl is set'
85    [ -z "$desthost" ] || warning 'the configured desthost is ignored since desturl is set'
86    [ -z "$destdir" ] || warning 'the configured destdir is ignored since desturl is set'
87    execstr_serverpart="$desturl"
88 else
89    execstr_serverpart="scp://$destuser@$desthost/$destdir"
90 fi
91
92 ### duplicity version
93 duplicity_version="`duplicity --version | @AWK@ '{print $2}'`"
94 duplicity_major="`echo $duplicity_version | @AWK@ -F '.' '{print $1}'`"
95 duplicity_minor="`echo $duplicity_version | @AWK@ -F '.' '{print $2}'`"
96 duplicity_sub="`echo $duplicity_version | @AWK@ -F '.' '{print $3}'`"
97
98 ### ssh/scp/sftp options
99 # 1. duplicity >= 0.4.2 needs --sftp-command
100 #    (NB: sftp does not support the -l option)
101 # 2. duplicity 0.4.3 to 0.4.9 replace --ssh-command with --ssh-options, which is
102 #    passed to scp and sftp commands by duplicity. We don't use it: since this
103 #    version does not use the ssh command anymore, we keep compatibility with
104 #    our previous config files by passing $sshoptions to --scp-command and
105 #    --sftp-command ourselves
106
107 scpoptions="$sshoptions"
108 [ "$bandwidthlimit" == 0 ] || scpoptions="$scpoptions -l $bandwidthlimit"
109
110 # < 0.4.2 : only uses ssh and scp
111 if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 2 ]; then
112    execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --ssh-command 'ssh $sshoptions'"
113 # >= 0.4.2 : also uses sftp, --sftp-command option is now supported
114 else
115    sftpoptions="$sshoptions"
116    # == 0.4.2 : uses ssh, scp and sftp
117    if [ "$duplicity_major" -eq 0 -a "$duplicity_minor" -eq 4 -a "$duplicity_sub" -eq 2 ]; then
118       execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --sftp-command 'sftp $sftpoptions' --ssh-command 'ssh $sshoptions'"
119    # >= 0.4.3 : uses only scp and sftp, --ssh-command option is not supported anymore
120    else
121       execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --sftp-command 'sftp $sftpoptions'"
122    fi
123 fi
124
125 ### Symmetric or asymmetric (public/private key pair) encryption
126 if [ -n "$encryptkey" ]; then
127    execstr_options="${execstr_options} --encrypt-key $encryptkey"
128    debug "Data will be encrypted with the GnuPG key $encryptkey."
129 else
130    debug "Data will be encrypted using symmetric encryption."
131 fi
132
133 ### Data signing (or not)
134 if [ "$sign" == yes ]; then
135    # duplicity is not able to sign data when using symmetric encryption
136    [ -n "$encryptkey" ] || fatal "The encryptkey option must be set when signing."
137    # if needed, initialize signkey to a value that is not empty (checked above)
138    [ -n "$signkey" ] || signkey="$encryptkey"
139    execstr_options="${execstr_options} --sign-key $signkey"
140    debug "Data will be signed will the GnuPG key $signkey."
141 else
142    debug "Data won't be signed."
143 fi
144
145 ### Incremental or full backup mode
146 # If incremental==yes, use the default duplicity behaviour: perform an
147 # incremental backup if old signatures can be found, else switch to
148 # full backup.
149 # If incremental==no, force a full backup anyway.
150 if [ "$incremental" == "no" ]; then
151    # before 0.4.4, full was an option and not a command
152    if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 4 ]; then   
153       execstr_options="${execstr_options} --full"
154    else
155       execstr_command="full"
156    fi
157 fi
158
159 ### Temporary directory
160 precmd=
161 if [ -n "$tmpdir" ]; then
162    if [ ! -d "$tmpdir" ]; then
163       info "Temporary directory ($tmpdir) does not exist, creating it."
164       mkdir -p "$tmpdir"
165       [ $? -eq 0 ] || fatal "Could not create temporary directory ($tmpdir)."
166    fi
167    info "Using $tmpdir as TMPDIR"
168    precmd="${precmd}TMPDIR=$tmpdir "
169 fi
170
171 ### Cleanup old backup sets (or not)
172 if [ "$keep" != "yes" ]; then
173    if [ "`echo $keep | tr -d 0-9`" == "" ]; then
174       keep="${keep}D"
175    fi
176    # before 0.4.4, remove-older-than was an option and not a command
177    if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 4 ]; then
178       execstr_options="${execstr_options} --remove-older-than $keep"
179    fi
180 fi
181
182 ### Source
183
184 set -o noglob
185
186 # excludes
187 for i in $exclude; do
188    str="${i//__star__/*}"
189    execstr_source="${execstr_source} --exclude '$str'"
190 done
191
192 # includes
193 for i in $include; do
194    [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
195    str="${i//__star__/*}"
196    execstr_source="${execstr_source} --include '$str'"
197 done
198
199 # vsincludes
200 if [ $usevserver = yes ]; then
201    for vserver in $vsnames; do
202       for vi in $vsinclude; do
203          str="${vi//__star__/*}"
204          str="$VROOTDIR/$vserver$str"
205          execstr_source="${execstr_source} --include '$str'"
206       done
207    done
208 fi
209
210 set +o noglob
211
212 ### EXECUTE ####################################################################
213
214 execstr_source=${execstr_source//\\*/\\\\\\*}
215
216 ### Cleanup commands (duplicity >= 0.4.4)
217
218 # cleanup
219 if [ "$duplicity_major" -ge 0 -a "$duplicity_minor" -ge 4 -a "$duplicity_sub" -ge 4 ]; then
220    debug "$precmd duplicity cleanup $execstr_options $execstr_serverpart"
221    if [ ! $test ]; then
222       export PASSPHRASE=$password
223       output=`nice -n $nicelevel \
224          su -c \
225          "$precmd duplicity cleanup $execstr_options $execstr_serverpart 2>&1"`
226       exit_code=$?
227       if [ $exit_code -eq 0 ]; then
228          debug $output
229          info "Duplicity cleanup finished successfully."
230       else
231          debug $output
232          warning "Duplicity cleanup failed."
233       fi
234    fi
235 fi
236
237 # remove-older-than
238 if [ "$keep" != "yes" ]; then
239    if [ "$duplicity_major" -ge 0 -a "$duplicity_minor" -ge 4 -a "$duplicity_sub" -ge 4 ]; then
240       debug "$precmd duplicity remove-older-than $keep $execstr_options $execstr_serverpart"
241       if [ ! $test ]; then
242          export PASSPHRASE=$password
243          output=`nice -n $nicelevel \
244                    su -c \
245                       "$precmd duplicity remove-older-than $keep $execstr_options $execstr_serverpart 2>&1"`
246          exit_code=$?
247          if [ $exit_code -eq 0 ]; then
248             debug $output
249             info "Duplicity remove-older-than finished successfully."
250          else
251             debug $output
252             warning "Duplicity remove-older-than failed."
253          fi
254       fi
255    fi
256 fi
257
258 ### Backup command
259 debug "$precmd duplicity $execstr_command $execstr_options $execstr_source --exclude '**' / $execstr_serverpart"
260 if [ ! $test ]; then
261    export PASSPHRASE=$password
262    output=`nice -n $nicelevel \
263              su -c \
264                 "$precmd duplicity $execstr_command $execstr_options $execstr_source --exclude '**' / $execstr_serverpart 2>&1"`
265    exit_code=$?
266    if [ $exit_code -eq 0 ]; then
267       debug $output
268       info "Duplicity finished successfully."
269    else
270       debug $output
271       fatal "Duplicity failed."
272    fi
273 fi
274
275 return 0