initial commit of file from CVS for e-smith-base on Thu 26 Oct 11:24:52 BST 2023
This commit is contained in:
3
root/sbin/e-smith/console-menu-items/configure.pl
Executable file
3
root/sbin/e-smith/console-menu-items/configure.pl
Executable file
@@ -0,0 +1,3 @@
|
||||
package esmith::console::configure;
|
||||
use esmith::console::configure;
|
||||
return new esmith::console::configure;
|
303
root/sbin/e-smith/console-menu-items/manageRAID.pl
Normal file
303
root/sbin/e-smith/console-menu-items/manageRAID.pl
Normal file
@@ -0,0 +1,303 @@
|
||||
package esmith::console::manageDiskRedundancy;
|
||||
use strict;
|
||||
use warnings;
|
||||
use esmith::console;
|
||||
use Locale::gettext;
|
||||
use Taint::Util;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
use constant DEBUG_MANAGE_RAID => 0;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $self = {
|
||||
name => gettext("Manage disk redundancy"),
|
||||
order => 45,
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub name
|
||||
{
|
||||
return $_[0]->{name};
|
||||
}
|
||||
|
||||
sub order
|
||||
{
|
||||
return $_[0]->{order};
|
||||
}
|
||||
|
||||
sub doit
|
||||
{
|
||||
my ($self, $console, $db) = @_;
|
||||
my ($rc, $choice);
|
||||
|
||||
use POSIX qw(strftime);
|
||||
|
||||
SCAN:
|
||||
my $today = strftime "%A %B %e, %Y %H:%M:%S", localtime;
|
||||
my $title = gettext("Disk redundancy status as of") . " " . $today,
|
||||
my $text = gettext("Current RAID status:") . "\n\n" .
|
||||
join("", get_raid_status()) . "\n\n";
|
||||
my %devices = get_raid_details();
|
||||
|
||||
warn $text if DEBUG_MANAGE_RAID;
|
||||
warn "devices: " . Dumper(\%devices) . "\n" if DEBUG_MANAGE_RAID;
|
||||
|
||||
unless (scalar %devices)
|
||||
{
|
||||
$text = gettext("There are no RAID devices configured");
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Determine the status of each array
|
||||
my @unclean = ();
|
||||
my @recovering = ();
|
||||
my @failed = ();
|
||||
my %used_disks = ();
|
||||
|
||||
for my $dev (keys %devices)
|
||||
{
|
||||
$used_disks{$_}++ for (@{$devices{$dev}{UsedDisks}});
|
||||
|
||||
if ($devices{$dev}{FailedDevices} > 0) {
|
||||
push @failed, "$dev => " . $devices{$dev}{FailedDevices};
|
||||
}
|
||||
|
||||
if ($devices{$dev}{State} =~ /recovering|resync/) {
|
||||
push @recovering, "$dev => " . $devices{$dev}{State};
|
||||
next;
|
||||
}
|
||||
|
||||
next if ($devices{$dev}{State} =~ /^(clean|active)\s*$/);
|
||||
push @unclean, "$dev => " . $devices{$dev}{State};
|
||||
}
|
||||
|
||||
warn "unclean: @unclean\n" if DEBUG_MANAGE_RAID;
|
||||
warn "recovering: @recovering\n" if DEBUG_MANAGE_RAID;
|
||||
warn "failed: @failed\n" if DEBUG_MANAGE_RAID;
|
||||
warn "used_disks: " . Dumper(\%used_disks) . "\n" if DEBUG_MANAGE_RAID;
|
||||
|
||||
# Check for any spare disks we could add
|
||||
my %free_disks = map {$_ => 1} get_disks();
|
||||
delete $free_disks{$_} for keys %used_disks;
|
||||
warn "free_disks: " . Dumper(\%free_disks) . "\n" if DEBUG_MANAGE_RAID;
|
||||
|
||||
# Report status and return if recovering
|
||||
if (scalar @recovering)
|
||||
{
|
||||
$text .= gettext("A RAID resynchronization is in progress.");
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Report status and return if arrays are inconsistent
|
||||
if ((scalar @unclean && scalar @unclean != scalar keys %devices) || (scalar @failed && scalar @failed != scalar keys %devices))
|
||||
{
|
||||
$text .= gettext("Only some of the RAID devices are unclean or contain failed disks.") .
|
||||
"\n\n" .
|
||||
gettext("Manual intervention may be required.") . "\n\n";
|
||||
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Report status if arrays are clean and continue if a spare disk is available or there's only one disk in the system
|
||||
unless (scalar @unclean || scalar @failed)
|
||||
{
|
||||
$text .= gettext("All RAID devices are in a clean state.");
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return unless scalar keys %free_disks > 0 || scalar keys %used_disks == 1;
|
||||
}
|
||||
|
||||
# Report status if all arrays are dirty and continue
|
||||
if ((scalar @unclean && scalar @unclean == scalar keys %devices) || (scalar @failed && scalar @failed == scalar keys %devices))
|
||||
{
|
||||
$text .= gettext("All RAID devices are in an unclean state or contain failed disks.");
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
}
|
||||
|
||||
# Summarise disk assignments
|
||||
my $disk_status = gettext("Current disk status:") . "\n\n";
|
||||
$disk_status .= gettext("Installed disks") . ": " .
|
||||
join(" ", get_disks()) . "\n";
|
||||
$disk_status .= gettext("Used disks") . ": " .
|
||||
join(" ", keys %used_disks) . "\n";
|
||||
$disk_status .= gettext("Free disks") . ": " .
|
||||
join(" ", keys %free_disks) . "\n";
|
||||
|
||||
# Spare disk scenarios
|
||||
# Scenario 1 - single disk or degraded array with no spare - warn
|
||||
if ((scalar @unclean || scalar @failed || scalar keys %used_disks == 1) && scalar keys %free_disks == 0)
|
||||
{
|
||||
$text = $disk_status .
|
||||
"\n\n" .
|
||||
gettext("To ensure continued redundancy, please shut down, install another drive of the same capacity and then return to this screen.");
|
||||
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Scenario 2 - no spares and not degraded so something has gone wrong
|
||||
if (scalar keys %free_disks == 0)
|
||||
{
|
||||
$text = $disk_status .
|
||||
"\n\n" .
|
||||
gettext("Your RAID devices are in an inconsistent state, and no spare drives were detected. You may need to manually remove a failed drive from your arrays using mdadm.");
|
||||
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Scenario 3 - multiple spares
|
||||
if (scalar keys %free_disks > 1)
|
||||
{
|
||||
$text = $disk_status .
|
||||
"\n\n" .
|
||||
gettext("Multiple spare drives have been detected. This utility can only add one drive at a time. Please either shut down and remove all but one of your spare drives, or configure your array manually.");
|
||||
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
return;
|
||||
}
|
||||
|
||||
# Scenario 4 - single spare ready to add
|
||||
$text = $disk_status .
|
||||
"\n\n" .
|
||||
gettext("There is an unused disk drive in your system. Do you want to add it to the existing RAID array(s)?") .
|
||||
"\n\n" .
|
||||
gettext("WARNING: ALL DATA ON THE NEW DISK WILL BE DESTROYED!") .
|
||||
"\n";
|
||||
|
||||
($rc, $choice) = $console->yesno_page(title => $title, text => $text, defaultno => 1);
|
||||
return unless ($rc == 0);
|
||||
|
||||
my @cmd = ("/sbin/e-smith/add_drive_to_raid", "-f", join("", keys %free_disks));
|
||||
my $cmd_out = qx( @cmd 2>&1 );
|
||||
untaint $cmd_out;
|
||||
|
||||
if ($? == 0) {
|
||||
$text = "\nSuccessfully added /dev/" . join("", keys %free_disks) . " to RAID!";
|
||||
} else {
|
||||
$text = gettext("The command failed:") . " @cmd" .
|
||||
"\n\n" . $cmd_out . "\n\n";
|
||||
}
|
||||
|
||||
($rc, $choice) = $console->message_page(title => $title, text => $text);
|
||||
goto SCAN;
|
||||
}
|
||||
|
||||
sub get_raid_status
|
||||
{
|
||||
die gettext("Couldn't open") . " /proc/mdstat:$!\n"
|
||||
unless (open(MDSTAT, "/proc/mdstat"));
|
||||
|
||||
my @mdstat;
|
||||
|
||||
while (<MDSTAT>)
|
||||
{
|
||||
push @mdstat, "$1\n" if (/(.*\w.*)/);
|
||||
}
|
||||
close MDSTAT;
|
||||
return @mdstat;
|
||||
}
|
||||
|
||||
sub get_raid_details
|
||||
{
|
||||
my @devices = ();
|
||||
|
||||
die gettext("Couldn't call") . " mdadm: $!\n"
|
||||
unless open(MDADM, "/sbin/mdadm --detail --scan|");
|
||||
|
||||
while (<MDADM>)
|
||||
{
|
||||
push @devices, $1 if ( m:ARRAY (/dev/md/\w+): )
|
||||
}
|
||||
close MDADM;
|
||||
|
||||
my %devices;
|
||||
|
||||
for my $dev (@devices)
|
||||
{
|
||||
die gettext("Couldn't call") . " mdadm --detail $dev: $!\n"
|
||||
unless open(MDADM, "/sbin/mdadm --detail $dev|");
|
||||
|
||||
while ( <MDADM> )
|
||||
{
|
||||
if ( /\s*(.*)\s+:\s+(\d+)\s+\(.*\)\s*/ )
|
||||
{
|
||||
my ($key, $value) = ($1, $2);
|
||||
$key =~ s/\s//g;
|
||||
|
||||
# Allow for different mdadm output formats for DeviceSize
|
||||
$key =~ s/UsedDevSize/DeviceSize/;
|
||||
|
||||
$devices{$dev}{$key} = $value;
|
||||
}
|
||||
elsif ( /\s*(.*)\s+:\s+(.*)\s*/ )
|
||||
{
|
||||
my ($key, $value) = ($1, $2);
|
||||
$key =~ s/\s//g;
|
||||
$devices{$dev}{$key} = $value;
|
||||
}
|
||||
|
||||
if ( m:\s+(\d+)\s+(\d+)\s+(\d+).*/dev/([\w\/]+): )
|
||||
{
|
||||
$devices{$dev}{$1} = $_;
|
||||
my $used_disk = $4;
|
||||
if (/(rd|ida|cciss|i2o)\//) {
|
||||
$used_disk =~ s/p\d+$//;
|
||||
} else {
|
||||
$used_disk =~ s/\d+//;
|
||||
}
|
||||
push (@{$devices{$dev}{UsedDisks}}, $used_disk);
|
||||
}
|
||||
}
|
||||
close MDADM;
|
||||
}
|
||||
|
||||
return %devices;
|
||||
}
|
||||
|
||||
sub get_partitions
|
||||
{
|
||||
die gettext("Couldn't read") . " /proc/partitions: $!\n"
|
||||
unless open (PARTITIONS, "/proc/partitions");
|
||||
|
||||
my %parts;
|
||||
|
||||
while (<PARTITIONS>)
|
||||
{
|
||||
if ( /\s+(\d+)\s+(\d+)\s+(\d+)\s+([\w\/]+)\s+/ )
|
||||
{
|
||||
my $name = $4;
|
||||
|
||||
$parts{$name}{major} = $1;
|
||||
$parts{$name}{minor} = $2;
|
||||
$parts{$name}{blocks} = $3;
|
||||
}
|
||||
}
|
||||
close PARTITIONS;
|
||||
|
||||
return %parts;
|
||||
}
|
||||
|
||||
sub get_disks
|
||||
{
|
||||
my %parts = get_partitions();
|
||||
|
||||
my @disks;
|
||||
|
||||
for (keys %parts)
|
||||
{
|
||||
push @disks, $_ unless (/[0-9]$/);
|
||||
push @disks, $_ if (/(rd|ida|cciss|i2o)\// && ! /p\d+$/);
|
||||
}
|
||||
|
||||
return @disks;
|
||||
}
|
||||
|
||||
return new esmith::console::manageDiskRedundancy;
|
80
root/sbin/e-smith/console-menu-items/reboot.pl
Executable file
80
root/sbin/e-smith/console-menu-items/reboot.pl
Executable file
@@ -0,0 +1,80 @@
|
||||
package esmith::console::reboot;
|
||||
use strict;
|
||||
use warnings;
|
||||
use esmith::console;
|
||||
use Locale::gettext;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $self = {
|
||||
name => gettext("Reboot, reconfigure or shut down this server"),
|
||||
order => 40,
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub name
|
||||
{
|
||||
return $_[0]->{name};
|
||||
}
|
||||
|
||||
sub order
|
||||
{
|
||||
return $_[0]->{order};
|
||||
}
|
||||
|
||||
sub doit
|
||||
{
|
||||
#------------------------------------------------------------
|
||||
# REBOOT_SHUTDOWN:
|
||||
#------------------------------------------------------------
|
||||
my ($self, $console, $db) = @_;
|
||||
my @args =
|
||||
(
|
||||
gettext("Reboot"), gettext("Reboot this server"),
|
||||
gettext("Reconfigure"), gettext("Reconfigure this server"),
|
||||
gettext("Shutdown"), gettext("Shutdown this server"),
|
||||
);
|
||||
|
||||
my ($rc, $choice) = $console->menu_page
|
||||
(
|
||||
title => gettext("Reboot, reconfigure or shutdown this server"),
|
||||
text =>
|
||||
gettext("Please select whether you wish to reboot, reconfigure or shutdown. The process will start as soon as you make your selection.") .
|
||||
"\n\n" .
|
||||
gettext("If you have an older computer without power management, the shutdown process will perform a clean halt of all system services, but will not actually power off your computer. In this case, wait for the power down message and then shut off the power manually.") .
|
||||
"\n\n" .
|
||||
gettext("If you have changed your mind and do not want to reboot or shutdown, use the Tab key to select Cancel, then press Enter."),
|
||||
argsref => \@args,
|
||||
left => gettext("Cancel"),
|
||||
right => gettext("OK"),
|
||||
);
|
||||
|
||||
return unless ($rc == 0);
|
||||
|
||||
if ($choice eq gettext('Shutdown'))
|
||||
{
|
||||
system("/usr/bin/tput", "clear");
|
||||
system("/sbin/e-smith/signal-event", "halt");
|
||||
}
|
||||
elsif ($choice eq gettext('Reboot'))
|
||||
{
|
||||
system("/usr/bin/tput", "clear");
|
||||
system("/sbin/e-smith/signal-event", "reboot");
|
||||
}
|
||||
elsif ($choice eq gettext('Reconfigure'))
|
||||
{
|
||||
system("/usr/bin/tput", "clear");
|
||||
system("/sbin/e-smith/signal-event", "post-upgrade");
|
||||
system("/sbin/e-smith/signal-event", "reboot");
|
||||
}
|
||||
|
||||
# A bit of a hack to avoid the console restarting before the
|
||||
# reboot takes effect.
|
||||
|
||||
sleep(600);
|
||||
}
|
||||
|
||||
return new esmith::console::reboot;
|
60
root/sbin/e-smith/console-menu-items/serverManager.pl
Executable file
60
root/sbin/e-smith/console-menu-items/serverManager.pl
Executable file
@@ -0,0 +1,60 @@
|
||||
package esmith::console::serverManager;
|
||||
use strict;
|
||||
use warnings;
|
||||
use esmith::console;
|
||||
use Locale::gettext;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $self = {
|
||||
name => gettext("Access server manager"),
|
||||
order => 50,
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub name
|
||||
{
|
||||
return $_[0]->{name};
|
||||
}
|
||||
|
||||
sub order
|
||||
{
|
||||
return $_[0]->{order};
|
||||
}
|
||||
|
||||
sub doit
|
||||
{
|
||||
my ($self, $console, $db) = @_;
|
||||
#------------------------------------------------------------
|
||||
# MANAGER:
|
||||
#------------------------------------------------------------
|
||||
my $SystemName = $db->get_value('SystemName');
|
||||
my ($rc, $choice) = $console->yesno_page
|
||||
(
|
||||
title => gettext("Access server manager"),
|
||||
text =>
|
||||
gettext("This option will start a text-mode browser to access the server manager from this console. Normally you would access the server manager from a web browser at the following url:") .
|
||||
"\n\n" .
|
||||
"http://${SystemName}/server-manager/" .
|
||||
"\n\n" .
|
||||
gettext("You should only proceed if you are comfortable using a text-mode browser. Note that you will be prompted for the administrator password in order to access the server manager.") .
|
||||
"\n\n" .
|
||||
gettext("NOTE: The 'q' key is used to quit from the text-mode browser.") .
|
||||
"\n\n" .
|
||||
gettext("Do you wish to proceed?"),
|
||||
);
|
||||
|
||||
if ($rc == 0)
|
||||
{
|
||||
system(
|
||||
"/usr/bin/links",
|
||||
"http://localhost/server-manager"
|
||||
);
|
||||
}
|
||||
$db->reload;
|
||||
}
|
||||
|
||||
return new esmith::console::serverManager;
|
70
root/sbin/e-smith/console-menu-items/status.pl
Executable file
70
root/sbin/e-smith/console-menu-items/status.pl
Executable file
@@ -0,0 +1,70 @@
|
||||
package esmith::console::status;
|
||||
use strict;
|
||||
use warnings;
|
||||
use esmith::console;
|
||||
use Locale::gettext;
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my $self = {
|
||||
name => gettext("Check status of this server"),
|
||||
order => 10,
|
||||
};
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub name
|
||||
{
|
||||
return $_[0]->{name};
|
||||
}
|
||||
|
||||
sub order
|
||||
{
|
||||
return $_[0]->{order};
|
||||
}
|
||||
|
||||
sub doit
|
||||
{
|
||||
#------------------------------------------------------------
|
||||
# STATUS:
|
||||
#------------------------------------------------------------
|
||||
my ($self, $console, $db) = @_;
|
||||
use POSIX qw(strftime);
|
||||
my $today = strftime "%A %B %e, %Y", localtime;
|
||||
|
||||
unless (open(UPTIME, "</proc/uptime"))
|
||||
{
|
||||
warn("Could not open /proc/uptime: $!");
|
||||
return;
|
||||
}
|
||||
my $seconds = <UPTIME>;
|
||||
close UPTIME or warn("Could not close /proc/uptime: $!");
|
||||
|
||||
# Select and untaint seconds
|
||||
$seconds =~ /(\d+)/;
|
||||
$seconds = $1;
|
||||
|
||||
my $days = int ($seconds / 86400);
|
||||
$seconds = $seconds % 86400;
|
||||
|
||||
my $hours = int ($seconds / 3600);
|
||||
$seconds = $seconds % 3600;
|
||||
|
||||
my $minutes = int ($seconds / 60);
|
||||
$seconds = $seconds % 60;
|
||||
|
||||
my ($rc, $choice) = $console->screen
|
||||
(
|
||||
"--title", gettext("Status of this server as of") . " " . $today,
|
||||
|
||||
"--msgbox", gettext("This server has been running for") . " " .
|
||||
$days . " " . gettext("days") . ", " .
|
||||
$hours . " " . gettext("hours") . ", " .
|
||||
$minutes . " " . gettext("minutes"),
|
||||
7, esmith::console::SCREEN_COLUMNS
|
||||
);
|
||||
}
|
||||
|
||||
return new esmith::console::status;
|
Reference in New Issue
Block a user