--- a/SI/dumper.pm Mon Jan 18 22:55:10 2010 +0100
+++ b/SI/dumper.pm Tue Jan 19 14:49:43 2010 +0100
@@ -6,44 +6,11 @@
use SI::tools;
use File::Basename;
-#$VAR1 = {
-# 'volume' => {
-# '/dev/mapper/debian-swap' => {
-# 'origin' => 'lvm',
-# 'label' => undef,
-# 'type' => 'swap',
-# 'uuid' => undef
-# },
-# '/dev/hda4' => {
-# 'ptable_type' => '0',
-# 'origin' => 'ptable'
-# },
-# '/dev/hda1' => {
-# 'ptable_type' => '83',
-# 'origin' => 'ptable',
-# 'label' => undef,
-# 'type' => 'ext2',
-# 'uuid' => 'a1fc3fc0-7bde-49c4-9afe-c71db8c4d08b'
-# },
-# '/dev/hda3' => {
-# 'ptable_type' => '0',
-# 'origin' => 'ptable'
-# },
-# '/dev/mapper/debian-root' => {
-# 'origin' => 'lvm',
-# 'label' => undef,
-# 'type' => 'ext3',
-# 'uuid' => 'b30578ac-841f-48b4-8ceb-1cdcbabc7fab'
-# },
-# '/dev/hda2' => {
-# 'ptable_type' => '8',
-# 'origin' => 'ptable',
-# 'label' => undef,
-# 'type' => 'lvm2pv',
-# 'uuid' => 'S4zDgc-hEWW-h9BY-XHz3-32TE-66W1-W0iMVE'
-# }
-# },
-# };
+my @cleanup;
+END {
+ #map { eval { run("lvchange -an $_ 2>/dev/null") } } @cleanup;
+ #map { eval { run("lvremove -ff $_ 2>/dev/null") } } @cleanup;
+}
sub dump($\%) {
my ($file, $devs) = @_;
@@ -54,20 +21,18 @@
verbose("dumping volume $volume->{name}");
my $dumpdev = $volume->{name};
- if ($volume->{origin} =~ /lvm/i) {
- verbose("(lvm)");
- my ($vg, $lv) = `lvdisplay -c $volume->{name}` =~ /\s*\/dev\/(.*?)\/(.*?):/;
- my $snap = "snap$$";
-
- END { eval { run("lvchange -an $vg/$snap 2>/dev/null") };
- eval { run("lvremove -ff $vg/$snap 2>/dev/null") }; }
-
- eval {
- run("lvcreate -s -L 1G -n snap$$ $vg/$lv 2>/dev/null");
- };
- if ($@) { warn "Can't create snapshot\n" }
- else { $dumpdev = "/dev/$vg/$snap$$" };
- }
+# if ($volume->{origin} =~ /lvm/i) {
+# verbose("(lvm)");
+# my ($vg, $lv) = `lvdisplay -c $volume->{name}` =~ /\s*\/dev\/(.*?)\/(.*?):/;
+# my $snap = "snap$$";
+# push @cleanup, "$vg/$lv";
+#
+# #eval {
+# # run("lvcreate -s -L 1G -n snap$$ $vg/$lv 2>/dev/null");
+# #};
+# if ($@) { warn "Can't create snapshot\n" }
+# else { $dumpdev = "/dev/$vg/$snap$$" };
+# }
my $of = sprintf $file, basename($volume->{name});
run("dump -0 -z -f $of $dumpdev");
--- a/SI/lvm.pm Mon Jan 18 22:55:10 2010 +0100
+++ b/SI/lvm.pm Tue Jan 19 14:49:43 2010 +0100
@@ -5,7 +5,8 @@
use strict;
use warnings;
use IO::File;
-
+use Cwd qw(abs_path);
+use File::Basename;
use SI::tools;
@@ -16,6 +17,7 @@
my $devs = shift;
+
# find the physical volumes we've already recognised as „non-removable“
my @pvs = grep { $_ ~~ $devs->{known} } map { s/\s*//; (split /:/)[0] } `pvdisplay -c`;
return @volumegroups = map { (split /:/)[1] } `pvdisplay -c @pvs 2>/dev/null`;
@@ -28,10 +30,12 @@
# physical devices known to lvm, not just the non-removable
my @vgs = _vgs(%$devs);
- my @lvs = map { readlink }
+ run("vgchange -ay @vgs 2>/dev/null");
+
+ my @lvs =
+ map { abs_path ((dirname $_) . "/" . readlink) }
map { s/^\s*//; (split /:/)[0] }
grep { (split /:/)[1] ~~ @vgs } `lvdisplay -c`;
-
foreach (@lvs) {
$devs->{volume}{$_} = { origin => "lvm" };
}
--- a/SI/ptable.pm Mon Jan 18 22:55:10 2010 +0100
+++ b/SI/ptable.pm Tue Jan 19 14:49:43 2010 +0100
@@ -19,17 +19,18 @@
# LVs (used as disk itself) too)
foreach (glob("/sys/block/*")) {
my $name = basename($_);
- verbose("device $name");
+ # verbose("device $name");
if (!-e "$_/device") {
- verbose("skipping (non-dev)\n");
+ # verbose("skipping (non-dev)\n");
next;
}
if ((grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./) {
- verbose("skipping (removable)\n");
+ # verbose("skipping (removable)\n");
next;
}
verbose("\n");
+ verbose("device $name\n");
die "ERR: /dev/$name does not exist. (should not happen)"
if !-e "/dev/$name";
@@ -50,7 +51,7 @@
# and let's prepare the volume entries
foreach (@sfdisk) {
- /^(\S+)\s*:.*Id=\s*(\d+)/ or next;
+ /^(\S+)\s*:.*Id=\s*([[:xdigit:]]+)/ or next;
$devs->{volume}{$1} = {
origin => "ptable",
ptable_type => $2,
--- a/SI/system.pm Mon Jan 18 22:55:10 2010 +0100
+++ b/SI/system.pm Tue Jan 19 14:49:43 2010 +0100
@@ -6,14 +6,12 @@
$ENV{LC_ALL} = "C";
-sub id($) {
- my ($file) = @_;
- open(my $f, ">$file") or die "Can't open $file: $!\n";
- # hope it's eth*
+sub id() {
+ # hope it's eth* or wlan*
local $_ = (sort grep { /^(eth|wlan)/ } `ifconfig -a`)[0];
- return if not $_;
- return if not /^(?<dev>\S+)\s.*HWaddr\s+(?<mac>[\da-f:]+)\s*$/i;
- print $f "ethernet $+{dev} $+{mac}\n";
+ /^(?<dev>\S+)\s.*HWaddr\s+(?<mac>[\da-f:]+)\s*$/i
+ and return $+{mac};
+ die "ERR: Can't get system identification (MAC address)\n";
}
1;
--- a/SI/tools.pm Mon Jan 18 22:55:10 2010 +0100
+++ b/SI/tools.pm Tue Jan 19 14:49:43 2010 +0100
@@ -5,9 +5,10 @@
use strict;
use warnings;
use File::Find;
+use Data::Dumper;
use base "Exporter";
-our @EXPORT = qw(&run &verbose &find_by_devid &cat);
+our @EXPORT = qw(&run &verbose &find_by_devid &cat &barf);
sub run(@) {
system(@_);
@@ -15,6 +16,8 @@
if $?;
}
+sub barf(@) { die Dumper @_ }
+
sub cat($) {
my $fh = new IO::File $_[0]
or die "Can't open $_[0]: $!\n";
--- a/si Mon Jan 18 22:55:10 2010 +0100
+++ b/si Tue Jan 19 14:49:43 2010 +0100
@@ -1,5 +1,7 @@
#! /usr/bin/perl
-# system imager
+# system imager - proof of concept
+# (c) 2010 Heiko Schlittermann <hs@schlittermann.de>
+# see http://keller.schlittermann.de/hg/ius/si
use if $ENV{DEBUG} ~~ /main|all/ => "Smart::Comments";
@@ -7,8 +9,10 @@
use warnings;
use Data::Dumper;
use IO::File;
-
use Sys::Hostname;
+use Getopt::Long;
+use File::Path;
+use File::Basename;
use SI::ptable;
use SI::blkid;
@@ -17,25 +21,46 @@
use SI::dumper;
use SI::system;
-MAIN: {
- my $OUT = "../out-" . hostname;
+my $opt_exit = "";
+my $opt_dir = "";
- unlink(glob("$OUT/*"));
- -d $OUT or mkdir($OUT, 0700) or die "Can't mkdir $OUT: $!\n";
+MAIN: {
- my %devices;
-
- SI::system::id("$OUT/system");
+ GetOptions("exit=s" => \$opt_exit,
+ "dir=s" => \$opt_dir)
+ or die "Bad usage\n";
- SI::ptable::volumes("$OUT/partitions.%s", %devices);
+ my %devices; # the overall data collector
+ my $dir;
+
+ if ($opt_dir ne "") {
+ $dir = $opt_dir;
+ }
+ else {
+ $dir = dirname($0) . "/../image-" . SI::system::id();
+ rmtree($dir);
+ -d $dir or mkdir($dir, 0700) or die "Can't mkdir $dir: $!\n";
+ }
+
+ SI::ptable::volumes("$dir/partitions.%s", %devices);
+ die Dumper \%devices if $opt_exit =~ /ptable/;
+
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);
+ die Dumper \%devices if $opt_exit =~ /lvm::volumes/;
+
+ SI::blkid::ids("$dir/blkid", %devices);
+ die Dumper \%devices if $opt_exit =~ /blkid/;
+
+ SI::lvm::vgcfgbackup("$dir/vg.%s", %devices);
+ die Dumper \%devices if $opt_exit =~ /lvm::vgcfg/;
- my $o = new IO::File ">$OUT/devices"
- or die "ERR: Can't open $OUT/devices: $!\n";
+ SI::mbr::save("$dir/mbr.%s", %devices);
+ die Dumper \%devices if $opt_exit =~ /mbr/;
+
+ SI::dumper::dump("$dir/dump.%s", %devices);
+
+ my $o = new IO::File ">$dir/devices"
+ or die "ERR: Can't open $dir/devices: $!\n";
$o->print(Dumper \%devices);