mirror of
https://github.com/webmin/webmin.git
synced 2026-05-04 22:30:33 +01:00
Work on 3ware support
This commit is contained in:
@@ -9,3 +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.
|
||||
|
||||
@@ -7,17 +7,18 @@ $mode = $in{'short'} ? "short" :
|
||||
$in{'ext'} ? "ext" : "data";
|
||||
&ui_print_header(undef, $text{$mode.'_title'}, "");
|
||||
|
||||
@drives = &fdisk::list_disks_partitions();
|
||||
($d) = grep { $_->{'device'} eq $in{'drive'} } @drives;
|
||||
@drives = &list_smart_disks_partitions();
|
||||
($d) = grep { $_->{'device'} eq $in{'drive'} &&
|
||||
$_->{'3ware'} == $in{'3ware'} } @drives;
|
||||
print &text($mode."_doing", $d->{'desc'}),"\n";
|
||||
if ($mode eq "short") {
|
||||
($ok, $out) = &short_test($in{'drive'});
|
||||
($ok, $out) = &short_test($in{'drive'}, $d);
|
||||
}
|
||||
elsif ($mode eq "ext") {
|
||||
($ok, $out) = &ext_test($in{'drive'});
|
||||
($ok, $out) = &ext_test($in{'drive'}, $d);
|
||||
}
|
||||
elsif ($mode eq "data") {
|
||||
($ok, $out) = &data_test($in{'drive'});
|
||||
($ok, $out) = &data_test($in{'drive'}, $d);
|
||||
}
|
||||
print "<pre>$out</pre>\n";
|
||||
if ($ok) {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 1.2 KiB |
@@ -26,9 +26,7 @@ if (!$ver) {
|
||||
&text('index_version', $ver));
|
||||
|
||||
# Get list of drives
|
||||
@drives = grep { $_->{'type'} eq 'ide' ||
|
||||
$_->{'type'} eq 'scsi' } &fdisk::list_disks_partitions();
|
||||
@drives = sort { $a->{'device'} cmp $b->{'device'} } @drives;
|
||||
@drives = &list_smart_disks_partitions();
|
||||
if (!@drives) {
|
||||
&ui_print_endpage($text{'index_eidescsi'});
|
||||
}
|
||||
@@ -63,9 +61,10 @@ 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);
|
||||
local $st = &get_drive_status($_[0]->{'device'});
|
||||
local $st = &get_drive_status($_[0]->{'device'}, $_[0]);
|
||||
print &ui_table_row($text{'index_desc'},
|
||||
$_[0]->{'desc'});
|
||||
if ($_[0]->{'cylsize'}) {
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
# Functions for getting SMART status
|
||||
=head1 smart-status-lib.pl
|
||||
|
||||
Functions for getting SMART status
|
||||
|
||||
=cut
|
||||
|
||||
do '../web-lib.pl';
|
||||
&init_config();
|
||||
do '../ui-lib.pl';
|
||||
&foreign_require("fdisk", "fdisk-lib.pl");
|
||||
$extra_args = $config{'extra'};
|
||||
if ($config{'ata'}) {
|
||||
$extra_args .= " -d ata";
|
||||
}
|
||||
|
||||
# get_smart_version()
|
||||
=head2 get_smart_version()
|
||||
|
||||
Returns the version number of the SMART tools on this system
|
||||
|
||||
=cut
|
||||
sub get_smart_version
|
||||
{
|
||||
if (!defined($smartctl_version_cache)) {
|
||||
@@ -21,12 +25,62 @@ if (!defined($smartctl_version_cache)) {
|
||||
return $smartctl_version_cache;
|
||||
}
|
||||
|
||||
# get_drive_status(device)
|
||||
# Returns a hash reference containing the status of some drive
|
||||
=head2 list_smart_disks_partitions
|
||||
|
||||
Returns a sorted list of disks that can support SMART.
|
||||
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) {
|
||||
# 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);
|
||||
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,
|
||||
});
|
||||
}
|
||||
$threecount++;
|
||||
}
|
||||
else {
|
||||
push(@rv, $d);
|
||||
}
|
||||
}
|
||||
return sort { $a->{'device'} cmp $b->{'device'} ||
|
||||
$a->{'3ware'} <=> $b->{'3ware'} } @rv;
|
||||
}
|
||||
|
||||
=head2 count_3ware_disks(&drive)
|
||||
|
||||
Returns the number of physical disks on some 3ware RAID device.
|
||||
|
||||
=cut
|
||||
sub count_3ware_disks
|
||||
{
|
||||
return 4; # XXX
|
||||
}
|
||||
|
||||
=head2 get_drive_status(device-name, [&drive])
|
||||
|
||||
Returns a hash reference containing the status of some drive
|
||||
|
||||
=cut
|
||||
sub get_drive_status
|
||||
{
|
||||
local ($device, $drive) = @_;
|
||||
local %rv;
|
||||
local $qd = quotemeta($_[0]);
|
||||
local $qd = quotemeta($device);
|
||||
local $extra_args = &get_extra_args($device, $drive);
|
||||
if (&get_smart_version() > 5.0) {
|
||||
# Use new command format
|
||||
|
||||
@@ -141,13 +195,16 @@ if ($config{'attribs'}) {
|
||||
return \%rv;
|
||||
}
|
||||
|
||||
# short_test(drive)
|
||||
# short_test(device, [&drive])
|
||||
# Starts a short drive test, and returns 1 for success or 0 for failure, plus
|
||||
# any output.
|
||||
sub short_test
|
||||
{
|
||||
local ($device, $drive) = @_;
|
||||
local $qm = quotemeta($device);
|
||||
local $extra_args = &get_extra_args($device, $drive);
|
||||
if (&get_smart_version() > 5.0) {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t short $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t short $qm 2>&1");
|
||||
if ($? || $out !~ /testing has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -156,7 +213,7 @@ if (&get_smart_version() > 5.0) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -S $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -S $qm 2>&1");
|
||||
if ($? || $out !~ /test has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -166,13 +223,16 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
# ext_test(drive)
|
||||
# ext_test(device, [&drive])
|
||||
# Starts an extended drive test, and returns 1 for success or 0 for failure,
|
||||
# plus any output.
|
||||
sub ext_test
|
||||
{
|
||||
local ($device, $drive) = @_;
|
||||
local $qm = quotemeta($device);
|
||||
local $extra_args = &get_extra_args($device, $drive);
|
||||
if (&get_smart_version() > 5.0) {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t long $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t long $qm 2>&1");
|
||||
if ($? || $out !~ /testing has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -181,7 +241,7 @@ if (&get_smart_version() > 5.0) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -X $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -X $qm 2>&1");
|
||||
if ($? || $out !~ /test has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -191,13 +251,16 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
# data_test(drive)
|
||||
# data_test(device, [&drive])
|
||||
# Starts offline data collection, and returns 1 for success or 0 for failure,
|
||||
# plus any output.
|
||||
sub data_test
|
||||
{
|
||||
local ($device, $drive) = @_;
|
||||
local $qm = quotemeta($device);
|
||||
local $extra_args = &get_extra_args($device, $drive);
|
||||
if (&get_smart_version() > 5.0) {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t offline $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -t offline $qm 2>&1");
|
||||
if ($? || $out !~ /testing has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -206,7 +269,7 @@ if (&get_smart_version() > 5.0) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -O $_[0] 2>&1");
|
||||
local $out = &backquote_logged("$config{'smartctl'} $extra_args -O $qm 2>&1");
|
||||
if ($? || $out !~ /test has begun/i) {
|
||||
return (0, $out);
|
||||
}
|
||||
@@ -216,5 +279,27 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
=head2 get_extra_args(device, [&drive])
|
||||
|
||||
Returns extra command-line args to smartctl, needed for some drive type.
|
||||
|
||||
=cut
|
||||
sub get_extra_args
|
||||
{
|
||||
local ($device, $drive) = @_;
|
||||
if (!$drive) {
|
||||
($drive) = grep { $_->{'device'} eq $device }
|
||||
&list_smart_disks_partitions();
|
||||
}
|
||||
local $extra_args = $config{'extra'};
|
||||
if ($drive && defined($drive->{'3ware'})) {
|
||||
$extra_args .= " -d 3ware,$drive->{'3ware'}";
|
||||
}
|
||||
elsif ($config{'ata'}) {
|
||||
$extra_args .= " -d ata";
|
||||
}
|
||||
return $extra_args;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
@@ -22,7 +22,15 @@ if (!-r $_[1]->{'drive'}) {
|
||||
return { 'up' => -1,
|
||||
'desc' => $text{'monitor_nosuch'} };
|
||||
}
|
||||
local $st = &get_drive_status($_[1]->{'drive'});
|
||||
local @drives = &list_smart_disks_partitions();
|
||||
local ($d) = grep { $_->{'device'} eq $_[1]->{'drive'} &&
|
||||
$_->{'3ware'} eq $_[1]->{'3ware'} } @drives;
|
||||
if (!$d) {
|
||||
# Not in list?!
|
||||
return { 'up' => -1,
|
||||
'desc' => $text{'monitor_nosuch'} };
|
||||
}
|
||||
local $st = &get_drive_status($d->{'drive'}, $d);
|
||||
|
||||
# Record number of errors since last time
|
||||
local %errors;
|
||||
@@ -64,15 +72,15 @@ else {
|
||||
sub status_monitor_dialog
|
||||
{
|
||||
local $rv;
|
||||
local @drives = grep { $_->{'type'} eq 'ide' ||
|
||||
$_->{'type'} eq 'scsi' } &fdisk::list_disks_partitions();
|
||||
@drives = sort { $a->{'device'} cmp $b->{'device'} } @drives;
|
||||
local ($inlist) = grep { $_->{'device'} eq $_[1]->{'drive'} } @drives;
|
||||
local @drives = &list_smart_disks_partitions();
|
||||
local ($inlist) = grep { $_->{'device'} eq $_[1]->{'drive'} &&
|
||||
$_->{'3ware'} eq $_[1]->{'3ware'} } @drives;
|
||||
$inlist = 1 if (!$_[1]->{'drive'});
|
||||
$rv .= &ui_table_row($text{'monitor_drive'},
|
||||
&ui_select("drive", !$_[1]->{'drive'} ? $drives[0]->{'device'} :
|
||||
$inlist ? $_[1]->{'drive'} : undef,
|
||||
[ (map { [ $_->{'device'},
|
||||
$inlist ? $inlist->{'drive'}.':'.$inlist->{'3ware'} :
|
||||
undef,
|
||||
[ (map { [ $_->{'device'}.':'.$_->{'3ware'},
|
||||
$_->{'desc'}.($_->{'model'} ?
|
||||
" ($_->{'model'})" : "") ] } @drives),
|
||||
[ "", $text{'monitor_other'} ] ]).
|
||||
@@ -89,8 +97,14 @@ return $rv;
|
||||
# Parse form for selecting a rule
|
||||
sub status_monitor_parse
|
||||
{
|
||||
$_[1]->{'drive'} = $_[2]->{'drive'} || $_[2]->{'other'};
|
||||
$_[1]->{'drive'} =~ /^\S+$/ || &error($text{'monitor_edrive'});
|
||||
if ($_[2]->{'drive'}) {
|
||||
($_[1]->{'drive'}, $_[1]->{'3ware'}) = split(/:/, $_[2]->{'drive'});
|
||||
}
|
||||
else {
|
||||
$_[1]->{'drive'} = $_[2]->{'other'};
|
||||
$_[1]->{'3ware'} = undef;
|
||||
$_[1]->{'drive'} =~ /^\S+$/ || &error($text{'monitor_edrive'});
|
||||
}
|
||||
$_[1]->{'errors'} = $_[2]->{'errors'};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user