mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-08-21 10:40:24 +00:00
enhance clusterstatus to report cluster status (#3900)
* enhance clusterstatus to report cluster status * modify usage for clusterstatus
This commit is contained in:
@@ -14,25 +14,70 @@ use warnings;
|
||||
|
||||
my $program_name = basename("$0");
|
||||
my $help;
|
||||
my $noderange = "compute";
|
||||
my $noderange = undef;
|
||||
my $test;
|
||||
my $output = "stdout";
|
||||
my $verbose = 0;
|
||||
my $rst = 0;
|
||||
my $interval = 5;
|
||||
my $terminal = 0;
|
||||
my $timeout = 0;
|
||||
my $start_time;
|
||||
|
||||
#-----------------------------
|
||||
# To store the node number of a specified type
|
||||
# May like this:
|
||||
# $type_nodesnum{pdu} = 2;
|
||||
# {switch} = 3;
|
||||
# {node} = 10;
|
||||
#-----------------------------
|
||||
my %type_nodesnum = ();
|
||||
|
||||
#-----------------------------
|
||||
# To store the type, state hash
|
||||
# May like this:
|
||||
# $state_node_hash{pdu}{state1}{pdu1} = 1;
|
||||
# $state_node_hash{pdu}{state1}{pdu2} = 1;
|
||||
# $state_node_hash{pdu}{state2}{pdu3} = 1;
|
||||
# $state_node_hash{pdu}{state3}{pdu4} = 1;
|
||||
# The state include but not limited to below:
|
||||
# matching --> matched --> configured (For PDU/Switch)
|
||||
# matching --> matched --> installing --> booting --> booted
|
||||
# matching --> matched --> booting --> installing --> xxx --> booted
|
||||
# The terminal state is configured(For PDU/Switch) or booted(for Node)
|
||||
#-----------------------------
|
||||
my %state_node_hash = ();
|
||||
|
||||
# $state_node_hash{pdu}{state1}{number} = xx;
|
||||
my %state_node_number = ();
|
||||
|
||||
#----------------------------
|
||||
# To store the node based current state
|
||||
# May like this:
|
||||
# $node_info{node1}{state} = "install";
|
||||
# $node_info{node1}{type} = "node";
|
||||
#----------------------------
|
||||
my %node_info = ();
|
||||
|
||||
#---------------------------
|
||||
# To store nodes who haven't finished the status
|
||||
#---------------------------
|
||||
my %unfinished_nodes = ();
|
||||
my %unmatched_nodes = ();
|
||||
|
||||
$::USAGE = "Usage:
|
||||
$program_name -h
|
||||
$program_name {-d|-g} [-n noderange] [-V|--verbose]
|
||||
$program_name [-n noderange] [-V|--verbose] [-i|--interval <seconds>] [--timeout <seconds>]
|
||||
|
||||
Description:
|
||||
Use this command to get a summary of the cluster.
|
||||
|
||||
Options:
|
||||
-h : Get usage information of $program_name
|
||||
-n : Range of nodes to check. Default is \"compute\".
|
||||
-d : Discovery. Display count of discovered nodes.
|
||||
-g : Group count. Display count of nodes in each group.
|
||||
-n : Range of nodes to check. All node objects will be used if not specified.
|
||||
-i : The interval for screen refreshing, unit is second(s), 5 seconds by default.
|
||||
-V : To print additional debug information.
|
||||
--timeout: The timout if not all nodes finish, unit is second(s), no timeout by default.
|
||||
";
|
||||
|
||||
#-------------------------------------
|
||||
@@ -44,6 +89,8 @@ if (
|
||||
"V|verbose" => \$VERBOSE,
|
||||
"d|discovery" => \$DISCOVERY,
|
||||
"g|groupcount" => \$GROUPCOUNT,
|
||||
"i|interval=s" => \$interval,
|
||||
"timeout=s" => \$timeout,
|
||||
"n=s" => \$noderange))
|
||||
{
|
||||
probe_utils->send_msg("$output", "f", "Invalid parameter for $program_name");
|
||||
@@ -65,12 +112,6 @@ if ($test) {
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ((!$DISCOVERY) and (!$GROUPCOUNT)) {
|
||||
probe_utils->send_msg("$output", "f", "Discovery or groupcount option is required for $program_name");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if (scalar(@ARGV) >= 1) {
|
||||
|
||||
# After processing all the expected flags and arguments,
|
||||
@@ -79,10 +120,42 @@ if (scalar(@ARGV) >= 1) {
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
if (!$DISCOVERY and !$GROUPCOUNT) {
|
||||
if(!defined($noderange)) {
|
||||
$noderange = "all";
|
||||
}
|
||||
} else {
|
||||
if (!defined($noderange)) {
|
||||
$noderange = "compute";
|
||||
}
|
||||
check_for_discovered_nodes() if ($DISCOVERY);
|
||||
groupcount_nodes() if ($GROUPCOUNT);
|
||||
exit 0;
|
||||
}
|
||||
|
||||
check_for_discovered_nodes() if ($DISCOVERY);
|
||||
groupcount_nodes() if ($GROUPCOUNT);
|
||||
$SIG{TERM} = $SIG{INT} = sub {
|
||||
$terminal = 1;
|
||||
};
|
||||
unless ($interval) {
|
||||
$interval = 5;
|
||||
}
|
||||
|
||||
&check_nodes_attributes();
|
||||
$start_time = time;
|
||||
while (1) {
|
||||
update_nodes_info();
|
||||
alarm_output(1);
|
||||
if ($terminal) {
|
||||
alarm_output(0);
|
||||
last;
|
||||
}
|
||||
if ($timeout and (time() - $start_time > $timeout)) {
|
||||
alarm_output(0);
|
||||
last;
|
||||
}
|
||||
sleep $interval;
|
||||
}
|
||||
exit 0;
|
||||
# Check for node definitions with MAC address defined
|
||||
sub check_for_discovered_nodes {
|
||||
my $na = "N/A";
|
||||
@@ -132,3 +205,128 @@ sub groupcount_nodes {
|
||||
probe_utils->send_msg("$output", "w", "Group count function is not yet implemented.");
|
||||
return $rc;
|
||||
}
|
||||
|
||||
sub alarm_output {
|
||||
my $flag = shift;
|
||||
if ($flag) {
|
||||
probe_utils->send_msg("$output", "xx", `clear`);
|
||||
my $time_elapsed = time - $start_time;
|
||||
probe_utils->send_msg("$output", "xx", "====".localtime()."($time_elapsed seconds Elapsed)");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "xx", "\nThe cluster state===============================");
|
||||
}
|
||||
foreach my $type (keys(%state_node_hash)) {
|
||||
unless ($type_nodesnum{$type}) {
|
||||
probe_utils->send_msg("$output", "w", "$type Total number: $type_nodesnum{$type}");
|
||||
next;
|
||||
}
|
||||
probe_utils->send_msg("$output", "xx", "$type(Total: $type_nodesnum{$type})--------------------------");
|
||||
foreach my $state (keys(%{$state_node_hash{$type}})) {
|
||||
my $node_number = scalar(keys %{$state_node_hash{$type}{$state}});
|
||||
if ($flag) {
|
||||
my $number = sprintf("%.2f", $node_number * 100.0/ $type_nodesnum{$type});
|
||||
probe_utils->send_msg("$output", "xx", "\t$state : $node_number($number%)");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "xx", "\t$state($node_number): ". join(",",keys %{$state_node_hash{$type}{$state}}) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub update_nodes_info {
|
||||
if (keys(%unmatched_nodes)) {
|
||||
my $unmatched_noderange = join(",", keys(%unmatched_nodes));
|
||||
my @unmatched_nodes_attributes = `lsdef -i mac -c $unmatched_noderange 2> /dev/null`;
|
||||
foreach (@unmatched_nodes_attributes) {
|
||||
if (/^(.*):\s*mac=(.*)$/) {
|
||||
if ($2) {
|
||||
update_node_info($1, "Matched");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keys(%unfinished_nodes)) {
|
||||
my $unfinished_noderange = join(",", keys(%unfinished_nodes));
|
||||
my @unfinished_nodes_attributes = `lsdef -i status -c $unfinished_noderange 2> /dev/null`;
|
||||
foreach (@unfinished_nodes_attributes) {
|
||||
if (/^(.*):\s*status=(.*)$/) {
|
||||
if ($2) {
|
||||
update_node_info($1, "$2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unless(scalar keys(%unfinished_nodes)) {
|
||||
$terminal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub update_node_info {
|
||||
my $node = shift;
|
||||
my $state = shift;
|
||||
my $node_type = $node_info{$node}{type};
|
||||
my $node_state = $node_info{$node}{state};
|
||||
if ($state and $state ne '') {
|
||||
if (exists($unmatched_nodes{$node})) {
|
||||
delete($unmatched_nodes{$node});
|
||||
$unfinished_nodes{$node} = 1;
|
||||
}
|
||||
}
|
||||
if ($state eq $node_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (exists($state_node_hash{$node_type}{$node_state}{$node})) {
|
||||
delete($state_node_hash{$node_type}{$node_state}{$node});
|
||||
}
|
||||
unless (scalar keys ($state_node_hash{$node_type}{$node_state})) {
|
||||
delete($state_node_hash{$node_type}{$node_state});
|
||||
}
|
||||
|
||||
$state_node_hash{$node_type}{$state}{$node} = 1;
|
||||
|
||||
$node_info{$node}{state} = $state;
|
||||
if ($state eq 'booted' or $state eq 'configured') {
|
||||
delete $unfinished_nodes{$node};
|
||||
}
|
||||
}
|
||||
sub check_nodes_attributes {
|
||||
my @nodes_attributes = `lsdef -i status,mac,mgt -c $noderange 2> /dev/null`;
|
||||
my %nodehash = ();
|
||||
foreach (@nodes_attributes) {
|
||||
if (/^(.*):\s*([^=]*)=(.*)$/) {
|
||||
$nodehash{$1}{$2}=$3;
|
||||
}
|
||||
}
|
||||
foreach (keys %nodehash) {
|
||||
if (!defined($nodehash{$_}{mgt})) {
|
||||
probe_utils->send_msg("$output", "w", "No 'mgt' set for node:$_");
|
||||
next;
|
||||
}
|
||||
if ($nodehash{$_}{status}) {
|
||||
$node_info{$_}{state} = $nodehash{$_}{status};
|
||||
$unfinished_nodes{$_} = 1;
|
||||
} elsif ($nodehash{$_}{mac}) {
|
||||
$node_info{$_}{state} = "Matched";
|
||||
$unfinished_nodes{$_} = 1;
|
||||
} else {
|
||||
$node_info{$_}{state} = "matching";
|
||||
$unmatched_nodes{$_} = 1;
|
||||
}
|
||||
if ($nodehash{$_}{mgt} eq 'pdu') {
|
||||
$node_info{$_}{type} = 'pdu';
|
||||
} elsif($nodehash{$_}{mgt} eq 'switch') {
|
||||
$node_info{$_}{type} = 'switch';
|
||||
} else {
|
||||
$node_info{$_}{type} = 'node';
|
||||
}
|
||||
my $node_type = $node_info{$_}{type};
|
||||
if (!exists($type_nodesnum{$node_type})) {
|
||||
$type_nodesnum{$node_type} = 1;
|
||||
} else {
|
||||
$type_nodesnum{$node_type} += 1;
|
||||
}
|
||||
$state_node_hash{$node_type}{$node_info{$_}{state}}{$_} = 1;
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
|
Reference in New Issue
Block a user