#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # 61haes_r714 src/43haes/usr/sbin/cluster/utilities/cllsvgdata.sh 1.16 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 2000,2011 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)13 1.12 src/43haes/usr/sbin/cluster/utilities/cllsvgdata.sh, hacmp.utils, 53haes_r560 10/3/07 13:52:21 ############################################################################### # # Name: main program # # This program runs on individual nodes in the cluster. It does an 'lspv' # followed by a call to 'lvlstmajor'. All output goes to the screen - # dsh/cspoc pick up this and concatenate into a single file. # # Arguments: - # # Returns: # ################################################################################ # Set the ENV PATH variable $dirname = `/usr/bin/dirname $0`; chop($dirname); $getpath_cmd = "$dirname/../utilities/cl_get_path all"; $path = `$getpath_cmd`; $ENV{'PATH'} = "$path"; # Set the ENV ODMDIR variable $HA_DIR = `cl_get_path`; $odmdir = "/etc/$HA_DIR/objrepos"; $ENV{'ODMDIR'} = "$odmdir"; #------------------------------------------------------------------------------- # Create Device Major and Volume Group Data hash tables here for later usage. # We determine all VGs up front via 'lsvg' so gathering the device major numbers # up front for all known VGs is a performance measure to prevent us from # repeatedly querying the same information. The performance benefits vary, # depending upon the specific system configurations, but makes for cleaner and # more efficient code regardless. # # Physical volumes not assigned to a Volume Group are effectively inactive and # will be tagged "None" below. Accordingly, we also obtain appropriate lsvg # output for VG "None" as well as create an associated 0 device major. #----------------------------------------------------------------------------- %dev_major = (); %vg_data = (); $dev_major{"None"} = 0; $vg_data{"None"} = `/usr/sbin/lsvg -L None 2>&1`; $lsvg_out = `/usr/sbin/lsvg`; foreach $vg (split(/\n/, $lsvg_out)) { $lsvg_output = `/usr/sbin/lsvg -L $vg 2>&1`; $vg_data{$vg} = $lsvg_output; if (!exists($dev_major{$vg})) { $dev_output = `/usr/bin/ls -al /dev/$vg`; if ($? == 0) { @dev_output_array = split(/\s+/, $dev_output); chop($dev_major{$vg} = $dev_output_array[4]); } else { # All VGs should have a device major number and this should be # unreachable!! # Directing the error to STDERR, to avoid interference with STDOUT messages. print STDERR "Error : **************\n"; # Set the device major number to Error. $dev_major{$vg} = "Error"; } } } #------------------------------------------------------------------------------- # Get local pv data #------------------------------------------------------------------------------- $LOCAL="1" ; $lspv_out = `/usr/es/sbin/cluster/utilities/cl_lspv`; foreach $pv_line (split("\n", $lspv_out)) { ($cl_phydisk, $cl_pvid, $cl_vgname, $leftovers) = split(/\s+/, $pv_line, 4); # Get the device type for this device and skip it if it is a rpvclient # The RPV devices are being printed below so there is no need to print them # here. $dev_type = `/usr/sbin/lsdev -r type -l $cl_phydisk`; chop $dev_type; if ( $dev_type eq "rpvclient" ) { next ; } # Get the size of the disk $dev_size=`/usr/sbin/bootinfo -s $cl_phydisk` ; chomp $dev_size; # Retrieve the device major number for the volume group. $cl_major_number = $dev_major{$cl_vgname}; # Exclude the VG from the list, if major number is set to Error if ($cl_major_number eq "Error") { next; } # Parse previously retrieved VG status ($cl_concurrency, $cl_active, $cl_quorum, $cl_vg_type) = ck_vg_status($cl_vgname); print "$cl_phydisk:$cl_pvid:$cl_vgname:$cl_major_number:$cl_concurrency:$cl_active:$cl_quorum:$LOCAL:$cl_vg_type:$dev_size\n"; } # Get the RPV site name my $rpv_server_sitename = ""; if ( -x '/usr/sbin/rpvsitename' ) { $rpv_server_sitename = `/usr/sbin/rpvsitename` ; chop $rpv_server_sitename; } if (-x '/usr/sbin/lsrpvclient') { my $local_addresses; my $server_addresses; #----------------------------------------------------------------------------- # Get RPV data #----------------------------------------------------------------------------- $LOCAL="0"; $lsrpvclient_out = `/usr/sbin/lsrpvclient`; foreach $rpv_line (split("\n", $lsrpvclient_out)) { $rpv_line =~ s/^\s+//; ($cl_phydisk, $cl_pvid, $leftovers) = split(/\s+/, $rpv_line, 3); $cl_vgname = `/usr/bin/odmget -q"value LIKE $cl_pvid*" CuAt | grep -w name | grep -v hdisk | cut -d'"' -f2`; if ($cl_vgname eq "") { # Physical Volume is not allocated to a VG $cl_vgname = "None"; } else { # Strip '\n' from ODM retrieved VG name chomp($cl_vgname); } $cl_major_number = $dev_major{$cl_vgname}; # Exclude the VG from the list, if major number is set to Error if ($cl_major_number eq "Error") { next; } ($cl_concurrency, $cl_active, $cl_quorum, $cl_vg_type) = ck_vg_status($cl_vgname); # Get the size of the disk $dev_size=`/usr/sbin/bootinfo -s $cl_phydisk` ; chomp $dev_size; ( $local_addresses, $server_addresses ) = get_ip_addresses_for_rpvclient( $cl_phydisk ); # Output the results for RPV if ($cl_active eq "active") { print "$cl_phydisk:$cl_pvid:$cl_vgname:$cl_active:$cl_major_number:$cl_concurrency:$cl_active:$cl_quorum:$LOCAL:$cl_vg_type:$dev_size:$rpv_server_sitename:$local_addresses:$server_addresses\n"; } else { print "$cl_phydisk:$cl_pvid:$cl_vgname:$cl_major_number:$cl_concurrency:$cl_active:$cl_quorum:$LOCAL:$cl_vg_type:$dev_size:$rpv_server_sitename:$local_addresses:$server_addresses\n"; } } } # Get RPV server information if (-x '/usr/sbin/lsrpvserver') { my $cl_rpv_devname; my $lsrpvserver_out; my $cl_backing_dev; #----------------------------------------------------------------------------- # Get RPV data #----------------------------------------------------------------------------- $lsrpvserver_out = `/usr/sbin/lsrpvserver` ; foreach $rpv_line (split("\n", $lsrpvserver_out)) { $rpv_line =~ s/^\s+//; ($cl_rpv_devname, $cl_pvid, $cl_backing_dev) = split(/\s+/, $rpv_line, 3); # remove white-spaces $cl_backing_dev =~ s/\s//g ; # Get client IP addresses associated with this RPV server $client_addresses = get_client_addr_for_rpvserver( $cl_rpv_devname ); print "$cl_rpv_devname:$cl_pvid:$cl_backing_dev"; print ":::::0:::$rpv_server_sitename:$client_addresses\n"; } } $freemajor = `/usr/sbin/lvlstmajor`; print "FREEMAJORS:$freemajor"; $migfile1 = "/usr/sbin/cluster/.mig"; $migfile2 = "/usr/es/sbin/cluster/.mig"; if (-e $migfile1) { print "NxN_in_progress\n"; } elsif (-e $migfile2) { print "NxN_in_progress\n"; } # this is the end of the main program .... #=============================================================================== # Name: get_client_addr_for_rpvserver # # Returns the list of IP addresses that are listed as the "clients" for a RPV # server. # # Arguments: $rpv_devname (RPV server's device name) # # Returns: list of IP addresses (delimited by ",") # #=============================================================================== sub get_client_addr_for_rpvserver { my ($rpv_server_dev) = @_; my $client_addr_list; my $output; my @dev_attrs; my $i; $output = ` /usr/sbin/lsattr -E -l $rpv_server_dev -O | tail -1 `; @dev_attrs = split(/:/, $output); #=========================================================================== # RPV server attributes are implemented in a weird manner. Instead of # using a fixed-num of attributes, the number of attributes returned for a # RPV server device name (by lsattr command) would vary depending on the # number of client IP addresses that are associated with the RPV server # device. #=========================================================================== $client_addr_list = "@dev_attrs[1..($#dev_attrs - 1)]"; $client_addr_list =~ s/\s/,/g ; return $client_addr_list; } #=============================================================================== # Name: get_ip_addresses_for_rpvclient # # Returns the local and server addresses associated with a RPV client disk. # server. # # Arguments: $rpv_devname (RPV client device name) # # Returns: list of Local IP addresses (delimited by ",") # list of Server IP addresses (delimited by ",") # #=============================================================================== sub get_ip_addresses_for_rpvclient { my ($rpv_client_dev) = @_; my $output; $output = `/usr/sbin/lsattr -E -O -l $rpv_client_dev | tail -1 `; @dev_attrs = split(/:/, $output); $local_addr = "@dev_attrs[1..4]"; $local_addr =~ s/\s/,/g ; $server_addr = "@dev_attrs[6..9]"; chomp ($server_addr); # get rid of trailing white space $server_addr =~ s/\s/,/g ; return ("$local_addr", "$server_addr" ); } ############################################################################### # # Name: ck_vg_status # # Finds whether or not a VG is concurrent-capable and what state it's in. # # Arguments: $vg volume group to check # # Returns: @retval 2-element list. # 1st element contains: 0 for concurrent-capable. # 1 for not concurrent-capable. # # 2nd element contains: active, inactive, or concurrent. # ############################################################################### sub ck_vg_status { my($vg) = $_[0]; # Initialize "local" variables to null. # --------------------------------------- my ($conc_cap_status, $activity_status, $tmprawout, $junk1, $junk2, $cl_quorum) = ""; my (@vgmode) = (); my (@lsvgout) = (); my (@vgmodeline) = (); my (@retval) = (); my ($vg_type) = "Unknown" ; my (@max_pvs_line) = (); my ($max_pvs) = ""; $tmprawout = $vg_data{$vg}; @lsvgout = split('\n', $tmprawout); # ----------------------------------------------------------------- # if VG is not defined. (i.e. if it's "None" in lspv output.) # bail now. # ----------------------------------------------------------------- if ($lsvgout[0] =~ /^0516-306\b/ ) { $activity_status = "inactive"; $conc_cap_status = "0"; $cl_quorum = "0"; @retval = ($conc_cap_status, $activity_status, $cl_quorum, $vg_type); return @retval; } # if VG is varied off... # ------------------------ if ($lsvgout[0] =~ /^0516-010\b/ ) { $activity_status = "inactive"; } # elsif other error(s), bail now. # --------------------------------- elsif ($lsvgout[0] =~ /^[0-9]{4}-[0-9]{3}\b/ ) { $thisnode = `hostname`; chop($thisnode); print "$thisnode: "; foreach (@lsvgout) {print "$_\n";} # Do we really want to set $activity_status = "inactive" for this # case? Will do so for now. $activity_status = "inactive"; $conc_cap_status = "0"; $cl_quorum = "0"; @retval = ($conc_cap_status, $activity_status, $cl_quorum, $vg_type); return @retval; } # otherwise we'll assume it to be active. # ----------------------------------------- else { $activity_status = "active"; # Note: If the VG is varied on concurrently, this will get # overidden to "concurrent" in some code below. } $tmprawout = `/usr/bin/odmget -q "name = $vg AND attribute = quorum AND value = n" CuAt`; if ($tmprawout eq "") { $cl_quorum = "1"; } else { $cl_quorum = "0"; } # ************************************************************************ # # Code for "inactive" VG starts here. # ************************************************************************ if ($activity_status eq "inactive") { # ------------------------------------------------------- # Use odmget to determine if it's concurrent-capable. # ------------------------------------------------------- $tmprawout = ""; $tmprawout = `/usr/bin/odmget -q "name = $vg AND attribute = conc_capable AND value = y" CuAt`; if ($tmprawout eq "") { $conc_cap_status = "0"; } else { $conc_cap_status = "1"; } } # ************************************************************************ # # Code for "active" VG starts here. # ************************************************************************ if ($activity_status eq "active") { # ------------------------------------------------------- # If we're still here, we KNOW it's active. # The code for this block just parses the lsvg output. # No more system calls are needed. # ------------------------------------------------------- @vgmodeline = grep /VG Mode:/, @lsvgout; if (scalar(@vgmodeline) < 1) { # If it's not even "Concurrent: Capable", # there will be no "VG Mode: " line. # ------------------------------------------ $conc_cap_status = "0"; } # else we know it's concurrent-capable. But is it concurrent? # -------------------------------------------------------------- else { $conc_cap_status = "1"; @vgmode = split(':', $vgmodeline[0]); if ($vgmode[1] !~ /Non-Concurrent/) { if ($vgmode[1] =~ /Concurrent/) { $activity_status = "concurrent"; } } } # For all active VGs, we return the type of the VG. That is, if the VG is # "Original", "Big" or "Scalable" type. # # lsvg -L command returnt the information in the following # format. # MAX PPs per PV: 1016 MAX PVs: 32 @max_pvs_line = grep /MAX PVs:/, @lsvgout; @max_pvs_line = split(':', $max_pvs_line[0]); $max_pvs = $max_pvs_line[2]; # Trim leading white-space characters $max_pvs =~ s/^\s+//g; if ( $max_pvs == "1024" ) { $vg_type = "Scalable"; } elsif ( $max_pvs == "32" ) { $vg_type = "Original" ; } elsif ( $max_pvs == "128" ) { $vg_type = "Big" ; } } # end: $activity_status eq "active" block. # All processing done, put the results into an array and return them. # -------------------------- @retval = ($conc_cap_status, $activity_status, $cl_quorum, $vg_type ); return @retval; } # end of ck_vg_status()