Works in KVM/Qemu now.
--- a/SI/blkid.pm Tue Jan 19 14:49:43 2010 +0100
+++ b/SI/blkid.pm Tue Jan 19 23:45:54 2010 +0100
@@ -4,6 +4,8 @@
use strict;
use warnings;
+use IO::File;
+use File::Basename;
use SI::tools;
@@ -24,6 +26,26 @@
$devs->{volume}{$dev}{uuid} = $uuid;
$devs->{volume}{$dev}{type} = $type;
$devs->{volume}{$dev}{label} = $label;
+
+ my ($of, $oh);
+ if (defined $uuid) {
+ $of = sprintf $file, "uuid." . basename $dev;
+ $oh = new IO::File ">$of" or die "ERR: Can't open $of: $!\n";
+ $oh->print("$uuid\n");
+ }
+
+ if (defined $label) {
+ $of = sprintf $file, "label." . basename $dev;
+ $oh = new IO::File ">$of" or die "ERR: Can't open $of: $!\n";
+ $oh->print("$label\n");
+ }
+
+ if (defined $type) {
+ $of = sprintf $file, "type." . basename $dev;
+ $oh = new IO::File ">$of" or die "ERR: Can't open $of: $!\n";
+ $oh->print("$type\n");
+ }
+
}
}
--- a/SI/dumper.pm Tue Jan 19 14:49:43 2010 +0100
+++ b/SI/dumper.pm Tue Jan 19 23:45:54 2010 +0100
@@ -6,34 +6,17 @@
use SI::tools;
use File::Basename;
-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) = @_;
foreach my $volume ( map { { name => $_, %{$devs->{volume}{$_}}}} keys %{$devs->{volume}}) {
next if !defined $volume->{type} or $volume->{type} !~ /^ext/i;
+ system("fsck -f -C0 $volume->{name}");
+ die "ERR: fsck failed\n" if $? > 2;
+
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$$";
-# 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");
verbose("\n");
--- a/SI/lvm.pm Tue Jan 19 14:49:43 2010 +0100
+++ b/SI/lvm.pm Tue Jan 19 23:45:54 2010 +0100
@@ -17,10 +17,13 @@
my $devs = shift;
+ # find the physical volumes we've already recognised as „non-removable“
+ my @known = keys %{$devs->{volume}}, keys %{$devs->{disk}};
- # 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`;
+ my @pvs = grep { $_ ~~ @known } map { s/\s*//; (split /:/)[0] } `pvdisplay -c`;
+ @volumegroups = map { (split /:/)[1] } `pvdisplay -c @pvs 2>/dev/null`;
+ run("vgchange -ay @volumegroups 2>&1 >/dev/null");
+ return @volumegroups;
}
sub volumes(\%) {
@@ -30,8 +33,6 @@
# physical devices known to lvm, not just the non-removable
my @vgs = _vgs(%$devs);
- run("vgchange -ay @vgs 2>/dev/null");
-
my @lvs =
map { abs_path ((dirname $_) . "/" . readlink) }
map { s/^\s*//; (split /:/)[0] }
--- a/SI/ptable.pm Tue Jan 19 14:49:43 2010 +0100
+++ b/SI/ptable.pm Tue Jan 19 23:45:54 2010 +0100
@@ -19,21 +19,23 @@
# LVs (used as disk itself) too)
foreach (glob("/sys/block/*")) {
my $name = basename($_);
- # verbose("device $name");
+ my $dev = "/dev/$name";
+
+ next if !-e "$_/device";
+ next if (grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./;
+ next if (stat $dev)[0] == (stat $0)[0];
- if (!-e "$_/device") {
- # verbose("skipping (non-dev)\n");
- next;
- }
- if ((grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./) {
- # verbose("skipping (removable)\n");
- next;
- }
+ # exclude the device (stick) we're part of - this HACK is
+ # only useful on KVM - the usb stick doesn't appear as a removeable
+ # device
+ next if (stat $0)[0] ~~ [map { (stat)[6] } map { "/dev/" . basename(dirname $_) } glob("$_/*/partition")];
+
+
verbose("\n");
- verbose("device $name\n");
+ verbose("device $dev\n");
- die "ERR: /dev/$name does not exist. (should not happen)"
- if !-e "/dev/$name";
+ die "ERR: $dev does not exist. (should not happen): $!"
+ if !-b $dev;
# now the physical disk -- let's ask for the partition table
@@ -47,8 +49,6 @@
pt => \@sfdisk
};
- push @{$devs->{known}}, "/dev/$name";
-
# and let's prepare the volume entries
foreach (@sfdisk) {
/^(\S+)\s*:.*Id=\s*([[:xdigit:]]+)/ or next;
@@ -56,7 +56,6 @@
origin => "ptable",
ptable_type => $2,
};
- push @{$devs->{known}}, $1;
}
}
--- a/SI/system.pm Tue Jan 19 14:49:43 2010 +0100
+++ b/SI/system.pm Tue Jan 19 23:45:54 2010 +0100
@@ -2,7 +2,9 @@
use strict;
use warnings;
+use File::Temp qw(tempdir);
use if $ENV{DEBUG} ~~ qw(system) => "Smart::Comments";
+use SI::tools;
$ENV{LC_ALL} = "C";
@@ -14,5 +16,24 @@
die "ERR: Can't get system identification (MAC address)\n";
}
+sub hostname(\%) {
+ my $devs = shift;
+ my $mnt = tempdir(CLEANUP => 1);
+ my $r;
+
+ foreach my $fs (grep { $devs->{volume}{$_}{type} =~ /^ext/i }
+ grep { exists $devs->{volume}{$_}{type} }
+ keys %{$devs->{volume}}) {
+ run("mount -r $fs $mnt");
+ if (-f "$mnt/etc/hostname") {
+ die "ERR: found 2nd hostname" if defined $r;
+ chomp($r = cat("$mnt/etc/hostname"));
+ }
+ run("umount $mnt");
+ }
+
+ return $r;
+}
+
1;
# vim:sts=4 sw=4 aw ai si:
--- a/si Tue Jan 19 14:49:43 2010 +0100
+++ b/si Tue Jan 19 23:45:54 2010 +0100
@@ -11,7 +11,7 @@
use IO::File;
use Sys::Hostname;
use Getopt::Long;
-use File::Path;
+use File::Path qw(make_path remove_tree);
use File::Basename;
use SI::ptable;
@@ -38,31 +38,38 @@
}
else {
$dir = dirname($0) . "/../image-" . SI::system::id();
- rmtree($dir);
+ remove_tree($dir);
-d $dir or mkdir($dir, 0700) or die "Can't mkdir $dir: $!\n";
}
+ make_path(map { "$dir/$_" } qw(ptable lvm blkid mbr dump));
- SI::ptable::volumes("$dir/partitions.%s", %devices);
+ SI::ptable::volumes("$dir/ptable/%s", %devices);
die Dumper \%devices if $opt_exit =~ /ptable/;
SI::lvm::volumes(%devices);
die Dumper \%devices if $opt_exit =~ /lvm::volumes/;
- SI::blkid::ids("$dir/blkid", %devices);
+ SI::blkid::ids("$dir/blkid/%s", %devices);
die Dumper \%devices if $opt_exit =~ /blkid/;
- SI::lvm::vgcfgbackup("$dir/vg.%s", %devices);
+ SI::lvm::vgcfgbackup("$dir/lvm/vg.%s", %devices);
die Dumper \%devices if $opt_exit =~ /lvm::vgcfg/;
- SI::mbr::save("$dir/mbr.%s", %devices);
+ SI::mbr::save("$dir/mbr/%s", %devices);
die Dumper \%devices if $opt_exit =~ /mbr/;
- SI::dumper::dump("$dir/dump.%s", %devices);
+ 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);
+ # we wait until now, since now it's sure that
+ # the filesystems are checked and that we mount the
+ # devices we need
+ my $hostname = SI::system::hostname(%devices);
+ symlink(basename($dir), "../image-$hostname");
+
exit;