75_MessageServerRestoreExtra.pl [plain text]
use strict;
use warnings;
use File::Basename 'basename';
use File::Basename 'dirname';
use File::Path 'rmtree';
use XML::Simple;
my $TAR = "/usr/bin/tar";
my $MKDIR = "/bin/mkdir";
my $MKTEMP_PATH = "/usr/bin/mktemp";
my $SQLITE = "/usr/bin/sqlite3";
my $g_log_dir = "/Library/Logs/Migration";
my $g_log_path = $g_log_dir."/message_server_restoreExtra.log";
my $g_src_path = "/Library/Server/Previous/.ServerBackups";
my $g_target_path = "/Library/Server/Previous";
&restore_for_migration_extra;
exit(0);
sub restore_for_migration_extra() {
my @files_to_unpack = (
"iChatServer/iChatServer_Rooms.data.tar.gz",
"iChatServer/iChatServer.conf.tar.gz",
"MessageServer/MessageServer_Rooms.data.tar.gz",
"MessageServer/MessageServer.conf.tar.gz"
);
foreach my $file (@files_to_unpack) {
my $file_path = $g_src_path."/".$file;
if (-e $file_path) {
if (&run("$TAR -C ${g_target_path} -xvf ${file_path}")) {
&bail("Error: necessary command failed. See log for details.");
}
}
}
my $src_data_tarball = "";
if (-e $g_src_path."/MessageServer/MessageServer.data.tar.gz") {
$src_data_tarball = $g_src_path."/MessageServer/MessageServer.data.tar.gz";
} elsif (-e $g_src_path."/iChatServer/iChatServer.data.tar.gz") {
$src_data_tarball = $g_src_path."/iChatServer/iChatServer.data.tar.gz";
} else {
&bail("Error: did not find a source database .tar.gz file for database restoration");
}
my $mask = umask;
umask(077);
my $dataTmpDir = "";
for (my $i = 0; $i < 5; $i++) {
$dataTmpDir = `$MKTEMP_PATH -d /tmp/postgres_restoreExtra_data.XXXXXXXXXXXXXXXXXXXXXXXX`;
if ($dataTmpDir =~ /failed/) {
next;
}
chomp($dataTmpDir);
if (-e $dataTmpDir) {
last;
}
if ($i == 4) {
&bail("Error: Cannot create temporary file:\n${dataTmpDir}");
}
}
umask($mask);
if (&run("$TAR -C ${dataTmpDir} -xvf ${src_data_tarball}")) {
rmtree($dataTmpDir);
&bail("Error: necessary command failed. See log for details.");
}
my $sql_file = "";
if (-e "${dataTmpDir}/iChatServer_data_backup.sql") {
$sql_file = "${dataTmpDir}/iChatServer_data_backup.sql";
} elsif (-e "${dataTmpDir}/MessageServer_data_backup.sql") {
$sql_file = "${dataTmpDir}/MessageServer_data_backup.sql";
} else {
rmtree($dataTmpDir);
&bail("Error: could not find SQL file in temp directory for database creation");
}
my $sm_config_path = "";
if (-e "${g_target_path}/private/etc/jabberd/sm.xml") {
$sm_config_path = "${g_target_path}/private/etc/jabberd/sm.xml";
} elsif (-e "${g_target_path}/Library/Server/Messages/Config/jabberd/sm.xml") {
$sm_config_path = "${g_target_path}/Library/Server/Messages/Config/jabberd/sm.xml";
} else {
rmtree($dataTmpDir);
&bail("Error: could not find an sm.xml in temp directory after restoring backup of jabberd configuration");
}
my $xs1 = XML::Simple->new (KeepRoot => 1);
my $doc = $xs1->XMLin($sm_config_path);
my $target_database_file = "";
if ($doc->{sm}->{storage}->{sqlite}->{dbname}) {
$target_database_file = $doc->{sm}->{storage}->{sqlite}->{dbname};
&log_message("Notice: found database name in sm.xml: ${target_database_file}");
} else {
&bail("Error: unable to determine target database path.");
}
if ($target_database_file eq "") {
rmtree($dataTmpDir);
&bail("Error: could not find database file location in restored sm.xml, cannot create database");
}
if ($target_database_file =~ /^\/Volumes/) {
&log_message("Notice: Target database file is on another partition. Skipping attempt to recreate it.");
} else {
my $parent_directory = dirname($target_database_file);
my $mask = umask;
umask(077);
if (&run("$MKDIR -p ${g_target_path}${parent_directory}")) {
rmtree($dataTmpDir);
&bail("Error: necessary command failed. See log for details.");
}
if (-e "${g_target_path}${target_database_file}") {
unlink("${g_target_path}${target_database_file}");
}
if (&run("$SQLITE \"${g_target_path}${target_database_file}\" < ${sql_file}")) {
rmtree($dataTmpDir);
&bail("Error: necessary command failed. See log for details.");
}
umask($mask);
}
rmtree($dataTmpDir);
}
sub run() {
my $command = shift;
&log_message("Executing command: ${command}");
my $mask = umask;
umask(077);
my $dataTmpDir = "";
for (my $i = 0; $i < 5; $i++) {
$dataTmpDir = `$MKTEMP_PATH -d /tmp/postgres_restoreExtra.XXXXXXXXXXXXXXXXXXXXXXXX`;
chomp($dataTmpDir);
if ($dataTmpDir =~ /failed/) {
next;
}
if (-e $dataTmpDir) {
last;
}
if ($i == 4) {
&bail("Error: Cannot create temporary file:\n${dataTmpDir}");
}
}
umask($mask);
my $ret = system("${command} 1> ${dataTmpDir}/cmd.output 2>&1");
if ($ret != 0) {
my $msg = "Error executing command. Return code: ${ret}";
if (-e "${dataTmpDir}/cmd.output}") {
$msg .= "\nOutput was:";
open(OUTPUT, "<${dataTmpDir}/cmd.output");
my @lines = <OUTPUT>;
close(OUTPUT);
foreach my $line (@lines) {
chomp($line);
$msg .= "\n${line}";
}
}
rmtree($dataTmpDir);
&log_message($msg);
return 1;
}
rmtree($dataTmpDir);
return 0;
}
sub timestamp()
{
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
localtime(time);
$year += 1900;
$mon += 1;
if ( $hour =~ /^\d$/ ) { $hour = "0" . $hour; }
if ( $min =~ /^\d$/ ) { $min = "0" . $min; }
if ( $sec =~ /^\d$/ ) { $sec = "0" . $sec; }
my $ret = $year."-".$mon."-".$mday."-${hour}:${min}:${sec}";
return $ret;
}
sub log_message {
if (! -e $g_log_dir) {
my $ret = mkdir("${g_log_dir}", 0755);
unless ($ret) {
print "Cannot create directory for log\n";
return;
}
}
if (! open(LOGFILE, ">>${g_log_path}")) {
print "$0: cannot open ${g_log_path}: $!";
return;
}
print LOGFILE ×tamp.": ".basename($0).": @_\n";
close(LOGFILE);
}
sub bail
{
&log_message(@_);
&log_message("Aborting!");
print "@_\n";
exit 1;
}