mirror of
https://github.com/webmin/webmin.git
synced 2026-05-04 22:30:33 +01:00
Fixed up 3ware support, added HP smart array support
This commit is contained in:
@@ -9,4 +9,4 @@ ATA mode is now used by default on CentOS and Redhat Enterprise versions 5 and a
|
||||
---- Changes since 1.440 ----
|
||||
SCSI drives are visible in the System and Server Status module.
|
||||
The SMART status monitor now has an option to only alert if the error count on a drive has increased.
|
||||
Improved support for 3ware drives, so that the underlying disks are now detected and can be reported on separately.
|
||||
Improved support for 3ware and HP RAID devices, so that the underlying disks are now detected and can be reported on separately.
|
||||
|
||||
@@ -9,7 +9,7 @@ $mode = $in{'short'} ? "short" :
|
||||
|
||||
@drives = &list_smart_disks_partitions();
|
||||
($d) = grep { $_->{'device'} eq $in{'drive'} &&
|
||||
$_->{'3ware'} == $in{'3ware'} } @drives;
|
||||
$_->{'subdisk'} == $in{'subdisk'} } @drives;
|
||||
print &text($mode."_doing", $d->{'desc'}),"\n";
|
||||
if ($mode eq "short") {
|
||||
($ok, $out) = &short_test($in{'drive'}, $d);
|
||||
|
||||
@@ -36,14 +36,16 @@ if ($config{'mode'} == 1 || $in{'drive'}) {
|
||||
print &ui_form_start("index.cgi");
|
||||
print "<b>$text{'index_show'}</b>\n";
|
||||
print &ui_select("drive", $in{'drive'},
|
||||
[ map { [ $_->{'device'},
|
||||
[ map { [ $_->{'device'}.":".$_->{'subdisk'},
|
||||
$_->{'desc'}.($_->{'model'} ? " ($_->{'model'})" : "") ] } @drives ],
|
||||
1, 0, 0, 0, "onChange='form.submit()'");
|
||||
print &ui_submit($text{'index_ok'}),"\n";
|
||||
print &ui_form_end();
|
||||
|
||||
if ($in{'drive'}) {
|
||||
($d) = grep { $_->{'device'} eq $in{'drive'} } @drives;
|
||||
($device, $subdisk) = split(/:/, $in{'drive'});
|
||||
($d) = grep { $_->{'device'} eq $device &&
|
||||
$_->{'subdisk'} == $subdisk } @drives;
|
||||
&show_drive($d);
|
||||
}
|
||||
}
|
||||
@@ -61,9 +63,13 @@ sub show_drive
|
||||
{
|
||||
print &ui_form_start("action.cgi");
|
||||
print &ui_hidden("drive", $_[0]->{'device'});
|
||||
print &ui_hidden("3ware", $_[0]->{'3ware'});
|
||||
print &ui_table_start(&text('index_drive', "<tt>$_[0]->{'device'}</tt>"),
|
||||
undef, 2);
|
||||
print &ui_hidden("subdisk", $_[0]->{'subdisk'});
|
||||
local $h = defined($_[0]->{'subdisk'}) ?
|
||||
&text('index_drivesub', "<tt>$_[0]->{'device'}</tt>",
|
||||
$_[0]->{'subdisk'}) :
|
||||
&text('index_drive', "<tt>$_[0]->{'device'}</tt>");
|
||||
print &ui_table_start($h, "width=100%", 4,
|
||||
[ "width=30%", undef, "width=30%", undef ]);
|
||||
local $st = &get_drive_status($_[0]->{'device'}, $_[0]);
|
||||
print &ui_table_row($text{'index_desc'},
|
||||
$_[0]->{'desc'});
|
||||
@@ -87,18 +93,32 @@ if ($st->{'support'} && $st->{'enabled'}) {
|
||||
"</font>");
|
||||
}
|
||||
print &ui_table_row($text{'index_check'},
|
||||
$st->{'check'} ? $text{'yes'} : "<font color=#ff0000>$text{'no'}</font>");
|
||||
if ($config{'attribs'}) {
|
||||
print &ui_table_hr();
|
||||
local $a;
|
||||
foreach $a (@{$st->{'attribs'}}) {
|
||||
next if ($a->[0] =~ /UDMA CRC Error Count/i); # too long
|
||||
print &ui_table_row($a->[0],
|
||||
$a->[2] =~ /^\s*(seconds|minutes|hours|days|months|years|weeks)\s*/i || !$a->[2] ? $a->[1]." ".$a->[2] : $a->[2]);
|
||||
}
|
||||
}
|
||||
$st->{'check'} ? $text{'yes'} :
|
||||
"<font color=#ff0000>$text{'no'}</font>");
|
||||
}
|
||||
print &ui_table_end();
|
||||
|
||||
# Show extra attributes
|
||||
if ($config{'attribs'} && @{$st->{'attribs'}}) {
|
||||
print &ui_hidden_table_start($text{'index_attrs'}, "width=100%", 2,
|
||||
"attrs", 1, [ "width=30%" ]);
|
||||
foreach my $a (@{$st->{'attribs'}}) {
|
||||
next if ($a->[0] =~ /UDMA CRC Error Count/i); # too long
|
||||
print &ui_table_row($a->[0],
|
||||
$a->[2] =~ /^\s*(seconds|minutes|hours|days|months|years|weeks)\s*/i || !$a->[2] ? $a->[1]." ".$a->[2] : $a->[2]);
|
||||
}
|
||||
print &ui_hidden_table_end();
|
||||
}
|
||||
|
||||
# Show raw data from smartctl
|
||||
if ($config{'attribs'} && $st->{'raw'}) {
|
||||
print &ui_hidden_table_start($text{'index_raw'}, "width=100%", 2,
|
||||
"raw", @{$st->{'attribs'}} ? 0 : 1);
|
||||
print &ui_table_row(undef,
|
||||
"<pre>".&html_escape($st->{'raw'})."</pre>", 2);
|
||||
print &ui_hidden_table_end();
|
||||
}
|
||||
|
||||
if ($st->{'support'} && $st->{'enabled'}) {
|
||||
print &ui_form_end([ [ "short", $text{'index_short'} ],
|
||||
[ "ext", $text{'index_ext'} ],
|
||||
|
||||
@@ -6,6 +6,7 @@ index_show=Show status of drive:
|
||||
index_ok=Show
|
||||
index_eidescsi=No IDE or SCSI drives were found on your system.
|
||||
index_drive=Status of drive $1
|
||||
index_drivesub=Status of drive $1, disk $2
|
||||
index_desc=Location
|
||||
index_size=Drive size
|
||||
index_model=Make and model
|
||||
@@ -17,6 +18,8 @@ index_ext=Extended Self Test
|
||||
index_data=Data Collection Test
|
||||
index_errors=Errors logged
|
||||
index_ecount=$1 errors detected
|
||||
index_attrs=Additional SMART attributes
|
||||
index_raw=Full SMART status report
|
||||
index_return=module index
|
||||
|
||||
monitor_type=SMART Drive Check
|
||||
|
||||
@@ -33,41 +33,65 @@ May include faked-up 3ware devices
|
||||
=cut
|
||||
sub list_smart_disks_partitions
|
||||
{
|
||||
local @drives = grep { $_->{'type'} eq 'ide' ||
|
||||
$_->{'type'} eq 'scsi' } &fdisk::list_disks_partitions();
|
||||
local @rv;
|
||||
local $threecount = 0;
|
||||
foreach my $d (@drives) {
|
||||
if ($d->{'type'} eq 'scsi' && $d->{'model'} =~ /3ware/i) {
|
||||
foreach my $d (&fdisk::list_disks_partitions()) {
|
||||
if (($d->{'type'} eq 'scsi' || $d->{'type'} eq 'raid') &&
|
||||
$d->{'model'} =~ /3ware/i) {
|
||||
# Actually a 3ware RAID device .. but we want to probe the
|
||||
# underlying real disks, so add fake devices for them
|
||||
my $count = &count_3ware_disks($d);
|
||||
my $count = &count_subdisks($d, "3ware");
|
||||
for(my $i=0; $i<$count; $i++) {
|
||||
push(@rv, { 'device' => '/dev/twe'.$threecount,
|
||||
'prefix' => '/dev/twe'.$threecount,
|
||||
'desc' => '3ware physical disk '.$i,
|
||||
'type' => 'scsi',
|
||||
'3ware' => $i,
|
||||
'subtype' => '3ware',
|
||||
'subdisk' => $i,
|
||||
});
|
||||
}
|
||||
$threecount++;
|
||||
}
|
||||
else {
|
||||
elsif ($d->{'device'} =~ /^\/dev\/cciss\/(.*)$/) {
|
||||
# HP Smart Array .. add underlying disks
|
||||
my $count = &count_subdisks($d, "cciss");
|
||||
for(my $i=0; $i<$count; $i++) {
|
||||
push(@rv, { 'device' => $d->{'device'},
|
||||
'prefix' => $d->{'device'},
|
||||
'desc' => 'HP Smart Array physical disk '.$i,
|
||||
'type' => 'scsi',
|
||||
'subtype' => 'cciss',
|
||||
'subdisk' => $i,
|
||||
});
|
||||
}
|
||||
}
|
||||
elsif ($d->{'type'} eq 'scsi' || $d->{'type'} eq 'ide') {
|
||||
# Some other disk
|
||||
push(@rv, $d);
|
||||
}
|
||||
}
|
||||
return sort { $a->{'device'} cmp $b->{'device'} ||
|
||||
$a->{'3ware'} <=> $b->{'3ware'} } @rv;
|
||||
$a->{'subdisk'} <=> $b->{'subdisk'} } @rv;
|
||||
}
|
||||
|
||||
=head2 count_3ware_disks(&drive)
|
||||
=head2 count_subdisks(&drive, type)
|
||||
|
||||
Returns the number of physical disks on some 3ware RAID device.
|
||||
Returns the number of sub-disks for a hardware RAID device, by calling
|
||||
smartctl on them until failure.
|
||||
|
||||
=cut
|
||||
sub count_3ware_disks
|
||||
sub count_subdisks
|
||||
{
|
||||
return 4; # XXX
|
||||
local ($d, $type) = @_;
|
||||
local $count = 0;
|
||||
while(1) {
|
||||
local $cmd = "$config{'smartctl'} -d $type,$count ".
|
||||
quotemeta($d->{'device'});
|
||||
&execute_command($cmd);
|
||||
last if ($?);
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
=head2 get_drive_status(device-name, [&drive])
|
||||
@@ -157,6 +181,7 @@ if ($config{'attribs'}) {
|
||||
# Fetch other attributes
|
||||
local ($lastline, @attribs);
|
||||
local $doneknown = 0;
|
||||
$rv{'raw'} = "";
|
||||
open(OUT, "$config{'smartctl'} $extra_args -a $qd |");
|
||||
while(<OUT>) {
|
||||
s/\r|\n//g;
|
||||
@@ -188,6 +213,7 @@ if ($config{'attribs'}) {
|
||||
$rv{'errors'} = $1;
|
||||
}
|
||||
$lastline = $_;
|
||||
$rv{'raw'} .= $_."\n";
|
||||
}
|
||||
close(OUT);
|
||||
$rv{'attribs'} = \@attribs;
|
||||
@@ -292,8 +318,8 @@ if (!$drive) {
|
||||
&list_smart_disks_partitions();
|
||||
}
|
||||
local $extra_args = $config{'extra'};
|
||||
if ($drive && defined($drive->{'3ware'})) {
|
||||
$extra_args .= " -d 3ware,$drive->{'3ware'}";
|
||||
if ($drive && defined($drive->{'subdisk'})) {
|
||||
$extra_args .= " -d $drive->{'subtype'},$drive->{'subdisk'}";
|
||||
}
|
||||
elsif ($config{'ata'}) {
|
||||
$extra_args .= " -d ata";
|
||||
|
||||
@@ -24,7 +24,7 @@ if (!-r $_[1]->{'drive'}) {
|
||||
}
|
||||
local @drives = &list_smart_disks_partitions();
|
||||
local ($d) = grep { $_->{'device'} eq $_[1]->{'drive'} &&
|
||||
$_->{'3ware'} eq $_[1]->{'3ware'} } @drives;
|
||||
$_->{'subdisk'} eq $_[1]->{'subdisk'} } @drives;
|
||||
if (!$d) {
|
||||
# Not in list?!
|
||||
return { 'up' => -1,
|
||||
@@ -74,13 +74,13 @@ sub status_monitor_dialog
|
||||
local $rv;
|
||||
local @drives = &list_smart_disks_partitions();
|
||||
local ($inlist) = grep { $_->{'device'} eq $_[1]->{'drive'} &&
|
||||
$_->{'3ware'} eq $_[1]->{'3ware'} } @drives;
|
||||
$_->{'subdisk'} eq $_[1]->{'subdisk'} } @drives;
|
||||
$inlist = 1 if (!$_[1]->{'drive'});
|
||||
$rv .= &ui_table_row($text{'monitor_drive'},
|
||||
&ui_select("drive", !$_[1]->{'drive'} ? $drives[0]->{'device'} :
|
||||
$inlist ? $inlist->{'drive'}.':'.$inlist->{'3ware'} :
|
||||
$inlist ? $inlist->{'drive'}.':'.$inlist->{'subdisk'} :
|
||||
undef,
|
||||
[ (map { [ $_->{'device'}.':'.$_->{'3ware'},
|
||||
[ (map { [ $_->{'device'}.':'.$_->{'subdisk'},
|
||||
$_->{'desc'}.($_->{'model'} ?
|
||||
" ($_->{'model'})" : "") ] } @drives),
|
||||
[ "", $text{'monitor_other'} ] ]).
|
||||
@@ -98,11 +98,11 @@ return $rv;
|
||||
sub status_monitor_parse
|
||||
{
|
||||
if ($_[2]->{'drive'}) {
|
||||
($_[1]->{'drive'}, $_[1]->{'3ware'}) = split(/:/, $_[2]->{'drive'});
|
||||
($_[1]->{'drive'}, $_[1]->{'subdisk'}) = split(/:/, $_[2]->{'drive'});
|
||||
}
|
||||
else {
|
||||
$_[1]->{'drive'} = $_[2]->{'other'};
|
||||
$_[1]->{'3ware'} = undef;
|
||||
$_[1]->{'subdisk'} = undef;
|
||||
$_[1]->{'drive'} =~ /^\S+$/ || &error($text{'monitor_edrive'});
|
||||
}
|
||||
$_[1]->{'errors'} = $_[2]->{'errors'};
|
||||
|
||||
Reference in New Issue
Block a user