[savepoint]
authorHeiko Schlittermann <hs@schlittermann.de>
Sun, 17 Jan 2010 00:03:04 +0100
changeset 9 1a6f6cfc46ea
parent 7 03ca6d811a17 (diff)
parent 8 2a66bb6a6a6e (current diff)
child 11 42c603eb6301
[savepoint]
SI/tools.pm
si
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Sun Jan 17 00:03:04 2010 +0100
@@ -0,0 +1,2 @@
+syntax: glob
+out/
--- a/SI/blkid.pm	Sun Jan 17 00:00:02 2010 +0100
+++ b/SI/blkid.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -4,7 +4,12 @@
 use warnings;
 use File::Find;
 
-sub ff($$) {
+
+use if $ENV{DEBUG} ~~ /blkid|all/ => "Smart::Comments";
+
+use SI::tools;
+
+sub find_by_devid($$) {
     my ($dir, $id) = @_;
     my $found;
     find(
@@ -18,33 +23,40 @@
     return $found;
 }
 
-sub info($\%) {
-    my ($file, $part) = @_;
+
+sub ids($\%) {
+    my ($file, $devs) = @_;
 
+    verbose("reading blkids:");
     foreach (`blkid -c /dev/null`) {
-        my ($dev) = (split /:/)[0];
+        my $dev = (split /:/)[0];
+	### $dev
+	verbose($dev);
 
         my ($uuid)  = /\sUUID=.(.*?).\s/;
         my ($type)  = /\sTYPE=.(.*?).\s/;
         my ($label) = /\sLABEL=.(.*?).\s/;
 
-        if ($dev ~~ $part->{physical}) {
-            $part->{physical}{$dev}{uuid}  = $uuid;
-            $part->{physical}{$dev}{type}  = $type;
-            $part->{physical}{$dev}{label} = $label;
-            next;
-        }
+        #if ($dev ~~ $devs->{physical}) {
+            #$devs->{physical}{$dev}{uuid}  = $uuid;
+            #$devs->{physical}{$dev}{type}  = $type;
+            #$devs->{physical}{$dev}{label} = $label;
+            #next;
+        #}
 
-        # dev mapper names should be replace by nicer ones
+        # dev mapper names should be replaced by nicer ones
         if ($dev ~~ /^\/dev\/dm-/) {
-            $dev = ff("/dev/mapper", (stat $dev)[6])
-              or next;
-            $part->{logical}{$dev}{uuid}  = $uuid;
-            $part->{logical}{$dev}{type}  = $type;
-            $part->{logical}{$dev}{label} = $label;
-        }
+            $dev = find_by_devid("/dev/mapper", (stat $dev)[6]);
+	};
+
+	if (exists $devs->{volume}{$dev}) {
+            $devs->{volume}{$dev}{uuid}  = $uuid;
+            $devs->{volume}{$dev}{type}  = $type;
+            $devs->{volume}{$dev}{label} = $label;
+	}
 
     }
+    verbose("\n");
 }
 
 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SI/dumper.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -0,0 +1,22 @@
+package SI::dumper;
+
+use strict;
+use warnings;
+use SI::tools;
+use if $ENV{DEBUG} ~~ /dumper|all/ => "Smart::Comments";
+
+sub dump($\%) {
+    my ($file, $devs) = @_;
+
+    ### $devs
+
+    my %volume = %{$devs->{volume}};
+
+    foreach my $v ( grep { $volume{$_}{type} ~~ /^ext/ } keys %volume ) {
+	verbose("dumping $v\n");
+    }
+}
+
+1;
+
+# vim:sts=4 sw=4 aw ai sm:
--- a/SI/lvm.pm	Sun Jan 17 00:00:02 2010 +0100
+++ b/SI/lvm.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -2,30 +2,61 @@
 
 use strict;
 use warnings;
+use IO::File;
+
+use if $ENV{DEBUG} ~~ /lvm|all/ => qw(Smart::Comments);
+
 use SI::tools;
 
-sub vg_info($\%) {
-    my ($file, $part) = @_;
-    foreach (map { (split /:/)[0] }
-        map { /^\s*(.*)/; } `vgs --noheadings --separator :`)
-    {
-        my $file = sprintf $file, $_;
-        run("vgcfgbackup -f $file >/dev/null");
-    }
+my @volumegroups = ();
+
+sub _vgs(\%) {
+    return @volumegroups if @volumegroups;
+
+    my $devs = shift;
+
+    my @pvs = grep { $devs->{volume}{$_}{type} =~ /^lvm/ } 
+	grep { defined $devs->{volume}{$_} }
+	keys %{$devs->{volume}};
+
+    return @volumegroups = map { (split /:/)[1] } `pvdisplay -c @pvs`;
 }
 
-sub lv_info($\%) {
-    my ($file, $part) = @_;
+sub volumes(\%) {
+    my ($devs) = @_;
+
+    # we can't just use `pvs', since this would return *all*
+    # physical devices known to lvm, not just the non-removable
+    my @pvs = grep { $devs->{volume}{$_}{type} =~ /^lvm/ } 
+	grep { defined $devs->{volume}{$_} }
+	keys %{$devs->{volume}};
+
+    my @vgs = _vgs(%$devs);
+    my @lvs = map { readlink } 
+	      map { s/^\s*//; (split /:/)[0] } 
+	      grep { (split /:/)[1] ~~ @vgs } `lvdisplay -c`;
 
-    foreach my $p (keys %$part) {
-        `pvs -o +uuid --nameprefix --noheadings $p` =~ /\bLVM2_PV_UUID='(.*?)'/
-          or next;
+    @{$devs->{volume}}{@lvs} = ();
+
+
+}
+
+sub vgcfgbackup($\%) {
+    my ($file, $devs) = @_;
 
-        $part->{$p}{type} = "pv";
-        $part->{$p}{uuid} = $1;
-
+    # we save it vg by vg to have the restore more easy
+    my @vgs = _vgs(%$devs);
+    foreach ( map { s/^\s*(.*)/$1/; $_ = (split /:/)[0] } `vgs --noheadings --separator : @vgs`)
+    {
+	verbose("saving vg $_\n");
+        my $file = sprintf $file, $_;
+        run("vgcfgbackup -f $file $_ >/dev/null");
     }
 
+    # for testing let's save it all
+    verbose("saving vg *\n");
+    $file = sprintf $file, "*";
+    run("vgcfgbackup -f '$file' >/dev/null");
 }
 
 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SI/mbr.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -0,0 +1,24 @@
+package SI::mbr;
+
+use strict;
+use warnings;
+use File::Basename;
+use if $ENV{DEBUG} ~~ q(mbr) => "Smart::Comments";
+
+use SI::tools;
+
+sub save($\%) {
+	my ($file, $devs) = @_;
+	
+
+	foreach my $disk (keys %{$devs->{disks}}) {
+		verbose("saving mbr of $disk\n");
+		open((my $o), $_ = sprintf(">$file", basename($disk))) or die "Can't open $_: $!\n";
+		local $/ = \512;
+
+		open(my $in, $disk) or die "Can't open $disk: $!\n";
+		print $o $_ = <$in>;
+	}
+}
+
+1;
--- a/SI/ptable.pm	Sun Jan 17 00:00:02 2010 +0100
+++ b/SI/ptable.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -2,53 +2,55 @@
 
 use strict;
 use warnings;
-use if $ENV{DEBUG} ~~ "ptable" => "Smart::Comments";
 use File::Find;
+use IO::File;
 
-$ENV{LC_ALL} = "C";
+use if $ENV{DEBUG} ~~ /ptable|all/ => qw(Smart::Comments);
 
 use SI::tools;
-
-sub info($\%) {
-    my ($file, $part) = @_;
+$ENV{LC_ALL} = "C";
 
-    # find major of devmapper
-    my $devmapper = 0;
-    {
-        local $/ = undef;
-        open(my ($i), "/proc/devices")
-          or die "ERR: Can't open /proc/devices: $!\n";
-        ($devmapper) = <$i> =~ /^\s*(\d+)\s+device.mapper\b/m;
-    }
+sub volumes($\%) {
+    my ($file, $devs) = @_;
 
-    my ($current, %dev);
+    # find the non-removable devices
+    my ($current, $of);
     foreach (`sfdisk -d 2>/dev/null`) {
         chomp;
-        ### $_
-        if (/^# partition table .*?(\/\S+)/) {
-            $current = (stat $1)[6] >> 8 == $devmapper ? undef : $1
-              and push(@{ $dev{$current} }, $_);
-            next;
+        if (/^# partition table .*?(\/\S+\/(\S+))/) {
+	    # skip the removable devices
+	    my ($device, $name) = ($1, $2);
+	    verbose("device $device");
+	    if ((grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./) {
+		    $current = undef;
+		    verbose("skipping (removable)\n");
+		    next;
+	    }
+
+	    # save in our data structure
+	    verbose("scanning\n");
+	    $current = $device;
+	    push @{$devs->{disk}{$current}{pt}}, $_;
+
+	    # and open the outfile
+	    my $f = sprintf ">$file", $name;
+	    $of = new IO::File $f or die "ERR: Can't open $f: $!\n";
+	    print $of "$_\n";
+
+	    next;
         }
         next if not $current;
-        push @{ $dev{$current} }, $_;
-    }
-    ### partiton tables of useful blockdevices:
-    ### %dev
+	push @{$devs->{disk}{$current}{pt}}, $_;
+	print $of "$_\n";
 
-    # process the partition tables
-    # and output the tables for relevant devices
-    foreach my $dev (keys %dev) {
-        ($_ = $dev) =~ s/^.*\///;
-        my $file = sprintf $file, $_;
-        die "ERR: $file exists already\n" if -f $file;
-        open(my $o, ">$file") or die "ERR: Can't open $file: $!\n";
-        print $o join "\n", @{ $dev{$dev} }, "";
+	if (/^(\/dev\/\S+)\s*:/) {
+	    $devs->{volume}{$1} = undef;
+	}
+
     }
 
-    # reserve entries in %part, one for each partition
-    @{ $part->{physical} }{ map { (split)[0] }
-          grep { /^\// } map { @$_ } values %dev } = ();
+### $devs
+    return;
 }
 1;
 # vim:sts=4 sw=4 aw ai si:
--- a/SI/tools.pm	Sun Jan 17 00:00:02 2010 +0100
+++ b/SI/tools.pm	Sun Jan 17 00:03:04 2010 +0100
@@ -3,13 +3,22 @@
 use strict;
 use warnings;
 use base "Exporter";
-our @EXPORT = qw(&run);
+our @EXPORT = qw(&run &verbose);
+use if $ENV{DEBUG} ~~ /tools|all/ => "Smart::Comments";
 
 sub run(@) {
 	system(@_);
-	die "$_[0] failed with exit code " . $? >> 8 . "\n"
+	die "$_[0] failed with exit code " . ($? >> 8) . "\n"
 	if $?;
 }
 
+my $last = "\n";
+sub verbose(@) { 
+    print $last eq "\n" ? "" : " "
+	if not(@_ == 1 and length($_[0]) == 1);
+    print @_;
+    $last = substr($_[-1], -1, 1);
+};
+
 1;
 # vim:sts=4 sw=4 aw ai si:
--- a/si	Sun Jan 17 00:00:02 2010 +0100
+++ b/si	Sun Jan 17 00:03:04 2010 +0100
@@ -3,25 +3,38 @@
 
 use strict;
 use warnings;
-use if $ENV{DEBUG} => "Smart::Comments";
+use if $ENV{DEBUG} ~~ /main|all/ => "Smart::Comments";
 
-use SI::system;
+use Sys::Hostname;
+
 use SI::ptable;
 use SI::blkid;
 use SI::lvm;
-
-my $OUT = "out";
+use SI::mbr;
+use SI::dumper;
+use SI::system;
 
-unlink(glob("$OUT/*"));
--d $OUT or mkdir($OUT, 0700) or die "Can't mkdir $OUT: $!\n";
+MAIN: {
+    my $OUT = "../out-" . hostname;
+
+    unlink(glob("$OUT/*"));
+    -d $OUT or mkdir($OUT, 0700) or die "Can't mkdir $OUT: $!\n";
 
-my %devices;
+    my %devices;
+
+    SI::system::id("$OUT/system");
 
-SI::system::id("$OUT/system");
-SI::ptable::info("$OUT/partitions.%s", %devices);
-SI::blkid::info("$OUT/blkid", %devices);
-SI::lvm::vg_info("$OUT/vg.%s", %devices);
+    SI::ptable::volumes("$OUT/partitions.%s", %devices);
+    SI::lvm::volumes(%devices);
+    SI::blkid::ids("$OUT/blkid", %devices);
+    SI::lvm::vgcfgbackup("$OUT/vg.%s", %devices);
+    SI::mbr::save("$OUT/mbr.%s", %devices);
+    SI::dumper::dump("$OUT/dump.%s", %devices);
+### %devices
+    exit;
 
 ### %devices;
 
+    }
+
 # vim:sts=4 sw=4 aw ai si: