web/modules/dobby/Dobby/BackupLog.pm | 59 ++++++++++++++++++++++-
web/modules/dobby/Dobby/CLI/BackupCommands.pm | 33 ++++++++++---
web/modules/dobby/Dobby/Files.pm | 65 ++++++++++++++++----------
3 files changed, 122 insertions(+), 35 deletions(-)
New commits:
commit 91ba3471fd4e9b1327aa7660bc786bd1bace64b7
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 22 16:00:17 2012 +0200
log into control file empty directories
diff --git a/web/modules/dobby/Dobby/BackupLog.pm b/web/modules/dobby/Dobby/BackupLog.pm
index 9b010dd..3928531 100644
--- a/web/modules/dobby/Dobby/BackupLog.pm
+++ b/web/modules/dobby/Dobby/BackupLog.pm
@@ -22,7 +22,7 @@ use Storable qw/freeze thaw/;
use XML::LibXML;
our @ISA = qw/RHN::SimpleStruct/;
-our @simple_struct_fields = qw/start finish sid tablespaces archive_logs control_file type cold_files base_dir/;
+our @simple_struct_fields = qw/start finish sid tablespaces archive_logs control_file type cold_files cold_dirs base_dir/;
# UGLY HACK for now; use Storable instead of a real data structure.
# ugh.
@@ -69,6 +69,11 @@ sub fromXml() {
$log->add_cold_file($fe->fromXml($fileentry));
}
+ foreach my $direntry ($doc->getElementsByTagName('direntry')){
+ my $de = new Dobby::BackupLog::DirEntry();
+ $log->add_cold_file($de->fromXml($direntry));
+ }
+
foreach my $tablespaceentry ($doc->getElementsByTagName('tablespaceentry')){
my $te = new Dobby::BackupLog::TablespaceEntry();
$log->add_tablespace_entry($te->fromXml($tablespaceentry));
@@ -110,6 +115,12 @@ sub toXml {
$cold_files-> appendChild($file_entry->toXml($doc));
}
}
+ my $cold_dirs = $doc->createElement('colddirs');
+ if (defined($self->cold_dirs)) {
+ for my $dir_entry (@{$self->cold_dirs}) {
+ $cold_dirs-> appendChild($dir_entry->toXml($doc));
+ }
+ }
my $tablespaces = $doc->createElement('tablespaces');
if (defined($self->tablespaces)) {
@@ -119,6 +130,7 @@ sub toXml {
}
$root->appendChild($cold_files);
+ $root->appendChild($cold_dirs);
$root->appendChild($tablespaces);
$root->appendChild($sid);
$root->appendChild($start);
@@ -171,9 +183,17 @@ sub add_tablespace_entry {
sub add_cold_file {
my $self = shift;
- my $cold_files = $self->cold_files;
- push @$cold_files, @_;
- $self->cold_files($cold_files);
+ foreach my $file (@_) {
+ if ($file->isa("Dobby::BackupLog::FileEntry")) {
+ my $cold_files = $self->cold_files;
+ push @$cold_files, @_;
+ $self->cold_files($cold_files);
+ } elsif ($file->isa("Dobby::BackupLog::DirEntry")) {
+ my $cold_dirs = $self->cold_dirs;
+ push @$cold_dirs, @_;
+ $self->cold_dirs($cold_dirs);
+ }
+ }
}
package Dobby::BackupLog::TablespaceEntry;
@@ -302,4 +322,35 @@ sub fromXml {
return $self;
}
+package Dobby::BackupLog::DirEntry;
+use RHN::SimpleStruct;
+
+our @ISA = qw/RHN::SimpleStruct/;
+our @simple_struct_fields = qw/from/;
+
+#convert the object to XML
+sub toXml {
+ my $self = shift;
+ my $doc = shift;
+
+ my $entry = $doc->createElement('direntry');
+
+ my $from = $doc->createElement('from');
+ Dobby::BackupLog::addTextValue($from, $doc, $self->from);
+
+ $entry->appendChild($from);
+
+ return $entry;
+}
+
+#fill out the object with the values
+#from the XML Dom.
+sub fromXml {
+ my $self = shift;
+ my $element = shift;
+
+ $self->from(Dobby::BackupLog::getTextValue($element, 'from'));
+
+ return $self;
+}
1;
diff --git a/web/modules/dobby/Dobby/CLI/BackupCommands.pm b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
index 440757d..ceb2a0f 100644
--- a/web/modules/dobby/Dobby/CLI/BackupCommands.pm
+++ b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
@@ -73,7 +73,11 @@ sub directory_contents {
}
push @files, map {[$_, cut_dir($_, $cut_off_dir)]} grep { -f $_ } map { File::Spec->catfile($dir, $_) } @dir_content;
- return @files;
+ if (@files) {
+ return @files;
+ } else { #directory is empty, return directory itself
+ return ([$dir, $cut_off_dir]) if ($dir ne $cut_off_dir);
+ }
}
sub command_backup {
@@ -111,6 +115,7 @@ sub command_backup {
}
for my $ret (@files) {
+ next unless $ret;
my ($file, $rel_dir) = @{$ret};
my $file_entry = Dobby::Files->backup_file($rel_dir, $file, $backup_dir);
$log->add_cold_file($file_entry);
@@ -271,12 +276,20 @@ sub command_restore {
# it, so the contents are correct.
print "Removing unnecessary files... ";
for my $ret (@existing_files) {
+ next unless $ret;
my ($file, $rel_dir) = @{$ret};
next if exists $seen_files{+$file};
unlink $file or warn "Error unlinking $file: $!";
}
+ print "done.\n";
+ print "Restoring empty directories... ";
+ for my $dir_entry (@{$log->cold_dirs}) {
+ if (my @dirs = File::Path::mkpath($dir_entry->from, 0, 0700)) {
+ chown $uid, $gid, @dirs;
+ }
+ }
print "done.\n";
print "Restoration complete, you may now start the database.\n";
diff --git a/web/modules/dobby/Dobby/Files.pm b/web/modules/dobby/Dobby/Files.pm
index df548d8..10afd37 100644
--- a/web/modules/dobby/Dobby/Files.pm
+++ b/web/modules/dobby/Dobby/Files.pm
@@ -100,27 +100,33 @@ sub gunzip_copy {
sub backup_file {
my ($class, $rel_dir, $file, $backup_dir) = @_;
- my $real_dest_dir = File::Spec->catdir($backup_dir, $rel_dir);
- File::Path::mkpath($real_dest_dir) or (-d $real_dest_dir) or die ("Error: could not create directory $real_dest_dir\n");
- my $dest = sprintf("%s/%s.gz", $real_dest_dir, basename($file));
- $dest =~ s(//+)(/)g;
- my $then = time;
-
- my $file_entry = new Dobby::BackupLog::FileEntry;
- $file_entry->start(time);
-
- print " $file -> $dest ... ";
- my $hexdigest = Dobby::Files->gzip_copy($file, $dest);
- print "done.\n";
-
- $file_entry->original_size(-s $file);
- $file_entry->compressed_size(-s $dest);
- $file_entry->from($file);
- $file_entry->to($dest);
- $file_entry->finish(time);
- $file_entry->digest($hexdigest);
-
- return $file_entry;
+ if (-d $file) { #empty directory
+ my $dir_entry = new Dobby::BackupLog::DirEntry;
+ $dir_entry->from($file);
+ print " Empty directory $file\n";
+ return $dir_entry;
+ } else {
+ my $file_entry = new Dobby::BackupLog::FileEntry;
+ my $real_dest_dir = File::Spec->catdir($backup_dir, $rel_dir);
+ File::Path::mkpath($real_dest_dir) or (-d $real_dest_dir) or die ("Error: could not create directory $real_dest_dir\n");
+ my $dest = sprintf("%s/%s.gz", $real_dest_dir, basename($file));
+ $dest =~ s(//+)(/)g;
+ my $then = time;
+
+ $file_entry->start(time);
+
+ print " $file -> $dest ... ";
+ my $hexdigest = Dobby::Files->gzip_copy($file, $dest);
+ print "done.\n";
+
+ $file_entry->original_size(-s $file);
+ $file_entry->compressed_size(-s $dest);
+ $file_entry->from($file);
+ $file_entry->to($dest);
+ $file_entry->finish(time);
+ $file_entry->digest($hexdigest);
+ return $file_entry;
+ }
}
1;
commit 03fcb2f7ba4c0c7f14266663fab3a3e6219c6706
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 22 15:58:56 2012 +0200
correctly set ownership of restored files
diff --git a/web/modules/dobby/Dobby/CLI/BackupCommands.pm b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
index 03eb937..440757d 100644
--- a/web/modules/dobby/Dobby/CLI/BackupCommands.pm
+++ b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
@@ -130,6 +130,7 @@ sub command_restore {
my $restore_dir = shift;
my $backend = PXT::Config->get('db_backend');
+ my $cfg = new PXT::Config("dobby");
$cli->usage("BACKUP_DIR") unless $restore_dir and -d $restore_dir;
my $restore_log = File::Spec->catfile($restore_dir, "backup-log.dat");
$cli->fatal("Error: restoration failed, unable to locate $restore_log") unless -r $restore_log;
@@ -212,11 +213,10 @@ sub command_restore {
printf " -> %s...", $tmpdst;
if (not $missing) {
- $digest = eval { Dobby::Files->gunzip_copy($src, $tmpdst) };
+ $digest = eval { Dobby::Files->gunzip_copy($src, $tmpdst, $uid, $gid) };
if (not defined $digest and $@) {
$err_msg = $@;
}
- chown $uid, $gid, $src;
}
$seen_files{+$dst} = 1;
diff --git a/web/modules/dobby/Dobby/Files.pm b/web/modules/dobby/Dobby/Files.pm
index 62e15fa..df548d8 100644
--- a/web/modules/dobby/Dobby/Files.pm
+++ b/web/modules/dobby/Dobby/Files.pm
@@ -17,7 +17,7 @@ use strict;
package Dobby::Files;
use Digest::MD5;
use Compress::Zlib;
-use File::Basename qw/basename/;
+use File::Basename qw/basename dirname/;
use File::Spec;
use File::Path;
@@ -50,13 +50,20 @@ sub gzip_copy {
# integrity of the archive)
sub gunzip_copy {
- my $class = shift;
- my $src = shift;
- my $dst = shift;
+ my ($class, $src, $dst, $uid, $gid) = @_;
+ if (defined($uid) or defined($gid)) {
+ # if not defined set it to -1 i.e. no change
+ $uid = -1 if not defined $uid;
+ $gid = -1 if not defined $gid;
+ }
my $write;
local * OUT;
if ($dst) {
+ my $dst_directory = dirname($dst);
+ if (my @dirs = File::Path::mkpath($dst_directory, 0, 0700)) {
+ chown $uid, $gid, @dirs;
+ }
open OUT, '>', $dst or die "open $dst: $!\n";
$write = 1
}
@@ -84,6 +91,8 @@ sub gunzip_copy {
$gz->gzclose;
close OUT if $write;
+ chown $uid, $gid, $dst;
+ chmod 0640, $dst;
return $ctx->hexdigest;
}
commit 6d136b39293bea0be6e0c22f41ba73c8df9cdff4
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 22 15:58:51 2012 +0200
set ownership of restored files under PG
diff --git a/web/modules/dobby/Dobby/CLI/BackupCommands.pm b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
index 076242d..03eb937 100644
--- a/web/modules/dobby/Dobby/CLI/BackupCommands.pm
+++ b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
@@ -129,6 +129,7 @@ sub command_restore {
my $command = shift;
my $restore_dir = shift;
+ my $backend = PXT::Config->get('db_backend');
$cli->usage("BACKUP_DIR") unless $restore_dir and -d $restore_dir;
my $restore_log = File::Spec->catfile($restore_dir, "backup-log.dat");
$cli->fatal("Error: restoration failed, unable to locate $restore_log") unless -r $restore_log;
@@ -180,6 +181,8 @@ sub command_restore {
return 1;
}
+ my $intended_username = $cfg->get("${backend}_user");
+ my ($username, undef, $uid, $gid) = getpwnam($intended_username);
for my $file_entry (@{$log->cold_files}) {
# to and from reverse since their names come from the backup
# script itself.
@@ -213,6 +216,7 @@ sub command_restore {
if (not defined $digest and $@) {
$err_msg = $@;
}
+ chown $uid, $gid, $src;
}
$seen_files{+$dst} = 1;
@@ -258,6 +262,7 @@ sub command_restore {
for my $entry (@rename_queue) {
rename $entry->[0] => $entry->[1] or warn "Rename $entry->[0] => $entry->[1] error: $!";
system("/sbin/restorecon", $entry->[1]);
+
}
print "done.\n";
commit f03c5a7bd6da2977b25aafa5779a1134e3237564
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 22 15:57:50 2012 +0200
restore selinux context after restore
diff --git a/web/modules/dobby/Dobby/CLI/BackupCommands.pm b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
index b62e0d6..076242d 100644
--- a/web/modules/dobby/Dobby/CLI/BackupCommands.pm
+++ b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
@@ -257,6 +257,7 @@ sub command_restore {
print "Extraction and verification complete, renaming files... ";
for my $entry (@rename_queue) {
rename $entry->[0] => $entry->[1] or warn "Rename $entry->[0] => $entry->[1] error: $!";
+ system("/sbin/restorecon", $entry->[1]);
}
print "done.\n";
commit 0ce4f30d21c2dacf8d27e252e4daddba69ec8435
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 22 15:57:02 2012 +0200
implement "db-control restore" on PG
diff --git a/web/modules/dobby/Dobby/CLI/BackupCommands.pm b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
index 5af2f77..b62e0d6 100644
--- a/web/modules/dobby/Dobby/CLI/BackupCommands.pm
+++ b/web/modules/dobby/Dobby/CLI/BackupCommands.pm
@@ -61,6 +61,7 @@ sub cut_dir {
sub directory_contents {
my ($cli, $dir, $cut_off_dir) = @_;
+ $cut_off_dir = $dir if not defined $cut_off_dir;
my @files;
opendir DIR, $dir or $cli->fatal("opendir $dir: $!");
@@ -160,7 +161,7 @@ sub command_restore {
my @existing_files;
if ($command eq 'restore') {
push @existing_files, directory_contents($cli, $d->data_dir);
- push @existing_files, directory_contents($cli, $d->archive_log_dir);
+ push @existing_files, directory_contents($cli, $d->archive_log_dir) if $d->archive_log_dir;
}
my $df = df($d->data_dir, "1024");
@@ -214,7 +215,7 @@ sub command_restore {
}
}
- $seen_files{+basename($dst)} = 1;
+ $seen_files{+$dst} = 1;
push @rename_queue, [ $tmpdst, $dst ];
}
elsif ($command eq 'examine') {
@@ -263,8 +264,9 @@ sub command_restore {
# in the backup set. if we've seen it before, then we overwrote
# it, so the contents are correct.
print "Removing unnecessary files... ";
- for my $file (@existing_files) {
- next if exists $seen_files{+basename($file)};
+ for my $ret (@existing_files) {
+ my ($file, $rel_dir) = @{$ret};
+ next if exists $seen_files{+$file};
unlink $file or warn "Error unlinking $file: $!";
}