[Fai-commit] r6334 - in trunk: bin lib/setup-storage
Michael Tautschnig
mt at alioth.debian.org
Thu Apr 14 11:31:44 UTC 2011
Author: mt
Date: 2011-04-14 11:31:40 +0000 (Thu, 14 Apr 2011)
New Revision: 6334
Modified:
trunk/bin/setup-storage
trunk/lib/setup-storage/Commands.pm
trunk/lib/setup-storage/Exec.pm
trunk/lib/setup-storage/Init.pm
trunk/lib/setup-storage/Parser.pm
trunk/lib/setup-storage/Volumes.pm
Log:
setup-storage, setup-storage/{Volumes,Commands,Exec,Init,Parser}.pm: Software RAID bugfixes
* setup-storage/Volumes.pm: Properly handle preserved partitions when marked
missing in RAID volume.
* setup-storage/Commands.pm: Don't add "missing" when doing mdadm --assemble.
* setup-storage/{Init,Parser,Volumes}.pm: Build device nesting tree.
* setup-storage/Commands.pm: Honor dependencies and nesting of LVM/RAID
devices when stopping and removing volumes and partitions.
* setup-storage/Commands.pm: Add mdadm --assemble call if arrays were detected
by mdadm --examine (these might exist but haven't necessarily been started).
* setup-storage/Exec.pm: Ignore error exit code 2 in this mdadm --assemble
call.
* setup-storage: Force start of arrays using mdadm-startall. Added debug
output of device nesting tree.
Modified: trunk/bin/setup-storage
===================================================================
--- trunk/bin/setup-storage 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/bin/setup-storage 2011-04-14 11:31:40 UTC (rev 6334)
@@ -130,6 +130,15 @@
# make sure there are no empty disk_config stanzas
&FAI::check_config;
+# first find the proper way to tell udev to settle
+$FAI::udev_settle = "udevadm settle --timeout=10" if (&FAI::in_path("udevadm"));
+$FAI::udev_settle = "udevsettle --timeout=10" if (&FAI::in_path("udevsettle"));
+defined($FAI::udev_settle) or die "Failed to find determine a proper way to tell udev to settle; is udev installed?";
+
+# start all RAID arrays in case some of the aren't running yet
+`mdadm-startall`;
+`$FAI::udev_settle`;
+
# read the sizes and partition tables of all disks listed in $FAI::disks
&FAI::get_current_disks;
@@ -163,6 +172,11 @@
our %current_raid_config;
print Dumper \%current_raid_config;
+
+ print "Current device tree\n";
+
+ our %current_dev_children;
+ print Dumper \%current_dev_children;
}
# compute the new LVM and partition sizes; do the partition sizes first to have
@@ -173,6 +187,8 @@
# print the current contents of $FAI::configs
$FAI::debug and print "Desired disk layout\n";
$FAI::debug and print Dumper \%FAI::configs;
+$FAI::debug and print "Desired device tree\n";
+$FAI::debug and print Dumper \%FAI::dev_children;
# generate the command script
&FAI::build_disk_commands;
@@ -193,10 +209,6 @@
}
# run the commands (if $FAI::no_dry_run is set)
-# first find the proper way to tell udev to settle
-$FAI::udev_settle = "udevadm settle --timeout=10" if (&FAI::in_path("udevadm"));
-$FAI::udev_settle = "udevsettle --timeout=10" if (&FAI::in_path("udevsettle"));
-defined($FAI::udev_settle) or die "Failed to find determine a proper way to tell udev to settle; is udev installed?";
foreach (&numsort(keys %FAI::commands)) {
`$FAI::udev_settle`;
next if ($FAI::commands{$_}{cmd} eq "true");
Modified: trunk/lib/setup-storage/Commands.pm
===================================================================
--- trunk/lib/setup-storage/Commands.pm 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/lib/setup-storage/Commands.pm 2011-04-14 11:31:40 UTC (rev 6334)
@@ -276,6 +276,19 @@
################################################################################
sub build_raid_commands {
+ # check RAID arrays if there are pre-existing ones
+ &FAI::push_command("mdadm --assemble --scan --config=$FAI::DATADIR/mdadm-from-examine.conf",
+ "", "mdadm_startall_examined") if (scalar(keys %FAI::current_raid_config));
+ foreach my $id (keys %FAI::current_raid_config) {
+ my $md = "/dev/md$id";
+ my $pre_deps_cl = "mdadm_startall_examined";
+ $pre_deps_cl .= ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{$md} })
+ if (defined($FAI::current_dev_children{$md}) &&
+ scalar(@{ $FAI::current_dev_children{$md} }));
+ &FAI::push_command( "mdadm -W --stop $md", "$pre_deps_cl", "self_cleared_$md");
+ }
+
foreach my $config (keys %FAI::configs) { # loop through all configs
# no encrypted, tmpfs, LVM or physical devices here
next if ($config eq "CRYPT" || $config eq "TMPFS" || $config =~ /^VG_./ || $config =~ /^PHY_./);
@@ -332,7 +345,7 @@
$pre_req =~ s/^,//;
# Assemble the array
&FAI::push_command(
- "mdadm --assemble /dev/md$id " . join(" ", @eff_devs),
+ "mdadm --assemble /dev/md$id " . join(" ", grep(!/^missing$/, @eff_devs)),
"$pre_req", "exist_/dev/md$id");
# create the filesystem on the volume, if requested
@@ -397,14 +410,14 @@
# create all the devices
foreach my $d (keys %{ $FAI::configs{$config}{devices} }) {
$d = &FAI::enc_name($d);
- my $pre = ",exist_$d";
+ my $pre = "exist_$d";
my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($d);
- $pre = ",pt_complete_$disk"
+ $pre .= ",pt_complete_$disk"
if (&FAI::set_partition_type_on_phys_dev($d, "lvm") &&
defined($FAI::configs{"PHY_$disk"}));
&FAI::push_command( "pvcreate -ff -y $pv_create_options $d",
- "all_pv_sigs_removed$pre", "pv_done_$d");
+ "$pre", "pv_done_$d");
$devs .= " $d";
$pre_dev .= ",pv_done_$d";
}
@@ -449,14 +462,14 @@
# create all the devices
foreach my $dev (@new_devices) {
- my $pre = ",exist_$dev";
+ my $pre = "exist_$dev";
my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($dev);
- $pre = ",pt_complete_$disk"
+ $pre .= ",pt_complete_$disk"
if (&FAI::set_partition_type_on_phys_dev($dev, "lvm") &&
defined($FAI::configs{"PHY_$disk"}));
&FAI::push_command( "pvcreate -ff -y $pv_create_options $dev",
- "all_pv_sigs_removed$pre", "pv_done_$dev");
+ "$pre", "pv_done_$dev");
$pre_dev .= ",pv_done_$dev";
}
$pre_dev =~ s/^,//;
@@ -467,7 +480,7 @@
&FAI::push_command( "vgextend $vg " . join (" ", @new_devices), "$pre_dev",
"vg_extended_$vg" );
} else {
- &FAI::push_command( "true", "all_pv_sigs_removed,$pre_dev", "vg_extended_$vg" );
+ &FAI::push_command( "true", "self_cleared_VG_$vg,$pre_dev", "vg_extended_$vg" );
}
# run vgreduce to get them removed
@@ -593,11 +606,13 @@
next;
} elsif ($dev =~ m{^/dev/md[\/]?(\d+)$}) {
my $vol = $1;
+ defined ($FAI::configs{RAID}) or next;
defined ($FAI::configs{RAID}{volumes}{$vol}) or next;
next if (1 == $FAI::configs{RAID}{volumes}{$vol}{preserve});
} elsif ($dev =~ m{^/dev/([^/\s]+)/([^/\s]+)$}) {
my $ivg = $1;
my $lv = $2;
+ defined($FAI::configs{"VG_$ivg"}) or next;
defined($FAI::configs{"VG_$ivg"}{volumes}{$lv}) or next;
next if (1 == $FAI::configs{"VG_$ivg"}{volumes}{$lv}{size}{preserve});
} else {
@@ -609,26 +624,35 @@
}
if (0 == $clear_vg) {
- my $vg_setup_pre = "vgchange_a_n";
- if (defined($FAI::configs{"VG_$vg"}{volumes})) {
+ my $vg_setup_pre = "vgchange_a_n_VG_$vg";
+ if (defined($FAI::configs{"VG_$vg"})) {
$FAI::configs{"VG_$vg"}{exists} = 1;
# remove all volumes that do not exist anymore or need not be preserved
foreach my $lv (keys %{ $FAI::current_lvm_config{$vg}{volumes} }) {
+ my $pre_deps_cl = "";
+ $pre_deps_cl = ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{"/dev/$vg/$lv"} })
+ if (defined($FAI::current_dev_children{"/dev/$vg/$lv"}) &&
+ scalar(@{ $FAI::current_dev_children{"/dev/$vg/$lv"} }));
# skip preserved/resized volumes
if (defined ( $FAI::configs{"VG_$vg"}{volumes}{$lv})) {
if ($FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} == 1 ||
$FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{resize} == 1) {
- &FAI::push_command("true", "vgchange_a_n", "exist_/dev/$vg/$lv");
+ &FAI::push_command("true", "vgchange_a_n_VG_$vg$pre_deps_cl",
+ "exist_/dev/$vg/$lv,self_cleared_/dev/$vg/$lv");
next;
}
}
- &FAI::push_command( "lvremove -f $vg/$lv", "vgchange_a_n", "lv_rm_$vg/$lv");
+ &FAI::push_command( "lvremove -f $vg/$lv",
+ "vgchange_a_n_VG_$vg$pre_deps_cl",
+ "lv_rm_$vg/$lv,self_cleared_/dev/$vg/$lv");
$vg_setup_pre .= ",lv_rm_$vg/$lv";
}
} else {
- &FAI::push_command("true", "vgchange_a_n", "exist_/dev/$vg/$_") foreach
+ &FAI::push_command("true", "vgchange_a_n_VG_$vg",
+ "exist_/dev/$vg/$_,self_cleared_/dev/$vg/$_") foreach
(keys %{ $FAI::current_lvm_config{$vg}{volumes} });
}
&FAI::push_command("true", $vg_setup_pre, "vg_exists_$vg");
@@ -636,9 +660,16 @@
return 0;
}
- my $vg_destroy_pre = "vgchange_a_n";
+ my $vg_destroy_pre = "vgchange_a_n_VG_$vg";
foreach my $lv (keys %{ $FAI::current_lvm_config{$vg}{volumes} }) {
- &FAI::push_command( "lvremove -f $vg/$lv", "vgchange_a_n", "lv_rm_$vg/$lv");
+ my $pre_deps_cl = "";
+ $pre_deps_cl = ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{"/dev/$vg/$lv"} })
+ if (defined($FAI::current_dev_children{"/dev/$vg/$lv"}) &&
+ scalar(@{ $FAI::current_dev_children{"/dev/$vg/$lv"} }));
+ &FAI::push_command( "lvremove -f $vg/$lv",
+ "vgchange_a_n_VG_$vg$pre_deps_cl",
+ "lv_rm_$vg/$lv,self_cleared_/dev/$vg/$lv");
$vg_destroy_pre .= ",lv_rm_$vg/$lv";
}
&FAI::push_command( "vgremove $vg", "$vg_destroy_pre", "vg_removed_$vg");
@@ -648,7 +679,7 @@
$devices .= " " . &FAI::enc_name($_) foreach
(@{ $FAI::current_lvm_config{$vg}{physical_volumes} });
$FAI::debug and print "Erased devices:$devices\n";
- &FAI::push_command( "pvremove $devices", "", "pv_sigs_removed_$vg" );
+ &FAI::push_command( "pvremove $devices", "vg_removed_$vg", "pv_sigs_removed_$vg" );
return 1;
}
@@ -662,14 +693,26 @@
sub build_lvm_commands {
# disable volumes if there are pre-existing ones
- &FAI::push_command("vgchange -a n", "", "vgchange_a_n");
- my $all_vg_pre = "vgchange_a_n";
- if (scalar(keys %FAI::current_lvm_config)) {
- foreach my $vg (keys %FAI::current_lvm_config) {
- $all_vg_pre .= ",pv_sigs_removed_$vg" if (&FAI::cleanup_vg($vg));
+ foreach my $d (keys %FAI::current_dev_children) {
+ next unless ($d =~ /^VG_(.+)$/);
+ my $vg = $1;
+ my $vg_pre = "vgchange_a_n_VG_$vg";
+ my $pre_deps_vgc = "";
+ foreach my $c (@{ $FAI::current_dev_children{$d} }) {
+ $pre_deps_vgc = ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{$c} })
+ if (defined($FAI::current_dev_children{$c}) &&
+ scalar(@{ $FAI::current_dev_children{$c} }));
}
+ $pre_deps_vgc =~ s/^,//;
+ &FAI::push_command("vgchange -a n $1", "$pre_deps_vgc", $vg_pre);
+ $vg_pre .= ",pv_sigs_removed_$vg" if (&FAI::cleanup_vg($vg));
+ my $pre_deps_cl = "";
+ $pre_deps_cl = ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{$d} })
+ if (scalar(@{ $FAI::current_dev_children{$d} }));
+ &FAI::push_command("true", "$vg_pre$pre_deps_cl", "self_cleared_VG_$vg");
}
- &FAI::push_command("true", "$all_vg_pre", "all_pv_sigs_removed");
# loop through all configs
foreach my $config (keys %FAI::configs) {
@@ -899,8 +942,15 @@
or die "Can't change disklabel, partitions are to be preserved\n";
# write the disklabel to drop the previous partition table
+ my $pre_deps = "";
+ foreach my $c (@{ $FAI::current_dev_children{$disk} }) {
+ $pre_deps .= ",self_cleared_" .
+ join(",self_cleared_", @{ $FAI::current_dev_children{$c} })
+ if (defined($FAI::current_dev_children{$c}) &&
+ scalar(@{ $FAI::current_dev_children{$c} }));
+ }
&FAI::push_command( ($needs_resize ? "parted -s $disk mklabel $label" : "true"),
- "exist_$disk,all_pv_sigs_removed", "cleared1_$disk" );
+ "exist_$disk$pre_deps", "cleared1_$disk" );
&FAI::rebuild_preserved_partitions($config, \@to_preserve) if ($needs_resize);
Modified: trunk/lib/setup-storage/Exec.pm
===================================================================
--- trunk/lib/setup-storage/Exec.pm 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/lib/setup-storage/Exec.pm 2011-04-14 11:31:40 UTC (rev 6334)
@@ -178,6 +178,15 @@
exit_codes => [0..255],
},
{
+ error => "mdadm_assemble",
+ message => "mdadm tried to assemble arrays but failed, ignoring as arrays might be running already\n",
+ stderr_regex => '^$',
+ stdout_regex => '^$',
+ program => "mdadm --assemble --scan --config=$FAI::DATADIR/mdadm-from-examine.conf",
+ response => "warn",
+ exit_codes => [2],
+ },
+ {
error => "catch_all_nonzero_exit_code",
message => "Command had non-zero exit code\n",
stderr_regex => "",
Modified: trunk/lib/setup-storage/Init.pm
===================================================================
--- trunk/lib/setup-storage/Init.pm 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/lib/setup-storage/Init.pm 2011-04-14 11:31:40 UTC (rev 6334)
@@ -145,6 +145,14 @@
################################################################################
#
+# @brief Map from devices to volumes stacked on top of them
+#
+################################################################################
+%FAI::dev_children = ();
+%FAI::current_dev_children = ();
+
+################################################################################
+#
# @brief Add command to hash
#
# @param cmd Command
Modified: trunk/lib/setup-storage/Parser.pm
===================================================================
--- trunk/lib/setup-storage/Parser.pm 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/lib/setup-storage/Parser.pm 2011-04-14 11:31:40 UTC (rev 6334)
@@ -139,6 +139,11 @@
preserveparts => 0,
partitions => {}
};
+
+ # Init device tree object
+ $FAI::dev_children{$disk} = ();
+
+ return 1;
}
################################################################################
@@ -161,10 +166,13 @@
# check that a physical device is being configured; logical partitions are
# only supported on msdos disk labels.
- ($FAI::device =~ /^PHY_/ && ($type ne "logical"
+ ($FAI::device =~ /^PHY_(.+)$/ && ($type ne "logical"
|| $FAI::configs{$FAI::device}{disklabel} eq "msdos")) or
die "Syntax error: invalid partition type";
+ # the disk
+ my $disk = $1;
+
# the index of the new partition
my $part_number = 0;
@@ -277,6 +285,9 @@
# add the resize = 0 flag, if it doesn't exist already
defined ($part_size->{resize}) or $part_size->{resize} = 0;
+
+ # add entry to device tree
+ push @{ $FAI::dev_children{$disk} }, &FAI::make_device_name($disk, $extended);
}
}
@@ -290,6 +301,7 @@
# the reference is used by all further processing of this config line
$FAI::partition_pointer =
(\%FAI::configs)->{$FAI::device}->{partitions}->{$part_number};
+ $FAI::partition_pointer_dev_name = &FAI::make_device_name($disk, $part_number);
# as we can't compute the index from the reference, we need to store the
# $part_number explicitly
@@ -309,6 +321,9 @@
# add the resize = 0 flag, if it doesn't exist already
defined ($FAI::partition_pointer->{size}->{resize})
or $FAI::partition_pointer->{size}->{resize} = 0;
+
+ # add entry to device tree
+ push @{ $FAI::dev_children{$disk} }, $FAI::partition_pointer_dev_name;
}
################################################################################
@@ -577,6 +592,18 @@
use Storable qw(dclone);
$FAI::configs{$FAI::device} = dclone($FAI::configs{"PHY_" . $ref_dev});
+ # add entries to device tree
+ defined($FAI::dev_children{$ref_dev}) or
+ &FAI::internal_error("dev_children missing reference entry");
+ ($FAI::device =~ /^PHY_(.+)$/) or
+ &FAI::internal_error("unexpected device name");
+ my $disk = $1;
+ foreach my $p (@{ $FAI::dev_children{$ref_dev} }) {
+ my ($i_p_d, $rd, $pd) = &FAI::phys_dev($p);
+ (1 == $i_p_d) or next;
+ ($rd eq $ref_dev) or &FAI::internal_error("dev_children is inconsistent");
+ push @{ $FAI::dev_children{$disk} }, &FAI::make_device_name($disk, $pd);
+ }
}
| /^sameas:(\S+)/
{
@@ -586,6 +613,18 @@
use Storable qw(dclone);
$FAI::configs{$FAI::device} = dclone($FAI::configs{"PHY_" . $ref_dev});
+ # add entries to device tree
+ defined($FAI::dev_children{$ref_dev}) or
+ &FAI::internal_error("dev_children missing reference entry");
+ ($FAI::device =~ /^PHY_(.+)$/) or
+ &FAI::internal_error("unexpected device name");
+ my $disk = $1;
+ foreach my $p (@{ $FAI::dev_children{$ref_dev} }) {
+ my ($i_p_d, $rd, $pd) = &FAI::phys_dev($p);
+ (1 == $i_p_d) or next;
+ ($rd eq $ref_dev) or &FAI::internal_error("dev_children is inconsistent");
+ push @{ $FAI::dev_children{$disk} }, &FAI::make_device_name($disk, $pd);
+ }
}
| /^always_format:(\d+(,\d+)*)/
{
@@ -619,6 +658,7 @@
# set the reference to the current volume
# the reference is used by all further processing of this config line
$FAI::partition_pointer = (\%FAI::configs)->{RAID}->{volumes}->{$vol_id};
+ $FAI::partition_pointer_dev_name = "/dev/md$vol_id";
}
mountpoint devices filesystem mount_options mdcreateopts
| /^(luks|tmp|swap)\s+/
@@ -639,6 +679,7 @@
$FAI::configs{CRYPT}{volumes}{$vol_id}{preserve} = 0;
$FAI::partition_pointer = (\%FAI::configs)->{CRYPT}->{volumes}->{$vol_id};
+ $FAI::partition_pointer_dev_name = "CRYPT$vol_id";
}
mountpoint devices filesystem mount_options lv_or_fsopts
| /^tmpfs\s+/
@@ -659,6 +700,7 @@
$FAI::configs{TMPFS}{volumes}{$vol_id}{preserve} = 0;
$FAI::partition_pointer = (\%FAI::configs)->{TMPFS}->{volumes}->{$vol_id};
+ $FAI::partition_pointer_dev_name = "TMPFS$vol_id";
}
mountpoint tmpfs_size mount_options
| type mountpoint size filesystem mount_options lv_or_fsopts
@@ -703,6 +745,9 @@
# set the reference to the current volume
# the reference is used by all further processing of this config line
$FAI::partition_pointer = (\%FAI::configs)->{$FAI::device}->{volumes}->{$2};
+ $FAI::partition_pointer_dev_name = "/dev/$1/$2";
+ # add entry to device tree
+ push @{ $FAI::dev_children{$FAI::device} }, $FAI::partition_pointer_dev_name;
}
mountpoint: m{^(-|swap|/[^\s\:]*)(:encrypt(:randinit)?)?}
@@ -736,6 +781,8 @@
$FAI::configs{$FAI::device}{volumes} = {};
# initialise the list of physical devices
$FAI::configs{$FAI::device}{devices} = ();
+ # init device tree
+ $FAI::dev_children{$FAI::device} = ();
# the rule must not return undef
1;
}
@@ -865,15 +912,21 @@
"spare" => $spare,
"missing" => $missing
};
+ # add entry to device tree
+ push @{ $FAI::dev_children{$dev} }, $FAI::partition_pointer_dev_name;
} elsif ($FAI::device eq "CRYPT") {
die "Failed to resolve $dev to a unique device name\n" if (scalar(@candidates) != 1);
$FAI::partition_pointer->{device} = $candidates[0];
&FAI::mark_encrypted($candidates[0]);
+ # add entry to device tree
+ push @{ $FAI::dev_children{$candidates[0]} }, $FAI::partition_pointer_dev_name;
} else {
die "Failed to resolve $dev to a unique device name\n" if (scalar(@candidates) != 1);
$dev = $candidates[0];
# create an empty hash for each device
$FAI::configs{$FAI::device}{devices}{$dev} = {};
+ # add entry to device tree
+ push @{ $FAI::dev_children{$dev} }, $FAI::device;
}
}
1;
@@ -1005,6 +1058,8 @@
next if ($this_mp eq "-");
defined($all_mount_pts{$this_mp}) and die
"Mount point $this_mp used twice\n";
+ defined($FAI::dev_children{&FAI::make_device_name($1, $p)}) and die
+ "Mount point $this_mp is shadowed by stacked devices\n";
($this_mp eq "none") or $all_mount_pts{$this_mp} = 1;
}
} elsif ($config =~ /^VG_(.+)$/) {
@@ -1014,6 +1069,8 @@
next if ($this_mp eq "-");
defined($all_mount_pts{$this_mp}) and die
"Mount point $this_mp used twice\n";
+ defined($FAI::dev_children{"/dev/$1/$p"}) and die
+ "Mount point $this_mp is shadowed by stacked devices\n";
($this_mp eq "none") or $all_mount_pts{$this_mp} = 1;
}
next;
@@ -1025,6 +1082,8 @@
next if ($this_mp eq "-");
defined($all_mount_pts{$this_mp}) and die
"Mount point $this_mp used twice\n";
+ defined($FAI::dev_children{"/dev/md$p"}) and die
+ "Mount point $this_mp is shadowed by stacked devices\n";
($this_mp eq "none") or $all_mount_pts{$this_mp} = 1;
}
} elsif ($config eq "CRYPT") {
Modified: trunk/lib/setup-storage/Volumes.pm
===================================================================
--- trunk/lib/setup-storage/Volumes.pm 2011-04-14 11:11:31 UTC (rev 6333)
+++ trunk/lib/setup-storage/Volumes.pm 2011-04-14 11:31:40 UTC (rev 6334)
@@ -98,6 +98,9 @@
# make sure, $disk is a proper block device
(-b $disk) or die "$disk is not a block special device!\n";
+ # init device tree
+ $FAI::current_dev_children{$disk} = ();
+
# the list to hold the output of parted commands as parsed below
my @parted_print = ();
@@ -326,6 +329,9 @@
( ( $FAI::current_config{$disk}{disklabel} eq "msdos" )
&& ( $6 eq "extended" ) )
and $FAI::current_config{$disk}{partitions}{$1}{is_extended} = 1;
+
+ # add entry in device tree
+ push @{ $FAI::current_dev_children{$disk} }, &FAI::make_device_name($disk, $1);
}
# reset the output list
@@ -378,6 +384,9 @@
# initialise the hash entry
$FAI::current_lvm_config{$vg}{physical_volumes} = ();
+ # init device tree
+ $FAI::current_dev_children{"VG_$vg"} = ();
+
# store the vg size in MB
my %vg_info = get_volume_group_information($vg);
if (%vg_info) {
@@ -395,12 +404,19 @@
$FAI::current_lvm_config{$vg}{volumes}{$short_name}{size} =
&FAI::convert_unit($lv_info{$lv_name}->{lv_size} .
$lv_info{$lv_name}->{lv_size_unit});
+ # add entry in device tree
+ push @{ $FAI::current_dev_children{"VG_$vg"} }, $lv_name;
}
# store the physical volumes
my %pv_info = get_physical_volume_information($vg);
- push @{ $FAI::current_lvm_config{$vg}{physical_volumes} },
- abs_path($_) foreach (sort keys %pv_info);
+ foreach my $pv_name (sort keys %pv_info) {
+ push @{ $FAI::current_lvm_config{$vg}{physical_volumes} },
+ abs_path($pv_name);
+
+ # add entry in device tree
+ push @{ $FAI::current_dev_children{abs_path($pv_name)} }, "VG_$vg";
+ }
}
}
@@ -442,29 +458,37 @@
# UUID=77a22e9f:83fd1276:135399f0:a895f15f
# devices=/dev/sde3,/dev/sdf3,/dev/sdd3
+ # create a temporary mdadm-from-examine.conf
+ open(MDADM_EX, ">$FAI::DATADIR/mdadm-from-examine.conf");
+
# the id of the RAID
my $id;
# parse the output line by line
foreach my $line (@mdadm_print) {
+ print MDADM_EX "$line";
if ($line =~ /^ARRAY \/dev\/md[\/]?(\d+)\s+/) {
$id = $1;
foreach (split (" ", $line)) {
- if ($_ =~ /^level=(\S+)/) {
- $FAI::current_raid_config{$id}{mode} = $1;
- }
+ $FAI::current_raid_config{$id}{mode} = $1 if ($_ =~ /^level=(\S+)/);
}
} elsif ($line =~ /^\s*devices=(\S+)$/) {
defined($id) or
&FAI::internal_error("mdadm ARRAY line not yet seen -- unexpected mdadm output:\n"
- . join("", @mdadm_print));
- push @{ $FAI::current_raid_config{$id}{devices} }, abs_path($_)
- foreach (split (",", $1));
-
+ . join("", @mdadm_print));
+ foreach my $d (split (",", $1)) {
+ push @{ $FAI::current_raid_config{$id}{devices} }, abs_path($d);
+
+ # add entry in device tree
+ push @{ $FAI::current_dev_children{abs_path($d)} }, "/dev/md$id";
+ }
+
undef($id);
}
}
+
+ close(MDADM_EX);
}
@@ -476,34 +500,49 @@
#
################################################################################
sub mark_preserve {
- my ($device_name) = @_;
+ my ($device_name, $missing) = @_;
my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($device_name);
if (1 == $i_p_d) {
- defined ($FAI::current_config{$disk}{partitions}{$part_no}) or die
- "Can't preserve $device_name because it does not exist\n";
- if (defined($FAI::configs{"PHY_$disk"}{partitions}{$part_no})) {
+ if (defined($FAI::configs{"PHY_$disk"}) &&
+ defined($FAI::configs{"PHY_$disk"}{partitions}{$part_no})) {
+ defined ($FAI::current_config{$disk}{partitions}{$part_no}) or die
+ "Can't preserve $device_name because it does not exist\n";
$FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{preserve} = 1;
$FAI::configs{"PHY_$disk"}{preserveparts} = 1;
+ } elsif (0 == $missing) {
+ defined ($FAI::current_config{$disk}{partitions}{$part_no}) or die
+ "Can't preserve $device_name because it does not exist\n";
}
} elsif ($device_name =~ m{^/dev/md[\/]?(\d+)$}) {
my $vol = $1;
- defined ($FAI::current_raid_config{$vol}) or die
- "Can't preserve $device_name because it does not exist\n";
- if (defined($FAI::configs{RAID}{volumes}{$vol}) &&
- $FAI::configs{RAID}{volumes}{$vol}{preserve} != 1) {
- $FAI::configs{RAID}{volumes}{$vol}{preserve} = 1;
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{RAID}{volumes}{$vol}{devices} });
+ if (defined($FAI::configs{RAID}) &&
+ defined($FAI::configs{RAID}{volumes}{$vol})) {
+ defined ($FAI::current_raid_config{$vol}) or die
+ "Can't preserve $device_name because it does not exist\n";
+ if ($FAI::configs{RAID}{volumes}{$vol}{preserve} != 1) {
+ $FAI::configs{RAID}{volumes}{$vol}{preserve} = 1;
+ &FAI::mark_preserve($_, $FAI::configs{RAID}{volumes}{$vol}{devices}{$_}{missing})
+ foreach (keys %{ $FAI::configs{RAID}{volumes}{$vol}{devices} });
+ }
+ } elsif (0 == $missing) {
+ defined ($FAI::current_raid_config{$vol}) or die
+ "Can't preserve $device_name because it does not exist\n";
}
} elsif ($device_name =~ m{^/dev/([^/\s]+)/([^/\s]+)$}) {
my $vg = $1;
my $lv = $2;
- defined ($FAI::current_lvm_config{$vg}{volumes}{$lv}) or die
- "Can't preserve $device_name because it does not exist\n";
- if (defined($FAI::configs{"VG_$vg"}{volumes}{$lv}) &&
- $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} != 1) {
- $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} = 1;
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{"VG_$vg"}{devices} });
+ if (defined($FAI::configs{"VG_$vg"}) &&
+ defined($FAI::configs{"VG_$vg"}{volumes}{$lv})) {
+ defined ($FAI::current_lvm_config{$vg}{volumes}{$lv}) or die
+ "Can't preserve $device_name because it does not exist\n";
+ if ($FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} != 1) {
+ $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} = 1;
+ &FAI::mark_preserve($_, $missing) foreach (keys %{ $FAI::configs{"VG_$vg"}{devices} });
+ }
+ } elsif (0 == $missing) {
+ defined ($FAI::current_lvm_config{$vg}{volumes}{$lv}) or die
+ "Can't preserve $device_name because it does not exist\n";
}
} else {
warn "Don't know how to mark $device_name for preserve\n";
@@ -561,7 +600,7 @@
"Can't preserve /dev/$1/$l because it does not exist\n";
defined ($FAI::configs{$config}{volumes}{$l}{size}{range}) or die
"Can't preserve /dev/$1/$l because it is not defined in the current config\n";
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{devices} });
+ &FAI::mark_preserve($_, 0) foreach (keys %{ $FAI::configs{$config}{devices} });
}
} elsif ($config eq "RAID") {
# check for volumes that need to be preserved and preserve the underlying
@@ -575,7 +614,8 @@
"Can't preserve /dev/md$r because it does not exist\n";
defined ($FAI::configs{$config}{volumes}{$r}{devices}) or die
"Can't preserve /dev/md$r because it is not defined in the current config\n";
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{volumes}{$r}{devices} });
+ &FAI::mark_preserve($_, $FAI::configs{$config}{volumes}{$r}{devices}{$_}{missing})
+ foreach (keys %{ $FAI::configs{$config}{volumes}{$r}{devices} });
}
} elsif ($config eq "CRYPT") {
# We don't do preserve for encrypted partitions
More information about the Fai-commit
mailing list