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