#!/usr/bin/env perl
#
# Description: Linux Cluster status verification
# Results are displayed on stdout or redirected to a file
#
# Last Update: 13 February 2016
# Designed by: Dusan U. Baljevic (dusan.baljevic@ieee.org)
# Coded by: Dusan U. Baljevic (dusan.baljevic@ieee.org)
#
# Copyright 2009-2016 Dusan Baljevic
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# There are not many comments throught the script and that
# is not best practices for writing good code. However,
# I view this script as a learning tool for system administrators
# too so lack of comments is partially left as an exercise.
#
# Like all scripts and programs, this one will continue to
# change as our needs change.
# Define important environment variables
#
$ENV{'PATH'} = "/bin:/usr/sbin:/sbin:/usr/bin:/usr/local/bin";
$ENV{'PATH'} = "$ENV{PATH}:/usr/local/qs/bin:/opt/qs/bin:/etc/init.d";
# Define Shell
#
$ENV{'SHELL'} = '/bin/sh' if $ENV{'SHELL'} ne '';
$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
use strict;
#use diagnostics;
#use warnings;
# Global variables
#
my $RACLCFG = '/etc/cluster/cluster.conf';
my $PVGconf = "/etc/lvm/lvm.conf";
my $INFOSTR = "INFO:";
my $WARNSTR = "WARN:";
my $PASSSTR = "PASS:";
my $ERRSTR = "FAIL:";
my @MYVGS = ();
my @CMANA = ();
my @MYCLUST = ();
my @LVarr = ();
my @cmanarr = ();
my @pvlist = ();
my @lvlist = ();
my @mkqdisk = ();
my @qdsk = ();
my $pvdisk = q{};
my $maxpv = q{};
my $curpv = q{};
my %VGfpe = ();
my %VGpes = ();
my %MAXPV = ();
my $pesize = q{};
my $vgname = q{};
my $lvdisk = q{};
my $NODECNT = q{};
my $TOTVOTES = q{};
my @DNAMEARR = ();
my @LVMCFGARR = ();
my $THRESHOLD_MAX_PV = q{};
my $LOCKTYPE = q{};
my $LOCKLIB = q{};
my $WAITLOCK = q{};
my $LOCKDIR = q{};
my $THRESHOLD = q{};
my @cmannode = ();
my $vgformat = q{};
my @VGCHKARR = ();
my $Hostname2 = `hostname -s 2>/dev/null`;
chomp($Hostname2);
my $Hostname3 = q{};
my $VH = `uname -a 2>&1`;
my ( $System, $Hostname3, $Maj, undef, $Hardware, undef ) = split( /\s+/, $VH );
my $Version = $Maj;
my $Hostname = $Hostname2 || $Hostname3;
# Delay and count values for commands vmstat, ioscan, and sar...
#
my $ITERATIONS = 10;
my $DELAY = 2;
# LVM Locking types
#
my %LVMLOCKARR = ( "0", "locking disabled (risk of corrupting metadata)",
"1", "locking mechanims is flock",
"2", "locking through provided through external locking_library",
"3", "Global File System (GFS) cluster-wide locking",
"4", "locking enforces read-only metadata",
);
sub print_header {
my $lline = shift;
print "$lline\n";
print "\n";
}
# Create syslog entry about Cluster checks
#
`clulog -s 5 "Brief Linux Cluster verification tests underway"`;
print_header("*** LOGICAL VOLUME MANAGER STATUS ***");
my @lsblk = `lsblk -f 2>/dev/null`;
if ( "@lsblk" ) {
print "$INFOSTR File systems and raids\n";
print @lsblk;
}
my @lsblkdet = `lsblk -t 2>/dev/null`;
if ( "@lsblkdet" ) {
print "\n$INFOSTR: Block devices\n";
print @lsblkdet;
}
my @lvscanv = `lvscan --version 2>/dev/null`;
if ( @lvscanv != 0 ) {
print "\n$INFOSTR LVM summary\n";
print @lvscanv;
}
my @VGCK = `vgck 2>/dev/null`;
if ( @VGCK != 0 ) {
print "\n$WARNSTR LVM volume group metadata check\n";
}
else {
print "\n$PASSSTR LVM volume group metadata check successful\n";
}
my @LVMDUMP = `lvm dumpconfig 2>/dev/null`;
if ( @LVMDUMP != 0 ) {
print "\n$INFOSTR LVM dumpconfig\n";
print @LVMDUMP;
}
my @VGS = `vgs 2>/dev/null`;
if ( @VGS != 0 ) {
print "\n$INFOSTR LVM volume group status\n";
print @VGS;
}
my @PVSCAN = `pvscan 2>/dev/null`;
if ( @PVSCAN != 0 ) {
print "\n$INFOSTR LVM physical volume status\n";
print @PVSCAN;
}
my @LVSCANALL = `lvs -o+seg_all 2>/dev/null | cat -s -`;
if ( @LVSCANALL != 0 ) {
print "\n$INFOSTR LVM logical volume status\n";
print @LVSCANALL;
}
else {
my @LVSCANALL = `lvs 2>/dev/null | cat -s -`;
print "\n$INFOSTR LVM logical volume status\n";
print @LVSCANALL;
}
my @LVMDSCAN = `lvmdiskscan 2>/dev/null | cat -s -`;
if ( @LVMDSCAN != 0 ) {
print "\n$INFOSTR LVM disk scan\n";
print @LVMDSCAN;
}
if ( open( NN, "vgdisplay -vv --partial 2>/dev/null |" ) ) {
print "\n$INFOSTR Volume group scan\n";
while () {
print $_;
chomp;
if ( grep( /VG Name/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, $vgname ) = split( /\s+/, $_ );
chomp($vgname);
if ( ! grep(/\Q$vgname\E/, @MYVGS ) ) {
push(@MYVGS, $vgname);
}
undef $VGfpe{$vgname};
undef $VGpes{$vgname};
}
if ( grep( /Format/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, $vgformat ) = split( /\s+/, $_ );
chomp($vgformat);
}
if ( grep( /Max PV/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, $maxpv ) = split( /\s+/, $_ );
chomp($maxpv);
$MAXPV{$vgname} = $maxpv;
if ( $vgformat eq "lvm2" ) {
if ( $maxpv == 0 ) {
push( @VGCHKARR, "$PASSSTR Max PV not limited for lvm2 volume group $vgname\n");
}
}
else {
if ( $maxpv < $THRESHOLD_MAX_PV ) {
push( @VGCHKARR, "$WARNSTR Max PV ($maxpv) below the threshold ($THRESHOLD_MAX_PV) for volume group $vgname\n");
}
else {
push( @VGCHKARR, "$PASSSTR Max PV ($maxpv) satisfies the threshold (minimum $THRESHOLD_MAX_PV) for volume group $vgname\n");
}
}
}
if ( grep( /Cur PV/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, $curpv ) = split( /\s+/, $_ );
chomp($curpv);
if ( $vgformat ne "lvm2" ) {
my $pvthresh = int( $curpv / $maxpv ) * 100;
if ( $curpv == $maxpv ) {
push( @VGCHKARR, "$ERRSTR Current PV ($curpv) reached Max PV threshold in volume group $vgname\n");
}
elsif ( $pvthresh == $THRESHOLD ) {
push( @VGCHKARR, "$WARNSTR Current PV ($curpv) reached 90% of Max PV ($maxpv) in volume group $vgname\n");
}
elsif ( $pvthresh > $THRESHOLD ) {
push( @VGCHKARR, "$WARNSTR Current PV ($curpv) exceeds 90% of Max PV ($maxpv) in volume group $vgname\n");
}
else {
push( @VGCHKARR, "$PASSSTR Current PV ($curpv) below 90% of Max PV ($maxpv) in volume group $vgname\n");
}
}
}
if ( grep( /VG Status/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, my $vgstat ) = split( /\s+/, $_ );
chomp($vgstat);
if ( $vgstat eq "resizable" ) {
push( @VGCHKARR, "$PASSSTR Volume group $vgname is resizable\n");
}
else {
push( @VGCHKARR, "$WARNSTR Volume group is not resizable\n");
}
}
if ( grep( /^Free PE|Free PE/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, my $freepe2 ) = split( /\//, $_ );
$freepe2 =~ s/^\s+//g;
$freepe2 =~ s/\s+$//g;
( undef, my $freepe ) = split( /\s+/, $_ );
chomp($freepe);
if ( $freepe == 0 ) {
push( @VGCHKARR, "$ERRSTR No free PEs available in volume group $vgname\n");
}
else {
push( @VGCHKARR, "$PASSSTR $freepe free PEs available in volume group $vgname\n");
}
$VGfpe{$vgname} = $freepe;
}
if ( grep( /^PE Size/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, $pesize, undef ) = split( /\s+/, $_ );
chomp($pesize);
$VGpes{$vgname} = $pesize;
}
if ( grep( /PV Name/, $_ ) ) {
$_ =~ s/^\s+//g;
( undef, undef, $pvdisk ) = split( /\s+/, $_ );
if ( !grep( /\Q$pvdisk\E/, @pvlist ) ) {
push( @pvlist, $pvdisk );
}
}
if ( grep( /LV Name/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
( undef, undef, $lvdisk ) = split( /\s+/, $_ );
push( @lvlist, $lvdisk );
}
if ( grep( /LV Status/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
}
if ( grep( /LV Size/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
}
if ( grep( /Current LE/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
}
if ( grep( /Allocated PE/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
}
if ( grep( /Used PV/, $_ ) ) {
$_ =~ s/^\s+//g;
push( @LVarr, "$_\n" );
}
}
close(NN);
if ( @VGCHKARR ) {
print @VGCHKARR;
}
foreach my $vgnn ( @MYVGS ) {
my @vgcfgr = `vgcfgrestore -l $vgnn 2>/dev/null | cat -s -`;
if ( "@vgcfgr" ) {
print "\n$INFOSTR vgcfgrestore status for volume group $vgnn\n";
print @vgcfgr;
}
else {
print "\n$WARNSTR Unknown vgcfgrestore status for volume group $vgnn\n";
}
}
}
else {
print "$WARNSTR Cannot run vgdisplay\n";
}
print_header("*** GLOBAL FILE SYSTEM (GFS) STATUS ***");
my @gfstool = `gfs_tool list 2>/dev/null`;
my @gfstool2 = `gfs2_tool list 2>/dev/null`;
my @gfssvc = `service gfs status 2>/dev/null`;
my @gfssvc2 = `service gfs2 status 2>/dev/null`;
my @mline = ();
my $fsreal = q{};
my $fsdev = q{};
my $fstype = q{};
my @GFSARR = ();
my @GFS2ARR = ();
my @GFSDEVARR = ();
my @GFS2DEVARR = ();
if ( open( MM, "mount | sort |" ) ) {
while () {
next if ( grep( /^$/, $_ ) );
chomp($_);
@mline = split(/\s+/, $_);
$fsreal = $mline[2];
$fsdev = $mline[0];
$fstype = $mline[4];
if ( $fstype eq "gfs" ) {
push( @GFSARR, $fsreal );
push( @GFSDEVARR, $fsdev );
}
else {
if ( $fstype eq "gfs2" ) {
push( @GFS2ARR, $fsreal );
push( @GFS2DEVARR, $fsdev );
}
}
}
close(MM);
}
if (@gfstool) {
print "$INFOSTR GFS file system listing\n";
print @gfstool;
my @gfstooldf = `gfs_tool df 2>/dev/null`;
if (@gfstooldf) {
print "\n$INFOSTR GFS file system status\n";
print @gfstooldf;
}
foreach my $gfsfs ( @GFSARR ) {
my @gfstoolext = `gfs_tool gettune $gfsfs 2>/dev/null`;
if (@gfstoolext) {
print "\n$INFOSTR GFS file system $gfsfs tunables\n";
print @gfstoolext;
}
my @gfstoolcnt = `gfs_tool counters $gfsfs 2>/dev/null`;
if (@gfstoolcnt) {
print "\n$INFOSTR GFS file system $gfsfs counters\n";
print @gfstoolcnt;
}
}
foreach my $gfsdev ( @GFSDEVARR ) {
my @gfsdevchk = `gfs2_edit -p sb inum statfs master $gfsdev 2>/dev/null`;
if (@gfsdevchk) {
print "\n$INFOSTR GFS device $gfsdev selected internal structures\n";
print @gfsdevchk;
}
}
if (@gfssvc) {
print "\n$INFOSTR GFS service status\n";
print @gfssvc;
}
}
else {
print "$INFOSTR GFS not installed or unused on local node\n";
}
if (@gfstool2) {
print "$INFOSTR GFS2 file system listing\n";
print @gfstool2;
my @gfstooldf2 = `gfs2_tool df 2>/dev/null`;
if (@gfstooldf2) {
print "\n$INFOSTR GFS2 file system status\n";
print @gfstooldf2;
}
foreach my $gfs2fs ( @GFS2ARR ) {
my @gfstool2ext = `gfs2_tool gettune $gfs2fs 2>/dev/null`;
if (@gfstool2ext) {
print "\n$INFOSTR GFS2 file system $gfs2fs tunables\n";
print @gfstool2ext;
}
}
foreach my $gfs2dev ( @GFS2DEVARR ) {
my @gfs2devchk = `gfs2_edit -p sb inum statfs master $gfs2dev 2>/dev/null`;
if (@gfs2devchk) {
print "\n$INFOSTR GFS2 device $gfs2dev selected internal structures\n";
print @gfs2devchk;
}
}
if (@gfssvc2) {
print "\n$INFOSTR GFS2 service status\n";
print @gfssvc2;
}
}
else {
print "$INFOSTR GFS2 not installed or unused on local node\n";
}
print "\n";
print_header("*** SYSTEM PERFORMANCE STATUS ON CURRENT NODE ***");
my @USED = `free -t`;
print @USED;
my @pcpu = `ps -e -o pcpu,cpu,nice,state,cputime,args --sort -pcpu 2>/dev/null`;
if ( "@pcpu" ) {
print "\n$INFOSTR List processes by CPU activity\n";
print @pcpu;
}
my @cpupoweri = `cpupower idle-info 2>/dev/null`;
if ( "@cpupoweri" ) {
print "\n$INFOSTR CPU idle kernel information\n";
print @cpupoweri;
}
my @pmem = `ps -e -o rss,args --sort -rss | pr -TW\$COLUMNS 2>/dev/null`;
if ( "@pmem" ) {
print "\n$INFOSTR List processes by memory usage\n";
print @pmem;
}
else {
@pmem = `ps aux --sort pmem 2>/dev/null`;
if ( "@pmem" ) {
print "\n$INFOSTR List processes by memory usage\n";
print @pmem;
}
}
my @TOP = `top -n 1 2>/dev/null`;
if ( "@TOP" ) {
print "\n$INFOSTR Top activity\n";
print @TOP;
}
my @VMSTATS = `vmstat -s 2>/dev/null`;
if ( "@VMSTATS" ) {
print "\n$INFOSTR Virtual memory counters\n";
print @VMSTATS;
}
my @AASTAT = `aa-status 2>/dev/null`;
if ( "@AASTAT" ) {
print "\n$INFOSTR Programs confined to limited set of resources in AppArmor\n";
print @AASTAT;
}
my @VMSTAT = `vmstat $DELAY $ITERATIONS 2>/dev/null`;
if ( "@VMSTAT" ) {
print "\n$INFOSTR Virtual memory statistics\n";
print @VMSTAT;
}
my @SARD = `sar -d $DELAY $ITERATIONS 2>/dev/null`;
if ( "@SARD" ) {
print "\n$INFOSTR SA Disk activity\n";
print @SARD;
}
my @IOSTATD = `iostat -dxNhtz $DELAY $ITERATIONS 2>/dev/null`;
if ( "@IOSTATD" ) {
print @IOSTATD;
}
my @MPSTAT = `mpstat -P ALL $DELAY $ITERATIONS 2>/dev/null`;
if ( "@MPSTAT" ) {
print @MPSTAT;
print "\n";
}
print_header("*** LINUX CLUSTER STATUS ***");
if ( -s $PVGconf ) {
if ( open( PVGC, "awk NF $PVGconf 2>/dev/null |" ) ) {
print "$INFOSTR LVM configuration file $PVGconf\n";
while () {
next if ( grep( /#/, $_ ) );
print $_;
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
if ( grep(/locking_type/i, $_ ) ) {
( undef, $LOCKTYPE ) = split( /=/, $_ );
$LOCKTYPE =~ s/^\s+//g;
$LOCKTYPE =~ s/\s+$//g;
push(@LVMCFGARR, "\n$INFOSTR LVM \"locking_type\" is $LOCKTYPE ($LVMLOCKARR{$LOCKTYPE})\n");
}
if ( grep(/wait_for_locks/i, $_ ) ) {
( undef, $WAITLOCK ) = split( /=/, $_ );
$WAITLOCK =~ s/^\s+//g;
$WAITLOCK =~ s/\s+$//g;
if ( "$WAITLOCK" eq 1 ) {
push(@LVMCFGARR, "\n$INFOSTR LVM tools wait if a lock request cannot be satisifed immediately (\"wait_for_locks\" set to $WAITLOCK)\n");
}
else {
if ( "$WAITLOCK" eq 0 ) {
push(@LVMCFGARR, "\n$INFOSTR LVM tools abort operation if a lock request cannot be satisifed immediately (\"wait_for_locks\" set to $WAITLOCK)\n");
}
}
}
if ( grep(/locking_library/i, $_ ) ) {
( undef, $LOCKLIB ) = split( /=/, $_ );
$LOCKLIB =~ s/^\s+//g;
$LOCKLIB =~ s/\s+$//g;
$LOCKLIB =~ s/"//g;
if ( "$LOCKTYPE" eq 2 ) {
if ( "$LOCKLIB" ) {
push(@LVMCFGARR, "\n$INFOSTR LVM \"locking_library\" set to $LOCKTYPE\n");
}
}
}
if ( "$LOCKTYPE" eq 1 ) {
if ( grep(/locking_dir/i, $_ ) ) {
( undef, $LOCKDIR ) = split( /=/, $_ );
$LOCKDIR =~ s/^\s+//g;
$LOCKDIR =~ s/\s+$//g;
$LOCKDIR =~ s/"//g;
if ( -d "$LOCKDIR" ) {
push(@LVMCFGARR, "\n$INFOSTR LVM \"lock_dir\" $LOCKDIR exists\n");
}
else {
push(@LVMCFGARR, "\n$WARNSTR LVM \"lock_dir\" $LOCKDIR does not exist\n");
}
}
}
}
close(PVGC);
}
else {
print "\n$INFOSTR $PVGconf cannot be opened\n";
}
}
if ( @LVMCFGARR ) {
print @LVMCFGARR;
}
if ( -s $RACLCFG ) {
if ( open( FROM, "awk NF $RACLCFG 2>/dev/null |" ) ) {
print "\n$INFOSTR Cluster configuration file $RACLCFG\n";
while () {
next if ( grep( /#/, $_ ) );
print $_;
}
close(FROM);
}
else {
print "\n$INFOSTR $RACLCFG cannot be opened\n";
}
}
else {
print "\n$INFOSTR $RACLCFG does not exist or empty\n";
}
my @clustat = `clustat 2>/dev/null | awk NF`;
if ( @clustat ) {
print "\n$INFOSTR Linux Cluster status\n";
print @clustat;
}
my @clusval = `ccs_config_validate 2>/dev/null`;
if ( @clusval ) {
print "\n$INFOSTR Linux Cluster configuration validation\n";
print @clusval;
}
my @FENCECAP = `ccs -h localhost --lsfenceopts 2>/dev/null`;
if ( @FENCECAP ) {
print "\n$INFOSTR Linux Cluster fence device options on local node\n";
print @FENCECAP;
}
if ( open( CMANC, "cman_tool status 2>/dev/null |" ) ) {
while () {
next if ( grep( /#/, $_ ) );
push(@MYCLUST, $_);
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
if ( grep(/^Nodes:/i, $_ ) ) {
( undef, $NODECNT ) = split( /:/, $_ );
$NODECNT =~ s/^\s+//g;
$NODECNT =~ s/\s+$//g;
}
if ( grep(/^Total votes:/i, $_ ) ) {
( undef, $TOTVOTES ) = split( /:/, $_ );
$TOTVOTES =~ s/^\s+//g;
$TOTVOTES =~ s/\s+$//g;
}
}
close(CMANC);
}
my @CMANVER = `cman_tool version 2>/dev/null`;
if ( @CMANVER ) {
print "\n$INFOSTR Linux Cluster version\n";
print @CMANVER;
}
my @CMANSER = `cman_tool services 2>/dev/null`;
if ( @CMANSER ) {
print "\n$INFOSTR Linux Cluster services\n";
print @CMANSER;
}
if ( "@MYCLUST" ) {
print "\n$INFOSTR Linux Cluster vote status\n";
print @MYCLUST;
}
my @CHKCONF = `ccs -h localhost --checkconf 2>/dev/null`;
if ( @CHKCONF ) {
print "\n$INFOSTR Linux Cluster check configuration\n";
print @CHKCONF;
}
if ( "$NODECNT" eq 1 ) {
printf "\n$ERRSTR Linux Cluster has 1 node (there is no redundancy in services)\n";
}
if ( "$NODECNT" eq 2 ) {
printf "\n$WARNSTR Linux Cluster has %s node%s (recommended to set up Quorum Disk in addition to fencing)\n", $NODECNT, $NODECNT == 1 ? "" : "s";
}
if ( "$TOTVOTES" lt "$NODECNT" ) {
print "\n$WARNSTR Linux Cluster has less votes that number of nodes ($TOTVOTES and $NODECNT respectively)\n";
print "$INFOSTR Best practice recommends at least one vote for each node\n";
}
if ( open( CMANC, "mkqdisk -L 2>/dev/null | awk NF |" ) ) {
while () {
push(@mkqdisk, $_);
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
if ( grep(/^\//, $_ ) ) {
chomp($_);
$_ =~ s/://g;
@qdsk = split( /\//, $_ );
my @DNAME = `lsblk -io KNAME,TYPE,SCHED,ROTA,DISC-GRAN,DISC-MAX | grep "^$qdsk[$#qdsk]"`;
if ( "@DNAME" ) {
push(@DNAMEARR, @DNAME);
}
}
}
}
if ( @mkqdisk ) {
print "\n$INFOSTR Linux Cluster lock disk status\n";
print @mkqdisk;
if ( @DNAMEARR ) {
print "\n$INFOSTR Linux Cluster lock disk IO elevator\n";
print "\n$INFOSTR Recommended to use \"deadline\" scheduler or \cfq\" scheduler with realtime priority (ionice -c 1 -n 0 -p \`pidof qdiskd\`)\n";
print @DNAMEARR;
}
}
my @ccstooll = `ccs_tool lsnode 2>/dev/null | awk NF`;
if ( @ccstooll ) {
print "\n$INFOSTR Linux Cluster node status\n";
print @ccstooll;
}
my @ccstoolf = `ccs_tool lsfence 2>/dev/null`;
if ( @ccstoolf ) {
print "\n$INFOSTR Linux Cluster fence device status\n";
print @ccstoolf;
my @fencearr = grep { !(/Name.*Agent/) } @ccstoolf;
if ( ! @fencearr ) {
print "\n$ERRSTR Linux Cluster has no fence devices\n";
}
}
my @grouptool = `group_tool ls 2>/dev/null | awk NF`;
if ( @grouptool ) {
print "\n$INFOSTR Linux Cluster fence group status\n";
print @grouptool;
}
my @victim = grep(/victim/, @grouptool);
if ( @victim ) {
print "\n$INFOSTR Linux Cluster victim status\n";
print @victim;
}
my @wait = grep(/wait state|change/, @grouptool);
if ( @wait ) {
print "\n$INFOSTR Linux Cluster wait and change summary\n";
print @wait;
}
if ( open( CMANC, "cman_tool nodes 2>/dev/null |" ) ) {
while () {
push(@cmannode, $_);
chomp($_);
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
@cmanarr = split( /\s+/, $_ );
if ( $cmanarr[1] eq "X" ) {
push(@CMANA, "$WARNSTR Node $cmanarr[$#cmanarr] is not a member of the cluster\n");
}
elsif ( $cmanarr[1] eq "d" ) {
push(@CMANA, "$WARNSTR Node $cmanarr[$#cmanarr] is a member of the cluster but access to it is disallowed\n");
}
else {
if ( $cmanarr[1] eq "M" ) {
push(@CMANA, "$PASSSTR Node $cmanarr[$#cmanarr] is an active member of the cluster\n");
}
}
}
}
if ( @cmannode ) {
print "\n$INFOSTR Linux Cluster nodes and last time each was fenced\n";
print @cmannode;
}
if ( ! grep(/$Hostname.*fence*/i, @ccstooll) ) {
my @clusvcadm = `clusvcadm -S 2>/dev/null`;
if ( @clusvcadm ) {
print "\n$INFOSTR Linux Cluster lock state\n";
print @clusvcadm;
}
}
if ( @CMANA ) {
print "\n$INFOSTR Linux Cluster nodes membership status\n";
print @CMANA;
}
exit(0);