--- Begin Message ---
Package: fai-client
Version: 3.2.13
Severity: important
Tags: patch
While executing commands that refer to device names, occasionally a
device-not-found error is encountered, even though the device is known to exist,
which is manually confirmed afterwards. Furthermore, a second attempt of
performing the same sequence of actions usually succeeds.
This problem is caused by udev refreshing its internal state, and setup-storage
not calling udevsettle in all situations where this would be required.
The attached patch fixes this issue by proactively calling udevsettle before
executing any of the commands.
Best,
Michael
2008-10-16 Michael Tautschnig <[EMAIL PROTECTED]>
* bin/setup-storage, lib/setup-storage/Commands.pm,
lib/setup-storage/Exec.pm:
Call udevsettle before doing any of the commands to avoid all
the possible
pitfalls, simplyfies the code quite a bit.
Index: trunk/bin/setup-storage
===================================================================
--- trunk.orig/bin/setup-storage
+++ trunk/bin/setup-storage
@@ -173,7 +173,7 @@
}
# run the commands (if $FAI::no_dry_run is set)
-&FAI::execute_command($FAI::commands{$_}{cmd}) foreach (&numsort(keys
%FAI::commands));
+&FAI::execute_with_udevsettle($FAI::commands{$_}{cmd}) foreach (&numsort(keys
%FAI::commands));
# generate the proposed fstab contents
# wait for udev to set up all devices
Index: trunk/lib/setup-storage/Commands.pm
===================================================================
--- trunk.orig/lib/setup-storage/Commands.pm
+++ trunk/lib/setup-storage/Commands.pm
@@ -218,26 +218,15 @@
$pre_req .= ",exist_$d";
}
}
- my $pre_req_no_comma = $pre_req;
- $pre_req_no_comma =~ s/^,//;
- # wait for udev to set up all devices
- &FAI::push_command( "udevsettle --timeout=10", $pre_req_no_comma,
- "settle_for_mdadm_create$id" );
# create the command
- if (0 == $id) {
- $pre_req = "settle_for_mdadm_create$id$pre_req";
- } else {
- $pre_req = "settle_for_mdadm_create$id,exist_/dev/md" . ( $id - 1 ) .
$pre_req;
- }
+ $pre_req = "exist_/dev/md" . ( $id - 1 ) . $pre_req if (0 != $id);
+ $pre_req =~ s/^,//;
&FAI::push_command(
"yes | mdadm --create /dev/md$id --level=$level --force --run
--raid-devices="
. scalar(@eff_devs) . " --spare-devices=" . scalar(@spares) . " "
. join(" ", @eff_devs) . " " . join(" ", @spares),
- "$pre_req", "run_udev_/dev/md$id" );
-
- &FAI::push_command( "udevsettle --timeout=10", "run_udev_/dev/md$id",
- "exist_/dev/md$id" );
+ "$pre_req", "exist_/dev/md$id" );
# create the filesystem on the volume
&FAI::build_mkfs_commands("/dev/md$id",
@@ -408,9 +397,7 @@
# create a new volume
&FAI::push_command( "lvcreate -n $lv -L " . $lv_size->{eff_size} . " $vg",
- "vg_enabled_$vg,$lv_rm_pre", "run_udev_/dev/$vg/$lv" );
- &FAI::push_command( "udevsettle --timeout=10", "run_udev_/dev/$vg/$lv",
- "exist_/dev/$vg/$lv" );
+ "vg_enabled_$vg,$lv_rm_pre", "exist_/dev/$vg/$lv" );
# create the filesystem on the volume
&FAI::build_mkfs_commands("/dev/$vg/$lv",
@@ -447,16 +434,12 @@
$type_pre .= ",exist_$d"
}
}
- $type_pre =~ s/^,//;
- # wait for udev to set up all devices
- &FAI::push_command( "udevsettle --timeout=10", "$type_pre",
- "settle_for_vgchange_$vg" );
# create the volume group or add/remove devices
&FAI::create_volume_group($config);
# enable the volume group
&FAI::push_command( "vgchange -a y $vg",
- "settle_for_vgchange_$vg,vg_created_$vg", "vg_enabled_$vg" );
+ "vg_created_$vg$type_pre", "vg_enabled_$vg" );
# perform all necessary operations on the underlying logical volumes
&FAI::setup_logical_volumes($config);
@@ -631,15 +614,12 @@
$part_nr++;
$FAI::current_config{$disk}{partitions}{$mapped_id}{new_id} = $part_nr;
- my $post = "run_udev_" . &FAI::make_device_name($disk, $part_nr);
+ my $post = "exist_" . &FAI::make_device_name($disk, $part_nr);
$post .= ",rebuilt_" . &FAI::make_device_name($disk, $part_nr) if
$FAI::configs{$config}{partitions}{$part_id}{size}{resize};
# build a parted command to create the partition
&FAI::push_command( "parted -s $disk mkpart $part_type $fs ${start}B
${end}B",
"cleared1_$disk", $post );
- &FAI::push_command( "udevsettle --timeout=10", "run_udev_" .
- &FAI::make_device_name($disk, $part_nr), "exist_" .
- &FAI::make_device_name($disk, $part_nr) );
}
}
@@ -749,13 +729,9 @@
# ntfsresize requires device names
my $eff_size = $part->{size}->{eff_size};
- # wait for udev to set up all devices
- &FAI::push_command( "udevsettle --timeout=10", "rebuilt_" .
- &FAI::make_device_name($disk, $p) . $deps, "settle_for_resize_" .
- &FAI::make_device_name($disk, $p) );
&FAI::push_command( "yes | ntfsresize -s $eff_size " .
- &FAI::make_device_name($disk, $p), "settle_for_resize_" .
- &FAI::make_device_name($disk, $p), "ntfs_ready_for_rm_" .
+ &FAI::make_device_name($disk, $p), "rebuilt_" .
+ &FAI::make_device_name($disk, $p) . $deps, "ntfs_ready_for_rm_" .
&FAI::make_device_name($disk, $p) );
&FAI::push_command( "parted -s $disk rm $p", "ntfs_ready_for_rm_" .
&FAI::make_device_name($disk, $p), "resized_" .
@@ -811,10 +787,7 @@
$pre = ",exist_" . &FAI::make_device_name($disk, $prev_id) if ($prev_id >
-1);
# build a parted command to create the partition
&FAI::push_command( "parted -s $disk mkpart $part_type $fs ${start}B
${end}B",
- "cleared2_$disk$pre", "run_udev_" . &FAI::make_device_name($disk,
$part_id) );
- &FAI::push_command( "udevsettle --timeout=10", "run_udev_" .
- &FAI::make_device_name($disk, $part_id), "exist_" .
- &FAI::make_device_name($disk, $part_id) );
+ "cleared2_$disk$pre", "exist_" . &FAI::make_device_name($disk, $part_id)
);
$prev_id = $part_id;
}
Index: trunk/lib/setup-storage/Exec.pm
===================================================================
--- trunk.orig/lib/setup-storage/Exec.pm
+++ trunk/lib/setup-storage/Exec.pm
@@ -202,7 +202,7 @@
}
################################################################################
#
-# @brief execute a /bin/bash command, given as string. also catch stderr and
+# @brief execute a shell command, given as string. also catch stderr and
# stdout, to be passed to the caller function, and also used for error
# recognition. This execute function does execute the in the error struct
# defined action, when an error occurs.
@@ -237,7 +237,27 @@
}
return "";
}
+################################################################################
+#
+# @brief Execute a command as in execute_command, but prefix it with udevsettle
+#
+# @return the identifier of the error
+#
+################################################################################
+sub execute_with_udevsettle {
+ my ($command, $stdout, $stderr) = @_;
+ return &execute_command("udevsettle --timeout 10 && $command", $stdout,
+ $stderr);
+}
+################################################################################
+#
+# @brief Execute a command that is known to be read-only and thus acceptable to
+# be run despite dry_run mode
+#
+# @return the identifier of the error
+#
+################################################################################
sub execute_ro_command {
my ($command, $stdout, $stderr) = @_;
pgpyYBzqubxbj.pgp
Description: PGP signature
--- End Message ---