Merge lp:~jontai/openvista-gtm-integration/bug362001 into lp:openvista-gtm-integration
- bug362001
- Merge into mainline
Proposed by
Jon Tai
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | not available | ||||
Proposed branch: | lp:~jontai/openvista-gtm-integration/bug362001 | ||||
Merge into: | lp:openvista-gtm-integration | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp:~jontai/openvista-gtm-integration/bug362001 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
jeff.apple | Approve | ||
Review via email: mp+5650@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
jeff.apple (jeff-apple) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'packages/rpm/openvista-utils.spec' |
2 | --- packages/rpm/openvista-utils.spec 2009-04-14 07:38:10 +0000 |
3 | +++ packages/rpm/openvista-utils.spec 2009-04-16 06:01:37 +0000 |
4 | @@ -44,6 +44,7 @@ |
5 | install -d %{buildroot}%{_sbindir}/ |
6 | install scripts/usr/sbin/ovinstanceadd %{buildroot}%{_sbindir}/ |
7 | install scripts/usr/sbin/ovinstancedel %{buildroot}%{_sbindir}/ |
8 | +install scripts/usr/sbin/ovrestore %{buildroot}%{_sbindir}/ |
9 | |
10 | install -d %{buildroot}%{_bindir}/ |
11 | install scripts/usr/bin/openvista %{buildroot}%{_bindir}/ |
12 | @@ -75,6 +76,7 @@ |
13 | %{_libdir}/openvista/functions |
14 | %{_sbindir}/ovinstanceadd |
15 | %{_sbindir}/ovinstancedel |
16 | +%{_sbindir}/ovrestore |
17 | %{_bindir}/openvista |
18 | %{_bindir}/ovtied |
19 | %{_bindir}/ovbackup |
20 | |
21 | === modified file 'scripts/etc/bash_completion.d/openvista' |
22 | --- scripts/etc/bash_completion.d/openvista 2009-04-14 07:21:58 +0000 |
23 | +++ scripts/etc/bash_completion.d/openvista 2009-04-16 06:01:37 +0000 |
24 | @@ -24,11 +24,15 @@ |
25 | root="/opt/openvista" |
26 | cur=${COMP_WORDS[COMP_CWORD]} |
27 | if [ $COMP_CWORD -eq 1 ]; then |
28 | - COMPREPLY=( $(compgen -W "$(ls -1 $root 2> /dev/null)" $cur ) ) |
29 | + COMPREPLY=( $(compgen -W "$(ls -1 $root 2> /dev/null)" $cur) ) |
30 | + else |
31 | + _filedir |
32 | fi |
33 | + return 0 |
34 | } |
35 | |
36 | complete -F _openvista_instances ovinstancedel |
37 | +complete -F _openvista_instances ovrestore |
38 | complete -F _openvista_instances openvista |
39 | complete -F _openvista_instances ovtied |
40 | complete -F _openvista_instances ovbackup |
41 | |
42 | === modified file 'scripts/etc/cron.d/openvista' |
43 | --- scripts/etc/cron.d/openvista 2009-04-13 22:31:11 +0000 |
44 | +++ scripts/etc/cron.d/openvista 2009-04-17 05:35:20 +0000 |
45 | @@ -14,9 +14,13 @@ |
46 | # |
47 | # Example: back up the production instance at 6am, noon, 6pm, and midnight |
48 | # every day; purge old journals right after a successful backup |
49 | -# 0 */6 * * * openvista ovbackup production && ovpurgejournals production |
50 | +# 0 */6 * * * openvista ovbackup -q production && ovpurgejournals production |
51 | # |
52 | # Example: back up the training instance at 3:45am on Mondays, Wednesdays, and |
53 | -# Fridays; let the daily cron job purge old journals |
54 | -# 45 3 * * 1,3,5 openvista ovbackup training |
55 | +# Fridays; let the daily cron job purge old journals (Warning: because |
56 | +# journals are being purged more often than backups are made, if the |
57 | +# training database is busy, it's possible that you won't be able to |
58 | +# restore a backup and then replay journals because the required |
59 | +# journals have already been purged) |
60 | +# 45 3 * * 1,3,5 openvista ovbackup -q training |
61 | |
62 | |
63 | === modified file 'scripts/etc/cron.daily/openvista' |
64 | --- scripts/etc/cron.daily/openvista 2009-04-15 05:16:53 +0000 |
65 | +++ scripts/etc/cron.daily/openvista 2009-04-17 05:35:20 +0000 |
66 | @@ -35,6 +35,7 @@ |
67 | |
68 | |
69 | root="/opt/openvista" |
70 | +user="openvista" |
71 | |
72 | for instance in `ls $root`; do |
73 | # the default is "yes" unless the etc/backups.conf file exists and it has |
74 | @@ -50,7 +51,7 @@ |
75 | # skip backing up this instance |
76 | ;; |
77 | *) |
78 | - ovbackup "$instance" || backup_failed=true |
79 | + su -c "ovbackup -q \"$instance\"" "$user" || backup_failed=true |
80 | ;; |
81 | esac |
82 | |
83 | @@ -67,7 +68,7 @@ |
84 | # skip this instance |
85 | ;; |
86 | *) |
87 | - ${backup_failed:-false} || ovpurgejournals "$instance" |
88 | + ${backup_failed:-false} || su -c "ovpurgejournals \"$instance\"" "$user" |
89 | ;; |
90 | esac |
91 | done |
92 | |
93 | === modified file 'scripts/etc/init.d/openvista_early' |
94 | --- scripts/etc/init.d/openvista_early 2009-04-15 05:14:43 +0000 |
95 | +++ scripts/etc/init.d/openvista_early 2009-04-17 02:51:59 +0000 |
96 | @@ -58,7 +58,7 @@ |
97 | |
98 | logger -p user.info -t "openvista_early[$$]" -- Performing recovery on $instance database |
99 | |
100 | - mupip journal -recover -backward "$root/$instance/journals/default.mjl" 2>&1 \ |
101 | + mupip journal -recover -backward '*' 2>&1 \ |
102 | | grep -v '^$' \ |
103 | | logger -p user.info -t "openvista_early[$$]" |
104 | retval=${PIPESTATUS[0]} |
105 | |
106 | === modified file 'scripts/usr/bin/ovbackup' |
107 | --- scripts/usr/bin/ovbackup 2009-04-15 17:31:43 +0000 |
108 | +++ scripts/usr/bin/ovbackup 2009-04-17 05:16:08 +0000 |
109 | @@ -27,19 +27,25 @@ |
110 | . /usr/lib/openvista/functions |
111 | |
112 | # parse arguments |
113 | -while getopts hy option; do |
114 | +while getopts hq option; do |
115 | case $option in |
116 | h) |
117 | - echo "Usage: ovbackup INSTANCE_NAME" |
118 | + echo "Usage: ovbackup [-q] INSTANCE_NAME" |
119 | echo " or ovbackup -h" |
120 | echo |
121 | + echo " -q quiet; suppress status messages" |
122 | echo " -h display this help text" |
123 | exit 0 |
124 | ;; |
125 | + q) |
126 | + skip_status=true |
127 | + ;; |
128 | esac |
129 | done |
130 | shift `expr $OPTIND - 1` |
131 | |
132 | +: ${skip_status:=false} |
133 | + |
134 | # check command syntax |
135 | if [ -z "$1" ]; then |
136 | echo "ovbackup: missing operand" >&2 |
137 | @@ -70,56 +76,38 @@ |
138 | ;; |
139 | esac |
140 | |
141 | -logger -p user.info -t "ovbackup[$$]" -- Starting backup of $instance requested by $USER |
142 | +print_status "ovbackup" "Starting backup of $instance" "$skip_status" |
143 | |
144 | -# it would be great if we could put these two calls in a subshell, but while |
145 | -# that would make the umask call temporary (good), it would also make the |
146 | -# tempdir variable temporary (bad) |
147 | +# we can't use a subshell to isolate the umask call because $tempdir wouldn't |
148 | +# survive, so save/restore the umask instead |
149 | +old_umask=`umask` |
150 | umask 077 |
151 | -tempdir=`mktemp -d -p "$root/$instance/backups" .ovbackup.XXXXXXXXXX` || { |
152 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to create temporary backup directory |
153 | - echo "ovbackup: Unable to create temporary backup directory" >&2 |
154 | - exit 1 |
155 | -} |
156 | +tempdir=`mktemp -d -p "$root/$instance/backups" .ovbackup.XXXXXXXXXX` || |
157 | +exit_with_error "ovbackup" "Unable to create temporary directory" |
158 | +umask "$old_umask" |
159 | |
160 | # the EXIT handler may or may not run if we're interrupted or killed depending |
161 | # on the shell used (from what I've read, it does run on bash, but not on |
162 | # dash); use $exit to exit with the correct status in both cases |
163 | -trap '[ -z "$exit" ] && rm -rf $tempdir; exit ${exit:-0}' EXIT |
164 | +trap '[ -z "$exit" ] && rm -rf "$tempdir"; exit ${exit:-0}' EXIT |
165 | |
166 | -trap 'logger -p user.info -t "ovbackup[$$]" -- Caught SIGINT, exiting; rm -rf $tempdir; exit ${exit:=130}' INT |
167 | -trap 'logger -p user.info -t "ovbackup[$$]" -- Caught SIGTERM, exiting; rm -rf $tempdir; exit ${exit:=143}' TERM |
168 | +trap 'print_status "ovbackup" "Caught SIGINT, exiting" "$skip_status"; rm -rf "$tempdir"; exit ${exit:=130}' INT |
169 | +trap 'print_status "ovbackup" "Caught SIGTERM, exiting" "$skip_status"; rm -rf "$tempdir"; exit ${exit:=143}' TERM |
170 | |
171 | # this signal is used to indicate failure of mupip backup, which is run in the background below |
172 | -trap 'logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to copy database files; echo "ovbackup: Unable to copy database files" >&2; rm -rf $tempdir; exit ${exit:=1}' USR1 |
173 | - |
174 | -{ |
175 | - install -m 2750 -d "$tempdir/etc" && |
176 | - cp -a "$root/$instance/etc/"*.conf "$tempdir/etc/" |
177 | -} || { |
178 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to copy configuration files |
179 | - echo "ovbackup: Unable to copy configuration files" >&2 |
180 | - exit 1 |
181 | -} |
182 | +trap 'logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to copy default.dat database file; echo "ovbackup: Unable to copy default.dat database file" >&2; rm -rf "$tempdir"; exit ${exit:=1}' USR1 |
183 | + |
184 | +print_status "ovbackup" "Copying routines" "$skip_status" |
185 | + |
186 | +cp -a "$root/$instance/routines" "$tempdir" || |
187 | +exit_with_error "ovbackup" "Unable to copy routines" |
188 | + |
189 | +print_status "ovbackup" "Copying database files" "$skip_status" |
190 | |
191 | { |
192 | install -m 2750 -d "$tempdir/globals" && |
193 | cp -a "$root/$instance/globals/mumps.gld" "$tempdir/globals/" |
194 | -} || { |
195 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to copy global directory file |
196 | - echo "ovbackup: Unable to copy global directory file" >&2 |
197 | - exit 1 |
198 | -} |
199 | - |
200 | -logger -p user.info -t "ovbackup[$$]" -- Copying routines |
201 | - |
202 | -cp -a "$root/$instance/routines" "$tempdir" || { |
203 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to copy routines |
204 | - echo "ovbackup: Unable to copy routines" >&2 |
205 | - exit 1 |
206 | -} |
207 | - |
208 | -logger -p user.info -t "ovbackup[$$]" -- Copying database files |
209 | +} || exit_with_error "ovbackup" "Unable to copy mumps.gld global directory file" |
210 | |
211 | # save this timestamp - this is the timestamp that the backup is consistent to. |
212 | # we will use this timestamp to name the final backup file. |
213 | @@ -157,49 +145,27 @@ |
214 | # FIXME: if the routines did change, we should probably try again instead of |
215 | # just aborting - rsync the routines, then re-run the database backup |
216 | output=`rsync -ai --delete --dry-run "$root/$instance/routines/" "$tempdir/routines/"` |
217 | -[ -z "$output" ] || { |
218 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Routines changed during backup |
219 | - echo "ovbackup: Routines changed during backup" >&2 |
220 | - exit 1 |
221 | -} |
222 | +[ -z "$output" ] || exit_with_error "ovbackup" "Routines changed during backup" |
223 | |
224 | # if we get here, that means that the routines haven't changed, and either the |
225 | # mupip backup is still running, or it completed successfully. make sure it's |
226 | # done before we move on. |
227 | wait $child_pid 2> /dev/null |
228 | |
229 | -logger -p user.info -t "ovbackup[$$]" -- Checking backup integrity |
230 | +print_status "ovbackup" "Checking backup integrity" "$skip_status" |
231 | |
232 | mupip integ -file "$tempdir/globals/default.dat" 2>&1 \ |
233 | | grep -v '^$' \ |
234 | | logger -p user.info -t "ovbackup[$$]" |
235 | retval=${PIPESTATUS[0]} |
236 | -[ $retval -eq 0 ] || { |
237 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Database file failed integrity check |
238 | - echo "ovbackup: Database file failed integrity check" >&2 |
239 | - exit 1 |
240 | -} |
241 | - |
242 | -logger -p user.info -t "ovbackup[$$]" -- Compressing backup |
243 | - |
244 | -# if available, use pbzip2 (parallel bzip2) - the author claims near linear |
245 | -# performance gains. testing on my Core 2 Duo laptop, it was 4m17s vs. 5m36s |
246 | -# (clearly not 200% better), but the task was clearly I/O bound. note that |
247 | -# pbzip2 did not support being called from tar until version 1.0.4 |
248 | -if [ -x /usr/bin/pbzip2 ] && [ `pbzip2 -V 2>&1 | head -n1 | awk '{ print $3 }'` ">" "v1.0.3" ]; then |
249 | - bzip2="--use-compress-prog=pbzip2" |
250 | -else |
251 | - bzip2="--bzip2" |
252 | -fi |
253 | +[ $retval -eq 0 ] || exit_with_error "ovbackup" "Database file failed integrity check" |
254 | + |
255 | +print_status "ovbackup" "Compressing backup" "$skip_status" |
256 | |
257 | ( |
258 | umask 007 |
259 | - tar -c --remove-files $bzip2 -f "$tempdir/${instance}-$timestamp.tar.bz2" -C "$tempdir" etc routines globals |
260 | -) || { |
261 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to compress temporary backup directory |
262 | - echo "ovbackup: Unable to compress temporary backup directory" |
263 | - exit 1 |
264 | -} |
265 | + tar -c --remove-files `choose_bzip2` -f "$tempdir/${instance}-$timestamp.tar.bz2" -C "$tempdir" routines globals |
266 | +) || exit_with_error "ovbackup" "Unable to compress temporary backup directory" |
267 | |
268 | # since redirection is not safe (it follows symlinks), create the file in the |
269 | # temporary directory first, then move it into place. if for whatever reason |
270 | @@ -210,13 +176,10 @@ |
271 | mv "$tempdir/${instance}-$timestamp.tar.bz2.md5" "$root/$instance/backups/${instance}-$timestamp.tar.bz2.md5" |
272 | ) |
273 | |
274 | -mv "$tempdir/${instance}-$timestamp.tar.bz2" "$root/$instance/backups/${instance}-$timestamp.tar.bz2" || { |
275 | - logger -p user.info -t "ovbackup[$$]" -- Backup of $instance failed: Unable to rename backup file |
276 | - echo "ovbackup: Unable to rename backup file" |
277 | - exit 1 |
278 | -} |
279 | +mv "$tempdir/${instance}-$timestamp.tar.bz2" "$root/$instance/backups/${instance}-$timestamp.tar.bz2" || |
280 | +exit_with_error "ovbackup" "Unable to rename backup file" |
281 | |
282 | -logger -p user.info -t "ovbackup[$$]" -- Backup of $instance written to "$root/$instance/backups/${instance}-$timestamp.tar.bz2" |
283 | +print_status "ovbackup" "Backup of $instance written to $root/$instance/backups/${instance}-$timestamp.tar.bz2" "$skip_status" |
284 | |
285 | # remove the oldest backup file until there are only $num_backups remaining |
286 | until [ `find "$root/$instance/backups" -type f -name "*.tar.bz2" | wc -l` -le $num_backups ]; do |
287 | |
288 | === modified file 'scripts/usr/bin/ovpurgejournals' |
289 | --- scripts/usr/bin/ovpurgejournals 2009-04-14 07:56:28 +0000 |
290 | +++ scripts/usr/bin/ovpurgejournals 2009-04-17 05:09:15 +0000 |
291 | @@ -24,7 +24,7 @@ |
292 | . /usr/lib/openvista/functions |
293 | |
294 | # parse arguments |
295 | -while getopts hy option; do |
296 | +while getopts h option; do |
297 | case $option in |
298 | h) |
299 | echo "Usage: ovpurgejournals INSTANCE_NAME" |
300 | |
301 | === modified file 'scripts/usr/lib/openvista/functions' |
302 | --- scripts/usr/lib/openvista/functions 2009-04-14 16:13:47 +0000 |
303 | +++ scripts/usr/lib/openvista/functions 2009-04-17 05:09:55 +0000 |
304 | @@ -94,3 +94,37 @@ |
305 | |
306 | return 1 |
307 | } |
308 | + |
309 | +# write a status message to syslog and stderr. the first argument is the name |
310 | +# of the calling program, the second argument is the message. if a third |
311 | +# argument is given and is "true", the message is not written to stderr. |
312 | +print_status() |
313 | +{ |
314 | + logger -p user.info -t "$1[$$]" -- "$2" |
315 | + "$3" || echo "`date '+%b %d %H:%M:%S'` - $2" >&2 |
316 | +} |
317 | + |
318 | +# write an error message to syslog and stderr, then exit 1. the first argument |
319 | +# is the name of the calling program, the second argument is the message |
320 | +exit_with_error() |
321 | +{ |
322 | + logger -p user.info -t "$1[$$]" -- "$2" |
323 | + echo "$1: $2" >&2 |
324 | + exit 1 |
325 | +} |
326 | + |
327 | +# if available, use pbzip2 (parallel bzip2) - the author claims near linear |
328 | +# performance gains. testing on my Core 2 Duo laptop, it was 4m17s vs. 5m36s |
329 | +# (clearly not 200% better), but the task was clearly I/O bound. note that |
330 | +# pbzip2 did not support being called from tar until version 1.0.4 |
331 | +# |
332 | +# example usage: tar -x `choose_bzip2` -f archive.tar.bz2 |
333 | +choose_bzip2() |
334 | +{ |
335 | + if [ -x /usr/bin/pbzip2 ] && [ `pbzip2 -V 2>&1 | head -n1 | awk '{ print $3 }'` ">" "v1.0.3" ]; then |
336 | + echo "--use-compress-prog=pbzip2" |
337 | + else |
338 | + echo "--bzip2" |
339 | + fi |
340 | +} |
341 | + |
342 | |
343 | === modified file 'scripts/usr/sbin/ovinstanceadd' |
344 | --- scripts/usr/sbin/ovinstanceadd 2009-04-14 19:22:56 +0000 |
345 | +++ scripts/usr/sbin/ovinstanceadd 2009-04-16 21:35:40 +0000 |
346 | @@ -201,9 +201,7 @@ |
347 | # create the global directory file, mumps.gld |
348 | ( |
349 | umask 027 |
350 | - # mumps doesn't exit non-zero even if something goes wrong in ^GDE, so grep for |
351 | - # the "success" message and exit if we don't find it |
352 | - ( mumps -run ^GDE 2>&1 | grep '%GDE-I-GDCREATE' > /dev/null ) <<EOF |
353 | + mumps -run ^GDE > /dev/null 2>&1 <<EOF |
354 | CHANGE -SEGMENT DEFAULT -ACCESS_METHOD=BG -BLOCK_SIZE=4096 -ALLOCATION=1024 -EXTENSION_COUNT=1024 -GLOBAL_BUFFER_COUNT=4096 -FILE=$root/$instance/globals/default.dat |
355 | CHANGE -REGION DEFAULT -RECORD_SIZE=4080 -KEY_SIZE=255 -JOURNAL=(BEFORE_IMAGE,FILE_NAME="$root/$instance/journals/default.mjl") -DYNAMIC_SEGMENT=DEFAULT |
356 | TEMPLATE -SEGMENT -ACCESS_METHOD=BG -BLOCK_SIZE=4096 -ALLOCATION=1024 -EXTENSION_COUNT=1024 -GLOBAL_BUFFER_COUNT=4096 |
357 | @@ -216,7 +214,11 @@ |
358 | TEMPLATE -REGION -RECORD_SIZE=4080 -KEY_SIZE=255 -JOURNAL=BEFORE_IMAGE |
359 | EXIT |
360 | EOF |
361 | -) || { |
362 | +) |
363 | + |
364 | +# mumps doesn't exit non-zero even if something goes wrong in ^GDE, so look for |
365 | +# the mumps.gld to determine success |
366 | +[ -f "$root/$instance/globals/mumps.gld" ] || { |
367 | echo "ovinstanceadd: Unable to create global directory file" >&2 |
368 | exit 1 |
369 | } |
370 | |
371 | === modified file 'scripts/usr/sbin/ovinstancedel' |
372 | --- scripts/usr/sbin/ovinstancedel 2009-04-14 19:22:56 +0000 |
373 | +++ scripts/usr/sbin/ovinstancedel 2009-04-17 04:09:48 +0000 |
374 | @@ -2,7 +2,7 @@ |
375 | |
376 | # This script deletes an OpenVista instance. All routines, database files, |
377 | # journals, backups, and tied accounts associated with the instance are |
378 | -# permanently removed. |
379 | +# permanently deleted. |
380 | |
381 | |
382 | # Copyright (C) 2009 Medsphere Systems Corporation |
383 | @@ -44,6 +44,8 @@ |
384 | done |
385 | shift `expr $OPTIND - 1` |
386 | |
387 | +: ${skip_confirmation:=false} |
388 | + |
389 | # check command syntax |
390 | if [ -z "$1" ]; then |
391 | echo "ovinstancedel: missing operand" >&2 |
392 | @@ -53,7 +55,7 @@ |
393 | |
394 | # check permissions |
395 | if [ `id -u` -ne 0 ]; then |
396 | - echo "ovinstancedel: Only root may remove an OpenVista instance from the system" >&2 |
397 | + echo "ovinstancedel: Only root may delete an OpenVista instance from the system" >&2 |
398 | exit 1 |
399 | fi |
400 | |
401 | @@ -76,11 +78,11 @@ |
402 | exit 1 |
403 | fi |
404 | |
405 | -${skip_confirmation:-false} || { |
406 | +$skip_confirmation || { |
407 | echo "All routines, database files, journals, backups, and tied accounts associated" >&2 |
408 | - echo "with this OpenVista instance will be PERMANENTLY removed." >&2 |
409 | - echo |
410 | - printf "Are you sure you want to remove this OpenVista instance (yes/no)? " >&2 |
411 | + echo "with '$instance' will be PERMANENTLY deleted." >&2 |
412 | + echo >&2 |
413 | + printf "Are you sure you want to delete '$instance' (yes/no)? " >&2 |
414 | while [ 1 ]; do |
415 | read response |
416 | case $response in |
417 | |
418 | === added file 'scripts/usr/sbin/ovrestore' |
419 | --- scripts/usr/sbin/ovrestore 1970-01-01 00:00:00 +0000 |
420 | +++ scripts/usr/sbin/ovrestore 2009-04-17 05:34:28 +0000 |
421 | @@ -0,0 +1,269 @@ |
422 | +#!/bin/bash |
423 | + |
424 | +# This script restores routines and database files from a backup file into an |
425 | +# OpenVista instance. |
426 | + |
427 | + |
428 | +# Copyright (C) 2009 Medsphere Systems Corporation |
429 | +# |
430 | +# This program is free software; you can redistribute it and/or modify it solely |
431 | +# under the terms of the GNU Affero General Public License version 3 as published |
432 | +# by the Free Software Foundation. |
433 | +# |
434 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
435 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
436 | +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License |
437 | +# for more details. |
438 | +# |
439 | +# You should have received a copy of the GNU Affero General Public License |
440 | +# along with this program. If not, see <http://www.gnu.org/licenses>. |
441 | +# |
442 | +# You can contact Medsphere Systems Corporation headquarters at 1917 Palomar |
443 | +# Oaks Way, Suite 200, Carlsbad, CA 92008 or at legal@medsphere.com. |
444 | + |
445 | + |
446 | +# common functions |
447 | +. /usr/lib/openvista/functions |
448 | + |
449 | +# parse arguments |
450 | +while getopts hyqjf option; do |
451 | + case $option in |
452 | + h) |
453 | + echo "Usage: ovrestore [-y] [-q] [-j] [-f] INSTANCE_NAME BACKUP_FILE" |
454 | + echo " or ovrestore -h" |
455 | + echo |
456 | + echo " -y do not ask for confirmation" |
457 | + echo " -q quiet; suppress status messages" |
458 | + echo " -j after restoring the backup, apply journal entries" |
459 | + echo " -f force; kill any processes accessing the database before restore" |
460 | + echo " -h display this help text" |
461 | + exit 0 |
462 | + ;; |
463 | + y) |
464 | + skip_confirmation=true |
465 | + ;; |
466 | + q) |
467 | + skip_status=true |
468 | + ;; |
469 | + j) |
470 | + apply_journals=true |
471 | + ;; |
472 | + f) |
473 | + force=true |
474 | + ;; |
475 | + esac |
476 | +done |
477 | +shift `expr $OPTIND - 1` |
478 | + |
479 | +: ${skip_confirmation:=false} |
480 | +: ${skip_status:=false} |
481 | +: ${apply_journals:=false} |
482 | +: ${force:=false} |
483 | + |
484 | +# check command syntax |
485 | +if [ -z "$1" ] || [ -z "$2" ]; then |
486 | + echo "ovrestore: missing operand" >&2 |
487 | + echo "Try 'ovrestore -h' for more information" >&2 |
488 | + exit 2 |
489 | +fi |
490 | + |
491 | +# check permissions |
492 | +if [ `id -u` -ne 0 ]; then |
493 | + echo "ovrestore: root privileges are required to restore backups" >&2 |
494 | + exit 1 |
495 | +fi |
496 | + |
497 | +# check for for valid arguments (requires correct permissions to do; must happen after permission checks) |
498 | +set_gtm_env "$1" || { |
499 | + echo "ovrestore: $instance: Not an OpenVista instance" >&2 |
500 | + exit 3 |
501 | +} |
502 | + |
503 | +backup_file=$2 |
504 | + |
505 | +if [ ! -f "$backup_file" ]; then |
506 | + echo "ovrestore: $backup_file: No such file" >&2 |
507 | + exit 3 |
508 | +fi |
509 | + |
510 | +if $apply_journals; then |
511 | + backup_instance=`basename "$backup_file" | awk -F '-' '{ print $1 }'` |
512 | + [ "$instance" = "$backup_instance" ] || { |
513 | + echo "ovrestore: Cannot apply journals when restoring backup from another instance" >&2 |
514 | + exit 3 |
515 | + } |
516 | +fi |
517 | + |
518 | +$skip_confirmation || { |
519 | + echo "Routines and database files in '$instance' will be OVERWRITTEN with" >&2 |
520 | + echo "the versions in '$backup_file'" >&2 |
521 | + echo >&2 |
522 | + printf "Are you sure you want to restore this backup to '$instance' (yes/no)? " >&2 |
523 | + while [ 1 ]; do |
524 | + read response |
525 | + case $response in |
526 | + yes) |
527 | + break |
528 | + ;; |
529 | + no) |
530 | + exit 0 |
531 | + ;; |
532 | + esac |
533 | + printf "Please type 'yes' or 'no': " >&2 |
534 | + done |
535 | + |
536 | + $skip_status || echo >&2 |
537 | +} |
538 | + |
539 | +print_status "ovrestore" "Starting restore of $backup_file to $instance" "$skip_status" |
540 | + |
541 | +# we can't use a subshell to isolate the umask call because $tempdir wouldn't |
542 | +# survive, so save/restore the umask instead |
543 | +old_umask=`umask` |
544 | +umask 077 |
545 | +tempdir=`mktemp -d -p "$root/$instance/backups" .ovrestore.XXXXXXXXXX` || |
546 | +exit_with_error "ovrestore" "Unable to create temporary directory" |
547 | +umask "$old_umask" |
548 | + |
549 | +# the EXIT handler may or may not run if we're interrupted or killed depending |
550 | +# on the shell used (from what I've read, it does run on bash, but not on |
551 | +# dash); use $exit to exit with the correct status in both cases |
552 | +trap '[ -z "$exit" ] && rm -rf "$tempdir"; exit ${exit:-0}' EXIT |
553 | + |
554 | +trap 'print_status "ovrestore" "Caught SIGINT, exiting" "$skip_status"; rm -rf "$tempdir"; exit ${exit:=130}' INT |
555 | +trap 'print_status "ovrestore" "Caught SIGTERM, exiting" "$skip_status"; rm -rf "$tempdir"; exit ${exit:=143}' TERM |
556 | + |
557 | +print_status "ovrestore" "Extracting contents of backup file" "$skip_status" |
558 | + |
559 | +# extract backup file before doing anything else. that way, if the file is |
560 | +# corrupted, we can abort and we don't affect the current database. |
561 | +# unfortunately, this requires more disk space, but we're doing the same thing |
562 | +# during the backup backup process anyway. |
563 | +tar -x `choose_bzip2` -f "$backup_file" -C "$tempdir" || |
564 | +exit_with_error "ovrestore" "Unable to extract contents of backup file" |
565 | + |
566 | +[ -d "$tempdir/routines" ] || exit_with_error "ovrestore" "Backup file does not contain routines" |
567 | +[ -f "$tempdir/globals/mumps.gld" ] || exit_with_error "ovrestore" "Backup file does not contain mumps.gld global directory file" |
568 | +[ -f "$tempdir/globals/default.dat" ] || exit_with_error "ovrestore" "Backup file does not contain default.dat database file" |
569 | + |
570 | +# at this point, we're committed... we're about to kill processes, lock the |
571 | +# instance, overwrite files, etc. |
572 | + |
573 | +print_status "ovrestore" "Attempting to acquire exclusive access to database" "$skip_status" |
574 | + |
575 | +if $force; then |
576 | + # find all processes using this database and kill them |
577 | + for pid in `ls /proc`; do |
578 | + [ -L "/proc/$pid/cwd" ] || continue |
579 | + cwd=`readlink "/proc/$pid/cwd"` |
580 | + [ "$root/$instance/tmp" = "$cwd" ] || continue |
581 | + |
582 | + [ -L "/proc/$pid/exe" ] || continue |
583 | + exe=`readlink "/proc/$pid/exe"` |
584 | + exe_base=`basename "$exe"` |
585 | + [ "mumps" = "$exe_base" ] || continue |
586 | + |
587 | + mupip stop "$pid" 2>&1 \ |
588 | + | grep -v '^$' \ |
589 | + | logger -p user.info -t "ovrestore[$$]" |
590 | + done |
591 | +fi |
592 | + |
593 | +# check to see if the database is in use |
594 | +mupip rundown -region '*' 2>&1 \ |
595 | + | grep -v '^$' \ |
596 | + | logger -p user.info -t "ovrestore[$$]" |
597 | +retval=${PIPESTATUS[0]} |
598 | +[ $retval -eq 200 ] && exit_with_error "ovrestore" "Database currently in use" |
599 | + |
600 | +# close this instance off so nobody can use it |
601 | +chmod 700 "$root/$instance" |
602 | + |
603 | +print_status "ovrestore" "Restoring routines" "$skip_status" |
604 | + |
605 | +rsync -a --delete "$tempdir/routines/" "$root/$instance/routines/" || |
606 | +exit_with_error "ovrestore" "Unable to restore routines" |
607 | + |
608 | +( |
609 | + find "$root/$instance/objects" -type f -name '*.o' -exec rm -f {} \; && |
610 | + umask 007 && |
611 | + cd "$root/$instance/objects" && |
612 | + find "$root/$instance/routines" -type f -name '*.m' -exec mumps {} \; 2> /dev/null |
613 | +) || exit_with_error "ovrestore" "Unable to recompile routines" |
614 | + |
615 | +# if we're not applying journals, shut off journaling on the old database so |
616 | +# that there's a clean break, then move the journal file out of the way |
617 | +$apply_journals || { |
618 | + print_status "ovrestore" "Disabling journaling on old database" "$skip_status" |
619 | + |
620 | + mupip set -journal="OFF" -region DEFAULT 2>&1 \ |
621 | + | grep -v '^$' \ |
622 | + | logger -p user.info -t "ovrestore[$$]" |
623 | + |
624 | + mupip set -nojournal -region DEFAULT 2>&1 \ |
625 | + | grep -v '^$' \ |
626 | + | logger -p user.info -t "ovrestore[$$]" |
627 | + |
628 | + mv -f "$root/$instance/journals/default.mjl" "$root/$instance/journals/default.mjl_`date +%Y%j%H%M%S`_ovrestore" |
629 | +} |
630 | + |
631 | +print_status "ovrestore" "Restoring database files" "$skip_status" |
632 | + |
633 | +mv -f "$tempdir/globals/mumps.gld" "$root/$instance/globals/mumps.gld" || |
634 | +exit_with_error "ovrestore" "Unable to restore mumps.gld global directory file" |
635 | + |
636 | +# update locations of databases in the global directory file, mumps.gld |
637 | +( |
638 | + umask 027 |
639 | + mumps -run ^GDE > /dev/null 2>&1 <<EOF |
640 | +CHANGE -REGION DEFAULT -JOURNAL=(BEFORE_IMAGE,FILE_NAME="$root/$instance/journals/default.mjl") |
641 | +CHANGE -SEGMENT DEFAULT -FILE=$root/$instance/globals/default.dat |
642 | +CHANGE -SEGMENT SCRATCH -FILE=$root/$instance/globals/scratch.dat |
643 | +EXIT |
644 | +EOF |
645 | +) |
646 | + |
647 | +# mumps doesn't exit non-zero even if something goes wrong in ^GDE, so re-run |
648 | +# ^GDE and look for the new paths to determine success |
649 | +( |
650 | + ( mumps -run ^GDE 2>&1 | grep -F "$root/$instance/globals/default.dat" > /dev/null ) <<EOF |
651 | +SHOW -SEGMENT DEFAULT |
652 | +QUIT |
653 | +EOF |
654 | +) || exit_with_error "ovrestore" "Unable to update mumps.gld global directory file" |
655 | + |
656 | +mv -f "$tempdir/globals/default.dat" "$root/$instance/globals/default.dat" || |
657 | +exit_with_error "ovrestore" "Unable to restore default.dat database file" |
658 | + |
659 | +{ |
660 | + mv -f "$root/$instance/globals/scratch.dat" "$root/$instance/globals/scratch.dat~" && |
661 | + mupip create -region=SCRATCH 2>&1 \ |
662 | + | grep -v '^$' \ |
663 | + | logger -p user.info -t "ovrestore[$$]" |
664 | + retval=${PIPESTATUS[0]} |
665 | + [ $retval -eq 0 ] |
666 | +} || exit_with_error "ovrestore" "Unable to recreate scratch.dat database file" |
667 | + |
668 | +if $apply_journals; then |
669 | + print_status "ovrestore" "Applying journal entries" "$skip_status" |
670 | + |
671 | + mupip journal -recover -forward '*' 2>&1 \ |
672 | + | grep -v '^$' \ |
673 | + | logger -p user.info -t "ovrestore[$$]" |
674 | + retval=${PIPESTATUS[0]} |
675 | + [ $retval -eq 0 ] || exit_with_error "ovrestore" "Unable to apply journal entries" |
676 | +fi |
677 | + |
678 | +print_status "ovrestore" "Enabling journaling on new database" "$skip_status" |
679 | + |
680 | +mupip set -journal="ENABLE,ON,BEFORE_IMAGES,FILE=\"$root/$instance/journals/default.mjl\"" -region DEFAULT 2>&1 \ |
681 | + | grep -v '^$' \ |
682 | + | logger -p user.info -t "ovrestore[$$]" |
683 | +retval=${PIPESTATUS[0]} |
684 | +[ $retval -eq 0 ] || exit_with_error "ovrestore" "Unable to enable journaling on new database" |
685 | + |
686 | +# re-open this instance for general use |
687 | +chmod 2750 "$root/$instance" |
688 | + |
689 | +print_status "ovrestore" "Finished restoring $backup_file to $instance" "$skip_status" |
690 | + |