diff options
-rwxr-xr-x | rescue/make_partimage_save_rest_all | 33 | ||||
-rwxr-xr-x | rescue/make_rescue_img | 18 | ||||
-rwxr-xr-x | rescue/partimage_whole_disk | 144 |
3 files changed, 125 insertions, 70 deletions
diff --git a/rescue/make_partimage_save_rest_all b/rescue/make_partimage_save_rest_all index d91bfd3ec..1a62fda16 100755 --- a/rescue/make_partimage_save_rest_all +++ b/rescue/make_partimage_save_rest_all @@ -1,24 +1,22 @@ #!/bin/sh -[ $# != 1 -a $# != 2 -a $# != 3 ] && { - echo "usage: make_partimage_save_rest_all <partimage special rpm> [<partimage dir> [</data/box>]]" ; +[ $# -lt 1 ] && { + echo "usage: make_partimage_save_rest_all <partimage special rpm> [<partimage dir> <data dirs>]" ; exit 1 } -rpm=$1 -partimage_dir=$2 -local_where=$3 - -where=/data/box -[ -z "$local_where" ] && local_where=$where +rpm=$1 ; shift +partimage_dir=$1 ; shift if [ -n "$partimage_dir" ]; then - [ -d "$partimage_dir$local_where" ] || { - echo "can't find $partimage_dir$local_where" + first_data_dir="$partimage_dir$1" + + [ -d "$first_data_dir" ] || { + echo "can't find $first_data_dir" exit 1 } - [ -r "$partimage_dir$local_where/lst" ] || { - echo "can't read $partimage_dir$local_where/*" + [ -r "$first_data_dir/lst" ] || { + echo "can't read $first_data_dir/*" exit 1 } fi @@ -27,7 +25,7 @@ rm -rf .tmp mkdir -p .tmp/isolinux cp -f /usr/lib/syslinux/isolinux.bin ../isolinux/alt0/* .tmp/isolinux -PARTIMAGE_DIR="$where" PARTIMAGE_RPM=$rpm DISTRIB_DESCR="partimage save/restore all" ./make_rescue_img +PARTIMAGE_DIR="$@" PARTIMAGE_RPM=$rpm DISTRIB_DESCR="partimage save/restore all" ./make_rescue_img mkdir -p .tmp/install/stage2 mv -f rescue.clp .tmp/install/stage2 @@ -52,9 +50,12 @@ label rescue append initrd=all.rdz $common_para EOF - if [ $action = rest_all ]; then - mkdir -p .tmp$where - ln -s $partimage_dir$local_where/* .tmp$where + if [ $action = rest_all -a -n "$partimage_dir" ]; then + for i in $*; do + dir=`dirname $i` + mkdir -p .tmp$dir + ln -s $partimage_dir$i .tmp$dir + done fi mkisofs -f -o part_$action.iso -r -J -hide-rr-moved -nobak -cache-inodes -publisher Mandrakesoft -V 'mdk part save/rest' -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table .tmp diff --git a/rescue/make_rescue_img b/rescue/make_rescue_img index 2b7a9e611..bf9e9c1d7 100755 --- a/rescue/make_rescue_img +++ b/rescue/make_rescue_img @@ -125,26 +125,32 @@ installown("../mdk-stage1/dhcp-client", "/usr/sbin"); #- note that on biarch systems, we may need to have both /lib and /lib64 __ "strip $tmp/{lib,$lib,bin,sbin}/* $tmp/usr/{bin,sbin}/* 2>/dev/null"; -if ($ENV{PARTIMAGE_DIR}) { +if ($ENV{PARTIMAGE_RPM}) { install_perl_script('partimage_whole_disk', '/usr/sbin'); _ "rpm2cpio $ENV{PARTIMAGE_RPM} | (cd $tmp ; cpio -idu ./usr/sbin/partimage)"; my $server = 'partimaged'; $server = 'leia'; + + my $default_dir = '/data/box'; + my $partimage_dir = $ENV{PARTIMAGE_DIR} || $default_dir; + my @local_dirs = map { "/tmp/image$_" } split(' ', $partimage_dir); + my $local_dir = $local_dirs[0]; + my $local_dirs = join(' ', @local_dirs); + substInFile { $_ = <<EOF if /^\s*rescue-gui/; if grep -q save_all /proc/cmdline; then - drvinst NETWORK ; dhcp-client ; partimage_whole_disk save_all $ENV{PARTIMAGE_DIR} $server + drvinst NETWORK ; dhcp-client ; partimage_whole_disk -s $server save_all $default_dir echo "Press enter" read fi if grep -q rest_all /proc/cmdline; then - local=/tmp/image$ENV{PARTIMAGE_DIR} - if [ -d \$local ]; then - partimage_whole_disk rest_all \$local + if [ -d $local_dir ]; then + partimage_whole_disk rest_all $local_dirs else - drvinst NETWORK ; dhcp-client ; partimage_whole_disk rest_all $ENV{PARTIMAGE_DIR} $server + drvinst NETWORK ; dhcp-client ; partimage_whole_disk -s $server rest_all $partimage_dir fi echo "Press enter" read diff --git a/rescue/partimage_whole_disk b/rescue/partimage_whole_disk index 18414170d..ef4b09482 100755 --- a/rescue/partimage_whole_disk +++ b/rescue/partimage_whole_disk @@ -14,10 +14,13 @@ use Carp::Heavy; #- help getting the file in make_rescue_img BEGIN { partition_table::raw::default_type() } -my ($action, $dir, $server) = @ARGV; +my ($server); +if ($ARGV[0] eq '-s') { + (undef, $server, @ARGV) = @ARGV; +} +my $action = shift @ARGV; -sub usage() { die "partimage_whole_disk <save_all | rest_all> <dir> [<server>]\n" } -@ARGV == 2 || @ARGV == 3 or usage(); +sub usage() { die "partimage_whole_disk [-s <server>] (save_all <dir> | rest_all <dirs>)\n" } $ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}"; $ENV{HOME} = '/'; @@ -26,14 +29,24 @@ my @partimage_cmd = ('partimage', if_($server, '-s', $server)); my $all_hds = fsedit::get_hds({}); if ($action eq 'save_all') { - save_all(); + @ARGV == 1 or usage(); + save_all($ARGV[0]); } elsif ($action eq 'rest_all') { - rest_all(); + @ARGV or usage(); + rest_all(@ARGV); } else { usage(); } -sub save_all() { +sub save_all { + my ($dir) = @_; + + my $base_dir = $dir; + for (my $i = 0; read_part_list($dir); $i++) { + #- find a free dir + $dir = sprintf("$base_dir.%03d", $i); + } + my $hd = $all_hds->{hds}[0] or die "no main hard drive\n"; log::l("save_all on $hd->{device}"); my $part_list = [ partition_table::get_normal_parts($hd) ]; @@ -46,27 +59,62 @@ sub save_all() { 'save', devices::make($_->{device}), "$dir/$_->{device}"); } } - save_part_list($hd->{geom}, $part_list); + save_part_list($dir, $hd->{geom}, $part_list); } -sub rest_all() { - my ($forced_geom, $part_list) = read_part_list(); - fs::type::set_fs_type($_, $_->{fs_type}) foreach @$part_list; - - my @used_hds; - foreach my $part (@$part_list) { - if (my $hd = find { $part->{device} =~ /^\Q$_->{device}\E./ } fs::get::hds($all_hds)) { - push @used_hds, $hd; - put_in_hash($part, partition_table::hd2minimal_part($hd)); +sub rest_all { + my (@dirs) = @_; + + my %best; + DIRS: foreach (@dirs) { + my ($forced_geom, $part_list) = read_part_list($_) or log::l("read_part_list $_ failed"), next; + my %h = (dir => $_, forced_geom => $forced_geom, part_list => $part_list); + log::l("trying with $h{dir}"); + + ($h{hd}) = my @used_hds = uniq(map { + my $part = $_; + find { $part->{device} =~ /^\Q$_->{device}\E./ } fs::get::hds($all_hds) + or log::l("can't find hard drive for partition $part->{device}"), next DIRS; + } @$part_list); + + @used_hds >= 1 or log::l("no matching hd"), next; + @used_hds <= 1 or log::l("multiple hds: " . join(' ', map { $_->{device} } @used_hds)), next; + + fs::type::set_fs_type($_, $_->{fs_type}) foreach @$part_list; + put_in_hash($_, partition_table::hd2minimal_part($h{hd})) foreach @$part_list; + + ($h{from_partimage}, my $other) = partition { $_->{saved} } @$part_list; + ($h{from_resize}, $h{created}) = partition { member($_->{fs_type}, 'vfat', 'ntfs') } @$other; + + $h{valid_resize} = every { + my $part = fs::get::device2part($_->{device}, [ fs::get::fstab($all_hds) ]) or log::l("partition to resize is missing ($_->{device})"); + my $ok = $part && $part->{fs_type} eq $_->{fs_type}; + $ok or log::l("partition $_->{device} doesn't have the right filesystem ($part->{fs_type} != $_->{fs_type})"); + $ok; + } @{$h{from_resize}}; + + $h{total} = sum(map { $_->{size} } @$part_list); + if ($h{total} > $h{hd}{totalsectors}) { + log::l("discarding $h{dir} since total $h{total} > $h{hd}{totalsectors}"); + } elsif ($h{valid_resize} < $best{valid_resize}) { + log::l("discarding $h{dir} since it has invalid resize whereas $best{dir} has valid resize"); + } elsif ($h{total} > $best{total}) { + log::l("$h{dir} is better than $best{dir} since total $h{total} > $best{total}"); + %best = %h; + } else { + log::l("$h{dir} is not better than $best{dir} since total $h{total} <= $best{total}"); } } - my ($from_partimage, $other) = partition { $_->{saved} } @$part_list; - my ($from_resize, $created) = partition { member($_->{fs_type}, 'vfat', 'ntfs') } @$other; + $best{dir} or die "no valid partimage data dirs\n"; + my %h = %best; + log::l("chosen dir $h{dir}"); - foreach (@$from_resize) { + my ($hd, $part_list) = ($h{hd}, $h{part_list}); + + foreach (@{$h{from_resize}}) { #- resize first my $part = fs::get::device2part($_->{device}, [ fs::get::fstab($all_hds) ]) or log::l("partition to resize is missing ($_->{device})"), next; - $_->{fs_type} eq $_->{fs_type} or log::l("partition $_->{device} doesn't have the right filesystem ($part->{fs_type} != $_->{fs_type})"), next; + $part->{fs_type} eq $_->{fs_type} or log::l("partition $_->{device} doesn't have the right filesystem ($part->{fs_type} != $_->{fs_type})"), next; $_->{start} = $part->{start}; if ($_->{size} < $part->{size}) { @@ -79,38 +127,37 @@ sub rest_all() { } } - foreach my $hd (uniq(@used_hds)) { - put_in_hash($hd->{geom}, $forced_geom); - partition_table::raw::compute_nb_cylinders($hd->{geom}, $hd->{totalsectors}); + put_in_hash($hd->{geom}, $h{forced_geom}); + log::l("totalsectors $hd->{totalsectors} heads $hd->{geom}{heads} sectors $hd->{geom}{sectors}"); + partition_table::raw::compute_nb_cylinders($hd->{geom}, $hd->{totalsectors}); - #- write the partition table - partition_table::raw::zero_MBR($hd); - foreach my $part (grep { $_->{rootDevice} eq $hd->{device} } @$part_list) { + #- write the partition table + partition_table::raw::zero_MBR($hd); + foreach my $part (grep { $_->{rootDevice} eq $hd->{device} } @$part_list) { - my $hole = find { isEmpty($_) && $_->{size} >= $part->{size} } partition_table::get_normal_parts_and_holes($hd) or die "not enough room"; - $part->{start} = $hole->{start}; + my $hole = find { isEmpty($_) && $_->{size} >= $part->{size} } partition_table::get_normal_parts_and_holes($hd) or die "not enough room"; + $part->{start} = $hole->{start}; - log::l("handling $part->{device}"); - my $extended = $part->{device} =~ /(\d+)$/ && $1 > 4 && $hd->hasExtended; - - my %wanted_part = %$part; - if ($extended || $part->{start} == 1) { - $part->{size} += $hd->{geom}{sectors}; - } - partition_table::add($hd, $part, $extended && 'Extended'); - foreach ('device', 'size') { - $part->{$_} eq $wanted_part{$_} or log::l("bad $_ for $part->{device}: $part->{$_} != $wanted_part{$_}"); - } + log::l("handling $part->{device}"); + my $extended = $part->{device} =~ /(\d+)$/ && $1 > 4 && $hd->hasExtended; + + my %wanted_part = %$part; + if ($extended || $part->{start} == 1) { + $part->{size} += $hd->{geom}{sectors}; + } + partition_table::add($hd, $part, $extended && 'Extended'); + foreach ('device', 'size') { + $part->{$_} eq $wanted_part{$_} or log::l("bad $_ for $part->{device}: $part->{$_} != $wanted_part{$_}"); } - partition_table::write($hd); } + partition_table::write($hd); #- restore from partimage - foreach (@$from_partimage) { - run_or_die(@partimage_cmd, 'restore', '-b', devices::make($_->{device}), "$dir/$_->{device}"); + foreach (@{$h{from_partimage}}) { + run_or_die(@partimage_cmd, 'restore', '-b', devices::make($_->{device}), "$h{dir}/$_->{device}"); } - foreach (@$created) { + foreach (@{$h{created}}) { fs::format::part_raw($_, undef); } @@ -119,21 +166,22 @@ sub rest_all() { sub lst_fields() { qw(device size fs_type saved) } sub save_part_list { - my ($geom, $part_list) = @_; + my ($dir, $geom, $part_list) = @_; my @l = map { join(' ', @$_{lst_fields()}) } @$part_list; - log::l("save_part_list: $_") foreach @l; + log::l("save_part_list $dir: $_") foreach @l; my $partimage = join(' ', @partimage_cmd); open(my $F, "| $partimage -z0 -Bfoo=bar -o save_file $dir/lst"); print $F join("/", $geom->{heads}, $geom->{sectors}), "\n"; print $F "$_\n" foreach @l; } -sub read_part_list() { +sub read_part_list { + my ($dir) = @_; my $partimage = join(' ', @partimage_cmd); open(my $F, "$partimage -z0 -Bfoo=bar rest_file $dir/lst |"); - my $geom_string = <$F>; + my $geom_string = <$F> or return; my %geom; @geom{'heads', 'sectors'} = split('/', chomp_($geom_string)); my @l = chomp_(cat__($F)); - log::l("read_part_list: $_") foreach @l; + log::l("read_part_list $dir: $_") foreach @l; \%geom, [ map { my %l; @l{lst_fields()} = split; \%l } @l ]; } |