2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-08-26 00:26:40 +00:00

Merge pull request #7740 from VersatusHPC/fix/getinstdisk-modern-devices

fix(getinstdisk): rank direct attached disks ahead of RAID volumes
This commit is contained in:
Vinícius Ferrão
2026-08-21 10:28:44 -03:00
committed by GitHub
4 changed files with 151 additions and 9 deletions
@@ -201,22 +201,26 @@ if [ -z "$install_disk" ]; then
# Sort disks by DRIVER type
case "$disk_driver" in
"ata_piix"*|"PMC MaxRAID"|"ahci"|"megaraid_sas")
"ata_piix"*|"ahci")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""firstchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre firstchoicedisks"
;;
"mptsas"|"mpt2sas"|"mpt3sas")
"PMC MaxRAID"|"megaraid_sas")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""secondchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre secondchoicedisks"
;;
*)
"mptsas"|"mpt2sas"|"mpt3sas")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""thirdchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre thirdchoicedisks"
;;
*)
echo "$disk $disk_data" >> "$tmpfile""$file_pre""fourthchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre fourthchoicedisks"
;;
esac
done
for seq in first second third; do
for seq in first second third fourth; do
if [ -s $tmpfile$file_pre${seq}choicedisks ]; then
install_file="$tmpfile$file_pre${seq}choicedisks"
break
@@ -201,22 +201,26 @@ if [ -z "$install_disk" ]; then
# Sort disks by DRIVER type
case "$disk_driver" in
"ata_piix"*|"PMC MaxRAID"|"ahci"|"megaraid_sas")
"ata_piix"*|"ahci")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""firstchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre firstchoicedisks"
;;
"mptsas"|"mpt2sas"|"mpt3sas")
"PMC MaxRAID"|"megaraid_sas")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""secondchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre secondchoicedisks"
;;
*)
"mptsas"|"mpt2sas"|"mpt3sas")
echo "$disk $disk_data" >> "$tmpfile""$file_pre""thirdchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre thirdchoicedisks"
;;
*)
echo "$disk $disk_data" >> "$tmpfile""$file_pre""fourthchoicedisks"
echo "[get_install_disk] Add disk: $disk $disk_data into $file_pre fourthchoicedisks"
;;
esac
done
for seq in first second third; do
for seq in first second third fourth; do
if [ -s $tmpfile$file_pre${seq}choicedisks ]; then
install_file="$tmpfile$file_pre${seq}choicedisks"
break
@@ -56,7 +56,7 @@ check:output=~0x500a0751036d9e61
check:output=~0x500a0751036d9e83
check:output=~0x500a0751036d9e7a
check:output=~0x500a0751036d9c24
cmd:cat /tmp/__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__fr_$$NO | grep "into wwn secondchoicedisks"
cmd:cat /tmp/__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__fr_$$NO | grep "into wwn thirdchoicedisks"
check:output=~sda 0x500a0751036d9e61
check:output=~sdb 0x500a0751036d9c24
check:output=~sdc 0x500a0751036d9e7a
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Spec;
use File::Temp qw(tempdir);
use Test::More;
my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' );
my $script_dir = File::Spec->catdir( $repo_root, 'xCAT-server', 'share', 'xcat', 'install', 'scripts' );
# The RHEL 10 installer includes its own copy of the script, so both carry the
# same selection order and both are exercised here.
my @scripts = map { File::Spec->catfile( $script_dir, $_ ) } qw(getinstdisk getinstdisk.rhels10);
plan skip_all => 'getinstdisk not found' if grep { !-r $_ } @scripts;
our $script;
sub slurp {
open( my $fh, '<', $_[0] ) or die "Unable to read $_[0]: $!";
my $c = do { local $/; <$fh> };
close($fh);
return $c;
}
# The script reads /proc/partitions and writes under /tmp, so each scenario
# runs a copy with those paths moved into its own sandbox, and a stub udevadm
# serves the device properties from fixture files.
sub run_scenario {
my (%disk) = @_;
my $sandbox = tempdir( CLEANUP => 1 );
my $fixdir = "$sandbox/fix";
my $bindir = "$sandbox/bin";
mkdir $fixdir;
mkdir $bindir;
my $body = slurp($script);
$body =~ s{/proc/partitions}{$sandbox/partitions}g;
$body =~ s{/tmp/xcat\.install_disk}{$sandbox/xcat.install_disk}g;
$body =~ s{/tmp/xcat\.getinstalldisk}{$sandbox/xcat.getinstalldisk}g;
$body =~ s{/dev/md/Volume0}{$sandbox/md/Volume0}g;
$body =~ s{"/dev/xvda"}{"$sandbox/xvda"}g;
open( my $sh, '>', "$sandbox/getinstdisk" ) or die $!;
print $sh $body;
close($sh);
open( my $parts, '>', "$sandbox/partitions" ) or die $!;
print $parts "major minor #blocks name\n\n";
my $minor = 0;
for my $name ( sort keys %disk ) {
printf $parts " 8 %5d 524288000 %s\n", $minor++, $name;
}
close($parts);
for my $name ( sort keys %disk ) {
my %attr = %{ $disk{$name} };
open( my $props, '>', "$fixdir/$name.props" ) or die $!;
print $props "ID_WWN=$attr{wwn}\n" if $attr{wwn};
print $props "DEVTYPE=disk\n";
close($props);
open( my $attrs, '>', "$fixdir/$name.attrs" ) or die $!;
print $attrs qq{ ATTRS{size}=="1024000000"\n};
print $attrs qq{ DRIVERS=="$attr{driver}"\n} if $attr{driver};
my @models = $attr{models} ? @{ $attr{models} } : ( $attr{model} ? $attr{model} : () );
print $attrs qq{ ATTRS{model}=="$_"\n} for @models;
close($attrs);
}
open( my $udev, '>', "$bindir/udevadm" ) or die $!;
print $udev <<'UDEV';
#!/bin/sh
for a in "$@"; do
case "$a" in
--name=*) name=${a#--name=} ;;
esac
done
name=${name#/dev/}
case "$*" in
*--query=property*) cat "$FIXDIR/$name.props" 2>/dev/null ;;
*--attribute-walk*) cat "$FIXDIR/$name.attrs" 2>/dev/null ;;
esac
exit 0
UDEV
close($udev);
chmod 0755, "$bindir/udevadm";
local $ENV{FIXDIR} = $fixdir;
local $ENV{PATH} = "$bindir:$ENV{PATH}";
local $ENV{MASTER_IP} = '';
system("sh $sandbox/getinstdisk >$sandbox/log 2>&1");
my $chosen = -r "$sandbox/xcat.install_disk" ? slurp("$sandbox/xcat.install_disk") : '';
chomp $chosen;
return $chosen;
}
# Every scenario asserts against both copies of the script.
sub selects {
my ( $expected, $name, %disk ) = @_;
for my $candidate (@scripts) {
local $script = $candidate;
my $variant = ( File::Spec->splitpath($candidate) )[2];
is( run_scenario(%disk), $expected, "$name ($variant)" );
}
return;
}
# A direct attached disk wins over a RAID volume when both are present. The
# RAID volume sorts first by name, so the choice comes from the driver group.
selects( '/dev/sdb', 'the direct attached disk wins over the RAID volume',
sda => { driver => 'megaraid_sas' },
sdb => { driver => 'ahci' } );
# A server with only RAID volumes still selects one.
selects( '/dev/sda', 'a RAID volume is selected when nothing better exists',
sda => { driver => 'megaraid_sas' } );
# A SAS host adapter loses to a direct attached disk, and still wins over a
# driver with no group of its own.
selects( '/dev/sdb', 'the direct attached disk wins over the host adapter',
sda => { driver => 'mpt3sas' },
sdb => { driver => 'ahci' } );
selects( '/dev/sda', 'the host adapter wins over an unknown driver',
sda => { driver => 'mpt3sas' },
sdb => { driver => 'virtio_blk' } );
# A driverless NVMe device still gets selected from the last group.
selects( '/dev/nvme0n1', 'an NVMe device is selected from the last group',
nvme0n1 => {} );
# No usable disk falls back to the documented default.
selects( '/dev/sda', 'no disks fall back to the default' );
done_testing();