#!/usr/bin/perl # IBM(c) 2008 EPL license http://www.eclipse.org/legal/epl-v10.html ########################################################################### # # # Command: getGuids # # # #-------------------------------------------------------------------------# # This xCAT script will use xdsh to get the Guids from Linux nodes # # and AIX nodes, and save the results to file /opt/xcat/samples/ib/ # # Guids.xcat, log file is /var/log/xcat/getGuids.log. # # Command Syntax: # # getGuids [-h] [-f output_file] # # -f output_file # # Specifies a file full path name that is used to save the # # GUIDs output. # # -h # # Display usage information. # # Exit codes: # # 0 - success # # 1 - fail # ########################################################################### use strict; use Getopt::Long; # Log file $::GUIDS_LOG = "/var/log/xcat/getGuids.log"; $::DEFAULT_RESULT_FILE = "/var/opt/xcat/ib/Guids.xcat"; $::GUIDS_LOG_PATH = "/var/log/xcat"; $::DEFAULT_RESULT_FILE_PATH = "/var/opt/xcat/ib"; # variables and Commands $::OK = 0; $::NOK = 1; $::logging = 0; $::GLOBAL_EXIT = 0; $::NODEGRP = "/opt/xcat/bin/nodels"; $::LinuxIBCmd = "/usr/bin/ibv_devinfo"; $::AIXIBCmd = "/usr/bin/ibstat"; # MAIN Main main# &getArgs; # Append logging information to getGuids.log &append_logging($::GUIDS_LOG); $::logging++; local *FILE; `/usr/bin/mkdir -p $::DEFAULT_RESULT_FILE_PATH`; unless (open(FILE, ">$::RESULT_FILE")) { print "Can't open file $::RESULT_FILE for writing.\n"; print $::LOG_FILE_HANDLE "Can't open file $::RESULT_FILE for writing.\n"; $::GLOBAL_EXIT = $::NOK; exit; } # get Linux nodes my @LnxNodes = `$::NODEGRP all nodetype.os | grep -E "sles|rhel"`; print $::LOG_FILE_HANDLE "Running command: $::NODEGRP LinuxNodes\n"; chomp @LnxNodes; my @ReachableLnxNodes; my @UnreachableLnxNodes; my @ValidLnxNodes; my @BadLnxNodes; my $num = scalar(@LnxNodes); if ($num > 0) { # Handle Linux Nodes # Check if xdsh is reachable foreach my $node (@LnxNodes) { my $rest; ($node, $rest) = split(/:/, $node); my $rc = &checkxDshReachability($node); if ($rc == 0) # xdsh is ok { push @ReachableLnxNodes, $node; } else { push @UnreachableLnxNodes, $node; } } if (scalar (@UnreachableLnxNodes)) { my $UnreachableLnxNodes = join (", ", @UnreachableLnxNodes); print "Warning: xdsh is unreachable for the node(s): $UnreachableLnxNodes.\n" . "Please use xdsh -K command to configure it.\n"; print $::LOG_FILE_HANDLE "Warning: xdsh is unreachable for the node(s): $UnreachableLnxNodes.\n" . "Please use xdsh -K command to configure it.\n"; } foreach my $node (@ReachableLnxNodes) { my $rc = &checkIBCmdAvailability($node, "Linux"); if ($rc == 0) { push @ValidLnxNodes, $node; } else { push @BadLnxNodes, $node; } } if (scalar (@BadLnxNodes)) { my $BadLnxNodes = join (", ", @BadLnxNodes); print "Warning: Command $::LinuxIBCmd is not available on the node(s): $BadLnxNodes.\nPlease ensure the libibverbs rpm is installed.\n"; print $::LOG_FILE_HANDLE "Warning: Command $::LinuxIBCmd is not available on the node(s): $BadLnxNodes.\nPlease ensure the libibverbs rpm is installed.\n"; } if (scalar (@ValidLnxNodes)) { my $rc = &getLinuxGUIDS(\@ValidLnxNodes); if ($rc) { $::GLOBAL_EXIT = $rc; exit; } } } # get AIX nodes my @AIXNodes = `$::NODEGRP all nodetype.os | grep "AIX"`; print $::LOG_FILE_HANDLE "Running command: $::NODEGRP\n"; chomp @AIXNodes; my @ReachableAIXNodes; my @UnreachableAIXNodes; my @ValidAIXNodes; my @BadAIXNodes; my $num = scalar(@AIXNodes); if ($num > 0) { # Handle AIX Nodes # Check if xdsh is reachable foreach my $node (@AIXNodes) { my $rest; ($node, $rest) = split(/:/, $node); my $rc = &checkxDshReachability($node); if ($rc == 0) # xdsh is ok { push @ReachableAIXNodes, $node; } else { push @UnreachableAIXNodes, $node; } } if (scalar (@UnreachableAIXNodes)) { my $UnreachableAIXNodes = join (", ", @UnreachableAIXNodes); print "Warning: The xdsh is unreachable for the node(s): $UnreachableAIXNodes.\n" . "Please use xdsh -K command to configure it.\n"; print $::LOG_FILE_HANDLE "Warning: The xdsh is unreachable for the node(s): $UnreachableAIXNodes.\n" . "Please use xdsh -K command to configure it.\n"; } foreach my $node (@ReachableAIXNodes) { my $rc = &checkIBCmdAvailability($node, "AIX"); if ($rc == 0) { push @ValidAIXNodes, $node; } else { push @BadAIXNodes, $node; } } if (scalar (@BadAIXNodes)) { my $BadAIXNodes = join (", ", @BadAIXNodes); print "Warning: Command $::AIXIBCmd is not available on the node(s): $BadAIXNodes.\nPlease ensure the devices.common.IBM.ib.rte fileset is installed.\n"; print $::LOG_FILE_HANDLE "Warning: Command $::AIXIBCmd is not available on the node(s): $BadAIXNodes.\nPlease ensure the devices.common.IBM.ib.rte fileset is installed.\n"; } if (scalar (@ValidAIXNodes)) { my $rc = &getAIXGUIDS(\@ValidAIXNodes); if ($rc) { $::GLOBAL_EXIT = $rc; exit; } } } if ((scalar(@LnxNodes) + scalar(@AIXNodes)) <= 0) { print "There is no nodes defined on this MN\n"; print $::LOG_FILE_HANDLE "There is no nodes defined on this MN\n"; $::GLOBAL_EXIT = $::NOK; exit; } print "The GUIDs are saved to file $::RESULT_FILE.\n"; # Finish up and exit END { close FILE; if ($::logging) { &stop_logging(); } #Determine exit code if ($::GLOBAL_EXIT > $?) { $? = $::GLOBAL_EXIT; } } exit; # end of Main #-------------------------------------------------------------------------------- =head3 getArgs Parse the command line and check the values =cut #-------------------------------------------------------------------------------- sub getArgs() { GetOptions( 'h' => \$::HELP, 'f=s' => \$::RESULT_FILE ); if ($::HELP) { &usage; $::GLOBAL_EXIT = $::OK; exit; } if (!$::RESULT_FILE) { $::RESULT_FILE = $::DEFAULT_RESULT_FILE; if (!-e "/var/opt/xcat/ib/") { `/usr/bin/mkdir -p /var/opt/xcat/ib/`; if ($?) { $::GLOBAL_EXIT = $?; exit; } } } } #-------------------------------------------------------------------------------- =head3 usage usage for getGuids =cut #-------------------------------------------------------------------------------- sub usage() { print "Usage: getGuids [-h] [-f output_file] -f output_file Specifies a file full path name that is used to save the GUIDs output. -h Display usage information.\n"; } #-------------------------------------------------------------------------------- =head3 checkxDshReachability Notes: Check the xdsh reachability between the Management Nodes and node. Arguments: $node - the remote node hostname. Returns: $::OK - The remote node is reachable through xdsh. $::NOK - The remote node is unreachable through xdsh. =cut #-------------------------------------------------------------------------------- sub checkxDshReachability() { my ($node) = @_; my $output = `xdsh $node date 2>/dev/null`; print $::LOG_FILE_HANDLE "Running command: xdsh $node date 2>/dev/null\n"; if ($? == $::OK) { return $::OK; } return $::NOK; } #-------------------------------------------------------------------------------- =head3 checkIBCmdAvailability Notes: Check availability of the IB command on the node. Arguments: $node - the remote node hostname. $os - the os type of the node Returns: $::OK - The IB command is available on the node. $::NOK - The IB command is not available on the node. =cut #-------------------------------------------------------------------------------- sub checkIBCmdAvailability() { my ($node, $os) = @_; my $output; if ($os eq "Linux") { $output = `xdsh $node ls $::LinuxIBCmd 2>/dev/null`; print $::LOG_FILE_HANDLE "Running command: xdsh $node ls $::LinuxIBCmd 2>/dev/null\n" } else { $output = `xdsh $node ls $::AIXIBCmd 2>/dev/null`; print $::LOG_FILE_HANDLE "Running command: xdsh $node ls $::AIXIBCmd 2>/dev/null\n" } #print "Here: " . $output; if ($? == $::OK) { return $::OK; } return $::NOK; } #------------------------------------------------------------------------------- =head3 append_logging Append logging messages to a logfile. =cut #------------------------------------------------------------------------------- sub append_logging() { #my ($class, $logfile) = @_; my ($logfile) = @_; my ($cmd, $rc); # # get log file ready # if (!-e $logfile) { # create the log file if not already there `/usr/bin/mkdir -p $::GUIDS_LOG_PATH`; unless (open(LOGFILE, ">$logfile")) { # Cannot open file print "Can't open file \"$logfile\" for writing.\n"; return $::NOK; } } else { # it's there so just append unless (open(LOGFILE, ">>$logfile")) { print "Can't update file \"$logfile\".\n"; return $::NOK; } } $::LOG_FILE_HANDLE = \*LOGFILE; # Print the date to the top of the logfile my $sdate = `/bin/date`; chomp $sdate; print "Output log is being written to \"$logfile\".\n"; print $::LOG_FILE_HANDLE "---------------------------------------------------------------------\n"; print $::LOG_FILE_HANDLE "Logging started $sdate.\n"; print $::LOG_FILE_HANDLE "---------------------------------------------------------------------\n"; return $::OK; } #------------------------------------------------------------------------------- =head3 stop_logging Turn off message logging. =cut #------------------------------------------------------------------------------- sub stop_logging() { # Print the date at the bottom of the logfile my $sdate = `/bin/date`; chomp $sdate; print $::LOG_FILE_HANDLE "---------------------------------------------------------------------\n"; print $::LOG_FILE_HANDLE "Logging stopped $sdate.\n"; print $::LOG_FILE_HANDLE "---------------------------------------------------------------------\n"; close($::LOG_FILE_HANDLE); $::LOG_FILE_HANDLE = undef; return $::OK; } #------------------------------------------------------------------------------- =head3 getAIXGUIDS Get GUIDs from AIX nodes. Arguments: $refAIXNodes - The reference to the group of AIX nodes. =cut #------------------------------------------------------------------------------- sub getAIXGUIDS() { my ($refAIXNodes) = @_; my $AIXNodes = join (",", @$refAIXNodes); print "Getting GUIDs from AIX nodes...\n"; print $::LOG_FILE_HANDLE "Getting GUIDs from AIX nodes...\n"; my $getCmd = "xdsh $AIXNodes $::AIXIBCmd -v 2>/dev/null"; print $::LOG_FILE_HANDLE "Running command: $getCmd.\n"; my @output = `$getCmd`; if ($?) { print "Command failed: $getCmd.\n"; print $::LOG_FILE_HANDLE "Command failed: $getCmd.\n"; return $::NOK; } my $oldhost = ""; my $host = ""; my $dev = ""; my $guid = ""; my $port = ""; my $gid = ""; my $baseguid = ""; my $lsw0 = ""; my $lsw1 = ""; foreach my $line (@output) { chomp $line; # Get node hostname if ($line =~ /(\S*):.*/) { $host = $1; if ($host ne $oldhost) { print FILE "Node name is $host.\n"; print $::LOG_FILE_HANDLE "Node name is $host.\n"; $oldhost=$host; } } # Get device name if ($line =~ /.*IB NODE INFORMATION.*\((\S*)\).*/) { $dev = $1; } # Get device GUID if ($line =~ /.*\(GUID\):.*\s+(\S*)/) { $guid = $1; $guid=~s/\.//g; $baseguid=$guid; $baseguid=~s/..$//; $lsw0=$guid; $lsw0=~s/..$/80/; $lsw1=$guid; $lsw1=~s/..$/81/; print FILE "$host: $dev: baseguid: $baseguid\n"; print FILE "$host: $dev: dev: $guid\n"; print FILE "$host: $dev: lsw0: $lsw0\n"; print FILE "$host: $dev: lsw1: $lsw1\n"; print $::LOG_FILE_HANDLE "$host: $dev: baseguid: $baseguid\n"; print $::LOG_FILE_HANDLE "$host: $dev: dev: $guid\n"; print $::LOG_FILE_HANDLE "$host: $dev: lsw0: $lsw0\n"; print $::LOG_FILE_HANDLE "$host: $dev: lsw1: $lsw1\n"; } # Get port number under device(iba) if ($line =~ /\s*IB PORT (\S*) INFORMATION.*/) { $port = $1; } # Get GUID under port if ($line =~ /.*GUID\[.*\s+(\S*)/) { $gid = $1; $gid=~s/\.//g; print FILE "$host: $dev: portGUID_$port: $gid\n"; print $::LOG_FILE_HANDLE "$host: $dev: portGUID_$port: $gid\n"; } } return $::OK; } #------------------------------------------------------------------------------- =head3 getLinuxGUIDS Get GUIDs from Linux nodes. Arguments: $refLnxNodes - The reference to the group of Linux nodes. =cut #------------------------------------------------------------------------------- sub getLinuxGUIDS() { my ($refLnxNodes) = @_; my $LnxNodes = join (",", @$refLnxNodes); print "Getting GUIDs from Linux nodes...\n"; print $::LOG_FILE_HANDLE "Getting GUIDs from Linux nodes...\n"; my $getCmd = "xdsh $LnxNodes $::LinuxIBCmd -v 2>/dev/null"; print $::LOG_FILE_HANDLE "Running command: $getCmd.\n"; my @output = `$getCmd`; if ($?) { print "Command failed: $getCmd.\n"; print $::LOG_FILE_HANDLE "Command failed: $getCmd.\n"; return $::NOK; } my $oldhost = ""; my $host =""; my $dev = ""; my $guid = ""; my $port = ""; my $gid = ""; my $baseguid = ""; my $lsw0 = "" ; my $lsw1 = ""; foreach my $line (@output) { chomp $line; # Get node hostname if ($line =~ /(\S*):.*/) { $host = $1; if ($host ne $oldhost) { print FILE "Node name is $host.\n"; print $::LOG_FILE_HANDLE "Node name is $host.\n"; $oldhost=$host; } } # Get device name if ($line =~ /.*hca_id:\s(\S*).*/) { $dev = $1; } # Get node_guid under hca_id if ($line =~ /.*node_guid:\s*(\S*)/) { $guid = $1; $guid =~s/://g; $baseguid = $guid; $baseguid =~s/..$//; $lsw0 = $guid; $lsw0 =~s/..$/80/; $lsw1 = $guid; $lsw1 =~s/..$/81/; print FILE "$host: $dev: baseguid: $baseguid\n"; print FILE "$host: $dev: dev: $guid\n"; print FILE "$host: $dev: lsw0: $lsw0\n"; print FILE "$host: $dev: lsw1: $lsw1\n"; print $::LOG_FILE_HANDLE "$host: $dev: baseguid: $baseguid\n"; print $::LOG_FILE_HANDLE "$host: $dev: dev: $guid\n"; print $::LOG_FILE_HANDLE "$host: $dev: lsw0: $lsw0\n"; print $::LOG_FILE_HANDLE "$host: $dev: lsw1: $lsw1\n"; } # Get port number under hca_id if ($line =~ /port:\s*(\S*).*/) { $port = $1; } # Get GID under port if ($line =~ /.*GID.* *(\S*:\S*:\S*:\S*).*/) { $gid = $1; $gid=~s/://g; my $prefix = substr $baseguid, 0, 4; $gid = $prefix . $gid; print FILE "$host: $dev: portGUID_$port: $gid\n"; print $::LOG_FILE_HANDLE "$host: $dev: portGUID_$port: $gid\n"; } } return $::OK; }