diff --git a/raid/lang/en b/raid/lang/en index b7665ea93..29f5b9424 100644 --- a/raid/lang/en +++ b/raid/lang/en @@ -101,6 +101,8 @@ view_remove=Remove partition: view_removedesc=Select a partition that is part of the RAID device and click this button to remove it. This may cause data to be lost! view_remove_det=Remove detached view_remove_detdesc=Remove partitions that are already physically detached from the system. +view_replace=Replace partition: +view_replacedesc=Select a partition that should be replaced. (Hot Replace) view_grow=Grow RAID: view_growdesc=Grow array (convert hot spares to active members) view_convert_to_raid6=Convert to RAID6 @@ -133,6 +135,7 @@ emdadmcreate=mdadm in --create mode failed : $1 emdadmadd=mdadm in --manage --add mode failed : $1 emdadmgrow=mdadm in --grow mode failed : $1 emdadmremove=mdadm in --manage --remove mode failed : $1 +emdadmreplace=mdadm in --manage --replace mode failed : $1 emdadmfail=mdadm in --manage --fail mode failed : $1 log_create=Created $1 RAID device $2 @@ -142,6 +145,7 @@ log_delete=Deleted RAID device $1 log_mkfs=Created $1 filesystem on $2 log_add=Added partition $2 to RAID device $1 log_remove=Removed partition $2 from RAID device $1 +log_replace=Hot replaced partition $2 in RAID device $1 with a spare partition log_grow=Grown RAID device $1 to a total of $2 disks log_convert_to_raid6=Converted RAID5 device $1 to a RAID6 device log_convert_to_raid5=Converted RAID6 device $1 to a RAID5 device diff --git a/raid/log_parser.pl b/raid/log_parser.pl index 8ece806d2..d07897684 100755 --- a/raid/log_parser.pl +++ b/raid/log_parser.pl @@ -30,6 +30,9 @@ elsif ($action eq 'add') { elsif ($action eq 'remove') { return &text('log_remove', "$object", "$p->{'disk'}"); } +elsif ($action eq 'replace') { + return &text('log_replace', "$object", "$p->{'disk'}"); + } elsif ($action eq 'grow') { return &text('log_grow', "$object", "$p->{'disk'}"); } diff --git a/raid/raid-lib.pl b/raid/raid-lib.pl index d786d370e..cb708d230 100755 --- a/raid/raid-lib.pl +++ b/raid/raid-lib.pl @@ -521,10 +521,10 @@ if ($raid_mode eq "mdadm") { # Call mdadm commands to fail and remove local $out = &backquote_logged( "mdadm --manage $_[0]->{'value'} --fail $_[1] 2>&1"); - &error(&text('emdadfail', "$out")) if ($?); + &error(&text('emdadmfail', "$out")) if ($?); local $out = &backquote_logged( "mdadm --manage $_[0]->{'value'} --remove $_[1] 2>&1"); - &error(&text('emdadremove', "$out")) if ($?); + &error(&text('emdadmremove', "$out")) if ($?); # Remove device from mdadm.conf local $lref = &read_file_lines($config{'mdadm'}); @@ -558,10 +558,22 @@ if ($raid_mode eq "mdadm") { # Call mdadm commands to remove local $out = &backquote_logged( "mdadm --manage $_[0]->{'value'} --remove detached 2>&1"); - &error(&text('emdadremove', "$out")) if ($?); + &error(&text('emdadmremove', "$out")) if ($?); } } +# replace_partition(&raid, device) +# Hot replaces a partition with a spare +sub replace_partition +{ +if ($raid_mode eq "mdadm") { + # Call mdadm commands to replace + local $out = &backquote_logged( + "mdadm --replace $_[0]->{'value'} $_[1] 2>&1"); + &error(&text('emdadmreplace', "$out")) if ($?); + } +} + # directive_lines(&directive, indent) sub directive_lines { @@ -798,5 +810,13 @@ local $ver = $out =~ /\s+v([0-9\.]+)/ ? $1 : undef; return wantarray ? ( $ver, $out ) : $ver; } +# supports_replace() +# Only kernels with version 3.3 and above support the hot replace feature +sub supports_replace +{ +my $out = &backquote_command("uname -r 2>/dev/null = 3; +} + 1; diff --git a/raid/save_raid.cgi b/raid/save_raid.cgi index feb884c83..d23309792 100755 --- a/raid/save_raid.cgi +++ b/raid/save_raid.cgi @@ -113,6 +113,14 @@ elsif ($in{'remove_det'}) { &unlock_raid_files(); &redirect(""); } +elsif ($in{'replace'}) { + # Hot replace a member disk with a spare + &lock_raid_files(); + &replace_partition($old, $in{'replacedisk'}); + &unlock_raid_files(); + &webmin_log("replace", undef, $old->{'value'}, { 'disk' => $in{'replacedisk'} } ); + &redirect(""); + } elsif ($in{'convert_to_raid6'}) { # Convert RAID level to RAID6 &lock_raid_files(); diff --git a/raid/view_raid.cgi b/raid/view_raid.cgi index 1a5028658..02e8d357c 100755 --- a/raid/view_raid.cgi +++ b/raid/view_raid.cgi @@ -163,6 +163,12 @@ if ($raid_mode eq "mdadm") { push(@grid, &ui_submit($text{'view_remove_det'}, "remove_det"), $text{'view_remove_detdesc'}); } + if ($sparescnt > 0 && &get_mdadm_version() >= 3.3 && &supports_replace()) { + @rdisks = sort { $a->[0] cmp $b->[0] } @rdisks; + push(@grid, &ui_submit($text{'view_replace'}, "replace")." ". + &ui_select("replacedisk", undef, \@rdisks), + $text{'view_replacedesc'}); + } if ($sparescnt > 0 && $lvl != 10) { @spares = sort { $a->[0] cmp $b->[0] } @spares; push(@grid, &ui_submit($text{'view_grow'}, "grow")." ".