git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@16922 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			2980 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			2980 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2013 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 xCAT::NetworkUtils;
 | 
						|
use File::Basename;
 | 
						|
use strict;
 | 
						|
use warnings;
 | 
						|
1;
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getNodeProps
 | 
						|
    Description : Get node properties
 | 
						|
    Arguments   :   Table
 | 
						|
                    Node
 | 
						|
                    Properties
 | 
						|
    Returns     : Node properties from given table
 | 
						|
    Example     : my $propVals = xCAT::zvmUtils->getNodeProps($tabName, $node, $propNames);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getNodeProps {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName, $node, @propNames ) = @_;
 | 
						|
 | 
						|
    # Get table
 | 
						|
    my $tab = xCAT::Table->new($tabName);
 | 
						|
 | 
						|
    # Get property values
 | 
						|
    my $propVals = $tab->getNodeAttribs( $node, [@propNames] );
 | 
						|
 | 
						|
    return ($propVals);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getTabPropsByKey
 | 
						|
    Description : Get table entry properties by key
 | 
						|
    Arguments   :   Table
 | 
						|
                    Key name
 | 
						|
                    Key value
 | 
						|
                    Requested properties
 | 
						|
    Returns     : Table entry properties
 | 
						|
    Example     : my $propVals = xCAT::zvmUtils->getTabPropsByKey($tabName, $key, $keyValue, @reqProps);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getTabPropsByKey {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName, $key, $keyVal, @propNames ) = @_;
 | 
						|
 | 
						|
    # Get table
 | 
						|
    my $tab = xCAT::Table->new($tabName);
 | 
						|
    my $propVals;
 | 
						|
 | 
						|
    # Get table attributes matching given key
 | 
						|
    $propVals = $tab->getAttribs( { $key => $keyVal }, @propNames );
 | 
						|
    return ($propVals);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getAllTabEntries
 | 
						|
    Description : Get all entries within given table
 | 
						|
    Arguments   : Table name
 | 
						|
    Returns     : All table entries
 | 
						|
    Example     : my $entries = xCAT::zvmUtils->getAllTabEntries($tabName);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getAllTabEntries {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName ) = @_;
 | 
						|
 | 
						|
    # Get table
 | 
						|
    my $tab = xCAT::Table->new($tabName);
 | 
						|
    my $entries;
 | 
						|
 | 
						|
    # Get all entries within given table
 | 
						|
    $entries = $tab->getAllEntries();
 | 
						|
    return ($entries);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   setNodeProp
 | 
						|
 | 
						|
    Description : Set a node property in a given table
 | 
						|
    Arguments   :   Table
 | 
						|
                    Node
 | 
						|
                    Property name
 | 
						|
                    Property value
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->setNodeProp($tabName, $node, $propName, $propVal);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub setNodeProp {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName, $node, $propName, $propVal ) = @_;
 | 
						|
 | 
						|
    # Get 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   setNodeProps
 | 
						|
 | 
						|
    Description : Set node properties in a given table
 | 
						|
    Arguments   :   Table
 | 
						|
                    Node
 | 
						|
                    Reference to property name/value hash
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->setNodeProps($tabName, $node, \%propHash);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub setNodeProps {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName, $node, $propHash ) = @_;
 | 
						|
 | 
						|
    # Get table
 | 
						|
    my $tab = xCAT::Table->new( $tabName, -create => 1, -autocommit => 0 );
 | 
						|
 | 
						|
    # Set property
 | 
						|
    $tab->setAttribs( { 'node' => $node }, $propHash );
 | 
						|
 | 
						|
    # Save table
 | 
						|
    $tab->commit;
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   delTabEntry
 | 
						|
 | 
						|
    Description : Delete a table entry
 | 
						|
    Arguments   :   Table
 | 
						|
                    Key name
 | 
						|
                    Key value 
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->delTabEntry($tabName, $keyName, $keyVal);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub delTabEntry {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $tabName, $keyName, $keyVal ) = @_;
 | 
						|
 | 
						|
    # Get table
 | 
						|
    my $tab = xCAT::Table->new( $tabName, -create => 1, -autocommit => 0 );
 | 
						|
 | 
						|
    # Delete entry from table
 | 
						|
    my %key = ( $keyName => $keyVal );
 | 
						|
    $tab->delEntries( \%key );
 | 
						|
 | 
						|
    # Save table
 | 
						|
    $tab->commit;
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   tabStr
 | 
						|
 | 
						|
    Description : Tab a 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 the whitespaces in a 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 a given pattern in a string
 | 
						|
    Arguments   : String
 | 
						|
    Returns     : New 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 a string to stdout
 | 
						|
    Arguments   : String
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->printLn($callback, $str);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub printLn {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $callback, $str ) = @_;
 | 
						|
 | 
						|
    # Print string
 | 
						|
    my $rsp;
 | 
						|
    my $type = "I";
 | 
						|
    if ($str =~ m/error/i) {  # Set to print error if the string contains error
 | 
						|
        $type = "E";
 | 
						|
    }
 | 
						|
    
 | 
						|
    $rsp->{data}->[0] = "$str";
 | 
						|
    xCAT::MsgUtils->message( $type, $rsp, $callback );
 | 
						|
    # xCAT::MsgUtils->message( "S", $str );  # Print to syslog
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   printSyslog
 | 
						|
 | 
						|
    Description : Print a string to syslog
 | 
						|
    Arguments   : String
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->printSyslog($str);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub printSyslog {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $str ) = @_;
 | 
						|
 | 
						|
    # Prepend where this message came from
 | 
						|
    $str = $class . "  " . $str;
 | 
						|
 | 
						|
    # Print string
 | 
						|
    xCAT::MsgUtils->message( "S", $str );
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   isZvmNode
 | 
						|
 | 
						|
    Description : Determines if a given 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 ) = @_;
 | 
						|
 | 
						|
    # Look in 'zvm' table
 | 
						|
    my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 );
 | 
						|
 | 
						|
    my @results = $tab->getAllAttribsWhere( "node like '%" . $node . "%'", 'userid' );
 | 
						|
    foreach (@results) {
 | 
						|
 | 
						|
        # Return 'TRUE' if given node is in the table
 | 
						|
        if ($_->{'userid'}) {
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getHwcfg
 | 
						|
 | 
						|
    Description : Get the hardware configuration file path (SUSE only)
 | 
						|
                  e.g. /etc/sysconfig/hardwarehwcfg-qeth-bus-ccw-0.0.0600
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Hardware configuration file path
 | 
						|
    Example     : my $hwcfg = xCAT::zvmUtils->getHwcfg($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getHwcfg {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get OS
 | 
						|
    my $os = xCAT::zvmUtils->getOs($user, $node);
 | 
						|
 | 
						|
    # Get network configuration file path
 | 
						|
    my $out;
 | 
						|
    my @parms;
 | 
						|
 | 
						|
    # If it is SUSE - hwcfg-qeth file is in /etc/sysconfig/hardware
 | 
						|
    if ( $os =~ m/SUSE/i ) {
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo ls /etc/sysconfig/hardware/hwcfg-qeth*"`;
 | 
						|
        @parms = split( '\n', $out );
 | 
						|
        return ( $parms[0] );
 | 
						|
    }
 | 
						|
 | 
						|
    # If no file is found - Return nothing
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getIp
 | 
						|
 | 
						|
    Description : Get the IP address of a given node
 | 
						|
    Arguments   : Node
 | 
						|
    Returns     : IP address of given node
 | 
						|
    Example     : my $ip = xCAT::zvmUtils->getIp($node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getIp {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $node ) = @_;
 | 
						|
 | 
						|
    # Get IP address
 | 
						|
    # You need the extra space in the pattern,
 | 
						|
    # else it will confuse gpok2 with gpok21
 | 
						|
    my $out   = `cat /etc/hosts | egrep -i "$node | $node."`;
 | 
						|
    my @parms = split( ' ', $out );
 | 
						|
 | 
						|
    return $parms[0];
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getIfcfg
 | 
						|
 | 
						|
    Description : Get the network configuration file path of a given node
 | 
						|
                    * Red Hat - /etc/sysconfig/network-scripts/ifcfg-eth
 | 
						|
                    * SUSE    - /etc/sysconfig/network/ifcfg-qeth
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Network configuration file path
 | 
						|
    Example     : my $ifcfg = xCAT::zvmUtils->getIfcfg($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getIfcfg {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Get OS
 | 
						|
    my $os = xCAT::zvmUtils->getOs($user, $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 $user\@$node "$sudo 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 $user\@$node "$sudo 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 the network configuration file path of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    NIC address
 | 
						|
    Returns     : Network configuration file path
 | 
						|
    Example     : my $ifcfg = xCAT::zvmUtils->getIfcfgByNic($user, $node, $nic);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getIfcfgByNic {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node, $nic ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get OS
 | 
						|
    my $os = xCAT::zvmUtils->getOs($user, $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 $user\@$node "$sudo ls /etc/sysconfig/network-scripts/ifcfg-eth*"`;
 | 
						|
        @parms = split( '\n', $out );
 | 
						|
 | 
						|
        # Go through each line
 | 
						|
        foreach (@parms) {
 | 
						|
 | 
						|
            # If the network file contains the NIC address
 | 
						|
            $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | egrep -i "$nic"`;
 | 
						|
            if ($out) {
 | 
						|
 | 
						|
                # Return network file path
 | 
						|
                return ($_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # If it is SLES 10 - ifcfg-qeth file is in /etc/sysconfig/network
 | 
						|
    elsif ( $os =~ m/SUSE Linux Enterprise Server 10/i ) {
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo ls /etc/sysconfig/network/ifcfg-qeth*" | grep -i "$nic"`;
 | 
						|
        @parms = split( '\n', $out );
 | 
						|
        return ( $parms[0] );
 | 
						|
    }
 | 
						|
 | 
						|
    # If it is SLES 11 - ifcfg-qeth file is in /etc/sysconfig/network
 | 
						|
    elsif ( $os =~ m/SUSE Linux Enterprise Server 11/i ) {
 | 
						|
 | 
						|
        # Get a list of ifcfg-eth files found
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo ls /etc/sysconfig/network/ifcfg-eth*"`;
 | 
						|
        my @file = split( '\n', $out );
 | 
						|
 | 
						|
        # Go through each ifcfg-eth file
 | 
						|
        foreach (@file) {
 | 
						|
 | 
						|
            # If the network file contains the NIC address
 | 
						|
            $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | grep -i "$nic"`;
 | 
						|
            if ($out) {
 | 
						|
 | 
						|
                # Return ifcfg-eth file path
 | 
						|
                return ($_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # If no file is found - Return nothing
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   sendFile
 | 
						|
 | 
						|
    Description : SCP a file to a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Source file
 | 
						|
                    Target file
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : xCAT::zvmUtils->sendFile($user, $node, $srcFile, $trgtFile);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub sendFile {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node, $srcFile, $trgtFile ) = @_;
 | 
						|
 | 
						|
    # Create destination string
 | 
						|
    my $dest = "$user\@$node";
 | 
						|
 | 
						|
    # SCP directory entry file over to HCP
 | 
						|
    my $out = `/usr/bin/scp $srcFile $dest:$trgtFile`;
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getRootDeviceAddr
 | 
						|
 | 
						|
    Description : Get the root device address of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Root device address
 | 
						|
    Example     : my $deviceAddr = xCAT::zvmUtils->getRootDeviceAddr($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getRootDeviceAddr {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
 | 
						|
    # Get the root device node
 | 
						|
    # LVM is not supported
 | 
						|
    my $out = `ssh $user\@$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 $user\@$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/enable a disk for a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Device address
 | 
						|
                    Option (-d|-e)
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : my $out = xCAT::zvmUtils->disableEnableDisk($callback, $user, $node, $option, $devAddr);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub disableEnableDisk {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node, $option, $devAddr ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Disable/enable disk
 | 
						|
    my $out;
 | 
						|
    if ( $option eq "-d" || $option eq "-e" ) {
 | 
						|
        $out = `ssh $user\@$node "$sudo /sbin/chccwdev $option $devAddr"`;
 | 
						|
    }
 | 
						|
 | 
						|
    return ($out);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getMdisks
 | 
						|
 | 
						|
    Description : Get the MDISK statements in the user entry of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : MDISK statements
 | 
						|
    Example     : my @mdisks = xCAT::zvmUtils->getMdisks($callback, $user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getMdisks {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $callback, $user, $node ) = @_;
 | 
						|
 | 
						|
    # Directory where executables are
 | 
						|
    my $dir = '/opt/zhcp/bin';
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # 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 $user\@$hcp "$sudo $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   getDedicates
 | 
						|
 | 
						|
    Description : Get the DEDICATE statements in the user entry of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : DEDICATE statements
 | 
						|
    Example     : my @dedicates = xCAT::zvmUtils->getDedicates($callback, $user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getDedicates {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $callback, $user, $node ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Directory where executables are
 | 
						|
    my $dir = '/opt/zhcp/bin';
 | 
						|
    
 | 
						|
    # Get zHCP
 | 
						|
    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 $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId" | egrep -i "DEDICATE"`;
 | 
						|
    
 | 
						|
    # Get DEDICATE statements
 | 
						|
    my @lines = split( '\n', $out );
 | 
						|
    my @dedicates;
 | 
						|
    foreach (@lines) {
 | 
						|
        $_ = xCAT::zvmUtils->trimStr($_);
 | 
						|
 | 
						|
        # Save statements
 | 
						|
        push( @dedicates, $_ );
 | 
						|
    }
 | 
						|
 | 
						|
    return (@dedicates);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getUserEntryWODisk
 | 
						|
 | 
						|
    Description : Get the user entry of a given node without MDISK statments, 
 | 
						|
                  and save it to a file
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    File name to save user entry under
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getUserEntryWODisk($callback, $user, $node, $file);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getUserEntryWODisk {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $callback, $user, $node, $file ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # 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 $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId" | sed '\$d' | 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 a hostname in front of a given string
 | 
						|
    Arguments   :   Hostname
 | 
						|
                    String
 | 
						|
    Returns     : String appended with hostname
 | 
						|
    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   checkOutput
 | 
						|
 | 
						|
    Description : Check the return of given output
 | 
						|
    Arguments   : Output string
 | 
						|
    Returns     :    0  Good output
 | 
						|
                    -1  Bad output
 | 
						|
    Example     : my $rtn = xCAT::zvmUtils->checkOutput($callback, $out);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub checkOutput {
 | 
						|
    my ( $class, $callback, $out ) = @_;
 | 
						|
 | 
						|
    # Check output string
 | 
						|
    my @outLn = split( "\n", $out );
 | 
						|
    foreach (@outLn) {
 | 
						|
 | 
						|
        # If output contains 'Failed', return -1
 | 
						|
        if ( $_ =~ m/Failed/i || $_ =~ m/Error/i ) {
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   checkOutputExtractReason
 | 
						|
 | 
						|
    Description : Check the return of given output. If bad, extract the reason.
 | 
						|
    Arguments   : Output string
 | 
						|
                  Reason (passed as a reference)
 | 
						|
    Returns     :    0  Good output
 | 
						|
                    -1  Bad output
 | 
						|
    Example     : my $rtn = xCAT::zvmUtils->checkOutput($callback, $out, \$reason);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub checkOutputExtractReason {
 | 
						|
    my ( $class, $callback, $out, $reason ) = @_;
 | 
						|
 | 
						|
    # Check output string
 | 
						|
    my @outLn = split("\n", $out);
 | 
						|
    foreach (@outLn) {
 | 
						|
        # If output contains 'ERROR: ', return -1 and pass back the reason.
 | 
						|
        if ($_ =~ /(.*?ERROR: )/) {
 | 
						|
            $$reason = substr($_, index($_, "ERROR: ") + length("ERROR: "));
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getDeviceNode
 | 
						|
 | 
						|
    Description : Get the device node for a given address
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Disk address
 | 
						|
    Returns     : Device node
 | 
						|
    Example     : my $devNode = xCAT::zvmUtils->getDeviceNode($user, $node, $tgtAddr);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getDeviceNode {
 | 
						|
    my ( $class, $user, $node, $tgtAddr ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Determine device node
 | 
						|
    my $out = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep ".$tgtAddr("`;
 | 
						|
    my @words = split(' ', $out);
 | 
						|
    my $tgtDevNode;
 | 
						|
 | 
						|
    # /proc/dasd/devices look similar to this:
 | 
						|
    # 0.0.0100(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 1802880 blocks, 7042 MB
 | 
						|
    # Look for the string 'is'
 | 
						|
    my $i = 0;
 | 
						|
    while ($tgtDevNode ne 'is') {
 | 
						|
        $tgtDevNode = $words[$i];
 | 
						|
        $i++;
 | 
						|
    }
 | 
						|
 | 
						|
    return $words[$i];
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getDeviceNodeAddr
 | 
						|
 | 
						|
    Description : Get the virtual device address for a given device node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Device node
 | 
						|
    Returns     : Virtual device address
 | 
						|
    Example     : my $addr = xCAT::zvmUtils->getDeviceNodeAddr($user, $node, $deviceNode);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getDeviceNodeAddr {
 | 
						|
    my ( $class, $user, $node, $deviceNode ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Find device node and determine virtual address
 | 
						|
    #   /proc/dasd/devices look similar to this:
 | 
						|
    #   0.0.0100(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 1802880 blocks, 7042 MB
 | 
						|
    my $addr = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep -i "is $deviceNode"`;
 | 
						|
    $addr =~ s/ +/ /g;
 | 
						|
    $addr =~ s/^0.0.([0-9a-f]*).*/$1/;
 | 
						|
    chomp($addr);
 | 
						|
 | 
						|
    return $addr;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   isAddressUsed
 | 
						|
 | 
						|
    Description : Check if a given address is used
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Disk address
 | 
						|
    Returns     :  0  Address used
 | 
						|
                  -1  Address not used
 | 
						|
    Example     : my $ans = xCAT::zvmUtils->isAddressUsed($user, $node, $address);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub isAddressUsed {
 | 
						|
    my ( $class, $user, $node, $address ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Search for disk address
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q v dasd" | grep "DASD $address"`;
 | 
						|
    if ($out) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getMacID
 | 
						|
 | 
						|
    Description : Get the MACID from /opt/zhcp/conf/next_macid on the HCP
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : MACID
 | 
						|
    Example     : my $macId = xCAT::zvmUtils->getMacID($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getMacID {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Check /opt/zhcp/conf directory on HCP
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo test -d /opt/zhcp/conf && echo 'Directory exists'"`;
 | 
						|
    if ( $out =~ m/Directory exists/i ) {
 | 
						|
 | 
						|
        # Check next_macid file
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo test -e /opt/zhcp/conf/next_macid && echo 'File exists'"`;
 | 
						|
        if ( $out =~ m/File exists/i ) {
 | 
						|
 | 
						|
            # Do nothing
 | 
						|
        } else {
 | 
						|
 | 
						|
            # Create next_macid file
 | 
						|
            $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo echo 'FFFFF0' > /opt/zhcp/conf/next_macid"`;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
 | 
						|
        # Create /opt/zhcp/conf directory
 | 
						|
        # Create next_mac - Contains next MAC address to use
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo mkdir /opt/zhcp/conf"`;
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo echo 'FFFFF0' > /opt/zhcp/conf/next_macid"`;
 | 
						|
    }
 | 
						|
 | 
						|
    # Read /opt/zhcp/conf/next_macid file
 | 
						|
    $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /opt/zhcp/conf/next_macid"`;
 | 
						|
    my $macId = xCAT::zvmUtils->trimStr($out);
 | 
						|
 | 
						|
    return $macId;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   generateMacId
 | 
						|
 | 
						|
    Description : Generate a new MACID 
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Nothing
 | 
						|
    Example     : my $macId = xCAT::zvmUtils->generateMacId($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub generateMacId {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Check /opt/zhcp/conf directory on HCP
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo test -d /opt/zhcp/conf && echo 'Directory exists'"`;
 | 
						|
    if ( $out =~ m/Directory exists/i ) {
 | 
						|
 | 
						|
        # Check next_macid file
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo test -e /opt/zhcp/conf/next_macid && echo 'File exists'"`;
 | 
						|
        if ( $out =~ m/File exists/i ) {
 | 
						|
 | 
						|
            # Do nothing
 | 
						|
        } else {
 | 
						|
 | 
						|
            # Create next_macid file
 | 
						|
            $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo echo 'FFFFF0' > /opt/zhcp/conf/next_macid"`;
 | 
						|
            $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /bin/chmod 666 /opt/zhcp/conf/next_macid"`;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
 | 
						|
        # Create /opt/zhcp/conf directory
 | 
						|
        # Create next_mac - Contains next MAC address to use
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo mkdir /opt/zhcp/conf"`;
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo echo 'FFFFF0' > /opt/zhcp/conf/next_macid"`;
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /bin/chmod 666 /opt/zhcp/conf/next_macid"`;
 | 
						|
    }
 | 
						|
 | 
						|
    # Read /opt/zhcp/conf/next_macid file
 | 
						|
    $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /opt/zhcp/conf/next_macid"`;
 | 
						|
    my $macId = xCAT::zvmUtils->trimStr($out);
 | 
						|
    my $int;
 | 
						|
 | 
						|
    if ($macId) {
 | 
						|
 | 
						|
        # Convert hexadecimal - decimal
 | 
						|
        $int   = hex($macId);
 | 
						|
        $macId = sprintf( "%d", $int );
 | 
						|
 | 
						|
        # Generate new MAC suffix
 | 
						|
        $macId = $macId - 1;
 | 
						|
 | 
						|
        # Convert decimal - hexadecimal
 | 
						|
        $macId = sprintf( "%X", $macId );
 | 
						|
 | 
						|
        # Save new MACID
 | 
						|
        $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo echo $macId > /opt/zhcp/conf/next_macid"`;
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   createMacAddr
 | 
						|
 | 
						|
    Description : Create a MAC address using the HCP MAC prefix and a given MAC suffix
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    MAC suffix
 | 
						|
    Returns     : MAC address
 | 
						|
    Example     : my $mac = xCAT::zvmUtils->createMacAddr($user, $node, $suffix);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub createMacAddr {
 | 
						|
    my ( $class, $user, $node, $suffix ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get node properties from 'zvm' table
 | 
						|
    my @propNames = ('hcp');
 | 
						|
    my $propVals  = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames );
 | 
						|
 | 
						|
    # Get HCP
 | 
						|
    my $hcp = $propVals->{'hcp'};
 | 
						|
    if ( !$hcp ) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    # Get USER Prefix
 | 
						|
    my $prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "USER Prefix:"`;
 | 
						|
    $prefix =~ s/(.*?)USER Prefix:(.*)/$2/;
 | 
						|
    $prefix =~ s/^\s+//;
 | 
						|
    $prefix =~ s/\s+$//;
 | 
						|
                        
 | 
						|
    # Get MACADDR Prefix instead if USER Prefix is not defined
 | 
						|
    if (!$prefix) {
 | 
						|
        $prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "MACADDR Prefix:"`;
 | 
						|
        $prefix =~ s/(.*?)MACADDR Prefix:(.*)/$2/;
 | 
						|
        $prefix =~ s/^\s+//;
 | 
						|
        $prefix =~ s/\s+$//;
 | 
						|
        
 | 
						|
        if (!$prefix) {
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Generate MAC address of source node
 | 
						|
    my $mac = $prefix . $suffix;
 | 
						|
 | 
						|
    # If length is less than 12, append a zero
 | 
						|
    if ( length($mac) != 12 ) {
 | 
						|
        $mac = "0" . $mac;
 | 
						|
    }
 | 
						|
 | 
						|
    # Format MAC address
 | 
						|
    $mac =
 | 
						|
        substr( $mac, 0, 2 ) . ":"
 | 
						|
      . substr( $mac, 2,  2 ) . ":"
 | 
						|
      . substr( $mac, 4,  2 ) . ":"
 | 
						|
      . substr( $mac, 6,  2 ) . ":"
 | 
						|
      . substr( $mac, 8,  2 ) . ":"
 | 
						|
      . substr( $mac, 10, 2 );
 | 
						|
 | 
						|
    return $mac;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getOs
 | 
						|
 | 
						|
    Description : Get the operating system of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Operating system name
 | 
						|
    Example     : my $osName = xCAT::zvmUtils->getOs($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getOs {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Get operating system
 | 
						|
    my $out = `ssh -o ConnectTimeout=10 $user\@$node "$sudo cat /etc/*release" | egrep -v "LSB_VERSION"`;
 | 
						|
    my @results = split( '\n', $out );
 | 
						|
    return ( xCAT::zvmUtils->trimStr( $results[0] ) );
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getArch
 | 
						|
 | 
						|
    Description : Get the architecture of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Architecture of node
 | 
						|
    Example     : my $arch = xCAT::zvmUtils->getArch($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getArch {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Get host using VMCP
 | 
						|
    my $arch = `ssh $user\@$node "$sudo uname -p"`;
 | 
						|
 | 
						|
    return ( xCAT::zvmUtils->trimStr($arch) );
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getUserProfile
 | 
						|
 | 
						|
    Description : Get the user profile
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Profile name
 | 
						|
    Returns     : User profile
 | 
						|
    Example     : my $profile = xCAT::zvmUtils->getUserProfile($user, $hcp, $name);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getUserProfile {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $hcp, $profile ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    # Set directory where executables are on zHCP
 | 
						|
    my $hcpDir = "/opt/zhcp/bin";
 | 
						|
        
 | 
						|
    my $out;
 | 
						|
 | 
						|
    # Set directory for cache
 | 
						|
    my $cache = '/var/opt/zhcp/cache';
 | 
						|
    # If the cache directory does not exist
 | 
						|
    if (!(`ssh $user\@$hcp "$sudo test -d $cache && echo Exists"`)) {
 | 
						|
        # Create cache directory
 | 
						|
        $out = `ssh $user\@$hcp "$sudo mkdir -p $cache"`;
 | 
						|
    }
 | 
						|
 | 
						|
    # Set output file name
 | 
						|
    my $file = "$cache/$profile.profile";
 | 
						|
 | 
						|
    # If a cache for the user profile exists
 | 
						|
    if (`ssh $user\@$hcp "$sudo ls $file"`) {
 | 
						|
 | 
						|
        # Get current Epoch
 | 
						|
        my $curTime = time();
 | 
						|
 | 
						|
        # Get time of last change as seconds since Epoch
 | 
						|
        my $fileTime = xCAT::zvmUtils->trimStr(`ssh $user\@$hcp "$sudo stat -c %Z $file"`);
 | 
						|
 | 
						|
        # If the current time is greater than 5 minutes of the file timestamp
 | 
						|
        my $interval = 300;    # 300 seconds = 5 minutes * 60 seconds/minute
 | 
						|
        if ( $curTime > $fileTime + $interval ) {
 | 
						|
 | 
						|
            # Get user profiles and save it in a file
 | 
						|
            $out = `ssh $user\@$hcp "$sudo $hcpDir/smcli Profile_Query_DM -T $profile > $file"`;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
 | 
						|
        # Get user profiles and save it in a file
 | 
						|
        $out = `ssh $user\@$hcp "$sudo $hcpDir/smcli Profile_Query_DM -T $profile > $file"`;
 | 
						|
    }
 | 
						|
 | 
						|
    # Return the file contents
 | 
						|
    $out = `ssh $user\@$hcp "$sudo cat $file"`;
 | 
						|
    return $out;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   inArray
 | 
						|
 | 
						|
    Description : Checks if a value exists in an array
 | 
						|
    Arguments   :   Search value
 | 
						|
                    Search array
 | 
						|
    Returns     : The searched expression
 | 
						|
    Example     : my $rtn = xCAT::zvmUtils->inArray($needle, @haystack);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub inArray {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $needle, @haystack ) = @_;
 | 
						|
    return grep{ $_ eq $needle } @haystack;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getOsVersion
 | 
						|
 | 
						|
    Description : Get the operating system of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Operating system name
 | 
						|
    Example     : my $os = xCAT::zvmUtils->getOsVersion($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getOsVersion {
 | 
						|
    
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $os = '';
 | 
						|
    my $version = '';
 | 
						|
 | 
						|
    # Get operating system
 | 
						|
    my $release = `ssh -o ConnectTimeout=2 $user\@$node "$sudo cat /etc/*release"`;
 | 
						|
    my @lines = split('\n', $release);
 | 
						|
    if (grep(/SUSE Linux Enterprise Server/, @lines)) {
 | 
						|
        $os = 'sles';
 | 
						|
        $version = `echo "$release" | grep "VERSION ="`;
 | 
						|
        $version =~ s/\s*$//;
 | 
						|
        $version =~ s/^\s*//;
 | 
						|
        $version =~ tr/\.//;
 | 
						|
        $version =~ s/[^0-9]*([0-9]+).*/$1/;
 | 
						|
        $os = $os . $version;
 | 
						|
        
 | 
						|
        # Append service level
 | 
						|
        $version = `echo "$release" | grep "LEVEL ="`;
 | 
						|
        $version =~ s/\s*$//;
 | 
						|
        $version =~ s/^\s*//;
 | 
						|
        $version =~ tr/\.//;
 | 
						|
        $version =~ s/[^0-9]*([0-9]+).*/$1/;
 | 
						|
        $os = $os . 'sp' . $version;
 | 
						|
    } elsif (grep(/Red Hat Enterprise Linux Server/, @lines)) {
 | 
						|
        $os = 'rhel';
 | 
						|
        $version = $lines[0];
 | 
						|
        $version =~ tr/\.//;
 | 
						|
        $version =~ s/([A-Za-z\s\(\)]+)//g;
 | 
						|
        $os = $os . $version;
 | 
						|
    }
 | 
						|
 | 
						|
    return xCAT::zvmUtils->trimStr($os);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getZfcpInfo
 | 
						|
 | 
						|
    Description : Get the zFCP device info
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : zFCP device info
 | 
						|
    Example     : my $info = xCAT::zvmUtils->getZfcpInfo($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getZfcpInfo {
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get zFCP device info
 | 
						|
    my $info = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/lszfcp -D"`;
 | 
						|
    my @zfcp = split("\n", $info);
 | 
						|
    if (!$info || $info =~ m/No zfcp support/i || $info =~ m/No fcp devices found/i) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get SCSI device and their attributes
 | 
						|
    my $scsi = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /usr/bin/lsscsi"`;
 | 
						|
    $info = "";
 | 
						|
        
 | 
						|
    my @args;
 | 
						|
    my $tmp;
 | 
						|
    my $id;
 | 
						|
    my $device;
 | 
						|
    my $wwpn;
 | 
						|
    my $lun;
 | 
						|
    my $size;
 | 
						|
    
 | 
						|
    foreach (@zfcp) {
 | 
						|
        @args = split(" ", $_);
 | 
						|
        $id = $args[1];
 | 
						|
        @args = split("/", $args[0]);
 | 
						|
        
 | 
						|
        $device = $args[0];
 | 
						|
        $wwpn = $args[1];
 | 
						|
        $lun = $args[2];
 | 
						|
        
 | 
						|
        # Make sure WWPN and LUN do not have 0x prefix
 | 
						|
        $wwpn = xCAT::zvmUtils->replaceStr($wwpn, "0x", "");
 | 
						|
        $lun = xCAT::zvmUtils->replaceStr($lun, "0x", "");
 | 
						|
        
 | 
						|
        # Find the device name
 | 
						|
        $tmp = `echo "$scsi" | egrep -i $id`;
 | 
						|
        $tmp = substr($tmp, index($tmp, "/dev/"));
 | 
						|
        chomp($tmp);
 | 
						|
        
 | 
						|
        # Find the size in MiB
 | 
						|
        $size = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /usr/bin/sg_readcap $tmp" | egrep -i "Device size:"`;
 | 
						|
        $size =~ s/Device size: //g;
 | 
						|
        @args = split(",", $size);
 | 
						|
        $size = xCAT::zvmUtils->trimStr($args[1]);
 | 
						|
 | 
						|
        $info .= "Device: $device  WWPN: 0x$wwpn  LUN: 0x$lun  Size: $size\n";
 | 
						|
    }
 | 
						|
 | 
						|
    $info = xCAT::zvmUtils->tabStr($info);
 | 
						|
    return ($info);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   isHypervisor
 | 
						|
 | 
						|
    Description : Determines if a given node is in the 'hypervisor' table
 | 
						|
    Arguments   : Node
 | 
						|
    Returns     :   1   Node exists
 | 
						|
                    0   Node does not exists
 | 
						|
    Example     : my $out = xCAT::zvmUtils->isHypervisor($node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub isHypervisor {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $node ) = @_;
 | 
						|
    
 | 
						|
    # Look in 'zvm' table
 | 
						|
    my $tab = xCAT::Table->new( "hypervisor", -create => 1, -autocommit => 0 );
 | 
						|
 | 
						|
    my @results = $tab->getAllAttribsWhere( "node like '%" . $node . "%'", 'type' );
 | 
						|
    foreach (@results) {
 | 
						|
        
 | 
						|
        # Return 'TRUE' if given node is in the table
 | 
						|
        if ($_->{"type"} eq "zvm") {
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getSudoer
 | 
						|
 | 
						|
    Description : Retrieve sudoer user name
 | 
						|
    Arguments   : Node
 | 
						|
    Returns     :   Sudoer user name
 | 
						|
                    Sudo keyword
 | 
						|
    Example     : my ($sudoer, $sudo) = xCAT::zvmUtils->getSudoer();
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getSudoer {
 | 
						|
    # Get inputs
 | 
						|
    my ( $class ) = @_;
 | 
						|
    
 | 
						|
    # Use sudo or not on zHCP
 | 
						|
    my @propNames = ('username');
 | 
						|
    my $propVals = xCAT::zvmUtils->getTabPropsByKey( 'passwd', 'key', 'sudoer', @propNames );
 | 
						|
    my $sudo = "sudo";
 | 
						|
    my $user = $propVals->{'username'};
 | 
						|
    
 | 
						|
    if (!$user) {
 | 
						|
        $user = "root";
 | 
						|
    }
 | 
						|
    
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    return ($user, $sudo);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getFreeAddress
 | 
						|
 | 
						|
    Description : Get a free(unused) virtual address
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Type (vmcp or non-vmcp)
 | 
						|
    Returns     : vdev  An address which is free to use
 | 
						|
                  -1    No free address is left
 | 
						|
    Example     : my $vdev = xCAT::zvmUtils->getFreeAddress($user, $node, $type);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getFreeAddress {
 | 
						|
    my ( $class, $user, $node, $type ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Although 0000 maybe is free, we do not use it
 | 
						|
    my $freeAddress = 1;
 | 
						|
    my $freeAddressHex = sprintf('%04X', $freeAddress);
 | 
						|
    
 | 
						|
    # All device type names in VM, do not contain CPU
 | 
						|
    my $deviceTypesVm = 'CONS|CTCA|DASD|FCP|GRAF|LINE|MSGD|OSA|PRT|PUN|RDR|SWCH|TAPE';
 | 
						|
    # All device type names in user directory, do not contain CPU
 | 
						|
    my $deviceTypesUserDir = 'CONSOLE|MDISK|NICDEF|SPOOL|RDEVICE'; 
 | 
						|
 | 
						|
    # Search for all address that is in use
 | 
						|
    my $allUsedAddr;
 | 
						|
    if ($type eq 'vmcp') {
 | 
						|
        # When the node is up, vmcp can be used
 | 
						|
        $allUsedAddr = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q v all | awk '$1 ~/^($deviceTypesVm)/ {print $2}' | sort"`;
 | 
						|
    } else {
 | 
						|
        # When the node is down, use zHCP to get its user directory entry
 | 
						|
        # 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'};
 | 
						|
        
 | 
						|
        # Get user directory entry
 | 
						|
        my $userDirEntry = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $userId"'`;
 | 
						|
        
 | 
						|
        # Get profile if user directory entry include a profile
 | 
						|
        if ($userDirEntry =~ "INCLUDE ") {
 | 
						|
            my $profileName = `cat $userDirEntry | awk '$1 ~/^(INCLUDE)/ {print $2}`;    
 | 
						|
            $profileName = xCAT::zvmUtils->trimStr($profileName);        
 | 
						|
            $userDirEntry .= `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $profileName"`;
 | 
						|
        }
 | 
						|
        
 | 
						|
        # Get all defined device address
 | 
						|
        $allUsedAddr = `cat $userDirEntry | awk '$1 ~/^($deviceTypesUserDir)/ {print $2}' | sort`;
 | 
						|
        # Get all linked device address
 | 
						|
        $allUsedAddr .= `cat $userDirEntry | awk '$1 ~/^(LINK)/ {print $4}' | sort`;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Loop to get the lowest free address
 | 
						|
    while ($freeAddress < 65536 && $allUsedAddr =~ $freeAddressHex) {
 | 
						|
        $freeAddress++;
 | 
						|
        $freeAddressHex = sprintf('%04X', $freeAddress);
 | 
						|
    }   
 | 
						|
    
 | 
						|
    if ($freeAddress < 65536) {
 | 
						|
        return $freeAddressHex;
 | 
						|
    }
 | 
						|
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getUsedCpuTime
 | 
						|
 | 
						|
    Description : Get used CPU time of instance
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP (to query on)
 | 
						|
                    node
 | 
						|
    Returns     : In nanoseconds for used CPU time
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getUsedCpuTime($hcp, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getUsedCpuTime {
 | 
						|
    my ( $class, $user, $hcp , $node ) = @_;
 | 
						|
 | 
						|
    # Directory where executables are
 | 
						|
    my $dir = '/opt/zhcp/bin';
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $userId = xCAT::zvmCPUtils->getUserId($user, $node);
 | 
						|
    
 | 
						|
    # Call IUO function to query CPU used time
 | 
						|
    my $time = `ssh $user\@$hcp "$sudo $dir/smcli Image_Performance_Query -T $userId -c 1" | egrep -i "Used CPU time:"`;
 | 
						|
    $time =~ s/^Used CPU time:(.*)/$1/;
 | 
						|
    $time =~ s/"//g;
 | 
						|
    $time =~ s/^\s+//;
 | 
						|
    $time =~ s/\s+$//;
 | 
						|
    if (!$time) {
 | 
						|
        $time = 0;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Not found, return 0
 | 
						|
    return $time;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getUpTime
 | 
						|
 | 
						|
    Description : Get running time of an instance
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
    Returns     : Running time
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getUpTime($user, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getUpTime {
 | 
						|
    my ( $class, $user, $node ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo uptime"`;
 | 
						|
    $out = xCAT::zvmUtils->trimStr($out);
 | 
						|
    $out =~ /.*up +(?:(\d+) days?,? +)?(\d+):(\d+),.*/;
 | 
						|
    my $uptime;
 | 
						|
    
 | 
						|
    if (!$1 && !$2) {
 | 
						|
        # Special case for less than 1 hour, will display X min
 | 
						|
        $out =~ /.*up +(\d+) min,.*/;
 | 
						|
        $uptime = "0 days $3 min";
 | 
						|
    } elsif (!$1) {
 | 
						|
        # Special case for less than 1 day, will display X hr X min
 | 
						|
        $uptime = "0 days $2 hr $3 min";
 | 
						|
    } else {
 | 
						|
        $uptime = "$1 days $2 hr $3 min";
 | 
						|
    }
 | 
						|
    
 | 
						|
    return ($uptime);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getSizeFromByte
 | 
						|
 | 
						|
    Description : Return disk size (G or M) from given bytes
 | 
						|
    Arguments   : Bytes
 | 
						|
    Returns     : Size string
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getSizeFromByte($bytes);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getSizeFromByte {
 | 
						|
    my ( $class, $bytes ) = @_;
 | 
						|
 | 
						|
    my $size = ($bytes)/(1024*1024);
 | 
						|
    if ($size > (1024*5)) {
 | 
						|
        $size = ($size / 1024);
 | 
						|
        # If the size > 5G, will use G to represent 
 | 
						|
        $size = sprintf("%.1f",$size);
 | 
						|
        $size = $size . 'G';
 | 
						|
    } else {
 | 
						|
        # If the size < 5G, will use M to represent
 | 
						|
        $size = sprintf("%d",$size);
 | 
						|
        $size = $size . 'M';
 | 
						|
    }
 | 
						|
 | 
						|
    return ($size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getSizeFromCyl
 | 
						|
 | 
						|
    Description : Return disk size (G or M) from given cylinders
 | 
						|
    Arguments   : Node
 | 
						|
    Returns     : Size string
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getSizeFromCyl($cyl);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getSizeFromCyl {
 | 
						|
    my ($class, $cyl) = @_;
 | 
						|
 | 
						|
    my $bytes = ($cyl * 737280);
 | 
						|
    my $size = xCAT::zvmUtils->getSizeFromByte($bytes);
 | 
						|
 | 
						|
    return ($size);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getSizeFromPage
 | 
						|
 | 
						|
    Description : Return disk size (G or M) from given pages
 | 
						|
    Arguments   : Page
 | 
						|
    Returns     : Size string
 | 
						|
    Example     : my $out = xCAT::zvmUtils->getSizeFromPage($page);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getSizeFromPage {
 | 
						|
    my ( $class, $page ) = @_;
 | 
						|
 | 
						|
    my $bytes = ($page * 4096);
 | 
						|
    my $size = xCAT::zvmUtils->getSizeFromByte($bytes);
 | 
						|
 | 
						|
    return ($size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getLparCpuTotal
 | 
						|
 | 
						|
    Description : Get total count of logical CPUs in the LPAR
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Total CPU count
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getLparCpuTotal($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getLparCpuTotal {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "LPAR CPUs Total"`;
 | 
						|
 | 
						|
    my @results = split(' ', $out);
 | 
						|
    return ($results[3]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getLparCpuUsed
 | 
						|
 | 
						|
    Description : Get count of used logical CPUs in the LPAR
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Used CPU count
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getLparCpuUsed($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getLparCpuUsed {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "LPAR CPUs Configured"`;
 | 
						|
 | 
						|
    my @results = split(' ', $out);
 | 
						|
    return ($results[3]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getCecModel
 | 
						|
 | 
						|
    Description : Get the model of this CEC (LPAR)
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Model of this CEC
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getCecModel($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getCecModel {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "^Type:"`;
 | 
						|
    my @results = split(' ', $out);
 | 
						|
 | 
						|
    return ($results[1]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getCecVendor
 | 
						|
 | 
						|
    Description : Get the vendor of this CEC (LPAR)
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Vendor of this CEC
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getCecVendor($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getCecVendor {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "Manufacturer"`;
 | 
						|
    my @results = split(' ', $out);
 | 
						|
 | 
						|
    return ($results[1]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getHypervisorInfo
 | 
						|
 | 
						|
    Description : Get the info(name & version) for this hypervisor
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Name & version of this hypervisor
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getHypervisorInfo($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getHypervisorInfo {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "VM00 Control Program"`;
 | 
						|
    my @results = split(' ', $out);
 | 
						|
 | 
						|
    my $str = "$results[3] $results[4]";
 | 
						|
 | 
						|
    return ($str);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getLparMemoryTotal
 | 
						|
 | 
						|
    Description : Get the total physical memory of this LPAR
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Total physical memory 
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getLparMemoryTotal($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getLparMemoryTotal {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query" | grep "real storage"`;
 | 
						|
    my @results = split(' ', $out);
 | 
						|
 | 
						|
    return ($results[5]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getLparMemoryOffline
 | 
						|
 | 
						|
    Description : Get the offline physical memory of this LPAR
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Offline physical memory 
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getLparMemoryOffline($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getLparMemoryOffline {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query" | grep "real storage"`;
 | 
						|
    my @results = split(' ', $out);
 | 
						|
 | 
						|
    return ($results[14]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getLparMemoryUsed
 | 
						|
 | 
						|
    Description : Get the used physical memory of this LPAR
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : Used physical memory 
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getLparMemoryUsed($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getLparMemoryUsed {
 | 
						|
    my ($class, $user, $hcp) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Performance_Info_Query " | grep "Used memory pages:"`;
 | 
						|
    my @results = split(':', $out);
 | 
						|
    
 | 
						|
    my $page = xCAT::zvmUtils->trimStr( $results[1] );
 | 
						|
    my $size = xCAT::zvmUtils->getSizeFromPage( $page );
 | 
						|
    
 | 
						|
    return ($size);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getDiskPoolUsed
 | 
						|
 | 
						|
    Description : Get the used size of specified disk pool 
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
                    Disk pool
 | 
						|
    Returns     : Used size of specified disk pool 
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getDiskPoolUsed($user, $hcp, $diskpool);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getDiskPoolUsed {
 | 
						|
    my ($class, $user, $hcp, $diskpool) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp);
 | 
						|
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli Image_Volume_Space_Query_DM -q 3 -e 3 -n $diskpool -T $hcpUserId"`;
 | 
						|
    my @lines = split('\n', $out);
 | 
						|
    my @results;
 | 
						|
    my $used = 0;
 | 
						|
 | 
						|
    foreach (@lines) {
 | 
						|
        @results = split(' ', $_);
 | 
						|
        if ($results[1] =~ '^9336') {
 | 
						|
            # Change the format from blocks (512 byte) to cylinder (737280)
 | 
						|
            my $cyls = ($results[3] * 512)/(737280);
 | 
						|
            $used += $cyls;
 | 
						|
        } elsif ($results[1] =~ '^3390') {
 | 
						|
            $used += $results[3];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    return ($used);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getDiskPoolFree
 | 
						|
 | 
						|
    Description : Get the free size of specified disk pool 
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP 
 | 
						|
                    Disk pool
 | 
						|
    Returns     : Free size of specified disk pool 
 | 
						|
    Example     : my $out = xCAT::zvmCPUtils->getDiskPoolFree($user, $hcp, $diskpool);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getDiskPoolFree {
 | 
						|
    my ($class, $user, $hcp, $diskpool) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp);
 | 
						|
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli Image_Volume_Space_Query_DM -q 2 -e 3 -n $diskpool -T $hcpUserId"`;
 | 
						|
    my @lines = split('\n', $out);
 | 
						|
    my @results;
 | 
						|
    my $free = 0;
 | 
						|
 | 
						|
    foreach (@lines) {
 | 
						|
        @results = split(' ', $_);
 | 
						|
        if ($results[1] =~ '^9336') {
 | 
						|
            # Change the format from blocks (512 byte) to cylinder (737280)
 | 
						|
            my $cyls = ( $results[3] * 512 ) / ( 737280 );
 | 
						|
            $free += $cyls;
 | 
						|
        } elsif ($results[1] =~ '^3390') {
 | 
						|
            $free += $results[3];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    return ($free);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getMaxMemory
 | 
						|
 | 
						|
    Description : Get the max memory of a given node
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP 
 | 
						|
                    Node
 | 
						|
    Returns     : Max memory
 | 
						|
    Example     : my $maxMemory = xCAT::zvmCPUtils->getMaxMemory($user, $hcp, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getMaxMemory {
 | 
						|
    my ($class, $user, $hcp , $node) = @_;
 | 
						|
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
 | 
						|
    my $userId = xCAT::zvmCPUtils->getUserId( $user, $node );
 | 
						|
 | 
						|
    # Query the maximum memory allowed in user directory entry
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli Image_Definition_Query_DM -T $userId -k STORAGE_MAXIMUM"`;
 | 
						|
    my @results = split('=', $out);
 | 
						|
 | 
						|
    return ($results[1]);
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   smapi4xcat
 | 
						|
 | 
						|
    Description : Verify if SMAPI EXEC (xCAT_Commands_IUO) exists
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     :   0  EXEC not found
 | 
						|
                    1  EXEC found
 | 
						|
    Example     : my $out = xCAT::zvmUtils->smapi4xcat($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub smapi4xcat {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
    
 | 
						|
    # Directory where executables are
 | 
						|
    my $dir = '/opt/zhcp/bin';
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Get zHCP user ID
 | 
						|
    my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp);
 | 
						|
    $hcpUserId =~ tr/a-z/A-Z/;
 | 
						|
    
 | 
						|
    # Check SMAPI level
 | 
						|
    # Levels 621 and greater support SMAPI EXEC
 | 
						|
    my $out = `ssh $user\@$hcp "$sudo $dir/smcli Query_API_Functional_Level -T $hcpUserId"`;
 | 
						|
    $out = xCAT::zvmUtils->trimStr($out);
 | 
						|
    if ( !($out =~ m/V6.2/i || $out =~ m/V6.1/i || $out =~ m/V5.4/i) ) {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Check if SMAPI EXEC exists
 | 
						|
    # EXEC found if RC = 8 and RS = 3002
 | 
						|
    $out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $hcpUserId -c ''"`;
 | 
						|
    $out = xCAT::zvmUtils->trimStr($out);
 | 
						|
    if ( $out =~ m/Return Code: 8/i && $out =~ m/Reason Code: 3002/i ) {
 | 
						|
        return 1;
 | 
						|
    } 
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   generateUserEntryFile
 | 
						|
 | 
						|
    Description : Generate a user entry file without Mdisk
 | 
						|
    Arguments   :   UserId
 | 
						|
                    Password
 | 
						|
                    Memory
 | 
						|
                    Privilege
 | 
						|
                    Profile
 | 
						|
                    Cpu
 | 
						|
    Returns     : If successful, return file path. Otherwise, return -1
 | 
						|
    Example     : my $out = xCAT::zvmUtils->generateUserEntryFile($userId, $password, $memorySize, $privilege, $profileName, $cpuCount);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub generateUserEntryFile {
 | 
						|
    my ( $class, $userId, $password, $memorySize, $privilege, $profileName, $cpuCount ) = @_;
 | 
						|
 | 
						|
    # If a file of this name already exists, just override it
 | 
						|
    my $file = "/tmp/$userId.txt";
 | 
						|
    my $content = "USER $userId $password $memorySize $memorySize $privilege\nINCLUDE $profileName\nCPU 00 BASE\n";
 | 
						|
    
 | 
						|
    # Add additional CPUs
 | 
						|
    my $i;
 | 
						|
    for ( $i = 1; $i < $cpuCount; $i++ ) {
 | 
						|
        $content = $content.sprintf("CPU %02X\n", $i)
 | 
						|
    }
 | 
						|
    
 | 
						|
    unless (open(FILE, ">$file")) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    print FILE $content;    
 | 
						|
    close(FILE);
 | 
						|
      
 | 
						|
    return $file;    
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   querySSI
 | 
						|
 | 
						|
    Description : Obtain the SSI and system status
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : SSI cluster name
 | 
						|
    Example     : my $out = xCAT::zvmUtils->querySSI($user, $hcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub querySSI {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
    
 | 
						|
    # Directory where executables are
 | 
						|
    my $dir = '/opt/zhcp/bin';
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $ssi = `ssh -o ConnectTimeout=10 $user\@$hcp "$sudo $dir/smcli SSI_Query" | egrep -i "ssi_name"`;
 | 
						|
    $ssi =~ s/ssi_name = //;
 | 
						|
    $ssi =~ s/\s*$//;
 | 
						|
    $ssi =~ s/^\s*//;
 | 
						|
    
 | 
						|
    return $ssi;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   rExecute
 | 
						|
 | 
						|
    Description : Execute a remote command
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    Node
 | 
						|
                    Command to execute
 | 
						|
    Returns     : Output returned from executing command
 | 
						|
    Example     : my $out = xCAT::zvmUtils->rExecute($user, $node, $cmd);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub rExecute {
 | 
						|
    my ( $class, $user, $node, $cmd ) = @_;
 | 
						|
    
 | 
						|
    my $out;
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        # Just execute the command if root        
 | 
						|
        $out = `ssh $user\@$node "$cmd"`;
 | 
						|
        return $out;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Encapsulate command in single quotes
 | 
						|
    $cmd = "'" . $cmd . "'";
 | 
						|
    $out = `ssh $user\@$node "$sudo sh -c $cmd"`;
 | 
						|
    return $out;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getUsedFcpDevices
 | 
						|
 | 
						|
    Description : Get a list of used FCP devices in the zFCP pools
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
    Returns     : List of known FCP devices
 | 
						|
    Example     : my %devices = xCAT::zvmUtils->getUsedFcpDevices($user, $zhcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getUsedFcpDevices {
 | 
						|
    my ( $class, $user, $hcp ) = @_;
 | 
						|
    
 | 
						|
    # Directory where zFCP pools are
 | 
						|
    my $pool = "/var/opt/zhcp/zfcp";
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Grep the pools for used or allocated zFCP devices
 | 
						|
    my %usedDevices;
 | 
						|
    my @args;
 | 
						|
    my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $pool/*.conf" | egrep -i "used|allocated"`);
 | 
						|
    foreach (@devices) {
 | 
						|
        @args = split(",", $_);
 | 
						|
        
 | 
						|
        # Sample pool configuration file:
 | 
						|
        #   #status,wwpn,lun,size,range,owner,channel,tag
 | 
						|
        #     used,1000000000000000,2000000000000110,8g,3B00-3B3F,ihost1,1a23,$root_device$
 | 
						|
        #     free,1000000000000000,2000000000000111,,3B00-3B3F,,,
 | 
						|
        #     free,1230000000000000,2000000000000112,,3B00-3B3F,,,
 | 
						|
        $args[6] = xCAT::zvmUtils->trimStr($args[6]);
 | 
						|
        
 | 
						|
        # Push used or allocated devices into hash 
 | 
						|
        if ($args[6]) {
 | 
						|
            $usedDevices{uc($args[6])} = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    return %usedDevices;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   establishMount
 | 
						|
 | 
						|
    Description : Establish an NFS mount point on a zHCP system.
 | 
						|
    Arguments   : Sudoer user name
 | 
						|
                  Sudo keyword
 | 
						|
                  zHCP hostname
 | 
						|
                  Local directory to remotely mount
 | 
						|
                  Mount access ('ro' for read only, 'rw' for read write)
 | 
						|
                  Directory as known to zHCP (out)
 | 
						|
    Returns     : 0 - Mounted, or zHCP and MN are on the same system
 | 
						|
                  1 - Mount failed
 | 
						|
    Example     : establishMount( $callback, $::SUDOER, $::SUDO, $hcp, "$installRoot/$provMethod", "ro", \$remoteDeployDir );
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub establishMount {
 | 
						|
    # Get inputs
 | 
						|
    my ($class, $callback, $sudoer, $sudo, $hcp, $localDir, $access, $mountedPt) = @_;    
 | 
						|
    my $out;
 | 
						|
 | 
						|
    # If the target system is not on this system then establish the NFS mount point.
 | 
						|
    my $hcpIP = xCAT::NetworkUtils->getipaddr( $hcp );
 | 
						|
    if (! defined $hcpIP) {
 | 
						|
        xCAT::zvmUtils->printLn( $callback, "(Error) Unable to obtain the IP address of the hcp node" );
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $masterIp = xCAT::TableUtils->get_site_Master();
 | 
						|
    if (! defined $masterIp) {
 | 
						|
        xCAT::zvmUtils->printLn( $callback, "$hcp: (Error) Unable to obtain the management node IP address from the site table" );
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if ($masterIp eq $hcpIP) {
 | 
						|
        # xCAT MN and zHCP are on the same box and will use the same directory without the need for an NFS mount.
 | 
						|
        $$mountedPt = $localDir;
 | 
						|
    } else {
 | 
						|
        # Determine the hostname for this management node
 | 
						|
        my $masterHostname = Sys::Hostname::hostname();
 | 
						|
        if (! defined $masterHostname) {
 | 
						|
            # For some reason, the xCAT MN's hostname is not known.  We pass along the IP address instead.
 | 
						|
            $masterHostname = $masterIp;
 | 
						|
        }
 | 
						|
        
 | 
						|
        xCAT::zvmUtils->printSyslog( "establishMount() Preparing the NFS mount point on zHCP ($hcpIP) to xCAT MN $masterHostname($masterIp) for $localDir" );
 | 
						|
        
 | 
						|
        # Prepare the staging mount point on zHCP, if they need to be established
 | 
						|
        $$mountedPt = "/mnt/$masterHostname$localDir";
 | 
						|
        my $rc = `ssh $sudoer\@$hcp "$sudo mkdir -p $$mountedPt && mount -t nfs -o $access $masterIp:$localDir $$mountedPt; echo \\\$?"`;
 | 
						|
        
 | 
						|
        # Return code = 0 (mount succeeded) or 32 (mount already exists)
 | 
						|
        if ($rc != '0' && $rc != '32') {
 | 
						|
            xCAT::zvmUtils->printLn( $callback, "$hcp: (Error) Unable to establish zHCP mount point: $$mountedPt" );
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   getFreeRepoSpace
 | 
						|
 | 
						|
    Description : Get the free space of image repository under /install
 | 
						|
    Arguments   : Node
 | 
						|
    Returns     : The available space for /install
 | 
						|
    Example     : my $free = getFreeRepoSpace($callback, $node);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub getFreeRepoSpace {
 | 
						|
    # Get inputs
 | 
						|
    my ($class, $user, $node) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Check if node is the management node
 | 
						|
    my @entries = xCAT::TableUtils->get_site_attribute("master");
 | 
						|
    my $master = xCAT::zvmUtils->trimStr($entries[0]);
 | 
						|
    my $ip = xCAT::NetworkUtils->getipaddr($node);
 | 
						|
    $ip = xCAT::zvmUtils->trimStr($ip);
 | 
						|
    my $mn = 0;
 | 
						|
    if ($master eq $ip) {
 | 
						|
        # If the master IP and node IP match, then it is the management node
 | 
						|
        my $out = `$sudo /bin/df -h /install | sed 1d`;
 | 
						|
        $out =~ s/\h+/ /g;
 | 
						|
        my @results = split(' ', $out);
 | 
						|
        return ($results[3]);
 | 
						|
    } 
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   findAndUpdatezFcpPool
 | 
						|
 | 
						|
    Description : Find and update a SCSI/FCP device in a given storage pool.
 | 
						|
                  xCAT will find and update the SCSI/FCP device in all known pools based on the unique WWPN/LUN combo.
 | 
						|
    Arguments   :   Message header
 | 
						|
                    User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
                    Storage pool
 | 
						|
                    Criteria hash including:
 | 
						|
                        - Status (free, reserved, or used)
 | 
						|
                        - zFCP channel
 | 
						|
                        - WWPN
 | 
						|
                        - LUN
 | 
						|
                        - Size requested
 | 
						|
                        - Owner
 | 
						|
                        - Tag                                      
 | 
						|
    Returns     :   Results hash including:
 | 
						|
                        - Return code (0 = Success, -1 = Failure)
 | 
						|
                        - zFCP device (if one is requested)
 | 
						|
                        - WWPN
 | 
						|
                        - LUN
 | 
						|
    Example     : my $resultsRef = xCAT::zvmUtils->findAndUpdatezFcpPool($callback, $header, $user, $hcp, $pool, $criteriaRef);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub findAndUpdatezFcpPool {
 | 
						|
    # Get inputs
 | 
						|
    my ($class, $callback, $header, $user, $hcp, $pool, $criteriaRef) = @_;
 | 
						|
        
 | 
						|
    # Determine if sudo is used
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Directory where executables are on zHCP
 | 
						|
    my $dir = "/opt/zhcp/bin";
 | 
						|
        
 | 
						|
    # Directory where FCP disk pools are on zHCP
 | 
						|
    my $zfcpDir = "/var/opt/zhcp/zfcp";
 | 
						|
    
 | 
						|
    my %results = ('rc' => -1);  # Default to error
 | 
						|
 | 
						|
    # Extract criteria
 | 
						|
    my %criteria = %$criteriaRef;
 | 
						|
    my $status = defined($criteria{status}) ? $criteria{status} : "";
 | 
						|
    my $fcpDevice = defined($criteria{fcp}) ? $criteria{fcp} : "";
 | 
						|
    my $wwpn = defined($criteria{wwpn}) ? $criteria{wwpn} : "";
 | 
						|
    my $lun = defined($criteria{lun}) ? $criteria{lun} : "";
 | 
						|
    my $size = defined($criteria{size}) ? $criteria{size} : "";
 | 
						|
    my $owner = defined($criteria{owner}) ? $criteria{owner} : "";
 | 
						|
    my $tag = defined($criteria{tag}) ? $criteria{tag} : "";
 | 
						|
    
 | 
						|
    # Check required arguments: pool, status
 | 
						|
    # If you do not know what to update, why update!
 | 
						|
    if (!$pool && !$status) {
 | 
						|
       return \%results;
 | 
						|
    }
 | 
						|
        
 | 
						|
    # Check status
 | 
						|
    if ($status !~ m/^(free|used|reserved)$/i) {
 | 
						|
        xCAT::zvmUtils->printLn($callback, "$header: (Error) Status not recognized. Status can be free, used, or reserved.");
 | 
						|
        return \%results;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Check FCP device syntax
 | 
						|
    if ($fcpDevice && ($fcpDevice !~ /^auto/i) && ($fcpDevice =~ /[^0-9a-f]/i)) {
 | 
						|
        xCAT::zvmUtils->printLn($callback, "$header: (Error) Invalid FCP channel address $fcpDevice.");
 | 
						|
        return \%results;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Check WWPN and LUN syntax
 | 
						|
    if ( $wwpn && ($wwpn =~ /[^0-9a-f;"]/i) ) {
 | 
						|
        xCAT::zvmUtils->printLn( $callback, "$header: (Error) Invalid world wide portname $wwpn." );
 | 
						|
        return \%results;
 | 
						|
    } if ( $lun && ($lun =~ /[^0-9a-f]/i) ) {
 | 
						|
        xCAT::zvmUtils->printLn( $callback, "$header: (Error) Invalid logical unit number $lun." );
 | 
						|
        return \%results;
 | 
						|
    }
 | 
						|
        
 | 
						|
    # Size can be M(egabytes) or G(igabytes). Convert size into MB.
 | 
						|
    my $originSize = $size;
 | 
						|
    if ($size) {
 | 
						|
        if ($size =~ m/G/i) {
 | 
						|
            # Convert to MegaBytes
 | 
						|
            $size =~ s/\D//g;
 | 
						|
            $size = int($size) * 1024
 | 
						|
        } elsif ($size =~ m/M/i || !$size) {
 | 
						|
            # Do nothing
 | 
						|
        } else {
 | 
						|
            xCAT::zvmUtils->printLn( $callback, "$header: (Error) Size not recognized. Size can be M(egabytes) or G(igabytes)." );
 | 
						|
            return \%results;
 | 
						|
        }
 | 
						|
    }
 | 
						|
        
 | 
						|
    # Check if WWPN and LUN are given
 | 
						|
    # WWPN can be given as a semi-colon separated list (multipathing)
 | 
						|
    my $useWwpnLun = 0;
 | 
						|
    if ($wwpn && $lun) {
 | 
						|
        xCAT::zvmUtils->printLn($callback, "$header: Using given WWPN and LUN");
 | 
						|
        $useWwpnLun = 1;
 | 
						|
        
 | 
						|
        # Make sure WWPN and LUN do not have 0x prefix
 | 
						|
        $wwpn = xCAT::zvmUtils->replaceStr($wwpn, "0x", "");
 | 
						|
        $lun = xCAT::zvmUtils->replaceStr($lun, "0x", "");
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Find disk pool (create one if non-existent)
 | 
						|
    my $out;
 | 
						|
    if (!(`ssh $user\@$hcp "$sudo test -d $zfcpDir && echo Exists"`)) {
 | 
						|
        # Create pool directory
 | 
						|
        $out = `ssh $user\@$hcp "$sudo mkdir -p $zfcpDir"`;
 | 
						|
    }
 | 
						|
    
 | 
						|
    # Find if disk pool exists
 | 
						|
    if (!(`ssh $user\@$hcp "$sudo test -e $zfcpDir/$pool.conf && echo Exists"`)) {
 | 
						|
        # Return if xCAT is expected to find a FCP device, but no disk pool exists.
 | 
						|
        xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP storage pool does not exist");
 | 
						|
        return \%results;
 | 
						|
    }
 | 
						|
        
 | 
						|
    # Find a free disk in the pool
 | 
						|
    # FCP devices are contained in /var/opt/zhcp/zfcp/<pool-name>.conf   
 | 
						|
    my $range = "";
 | 
						|
    my $sizeFound = "*";
 | 
						|
    my @info;
 | 
						|
    if (!$useWwpnLun) {
 | 
						|
        # Find a suitable pair of WWPN and LUN in device pool based on requested size
 | 
						|
        # Sample pool configuration file:
 | 
						|
        #   #status,wwpn,lun,size,range,owner,channel,tag
 | 
						|
        #     used,1000000000000000,2000000000000110,8g,3B00-3B3F,ihost1,1a23,$root_device$
 | 
						|
        #     free,1000000000000000,2000000000000111,,3B00-3B3F,,,
 | 
						|
        #     free,1230000000000000;4560000000000000,2000000000000112,,3B00-3B3F,,,
 | 
						|
        my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | egrep -i ^free`);            
 | 
						|
        $sizeFound = 0;
 | 
						|
        foreach (@devices) {
 | 
						|
            @info = split(',', $_);
 | 
						|
                    
 | 
						|
            # Check if the size is sufficient. Convert size into MB.
 | 
						|
            if ($info[3] =~ m/G/i) {
 | 
						|
                # Convert to MegaBytes
 | 
						|
                $info[3] =~ s/\D//g;
 | 
						|
                $info[3] = int($info[3]) * 1024
 | 
						|
            } elsif ($info[3] =~ m/M/i) {
 | 
						|
                # Do nothing
 | 
						|
                $info[3] =~ s/\D//g;
 | 
						|
            } else {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            
 | 
						|
            # Find optimal disk based on requested size
 | 
						|
            if ($sizeFound && $info[3] >= $size && $info[3] < $sizeFound) {
 | 
						|
                $sizeFound = $info[3];
 | 
						|
                $wwpn = $info[1];                    
 | 
						|
                $lun = $info[2];
 | 
						|
                $range = $info[4];
 | 
						|
            } elsif (!$sizeFound && $info[3] >= $size) {
 | 
						|
                $sizeFound = $info[3];
 | 
						|
                $wwpn = $info[1];
 | 
						|
                $lun = $info[2];   
 | 
						|
                $range = $info[4];       
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        # Do not continue if no devices can be found
 | 
						|
        if (!$wwpn && !$lun) {
 | 
						|
            xCAT::zvmUtils->printLn($callback, "$header: (Error) A suitable device of $size" . "M or larger could not be found");
 | 
						|
            return \%results;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
    	# Find given WWPN and LUN. Do not continue if device is used
 | 
						|
        my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$wwpn,$lun"`;
 | 
						|
        chomp($select);
 | 
						|
        
 | 
						|
        @info = split(',', $select);
 | 
						|
        
 | 
						|
        if ($size) {
 | 
						|
            if ($info[3] =~ m/G/i) {
 | 
						|
                # Convert to MegaBytes
 | 
						|
                $info[3] =~ s/\D//g;
 | 
						|
                $info[3] = int($info[3]) * 1024
 | 
						|
            } elsif ($info[3] =~ m/M/i) {
 | 
						|
                # Do nothing
 | 
						|
                $info[3] =~ s/\D//g;
 | 
						|
            } else {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
                
 | 
						|
            # Do not continue if specified device does not have enough capacity
 | 
						|
            if ($info[3] < $size) {
 | 
						|
                xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP device $wwpn/$lun is not large enough");
 | 
						|
                return \%results;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Find range of the specified disk
 | 
						|
        $range = $info[4];
 | 
						|
    }
 | 
						|
       
 | 
						|
    # If there are multiple paths, take the 1st one
 | 
						|
    # Handle multi-pathing in postscript because autoyast/kickstart does not support it.
 | 
						|
    my $origWwpn = $wwpn;
 | 
						|
    if ($wwpn =~ m/;/i) {
 | 
						|
        @info = split(';', $wwpn);
 | 
						|
        $wwpn = xCAT::zvmUtils->trimStr($info[0]);
 | 
						|
    }
 | 
						|
        
 | 
						|
    xCAT::zvmUtils->printLn($callback, "$header: Found FCP device 0x$wwpn/0x$lun");
 | 
						|
        
 | 
						|
    # Find a free FCP device based on the given range
 | 
						|
    if ($fcpDevice =~ m/^auto/i) {
 | 
						|
        my @ranges;
 | 
						|
        my $min;
 | 
						|
        my $max;
 | 
						|
        my $found = 0;
 | 
						|
                
 | 
						|
        if ($range =~ m/;/i) {
 | 
						|
            @ranges = split(';', $range);
 | 
						|
        } else {
 | 
						|
            push(@ranges, $range);
 | 
						|
        }
 | 
						|
                    
 | 
						|
        if (!$found) {
 | 
						|
            # If the node has an eligible FCP device, use it
 | 
						|
            my @deviceList = xCAT::zvmUtils->getDedicates($callback, $user, $owner);
 | 
						|
            foreach (@deviceList) {
 | 
						|
                # Check if this devide is eligible (among the range specified for disk $lun)
 | 
						|
                @info = split(' ', $_);
 | 
						|
                my $candidate = $info[2];
 | 
						|
                foreach (@ranges) {
 | 
						|
                    ($min, $max) = split('-', $_);
 | 
						|
                    if (hex($candidate) >= hex($min) && hex($candidate) <= hex($max)) {
 | 
						|
                        $found = 1;
 | 
						|
                        $fcpDevice = uc($candidate);
 | 
						|
                        
 | 
						|
                        last;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                
 | 
						|
                if ($found) {
 | 
						|
                	xCAT::zvmUtils->printLn($callback, "$header: Found eligible FCP channel $fcpDevice");
 | 
						|
                    last;
 | 
						|
                }       
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (!$found) {
 | 
						|
            # If the node has no eligible FCP device, find a free one for it.
 | 
						|
            my %usedDevices = xCAT::zvmUtils->getUsedFcpDevices($user, $hcp);
 | 
						|
            
 | 
						|
            my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp);
 | 
						|
            $hcpUserId =~ tr/a-z/A-Z/;
 | 
						|
        
 | 
						|
            # Find a free FCP channel
 | 
						|
            $out = `ssh $user\@$hcp "$sudo $dir/smcli System_WWPN_Query -T $hcpUserId" | egrep -i "FCP device number|Status"`;
 | 
						|
            my @devices = split( "\n", $out );
 | 
						|
            for (my $i = 0; $i < @devices; $i++) {
 | 
						|
                # Extract the device number and status
 | 
						|
                $fcpDevice = $devices[$i];
 | 
						|
                $fcpDevice =~ s/^FCP device number:(.*)/$1/;
 | 
						|
                $fcpDevice =~ s/^\s+//;
 | 
						|
                $fcpDevice =~ s/\s+$//;
 | 
						|
                        
 | 
						|
                $i++;
 | 
						|
                my $fcpStatus = $devices[$i];
 | 
						|
                $fcpStatus =~ s/^Status:(.*)/$1/;
 | 
						|
                $fcpStatus =~ s/^\s+//;
 | 
						|
                $fcpStatus =~ s/\s+$//;                    
 | 
						|
                        
 | 
						|
                # Only look at free FCP devices
 | 
						|
                if ($fcpStatus =~ m/free/i) {                    
 | 
						|
                    # If the device number is within the specified range, exit out of loop
 | 
						|
                    # Range: 3B00-3C00;4B00-4C00;5E12-5E12
 | 
						|
                    foreach (@ranges) {
 | 
						|
                        ($min, $max) = split('-', $_);
 | 
						|
                        if (hex($fcpDevice) >= hex($min) && hex($fcpDevice) <= hex($max)) {
 | 
						|
                            $fcpDevice = uc($fcpDevice);
 | 
						|
                
 | 
						|
                            # Used found FCP channel if not in use or allocated                        
 | 
						|
                            if (!$usedDevices{$fcpDevice}) {
 | 
						|
                                $found = 1;
 | 
						|
                                last;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                
 | 
						|
                # Break out of loop if FCP channel is found
 | 
						|
                if ($found) {
 | 
						|
                	xCAT::zvmUtils->printLn($callback, "$header: Found FCP channel within acceptable range $fcpDevice");
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
            
 | 
						|
        # Do not continue if no FCP channel is found
 | 
						|
        if (!$found) {
 | 
						|
            xCAT::zvmUtils->printLn($callback, "$header: (Error) A suitable FCP channel could not be found");
 | 
						|
            return \%results;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    # If there are multiple devices (multipathing), take the 1st one
 | 
						|
    if ($fcpDevice) {
 | 
						|
        if ($fcpDevice =~ m/;/i) {
 | 
						|
            @info = split(';', $fcpDevice);
 | 
						|
            $fcpDevice = xCAT::zvmUtils->trimStr($info[0]);
 | 
						|
        }
 | 
						|
                    
 | 
						|
        # Make sure channel has a length of 4
 | 
						|
        while (length($fcpDevice) < 4) {
 | 
						|
            $fcpDevice = "0" . $fcpDevice;
 | 
						|
        }
 | 
						|
    }
 | 
						|
            
 | 
						|
    # Mark WWPN and LUN as used, free, or reserved and set the owner/channel appropriately
 | 
						|
    # This config file keeps track of the owner of each device, which is useful in nodeset
 | 
						|
    $size = $size . "M";
 | 
						|
    my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$lun" | grep -i "$wwpn"`;
 | 
						|
    chomp($select);
 | 
						|
    if ($select) {
 | 
						|
        @info = split(',', $select);
 | 
						|
        
 | 
						|
        if (!$info[3]) {
 | 
						|
            $info[3] = $size;
 | 
						|
        }
 | 
						|
            
 | 
						|
        # Do not update if WWPN/LUN pair is specified but the pair does not exist
 | 
						|
        if (!($info[1] =~ m/$wwpn/i)) {
 | 
						|
            xCAT::zvmUtils->printLn($callback, "$header: (Error) FCP device $wwpn/$lun does not exists");
 | 
						|
            return \%results;
 | 
						|
        }
 | 
						|
                    
 | 
						|
        # Entry order: status,wwpn,lun,size,range,owner,channel,tag
 | 
						|
        # The following are never updated: wwpn, lun, size, and range
 | 
						|
        my $update = "$status,$info[1],$info[2],$info[3],$info[4],$owner,$fcpDevice,$tag";
 | 
						|
        my $expression = "'s#" . $select . "#" .$update . "#i'";
 | 
						|
        $out = `ssh $user\@$hcp "$sudo sed --in-place -e $expression $zfcpDir/$pool.conf"`;
 | 
						|
    } else {
 | 
						|
        # Insert device entry into file
 | 
						|
        $out = `ssh $user\@$hcp "$sudo echo \"$status,$origWwpn,$lun,$size,,$owner,$fcpDevice,$tag\" >> $zfcpDir/$pool.conf"`;
 | 
						|
    }
 | 
						|
 | 
						|
    # Generate results hash
 | 
						|
    %results = (
 | 
						|
        'rc' => 0,
 | 
						|
        'fcp' => $fcpDevice,
 | 
						|
        'wwpn' => $wwpn,
 | 
						|
        'lun' => $lun
 | 
						|
    );
 | 
						|
    return \%results;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   findzFcpDevicePool
 | 
						|
 | 
						|
    Description : Find the zFCP storage pool that contains the given zFCP device
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
                    WWPN
 | 
						|
                    LUN
 | 
						|
    Returns     : Storage pool where zFCP device resides
 | 
						|
    Example     : my $pool = xCAT::zvmUtils->findzFcpDevicePool($user, $hcp, $wwpn, $lun);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub findzFcpDevicePool {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $hcp, $wwpn, $lun ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
            
 | 
						|
    # Directory where FCP disk pools are on zHCP
 | 
						|
    my $zfcpDir = "/var/opt/zhcp/zfcp";
 | 
						|
 | 
						|
    # Find the pool that contains the SCSI/FCP device
 | 
						|
    my @pools = split("\n", `ssh $user\@$hcp "$sudo grep -i -l \"$wwpn,$lun\" $zfcpDir/*.conf"`);
 | 
						|
    my $pool = ""; 
 | 
						|
    if (scalar(@pools)) {
 | 
						|
        $pool = basename($pools[0]);
 | 
						|
        $pool =~ s/\.[^.]+$//;  # Do not use extension
 | 
						|
    }
 | 
						|
 | 
						|
    return $pool;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   findzFcpDeviceAttr
 | 
						|
 | 
						|
    Description : Find the zFCP device attributes
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
                    Storage pool
 | 
						|
                    WWPN
 | 
						|
                    LUN
 | 
						|
    Returns     : Architecture of node
 | 
						|
    Example     : my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($user, $hcp, $wwpn, $lun);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub findzFcpDeviceAttr {
 | 
						|
 | 
						|
    # Get inputs
 | 
						|
    my ( $class, $user, $hcp, $pool, $wwpn, $lun ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
            
 | 
						|
    # Directory where FCP disk pools are on zHCP
 | 
						|
    my $zfcpDir = "/var/opt/zhcp/zfcp";
 | 
						|
 | 
						|
    # Find the SCSI/FCP device
 | 
						|
    # Entry order: status,wwpn,lun,size,range,owner,channel,tag
 | 
						|
    my @info = split("\n", `ssh $user\@$hcp "$sudo grep \"$wwpn,$lun\" $zfcpDir/$pool.conf"`);
 | 
						|
    my $entry = $info[0];
 | 
						|
    chomp($entry);
 | 
						|
    
 | 
						|
    # Do not continue if no device is found
 | 
						|
    my %attrs = ();
 | 
						|
    if (!$entry) {
 | 
						|
        return \%attrs;
 | 
						|
    }
 | 
						|
    
 | 
						|
    @info = split(',', $entry);    
 | 
						|
    %attrs = (
 | 
						|
        'status' => $info[0],
 | 
						|
        'wwpn' => $info[1],
 | 
						|
        'lun' => $info[2],
 | 
						|
        'size' => $info[3],
 | 
						|
        'range' => $info[4],
 | 
						|
        'owner' => $info[5],
 | 
						|
        'fcp' => $info[6],
 | 
						|
        'tag' => $info[7]        
 | 
						|
    );
 | 
						|
    
 | 
						|
    return \%attrs;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3   findUsablezHcpNetwork
 | 
						|
 | 
						|
    Description : Find a useable NIC shared with the zHCP for a given user Id
 | 
						|
    Arguments   :   User (root or non-root)
 | 
						|
                    zHCP
 | 
						|
                    User Id to find a useable NIC on
 | 
						|
                    DHCP is used or not (0 or 1)
 | 
						|
    Returns     : NIC, device channel, and layer (2 or 3)
 | 
						|
    Example     : my ($nic, $channel, $layer) = xCAT::zvmUtils->findUsablezHcpNetwork($user, $hcp, $userId, $dhcp);
 | 
						|
    
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub findUsablezHcpNetwork {
 | 
						|
	# Get inputs
 | 
						|
    my ( $class, $user, $hcp, $userId, $dhcp ) = @_;
 | 
						|
    
 | 
						|
    my $sudo = "sudo";
 | 
						|
    if ($user eq "root") {
 | 
						|
        $sudo = "";
 | 
						|
    }
 | 
						|
    
 | 
						|
    my $nic = '';  # Usuable NIC on zHCP
 | 
						|
    my $channel = '';  # Device channel where NIC is attached
 | 
						|
    my $layer;
 | 
						|
    my $i;
 | 
						|
    my @words;
 | 
						|
    
 | 
						|
    # Get the networks used by the zHCP
 | 
						|
    my @hcpNetworks = xCAT::zvmCPUtils->getNetworkNamesArray($user, $hcp);        
 | 
						|
 | 
						|
    # Search directory entry for network name
 | 
						|
    my $userEntry = `ssh $user\@$hcp "$sudo $::DIR/smcli Image_Query_DM -T $userId" | sed '\$d'`;    
 | 
						|
    xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() smcli Image_Query_DM -T $userId");
 | 
						|
    xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() $userEntry");
 | 
						|
    
 | 
						|
    my $out = `echo "$userEntry" | grep "NICDEF"`;
 | 
						|
    my @lines = split('\n', $out);
 | 
						|
        
 | 
						|
    # Go through each line
 | 
						|
    for ($i = 0; $i < @lines; $i++) {
 | 
						|
        # Go through each network device attached to zHCP
 | 
						|
        foreach (@hcpNetworks) {
 | 
						|
                
 | 
						|
            # If network device is found
 | 
						|
            if ($lines[$i] =~ m/ $_/i) {
 | 
						|
                # Get network layer
 | 
						|
                $layer = xCAT::zvmCPUtils->getNetworkLayer($user, $hcp, $_);
 | 
						|
                xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() NIC:$_ layer:$layer");
 | 
						|
                    
 | 
						|
                # If template using DHCP, layer must be 2
 | 
						|
                if ((!$dhcp && $layer != 2) || (!$dhcp && $layer == 2) || ($dhcp && $layer == 2)) {
 | 
						|
                    # Save network name
 | 
						|
                    $nic = $_;
 | 
						|
                        
 | 
						|
                    # Get network virtual address
 | 
						|
                    @words = split(' ',  $lines[$i]);
 | 
						|
                        
 | 
						|
                    # Get virtual address (channel)
 | 
						|
                    # Convert subchannel to decimal
 | 
						|
                    $channel = sprintf('%d', hex($words[1]));
 | 
						|
                    
 | 
						|
                    xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() Candidate found NIC:$nic channel:$channel layer:$layer"); 
 | 
						|
                    return ($nic, $channel, $layer);
 | 
						|
                } else {
 | 
						|
                    # Go to next network available
 | 
						|
                    $nic = '';
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # If network device is not found
 | 
						|
    if (!$nic) {
 | 
						|
        # Check for user profile
 | 
						|
        my $profileName = `echo "$userEntry" | grep "INCLUDE"`;
 | 
						|
        if ($profileName) {
 | 
						|
            @words = split(' ', xCAT::zvmUtils->trimStr($profileName));
 | 
						|
                
 | 
						|
            # Get user profile
 | 
						|
            my $userProfile = xCAT::zvmUtils->getUserProfile($user, $hcp, $words[1]);
 | 
						|
            xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() $userProfile");
 | 
						|
                
 | 
						|
            # Get the NICDEF statement containing the HCP network
 | 
						|
            $out = `echo "$userProfile" | grep "NICDEF"`;
 | 
						|
            @lines = split('\n', $out);
 | 
						|
                
 | 
						|
            # Go through each line
 | 
						|
            for ($i = 0; $i < @lines; $i++) {
 | 
						|
                # Go through each network device attached to zHCP
 | 
						|
                foreach (@hcpNetworks) {
 | 
						|
                        
 | 
						|
                    # If network device is found
 | 
						|
                    if ($lines[$i] =~ m/ $_/i) {
 | 
						|
                        # Get network layer
 | 
						|
                        $layer = xCAT::zvmCPUtils->getNetworkLayer($user, $hcp, $_);
 | 
						|
                        xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() NIC:$_ layer:$layer");
 | 
						|
                    
 | 
						|
                        # If template using DHCP, layer must be 2
 | 
						|
                        if ((!$dhcp && $layer != 2) || (!$dhcp && $layer == 2) || ($dhcp && $layer == 2)) {
 | 
						|
                            # Save network name
 | 
						|
                            $nic = $_;
 | 
						|
                                
 | 
						|
                            # Get network virtual address
 | 
						|
                            @words = split(' ',  $lines[$i]);
 | 
						|
                            
 | 
						|
                            # Get virtual address (channel)
 | 
						|
                            # Convert subchannel to decimal
 | 
						|
                            $channel = sprintf('%d', hex($words[1]));
 | 
						|
                            
 | 
						|
                            xCAT::zvmUtils->printSyslog("findUsablezHcpNetwork() Candidate found NIC:$nic channel:$channel layer:$layer");
 | 
						|
                            return ($nic, $channel, $layer);
 | 
						|
                        } else {
 | 
						|
                            # Go to next network available
 | 
						|
                            $nic = '';
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                } # End of foreach
 | 
						|
            } # End of for
 | 
						|
        } # End of if
 | 
						|
    }
 | 
						|
    
 | 
						|
    return;
 | 
						|
} |