mdadm raid 10 support and monitoring
authorJamie Cameron <jcameron@webmin.com>
Thu, 6 Sep 2007 23:22:33 +0000 (23:22 +0000)
committerJamie Cameron <jcameron@webmin.com>
Thu, 6 Sep 2007 23:22:33 +0000 (23:22 +0000)
init/init-lib.pl
raid/CHANGELOG
raid/images/10.gif [new file with mode: 0644]
raid/images/10.ia.gif [new file with mode: 0644]
raid/index.cgi
raid/lang/en
raid/raid-lib.pl
raid/raid_form.cgi
raid/save_mdadm.cgi [new file with mode: 0644]
raid/view_raid.cgi

index 6268a1a..31f68de 100755 (executable)
@@ -750,7 +750,7 @@ if ($init_mode eq "init" || $init_mode eq "local") {
        local $temp = &transname();
        &foreign_require("proc", "proc-lib.pl");
        open(TEMP, ">$temp");
-       &proc::safe_process_exec_logged("$fh start", 0, 0, TEMP);
+       &proc::safe_process_exec_logged("$fn start", 0, 0, TEMP);
        close(TEMP);
        local $ex = $?;
        local $out = &read_file_contents($temp);
@@ -786,7 +786,7 @@ if ($init_mode eq "init" || $init_mode eq "local") {
        local $temp = &transname();
        &foreign_require("proc", "proc-lib.pl");
        open(TEMP, ">$temp");
-       &proc::safe_process_exec_logged("$fh stop", 0, 0, TEMP);
+       &proc::safe_process_exec_logged("$fn stop", 0, 0, TEMP);
        close(TEMP);
        local $ex = $?;
        local $out = &read_file_contents($temp);
index fb28611..f42c0c6 100644 (file)
@@ -7,3 +7,7 @@ RAID devices can now be easily mounted as virtual memory.
 Added support for RAID 6 arrays when using MDADM.
 ---- Changes since 1.340 ----
 Removed need to explicitly select a parity disk for RAID 4 when using MDADM.
+---- Changes since 1.360 ----
+Added support for RAID 10 arrays when using MDADM.
+Changed the main page to use a table for existing RAID arrays, rather than icons.
+Added a section for configuring RAID problem notification when using MDADM.
diff --git a/raid/images/10.gif b/raid/images/10.gif
new file mode 100644 (file)
index 0000000..3cd6531
Binary files /dev/null and b/raid/images/10.gif differ
diff --git a/raid/images/10.ia.gif b/raid/images/10.ia.gif
new file mode 100644 (file)
index 0000000..3b4060d
Binary files /dev/null and b/raid/images/10.ia.gif differ
index 45079a7..f5f972e 100755 (executable)
@@ -30,29 +30,75 @@ else {
 # Display configured raid devices
 $conf = &get_raidtab();
 if (@$conf) {
-       &show_button();
+       print &ui_columns_start([ $text{'index_name'},
+                               $text{'index_active'},
+                               $text{'index_level'},
+                               $text{'index_members'} ]);
        foreach $c (@$conf) {
                $lvl = &find_value('raid-level', $c->{'members'});
-               push(@titles, &html_escape($c->{'value'}));
-               push(@images, $c->{'active'} ? "images/$lvl.gif"
-                                            : "images/$lvl.ia.gif");
-               push(@links, "view_raid.cgi?idx=$c->{'index'}");
+               @mems = ( );
+               foreach $d (&find('device', $c->{'members'})) {
+                       if (&find('raid-disk', $d->{'members'}) ||
+                           &find('parity-disk', $d->{'members'})) {
+                               push(@mems, $d->{'value'});
+                               }
+                       }
+               print &ui_columns_row([
+                       "<a href='view_raid.cgi?idx=$c->{'index'}'>".
+                       &html_escape($c->{'value'})."</a>",
+                       $c->{'active'} ?
+                               "<font color=#00aa00>$text{'yes'}</font>" :
+                               "<font color=#ff0000>$text{'no'}</font>",
+                       $lvl eq 'linear' ? $text{'linear'} : $text{'raid'.$lvl},
+                       join(" ", @mems),
+                       ]);
                }
-       &icons_table(\@links, \@titles, \@images);
+       print &ui_columns_end();
        }
 else {
        print "<p><b>$text{'index_none'}</b><p>\n";
        }
 &show_button();
 
+# Form for mdadm monitoring options
+if ($raid_mode eq "mdadm") {
+       $notif = &get_mdadm_notifications();
+       print "<hr>\n";
+       print &ui_form_start("save_mdadm.cgi", "post");
+       print &ui_table_start($text{'index_header'}, undef, 2, [ "width=30%" ]);
+
+       # Is monitoring enabled?
+       if (&get_mdadm_action()) {
+               print &ui_table_row($text{'index_monitor'},
+                  &ui_yesno_radio("monitor", &get_mdadm_monitoring() ? 1 : 0));
+               }
+
+       # Notification address
+       print &ui_table_row($text{'index_mailaddr'},
+               &ui_opt_textbox("mailaddr", $notif->{'MAILADDR'}, 40,
+                               $text{'index_mailaddrnone'}));
+
+       # Notification sender
+       print &ui_table_row($text{'index_mailfrom'},
+               &ui_opt_textbox("mailfrom", $notif->{'MAILFROM'}, 40,
+                               $text{'index_mailfromnone'}));
+
+       # Program to call for problems
+       print &ui_table_row($text{'index_program'},
+               &ui_opt_textbox("program", $notif->{'PROGRAM'}, 40,
+                               $text{'index_programnone'}));
+
+       print &ui_table_end();
+       print &ui_form_end([ [ undef, $text{'save'} ] ]);
+       }
+
 &ui_print_footer("/", $text{'index'});
 
 sub show_button
 {
 print &ui_form_start("raid_form.cgi");
 print &ui_submit($text{'index_add'});
-local @levels = ( 0, 1, 4, 5 );
-push(@levels, 6) if ($raid_mode eq "mdadm");
+local @levels = &get_raid_levels();
 print &ui_select("level", "linear",
                 [ [ "linear", $text{'linear'} ],
                   map { [ $_, $text{'raid'.$_} ] } @levels ]),"\n";
index 6f7303c..217039b 100644 (file)
@@ -6,6 +6,18 @@ index_emdstat=The kernel RAID status file $1 does not exist on your system. Your
 index_eprogs=Niether the RAID tools or MDADM packages are installed on your system.
 index_mdadm=Using MDADM
 index_raidtools=Using RaidTools
+index_name=Device name
+index_active=Active?
+index_level=RAID level
+index_members=Member disk devices
+index_header=RAID problem notification options
+index_mailaddr=Send notifications to
+index_mailaddrnone=Don't send
+index_mailfrom=From address for notifications
+index_mailfromnone=Default (<tt>root</tt>)
+index_program=Command to run when problems are detected
+index_programnone=Don't run any
+index_monitor=Monitoring enabled?
 
 linear=Concatenated (Linear)
 raid0=Striped (RAID0)
@@ -13,6 +25,7 @@ raid1=Mirrored (RAID1)
 raid4=Parity (RAID4)
 raid5=Redundant (RAID5)
 raid6=Dual Redundant (RAID6)
+raid10=Striped and Mirrored (RAID10)
 blocks=blocks
 
 create_title=Create RAID Device
@@ -102,3 +115,9 @@ 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_notif=Updated RAID problem notification options
+
+notif_err=Failed to save RAID problem notification options
+notif_emailaddr=Missing or invalid notification address
+notif_emailfrom=Missing or invalid From address
+notif_eprogram=Missing or non-existant program to run
index 34f6d58..b3054e2 100644 (file)
@@ -13,6 +13,18 @@ close(MODE);
 %container = ( 'raiddev', 1,
               'device', 1 );
 
+# get_raid_levels()
+# Returns a list of allowed RAID levels
+sub get_raid_levels
+{
+if ($raid_mode eq "mdadm") {
+       return ( 0, 1, 4, 5, 6, 10 );
+       }
+else {
+       return ( 0, 1, 4, 5 );
+       }
+}
+
 # get_mdstat()
 # Read information about active RAID devices. Returns a hash indexed by
 # device name (like /dev/md0), with each value being an array reference
@@ -537,5 +549,102 @@ else {
        }
 }
 
+%mdadm_notification_opts = map { $_, 1 } ( 'MAILADDR', 'MAILFROM', 'PROGRAM' );
+
+# get_mdadm_notifications()
+# Returns a hash from mdadm.conf notification-related settings to values
+sub get_mdadm_notifications
+{
+local $lref = &read_file_lines($config{'mdadm'});
+local %rv;
+foreach my $l (@$lref) {
+       $l =~ s/#.*$//;
+       if ($l =~ /^(\S+)\s+(\S.*)/ && $mdadm_notification_opts{$1}) {
+               $rv{$1} = $2;
+               }
+       }
+return \%rv;
+}
+
+# save_mdadm_notifications(&notifications)
+# Updates mdadm.conf with settings from the given hash. Those set to undef
+# are removed from the file.
+sub save_mdadm_notifications
+{
+local ($notif) = @_;
+local $lref = &read_file_lines($config{'mdadm'});
+local %done;
+for(my $i=0; $i<@$lref; $i++) {
+       my $l = $lref->[$i];
+       $l =~ s/#.*$//;
+       local ($k, $v) = split(/\s+/, $l, 2);
+       if (exists($notif->{$k})) {
+               if (defined($notif->{$k})) {
+                       $lref->[$i] = "$k $notif->{$k}";
+                       }
+               else {
+                       splice(@$lref, $i--, 1);
+                       }
+               $done{$k}++;
+               }
+       }
+foreach my $k (grep { !$done{$_} && defined($notif->{$_}) } keys %$notif) {
+       push(@$lref, "$k $notif->{$k}");
+       }
+&flush_file_lines($config{'mdadm'});
+}
+
+# get_mdadm_action()
+# Returns the name of an init module action for mdadm monitoring, or undef if
+# not supported.
+sub get_mdadm_action
+{
+if (&foreign_installed("init")) {
+       &foreign_require("init", "init-lib.pl");
+       foreach my $a ("mdmonitor", "mdadm", "mdadmd") {
+               local $st = &init::action_status($a);
+               return $a if ($st);
+               }
+       }
+return undef;
+}
+
+# get_mdadm_monitoring()
+# Returns 1 if mdadm monitoring is enabled, 0 if not
+sub get_mdadm_monitoring
+{
+local $act = &get_mdadm_action();
+if ($act) {
+       &foreign_require("init", "init-lib.pl");
+       local $st = &init::action_status($act);
+       return $st == 2;
+       }
+return 0;
+}
+
+# save_mdadm_monitoring(enabled)
+# Tries to enable or disable mdadm monitoring. Returns an error mesage
+# if something goes wrong, undef on success
+sub save_mdadm_monitoring
+{
+local ($enabled) = @_;
+local $act = &get_mdadm_action();
+if ($act) {
+       &foreign_require("init", "init-lib.pl");
+       if ($enabled) {
+               &init::enable_at_boot($act);
+               &init::stop_action($act);
+               sleep(2);
+               local ($ok, $err) = &init::start_action($act);
+               return $err if (!$ok);
+               }
+       else {
+               &init::disable_at_boot($act);
+               &init::stop_action($act);
+               }
+       }
+return undef;
+}
+
 1;
 
index 79135f2..9b8c59e 100755 (executable)
@@ -82,7 +82,7 @@ print "<td><select name=disks multiple size=4>\n";
 print $disks;
 print "</select></td> </tr>\n";
 
-if ($lvl >= 4) {
+if ($lvl >= 4 && $lvl != 10) {
        print "<tr> <td valign=top><b>$text{'create_spares'}</b></td>\n";
        print "<td><select name=spares multiple size=4>\n";
        print $disks;
diff --git a/raid/save_mdadm.cgi b/raid/save_mdadm.cgi
new file mode 100644 (file)
index 0000000..6be3f87
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/local/bin/perl
+# Update mdadm.conf with notification settings
+
+require './raid-lib.pl';
+&ReadParse();
+&error_setup($text{'notif_err'});
+
+# Validate inputs
+$notif = { };
+if (!$in{'mailaddr_def'}) {
+       $in{'mailaddr'} =~ /^\S+\@\S+$/ || &error($text{'notif_emailaddr'});
+       $notif->{'MAILADDR'} = $in{'mailaddr'};
+       }
+else {
+       $notif->{'MAILADDR'} = undef;
+       }
+if (!$in{'mailfrom_def'}) {
+       $in{'mailfrom'} =~ /^\S+\@\S+$/ || &error($text{'notif_emailfrom'});
+       $notif->{'MAILFROM'} = $in{'mailfrom'};
+       }
+else {
+       $notif->{'MAILFROM'} = undef;
+       }
+if (!$in{'program_def'}) {
+       -x $in{'program'} || &error($text{'notif_eprogram'});
+       $notif->{'PROGRAM'} = $in{'program'};
+       }
+else {
+       $notif->{'PROGRAM'} = undef;
+       }
+
+# Save them
+&lock_file($config{'mdadm'});
+&save_mdadm_notifications($notif);
+&unlock_file($config{'mdadm'});
+
+# Enable/disable
+if (&get_mdadm_action()) {
+       &save_mdadm_monitoring($in{'monitor'});
+       }
+
+&webmin_log("notif");
+
+&redirect("");
+
index a1daae5..1939a57 100755 (executable)
@@ -154,12 +154,13 @@ if ($raid_mode eq "mdadm") {
 
 if ($raid->{'active'} && !$st[2]) {
        # Show buttons for creating filesystems
+       $fstype = $st[1] || "ext3";
        print "<tr> <td nowrap><input type=submit name=mkfs ",
              "value='$text{'view_mkfs2'}'>\n";
        print "<select name=fs>\n";
        foreach $f (&fdisk::supported_filesystems()) {
                printf "<option value=%s %s>%s (%s)\n",
-                       $f, $stat[1] eq $f ? "selected" : "",
+                       $f, $fstype eq $f ? "selected" : "",
                        $fdisk::text{"fs_$f"}, $f;
                }
        print "</select></td>\n";