# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html #------------------------------------------------------- =head1 This is a utility plugin for z/VM. =cut #------------------------------------------------------- package xCAT::zvmUtils; use xCAT::MsgUtils; use xCAT::Utils; use xCAT::Table; use strict; use warnings; 1; #------------------------------------------------------- =head3 getNodeProps Description : Get node properties Arguments : Table Node Properties Returns : Properties from specifed table Example : my $propVals = xCAT::zvmUtils->getNodeProps($tabName, $node, $propNames); =cut #------------------------------------------------------- sub getNodeProps { # Get inputs my ( $class, $tabName, $node, @propNames ) = @_; # Get specified table my $tab = xCAT::Table->new($tabName); # Get value from column my $propVals = $tab->getNodeAttribs( $node, [@propNames] ); return ($propVals); } #------------------------------------------------------- =head3 getTabPropsByKey Description : Get node properties by key Arguments : Table Key Key value Requested properties Returns : Properties from specifed table Example : my $propVals = xCAT::zvmUtils->getTabPropsByKey($tabName, $key, $keyValue, @reqProps); =cut #------------------------------------------------------- sub getTabPropsByKey { # Get inputs my ( $class, $tabName, $key, $keyVal, @propNames ) = @_; # Get specified table my $tab = xCAT::Table->new($tabName); my $propVals; # Get table attributes matching specified key $propVals = $tab->getAttribs( { $key => $keyVal }, @propNames ); return ($propVals); } #------------------------------------------------------- =head3 setNodeProp Description : Set node property Arguments : Table Node Property Returns : Nothing Example : xCAT::zvmUtils->setNodeProp($tabName, $node, $propName, $propVal); =cut #------------------------------------------------------- sub setNodeProp { # Get inputs my ( $class, $tabName, $node, $propName, $propVal ) = @_; # Get specified table my $tab = xCAT::Table->new( $tabName, -create => 1, -autocommit => 0 ); # Set property $tab->setAttribs( { 'node' => $node }, { $propName => $propVal } ); # Save table $tab->commit; return; } #------------------------------------------------------- =head3 delTabEntry Description : Delete node Arguments : Table Node Returns : Nothing Example : xCAT::zvmUtils->delTabEntry($tabName, $node); =cut #------------------------------------------------------- sub delTabEntry { # Get inputs my ( $class, $tabName, $node ) = @_; # Get specified table my $tab = xCAT::Table->new( $tabName, -create => 1, -autocommit => 0 ); # Delete node from table my %key = ( 'node' => $node ); $tab->delEntries( \%key ); # Save table $tab->commit; return; } #------------------------------------------------------- =head3 tabStr Description : Tab string (4 spaces) Arguments : String Returns : Tabbed string Example : my $str = xCAT::zvmUtils->tabStr($str); =cut #------------------------------------------------------- sub tabStr { # Get inputs my ( $class, $inStr ) = @_; my @lines = split( "\n", $inStr ); # Tab output my $outStr; foreach (@lines) { $outStr .= " $_\n"; } return ($outStr); } #------------------------------------------------------- =head3 trimStr Description : Trim whitespaces in string Arguments : String Returns : Trimmed string Example : my $str = xCAT::zvmUtils->trimStr($str); =cut #------------------------------------------------------- sub trimStr { # Get string my ( $class, $str ) = @_; # Trim right $str =~ s/\s*$//; # Trim left $str =~ s/^\s*//; return ($str); } #------------------------------------------------------- =head3 replaceStr Description : Replace string Arguments : String Returns : Replaced string Example : my $str = xCAT::zvmUtils->replaceStr($str, $pattern, $replacement); =cut #------------------------------------------------------- sub replaceStr { # Get string my ( $class, $str, $pattern, $replacement ) = @_; # Replace string $str =~ s/$pattern/$replacement/g; return ($str); } #------------------------------------------------------- =head3 printLn Description : Print string Arguments : String Returns : Nothing Example : xCAT::zvmUtils->printLn($callback, $str); =cut #------------------------------------------------------- sub printLn { # Get inputs my ( $class, $callback, $str ) = @_; # Print string my $rsp; $rsp->{data}->[0] = "$str"; xCAT::MsgUtils->message( "I", $rsp, $callback ); return; } #------------------------------------------------------- =head3 isZvmNode Description : Check if a node is in the 'zvm' table Arguments : Node Returns : TRUE Node exists FALSE Node does not exists Example : my $out = xCAT::zvmUtils->isZvmNode($node); =cut #------------------------------------------------------- sub isZvmNode { # Get inputs my ( $class, $node ) = @_; # zVM guest ID my $id; # Look in 'zvm' table my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 ); my @results = $tab->getAllAttribsWhere( "node like '%" . $node . "%'", 'userid' ); foreach (@results) { $id = $_->{'userid'}; # Get userID if one is not in the table if ($id) { return ('TRUE'); } } return ('FALSE'); } #------------------------------------------------------- =head3 getIp Description : Get IP address of given node Arguments : Node Returns : IP address Example : my $ip = xCAT::zvmUtils->getIp($node); =cut #------------------------------------------------------- sub getIp { # Get inputs my ( $class, $node ) = @_; # Get IP address my $out = `ssh -o ConnectTimeout=10 $node "ifconfig" | grep "inet addr:" | grep -v "127.0.0.1"`; my @lines = split( '\n', $out ); # Get the first IP that comes back my @parms = split( ' ', $lines[0] ); foreach (@parms) { # Get inet addr parameter if ( $_ =~ m/addr:/i ) { my @ip = split( ':', $_ ); return ( $ip[1] ); } } return; } #------------------------------------------------------- =head3 getIfcfg Description : Get network configuration file path for given node Red Hat -- /etc/sysconfig/network-scripts/ifcfg-eth SUSE -- /etc/sysconfig/network/ifcfg-qeth Arguments : Node Returns : Network configuration file path Example : my $ifcfg = xCAT::zvmUtils->getIfcfg($node); =cut #------------------------------------------------------- sub getIfcfg { # Get inputs my ( $class, $node ) = @_; # Get OS my $os = xCAT::zvmCPUtils->getOs($node); # Get network configuration file path my $out; my @parms; # If it is Red Hat -- ifcfg-qeth file is in /etc/sysconfig/network-scripts if ( $os =~ m/Red Hat/i ) { $out = `ssh -o ConnectTimeout=5 $node "ls /etc/sysconfig/network-scripts/ifcfg-eth*"`; @parms = split( '\n', $out ); return ( $parms[0] ); } # If it is SUSE -- ifcfg-qeth file is in /etc/sysconfig/network elsif ( $os =~ m/SUSE/i ) { $out = `ssh -o ConnectTimeout=5 $node "ls /etc/sysconfig/network/ifcfg-qeth*"`; @parms = split( '\n', $out ); return ( $parms[0] ); } # If no file is found -- Return nothing return; } #------------------------------------------------------- =head3 getIfcfgByNic Description : Get /etc/sysconfig/network/ifcfg-qeth file name for given NIC Arguments : Node NIC address Returns : /etc/sysconfig/network/ifcfg-qeth file name Example : my $ifcfg = xCAT::zvmUtils->getIfcfgByNic($node, $nic); =cut #------------------------------------------------------- sub getIfcfgByNic { # Get inputs my ( $class, $node, $nic ) = @_; # Get OS my $os = xCAT::zvmCPUtils->getOs($node); # Get network configuration file path my $out; my @parms; # If it is Red Hat -- ifcfg-qeth file is in /etc/sysconfig/network-scripts if ( $os =~ m/Red Hat/i ) { $out = `ssh -o ConnectTimeout=5 $node "ls /etc/sysconfig/network-scripts/ifcfg-eth*" | grep "$nic"`; @parms = split( '\n', $out ); return ( $parms[0] ); } # If it is SUSE -- ifcfg-qeth file is in /etc/sysconfig/network elsif ( $os =~ m/SUSE/i ) { $out = `ssh -o ConnectTimeout=5 $node "ls /etc/sysconfig/network/ifcfg-qeth*" | grep "$nic"`; @parms = split( '\n', $out ); return ( $parms[0] ); } # If no file is found -- Return nothing return; } #------------------------------------------------------- =head3 getBroadcastIP Description : Get IP broadcast of given node Arguments : Node Returns : IP broadcast Example : my $broadcast = xCAT::zvmUtils->getBroadcastIP($node); =cut #------------------------------------------------------- sub getBroadcastIP { # Get inputs my ( $class, $node ) = @_; # Get IP address my $out = `ssh -o ConnectTimeout=5 $node "ifconfig" | grep "Bcast:" | cut -d: -f3`; my @parms = split( ' ', $out ); return ( $parms[0] ); } #------------------------------------------------------- =head3 getDns Description : Get DNS server of given node Arguments : Node Returns : DNS server Example : my $dns = xCAT::zvmUtils->getDns($node); =cut #------------------------------------------------------- sub getDns { # Get inputs my ( $class, $node ) = @_; # Get IP address my $out = `ssh -o ConnectTimeout=5 $node "cat /etc/resolv.conf" | grep "nameserver"`; my @parms = split( ' ', $out ); return ( $parms[1] ); } #------------------------------------------------------- =head3 getGateway Description : Get default gateway of given node Arguments : Node Returns : Default gateway Example : my $gw = xCAT::zvmUtils->getGateway($node); =cut #------------------------------------------------------- sub getGateway { # Get inputs my ( $class, $node ) = @_; # Get IP address my $out = `ssh -o ConnectTimeout=5 $node "cat /etc/sysconfig/network/routes"`; my @parms = split( ' ', $out ); return ( $parms[1] ); } #------------------------------------------------------- =head3 sendFile Description : SCP file to given node Arguments : Node File Returns : Nothing Example : my $out = xCAT::zvmUtils->sendFile($node, $file); =cut #------------------------------------------------------- sub sendFile { # Get inputs my ( $class, $node, $file ) = @_; # Create destination string my $dest = "root@"; $dest .= $node; # SCP directory entry file over to HCP my $out = `scp $file $dest:$file`; return; } #------------------------------------------------------- =head3 getRootDiskAddr Description : Get root disk address of given node Arguments : Node name Returns : Root disk address Example : my $deviceNode = xCAT::zvmUtils->getRootDiskAddr($node); =cut #------------------------------------------------------- sub getRootDiskAddr { # Get inputs my ( $class, $node ) = @_; # Get device node mounted on (/) my $out = `ssh $node "mount" | grep "/ type" | sed 's/1//'`; my @parms = split( " ", $out ); @parms = split( "/", xCAT::zvmUtils->trimStr( $parms[0] ) ); my $devNode = $parms[0]; # Get disk address $out = `ssh $node "cat /proc/dasd/devices" | grep "$devNode" | sed 's/(ECKD)//' | sed 's/(FBA )//' | sed 's/0.0.//'`; @parms = split( " ", $out ); return ( $parms[0] ); } #------------------------------------------------------- =head3 disableEnableDisk Description : Disable or enable disk for given node Arguments : Device address Option [-d | -e] Returns : Nothing Example : my $out = xCAT::zvmUtils->disableEnableDisk($callback, $node, $option, $devAddr); =cut #------------------------------------------------------- sub disableEnableDisk { # Get inputs my ( $class, $callback, $node, $option, $devAddr ) = @_; # Disable or enable disk if ( $option eq "-d" || $option eq "-e" ) { my $out = `ssh $node "chccwdev $option $devAddr"`; } return; } #------------------------------------------------------- =head3 getMdisks Description : Get MDisk statements in user directory entry Arguments : Node Returns : MDisk statements Example : my @mdisks = xCAT::zvmUtils->getMdisks($callback, $node); =cut #------------------------------------------------------- sub getMdisks { # Get inputs my ( $class, $callback, $node ) = @_; # Directory where executables are my $dir = '/opt/zhcp/bin'; # Get HCP my @propNames = ( 'hcp', 'userid' ); my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames ); my $hcp = $propVals->{'hcp'}; # Get node userID my $userId = $propVals->{'userid'}; my $out = `ssh $hcp "$dir/getuserentry $userId" | grep "MDISK"`; # Get MDISK statements my @lines = split( '\n', $out ); my @disks; foreach (@lines) { $_ = xCAT::zvmUtils->trimStr($_); # Save MDISK statements push( @disks, $_ ); } return (@disks); } #------------------------------------------------------- =head3 readConfigFile Description : Read in configuration file Arguments : Node Configuration file Returns : Hash arrary containing node configuration Example : my %nodeConfig = xCAT::zvmUtils->readConfigFile($callback, $node, $file); =cut #------------------------------------------------------- sub readConfigFile { # Get inputs my ( $class, $callback, $node, $file ) = @_; # Hash array containing new node configuration my %target; # Get configuration file if ( !$file ) { xCAT::zvmUtils->printLn( $callback, "Error: Missing configuration file" ); return; } else { # Open configuration file open( CONFIG, $file ) || die("Error: Could not open file"); my @configFile = ; close(CONFIG); # Read configuration file my @parms; my $pattern = $node . ":"; my $save = 0; foreach (@configFile) { $_ = xCAT::zvmUtils->trimStr($_); # If the line contains specified node if ( $_ =~ m/$pattern/i ) { # Save configuration $save = 1; # Find ':' and replace with '' $_ =~ s/://g; $target{"Hostname"} = $_; } # Stop saving at next line containing ':' if ( $save == 1 && $_ =~ m/:/i ) { $save = 0; } # Save configuration if ( $save == 1 ) { # Create hash array @parms = split( "=", $_ ); $target{"$parms[0]"} = "$parms[1]"; } } # End of foreach } # End of else # If there is not a new node configuration if ( !$target{"Hostname"} ) { xCAT::zvmUtils->printLn( $callback, "Error: Node configuration not found" ); return; } return %target; } #------------------------------------------------------- =head3 saveDirEntryNoDisk Description : Get user directory entry for given node, remove MDISK statments, and save it to a file Arguments : Node name File name Returns : Nothing Example : my $out = xCAT::zvmUtils->saveDirEntryNoDisk($callback, $node, $file); =cut #------------------------------------------------------- sub saveDirEntryNoDisk { # Get inputs my ( $class, $callback, $node, $file ) = @_; # Directory where executables are my $dir = '/opt/zhcp/bin'; # Get node properties from 'zvm' table my @propNames = ( 'hcp', 'userid' ); my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames ); # Get HCP my $hcp = $propVals->{'hcp'}; if ( !$hcp ) { xCAT::zvmUtils->printLn( $callback, "Error: Missing node HCP" ); return; } # Get node userID my $userId = $propVals->{'userid'}; if ( !$userId ) { xCAT::zvmUtils->printLn( $callback, "Error: Missing node ID" ); return; } my $out = `ssh $hcp "$dir/getuserentry $userId" | grep -v "MDISK"`; # Create a file to save output open( DIRENTRY, ">$file" ); # Save output my @lines = split( '\n', $out ); foreach (@lines) { # Trim line $_ = xCAT::zvmUtils->trimStr($_); # Write directory entry into file print DIRENTRY "$_\n"; } close(DIRENTRY); return; } #------------------------------------------------------- =head3 appendHostname Description : Append specified hostname in front of given string Arguments : Hostname String Returns : String with hostname in front Example : my $str = xCAT::zvmUtils->appendHostname($hostname, $str); =cut #------------------------------------------------------- sub appendHostname { my ( $class, $hostname, $str ) = @_; # Append hostname to every line my @outLn = split( "\n", $str ); $str = ""; foreach (@outLn) { $str .= "$hostname: " . $_ . "\n"; } return $str; } #------------------------------------------------------- =head3 isOutputGood Description : Check return of given output Arguments : Output string Returns : 0 Good output -1 Bad output Example : my $ans = xCAT::zvmUtils->isOutputGood($callback, $out); =cut #------------------------------------------------------- sub isOutputGood { my ( $class, $callback, $out ) = @_; # Check output string my @outLn = split( "\n", $out ); foreach (@outLn) { # If output contains 'Failed' return -1 if ( $_ =~ m/Failed/i ) { return -1; } } return 0; } #------------------------------------------------------- =head3 isAddressUsed Description : Check if given address is used Arguments : Node Disk address Returns : 0 Address used -1 Address not used Example : my $ans = xCAT::zvmUtils->isAddressUsed($node, $address); =cut #------------------------------------------------------- sub isAddressUsed { my ( $class, $node, $address ) = @_; # Search for disk address my $out = `ssh -o ConnectTimeout=5 $node "vmcp q v dasd" | grep "DASD $address"`; if ($out) { return 0; } return -1; } #------------------------------------------------------- =head3 getMacID Description : Get MACID from /opt/zhcp/conf/next_mac on HCP Arguments : HCP node Returns : MACID Example : my $mac = xCAT::zvmUtils->getMacID($hcp); =cut #------------------------------------------------------- sub getMacID { my ( $class, $hcp ) = @_; # Check /opt/zhcp/conf directory on HCP my $out = `ssh -o ConnectTimeout=5 $hcp "test -d /opt/zhcp/conf && echo 'Directory exists'"`; if ( $out =~ m/Directory exists/i ) { # Read next_mac file $out = `ssh -o ConnectTimeout=5 $hcp "cat /opt/zhcp/conf/next_mac"`; } else { # Create /opt/zhcp/conf directory # Create next_mac -- Contains next MAC address to use $out = `ssh -o ConnectTimeout=5 $hcp "mkdir /opt/zhcp/conf"`; $out = `ssh -o ConnectTimeout=5 $hcp "echo 'FFFFFF' > /opt/zhcp/conf/next_mac"`; } # Create /opt/zhcp/conf/next_mac file on HCP $out = `ssh -o ConnectTimeout=5 $hcp "cat /opt/zhcp/conf/next_mac"`; my $mac = xCAT::zvmUtils->trimStr($out); return $mac; } #------------------------------------------------------- =head3 generateMac Description : Generate a MAC address Arguments : HCP node Returns : MAC suffix Example : my $mac = xCAT::zvmUtils->generateMac($hcp); =cut #------------------------------------------------------- sub generateMac { my ( $class, $hcp ) = @_; # Check /opt/zhcp/conf directory on HCP my $out = `ssh -o ConnectTimeout=5 $hcp "test -d /opt/zhcp/conf && echo 'Directory exists'"`; if ( $out =~ m/Directory exists/i ) { # Read next_mac file $out = `ssh -o ConnectTimeout=5 $hcp "cat /opt/zhcp/conf/next_mac"`; } else { # Create /opt/zhcp/conf directory # Create next_mac -- Contains next MAC address to use $out = `ssh -o ConnectTimeout=5 $hcp "mkdir /opt/zhcp/conf"`; $out = `ssh -o ConnectTimeout=5 $hcp "echo 'FFFFFF' > /opt/zhcp/conf/next_mac"`; } # Read /opt/zhcp/conf/next_mac file $out = `ssh -o ConnectTimeout=5 $hcp "cat /opt/zhcp/conf/next_mac"`; my $mac = xCAT::zvmUtils->trimStr($out); my $int; if ($mac) { # Convert hexadecimal to decimal $int = hex($mac); $mac = sprintf( "%d", $int ); # Generate new MAC suffix $mac = $mac - 1; # Convert decimal to hexadecimal $mac = sprintf( "%X", $mac ); $out = `ssh -o ConnectTimeout=5 $hcp "echo $mac > /opt/zhcp/conf/next_mac"`; } return $mac; # # Find the highest MAC address on given LAN # my $newMac = 0; # my $mac; # my $temp; # my $layer = -1; # my @vars; # my $out = `ssh -o ConnectTimeout=5 $hcp "vmcp --buffer 1000000 q lan $lanName details"`; # my @outLn = split( "\n", $out ); # # # Go through each line # foreach (@outLn) { # # # Get the MAC address for layer 3 LAN # if ( $layer == 3 ) { # @vars = split( " ", $_ ); # $mac = $vars[2]; # # # Replace - with : # $mac = xCAT::zvmUtils->replaceStr( $mac, "-", ":" ); # # # Convert to decimal # if ($mac) { # # # Remove dash # $temp = xCAT::zvmUtils->replaceStr( $mac, ":", "" ); # # $temp = hex($temp); # $mac = sprintf( "%d", $temp ); # } # # # Compare MAC address value to previous one # # Save the highest MAC address # if ( $mac > $newMac ) { # $newMac = $mac; # } # # $layer = -1; # } # # # Get the MAC address for layer 2 LAN # elsif ( $layer == 2 ) { # @vars = split( " ", $_ ); # $mac = $vars[0]; # # # Replace - with : # $mac = xCAT::zvmUtils->replaceStr( $mac, "-", ":" ); # # # Convert to decimal # if ($mac) { # # # Remove dash # $temp = xCAT::zvmUtils->replaceStr( $mac, ":", "" ); # # $temp = hex($temp); # $mac = sprintf( "%d", $temp ); # } # # # Compare MAC address value to previous one # # Save the highest MAC address # if ( $mac > $newMac ) { # $newMac = $mac; # } # # $layer = -1; # } # # # If the line contains 'Unicast IP/MAC Addresses' -- Then the next line contain a MAC address # if ( $_ =~ m/Unicast IP Addresses/i ) { # $layer = 3; # } # elsif ( $_ =~ m/ Unicast MAC Addresses/i ) { # $layer = 2; # } # } # # # Convert the highest MAC address from decimal to hexadecimal # $newMac = $newMac + 1; # $newMac = sprintf( "%x", $newMac ); # # # Append a zero if length is less than 12 # if ( length($newMac) != 12 ) { # $newMac = "0" . $newMac; # } # # $newMac = # substr( $newMac, 0, 2 ) . ":" # . substr( $newMac, 2, 2 ) . ":" # . substr( $newMac, 4, 2 ) . ":" # . substr( $newMac, 6, 2 ) . ":" # . substr( $newMac, 8, 2 ) . ":" # . substr( $newMac, 10, 2 ); # # return $newMac; }