#!/usr/bin/perl -w #---------------------------------------------------------------------- # copyright (C) 1999-2005 Mitel Networks Corporation # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #---------------------------------------------------------------------- # Restore e-smith config etc from tape using flexbackup package esmith; use esmith::ConfigDB; use esmith::Backup; use strict; my $conf = esmith::ConfigDB->open_ro or die "Could not open config db"; my $backup_program = $conf->get('backup')->prop('Program'); unless (defined $backup_program && $backup_program eq 'flexbackup') { exit(0); } package main; ########################################################################### use POSIX; use English; use strict; my $configfile = "/etc/flexbackup.conf"; my $filesystem = "/"; my $tempfile = "/tmp/restore.$$"; my $backup = new esmith::Backup or die "Couldn't create Backup object\n"; my @restore = $backup->restore_list; package cfg; require $configfile; @cfg::filesystems = split(/ /, $cfg::set{full}); package main; sub FindTapeFile ($); sub ProbeTape ($); sub RewindTape ($); sub FSFTape ($$); sub DetermineBlocksize($); sub CreateFileList($); sub ExtractFiles($$$); sub NotifyAdmin ($$); sub DetermineBackupType; unless (defined @cfg::filesystems && @cfg::filesystems) { my $message = << "EOF"; An error occurred while restoring from tape. As there were no filesystems listed for backup in /etc/flexbackup.conf the correct dump file on the tape could not be located. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: no filesystems listed for backup" . " in $cfg::filesystems.\n"; } my $tapefile = &FindTapeFile($filesystem); ++$tapefile; # Skip the index file &ProbeTape($cfg::device); &RewindTape($cfg::device); &FSFTape($cfg::device, $tapefile); my $tape_blocksize = &DetermineBlocksize($cfg::device); &RewindTape($cfg::device); &FSFTape($cfg::device, $tapefile); &CreateFileList($tempfile); &ExtractFiles($filesystem, $tempfile, $tape_blocksize); ########################################################################### sub FindTapeFile ($) { # Need to locate which file on the tape contains the dump of the # root filesystem. Assume it is a one tape archive for the moment. my $filesystem = shift; foreach (@cfg::filesystems) { if (m:\W*$filesystem\W*:) { my @fs = split(/\s+/, $_); for (my $i = 0; $i < @fs; $i++) { return $i if ($fs[$i] eq "$filesystem") } } my $message = << "EOF"; An error occurred while restoring from tape. The $filesystem filesystem is not listed on the first tape. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: $filesystem filesystem is not listed" . " on the first tape.\n"; } } sub ProbeTape ($) { my $device = shift; system("/bin/mt -f $device status > /dev/null 2>&1"); if ($CHILD_ERROR) { my $message = << "EOF"; An error occurred while restoring from tape. No tape loaded at $device. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: no tape loaded at $device.\n"; } } sub RewindTape ($) { my $device = shift; system("/bin/mt -f $device rewind > /dev/null 2>&1"); if ($CHILD_ERROR) { my $message = << "EOF"; An error occurred while restoring from tape. Could not rewind tape at $device. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: could not rewind tape at $device.\n"; } } sub FSFTape ($$) { my $device = shift; my $files = shift; system("/bin/mt -f $device fsf $files > /dev/null 2>&1"); if ($CHILD_ERROR) { my $message = << "EOF"; An error occurred while restoring from tape. Could not position tape at file $files at $device. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: could not position tape at $device.\n"; } } sub DetermineBlocksize($) { my $device = shift; use File::Temp 'tempdir'; use File::stat; my $dir = File::Temp::tempdir( CLEANUP => 1 ); my $file = "$dir/xx"; system("dd", "if=$device", "bs=1M", "count=1", "of=$file"); my $st = stat($file) or die "No $file: $!"; return (($st->size)/1024); } sub DetermineBackupType { my $device = shift; my $magic = `/usr/bin/file -sz $device 2>/dev/null`; return "tar" if ($magic =~ /tar archive/); return "dump" if ($magic =~ /new-fs dump file/); return undef; } sub CreateFileList ($) { my $file = shift; unless (open(FILE, "> $file")) { my $error = $!; my $message = << "EOF"; An error occurred while restoring from tape. Could not open temporary file $file for writing: $!. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: Could not open temporary file" . " $file for writing: $error\n"; } foreach (@restore) { print FILE "$_\n"; } close FILE; } sub ExtractFiles ($$$) { my $filesystem = shift; my $filelist = shift; my $blocksize = shift; unless (chdir $filesystem) { my $error = $!; my $message = << "EOF"; An error occurred while restoring from tape. Could not change directories to $filesystem: $!. EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: could not change directories" . " to $filesystem. $error\n"; } $ENV{'PATH'} = "/bin:/usr/bin:/sbin"; system( "/usr/bin/flexbackup", "-extract", "-d", "blksize=$blocksize", "-flist", $filelist ); if ($CHILD_ERROR) { my $message = << "EOF"; An error occurred while restoring from tape. Flexbackup returned with an error. For more details concerning this error see: /var/log/messages /flexbackup.extract.log EOF NotifyAdmin("Tape restore failed", $message); die "Tape restore failed: flexbackup error.\n"; } unlink $filelist; my $message = << "EOF"; Restoring from tape was successful. For more details concerning this successful restore see: /var/log/messages /flexbackup.extract.log EOF NotifyAdmin("Tape restore succeeded", $message); } sub NotifyAdmin ($$) { my $subject = shift; my $message = shift; open(DATEMAIL, "|-") or exec qw(/var/qmail/bin/datemail -t); print DATEMAIL << "EOF"; To: admin Subject: $subject $message EOF close DATEMAIL; }