2007-10-26 22:44:33 +00:00
#!/usr/bin/env perl
2010-05-07 02:04:04 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
2007-10-26 22:44:33 +00:00
package xCAT::Utils ;
2009-02-04 17:18:44 +00:00
2008-09-26 23:07:45 +00:00
BEGIN
{
2009-02-04 17:18:44 +00:00
$ ::XCATROOT = $ ENV { 'XCATROOT' } ? $ ENV { 'XCATROOT' } : '/opt/xcat' ;
2008-09-26 23:07:45 +00:00
}
2009-07-29 16:54:53 +00:00
# if AIX - make sure we include perl 5.8.2 in INC path.
# Needed to find perl dependencies shipped in deps tarball.
if ( $^O =~ /^aix/i ) {
2012-08-08 17:27:50 +00:00
unshift ( @ INC , qw( /usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2 ) ) ;
2009-07-29 16:54:53 +00:00
}
2008-09-26 23:07:45 +00:00
use lib "$::XCATROOT/lib/perl" ;
2011-04-01 14:02:44 +00:00
# do not put a use or require for xCAT::Table here. Add to each new routine
# needing it to avoid reprocessing of user tables ( ExtTab.pm) for each command call
2008-02-25 14:18:18 +00:00
use POSIX qw( ceil ) ;
2010-02-24 06:41:20 +00:00
use File::Path ;
2008-02-02 19:39:33 +00:00
use Socket ;
2008-07-18 12:30:22 +00:00
use strict ;
2010-05-18 19:30:49 +00:00
use Symbol ;
2012-06-15 14:17:07 +00:00
my $ sha1support = eval {
require Digest::SHA1 ;
1 ;
} ;
2010-05-18 19:35:39 +00:00
use IPC::Open3 ;
2011-08-25 13:06:55 +00:00
use IO::Select ;
2012-04-22 10:25:50 +00:00
use xCAT::GlobalDef ;
2012-06-14 18:43:11 +00:00
eval {
require xCAT::RemoteShellExp ;
} ;
2010-02-04 18:29:12 +00:00
use warnings "all" ;
2009-11-25 16:24:08 +00:00
require xCAT::InstUtils ;
2012-08-23 04:21:28 +00:00
#require xCAT::NetworkUtils;
2008-04-05 14:53:35 +00:00
require xCAT::Schema ;
2011-04-11 13:49:13 +00:00
#require Data::Dumper;
2008-04-05 14:53:35 +00:00
require xCAT::NodeRange ;
2011-04-26 16:57:13 +00:00
require xCAT::Version ;
2008-04-05 14:53:35 +00:00
require DBI ;
2008-05-07 17:35:14 +00:00
2008-05-13 12:36:13 +00:00
our @ ISA = qw( Exporter ) ;
2010-05-18 19:30:49 +00:00
our @ EXPORT_OK = qw( genpassword runcmd3 ) ;
2008-05-07 14:51:12 +00:00
2012-08-16 07:03:02 +00:00
# The functions that has been moved to TableUtils.pm
# xCAT::Utils->list_all_nodes ====> xCAT::TableUtils->list_all_nodes
# xCAT::Utils->list_all_nodegroups ====> xCAT::TableUtils->list_all_nodegroups
# xCAT::Utils->bldnonrootSSHFiles ====> xCAT::TableUtils->bldnonrootSSHFiles
# xCAT::Utils->setupSSH ====> xCAT::TableUtils->setupSSH
# xCAT::Utils->cpSSHFiles ====> xCAT::TableUtils->cpSSHFiles
# xCAT::Utils->GetNodeOSARCH ====> xCAT::TableUtils->GetNodeOSARCH
# xCAT::Utils->logEventsToDatabase ====> xCAT::TableUtils->logEventsToDatabase
# xCAT::Utils->logEventsToTealDatabase ====> xCAT::TableUtils->logEventsToTealDatabase
# xCAT::Utils->setAppStatus ====> xCAT::TableUtils->setAppStatus
# xCAT::Utils->getAppStatus ====> xCAT::TableUtils->getAppStatus
# xCAT::Utils->get_site_attribute ====> xCAT::TableUtils->get_site_attribute
# xCAT::Utils->getInstallDir ====> xCAT::TableUtils->getInstallDir
# xCAT::Utils->getTftpDir ====> xCAT::TableUtils->getTftpDir
# xCAT::Utils->GetMasterNodeName ====> xCAT::TableUtils->GetMasterNodeName
# xCAT::Utils->create_postscripts_tar ====> xCAT::TableUtils->create_postscripts_tar
# xCAT::Utils->get_site_Master ====> xCAT::TableUtils->get_site_Master
# xCAT::Utils->checkCreds ====> xCAT::TableUtils->checkCreds
# xCAT::Utils->enablessh ====> xCAT::TableUtils->enablessh
# xCAT::Utils->getrootimage ====> xCAT::TableUtils->getrootimage
# The functions that has been moved to ServiceNodeUtils.pm
# xCAT::Utils->readSNInfo ====> xCAT::ServiceNodeUtils->readSNInfo
# xCAT::Utils->isServiceReq ====> xCAT::ServiceNodeUtils->isServiceReq
# xCAT::Utils->get_AllSN ====> xCAT::ServiceNodeUtils->get_AllSN
# xCAT::Utils->getSNandNodes ====> xCAT::ServiceNodeUtils->getSNandNodes
# xCAT::Utils->getSNList ====> xCAT::ServiceNodeUtils->getSNList
# xCAT::Utils->get_ServiceNode ====> xCAT::ServiceNodeUtils->get_ServiceNode
# xCAT::Utils->getSNformattedhash ====> xCAT::ServiceNodeUtils->getSNformattedhash
# The functions that has been moved to NetworkUtils.pm
# xCAT::Utils->classful_networks_for_net_and_mask ====> xCAT::NetworkUtils->classful_networks_for_net_and_mask
# xCAT::Utils->my_hexnets ====> xCAT::NetworkUtils->my_hexnets
# xCAT::Utils->get_host_from_ip ====> xCAT::NetworkUtils->get_host_from_ip (shall not be used)
# xCAT::Utils::isPingable ====> xCAT::NetworkUtils::isPingable
# xCAT::Utils::my_nets ====> xCAT::NetworkUtils::my_nets
# xCAT::Utils::my_if_netmap ====> xCAT::NetworkUtils::my_if_netmap
# xCAT::Utils->my_ip_facing ====> xCAT::NetworkUtils->my_ip_facing
# xCAT::Utils::formatNetmask ====> xCAT::NetworkUtils::formatNetmask
# xCAT::Utils::isInSameSubnet ====> xCAT::NetworkUtils::isInSameSubnet
# xCAT::Utils->nodeonmynet ====> xCAT::NetworkUtils->nodeonmynet
# xCAT::Utils::getNodeIPaddress ====> xCAT::NetworkUtils::getNodeIPaddress
# xCAT::Utils->thishostisnot ====> xCAT::NetworkUtils->thishostisnot
# xCAT::Utils->gethost_ips ====> xCAT::NetworkUtils->gethost_ips
2012-08-23 04:21:28 +00:00
# xCAT::Utils::get_subnet_aix ====> xCAT::NetworkUtils::get_subnet_aix
2012-08-16 07:03:02 +00:00
# xCAT::Utils->determinehostname ====> xCAT::NetworkUtils->determinehostname
# xCAT::Utils::toIP ====> xCAT::NetworkUtils::toIP
# xCAT::Utils->validate_ip ====> xCAT::NetworkUtils->validate_ip
# xCAT::Utils->getFacingIP ====> xCAT::NetworkUtils->getFacingIP
# xCAT::Utils->isIpaddr ====> xCAT::NetworkUtils->isIpaddr
# xCAT::Utils::getNodeNetworkCfg ====> xCAT::NetworkUtils::getNodeNetworkCfg
# xCAT::Utils::get_hdwr_ip ====> xCAT::NetworkUtils::get_hdwr_ip
2012-08-23 04:21:28 +00:00
# xCAT::Utils->pingNodeStatus ====> xCAT::NetworkUtils->pingNodeStatus
2012-08-16 07:03:02 +00:00
2012-08-09 03:48:50 +00:00
2008-05-07 17:35:14 +00:00
#--------------------------------------------------------------------------------
= head1 xCAT:: Utils
= head2 Package Description
This program module file , is a set of utilities used by xCAT commands .
= cut
2008-07-28 13:48:15 +00:00
#-------------------------------------------------------------
2009-02-04 17:18:44 +00:00
2008-07-28 13:48:15 +00:00
= head3 genUUID
2010-05-16 22:56:22 +00:00
Returns an RFC 4122 compliant UUIDv4 or UUIDv1
2008-07-28 13:48:15 +00:00
Arguments:
2010-05-16 22:56:22 +00:00
mac: If requesting a UUIDv1 , the mac to use to base it upon
2008-07-28 13:48:15 +00:00
Returns:
string representation of a UUDv4 ,
for example: f16196d1 - 7534 - 41 c1 - a0ae - a9633b030583
2009-12-10 18:51:03 +00:00
for example: f16196d1 - 7534 - 41 c1 - a0ae - a9633b030583
2008-07-28 13:48:15 +00:00
= cut
2009-02-04 17:18:44 +00:00
2008-07-28 13:48:15 +00:00
#-------------------------------------------------------
2009-02-04 17:18:44 +00:00
sub genUUID
{
2008-07-28 13:48:15 +00:00
#UUIDv4 has 6 fixed bits and 122 random bits
#Though a UUID of this form is not guaranteed to be unique absolutely,
2009-02-04 17:18:44 +00:00
#the chances of a cluster the size of the entire internet generating
#two identical UUIDs is 4 in 10 octillion.
2010-05-16 18:54:46 +00:00
my % args = @ _ ;
if ( $ args { mac } ) { #if a mac address was supplied, generate a uuidv1 instead
2010-05-19 13:54:38 +00:00
use Math::BigInt ;
no warnings 'portable' ;
use Time::HiRes qw/gettimeofday/ ;
my $ sec ;
my $ usec ;
( $ sec , $ usec ) = gettimeofday ( ) ;
my $ uuidtime = Math::BigInt - > new ( $ sec ) ;
2010-05-19 14:05:00 +00:00
$ uuidtime - > bmul ( '10000000' ) ;
$ uuidtime - > badd ( $ usec * 10 ) ;
2010-05-19 13:54:38 +00:00
$ uuidtime - > badd ( '0x01B21DD213814000' ) ;
my $ timelow = $ uuidtime - > copy ( ) ;
2010-05-19 14:01:44 +00:00
$ timelow - > band ( '0xffffffff' ) ; # get lower 32bit
2010-05-19 13:54:38 +00:00
my $ timemid = $ uuidtime - > copy ( ) ;
2010-05-19 14:01:44 +00:00
$ timemid - > band ( '0xffff00000000' ) ;
2010-05-19 13:54:38 +00:00
my $ timehigh = $ uuidtime - > copy ( ) ;
2010-05-19 14:01:44 +00:00
$ timehigh - > band ( '0xffff000000000000' ) ;
$ timemid - > brsft ( 32 ) ;
$ timehigh - > brsft ( 48 ) ;
$ timehigh - > bior ( '0x1000' ) ; #add in version, don't bother stripping out the high bits since by the year 5236, none of this should matter
2010-05-19 13:54:38 +00:00
my $ clockseq = rand ( 8191 ) ; #leave the top three bits alone. We could leave just top two bits, but it's unneeded
#also, randomness matters very little, as the time+mac is here
$ clockseq = $ clockseq | 0x8000 ; #RFC4122 variant
#time to assemble...
$ timelow = $ timelow - > bstr ( ) ;
2010-05-19 14:01:44 +00:00
$ usec = $ timelow == 0 ; # doing numeric comparison induces perl to 'int'-ify it. Safe at this point as the subpieces are all sub-32 bit now
#assign to $usec the result so that perl doesn't complain about this trickery
2010-05-19 13:54:38 +00:00
$ timemid = $ timemid - > bstr ( ) ;
2010-05-19 14:01:44 +00:00
$ usec = $ timemid == 0 ;
$ timehigh = $ timehigh - > bstr ( ) ;
$ usec = $ timehigh == 0 ;
2010-05-19 13:54:38 +00:00
my $ uuid = sprintf ( "%08x-%04x-%04x-%04x-" , $ timelow , $ timemid , $ timehigh , $ clockseq ) ;
my $ mac = $ args { mac } ;
$ mac =~ s/://g ;
$ mac = lc ( $ mac ) ;
$ uuid . = $ mac ;
return $ uuid ;
2012-06-15 14:17:07 +00:00
} elsif ( $ args { url } and $ sha1support ) { #generate a UUIDv5 from URL
2010-07-16 20:49:38 +00:00
#6ba7b810-9dad-11d1-80b4-00c04fd430c8 is the uuid for URL namespace
2012-06-15 14:17:07 +00:00
my $ sum = Digest::SHA1:: sha1 ( '6ba7b810-9dad-11d1-80b4-00c04fd430c8' . $ args { url } ) ;
2010-07-16 20:49:38 +00:00
my @ data = unpack ( "C*" , $ sum ) ;
splice @ data , 16 ;
$ data [ 6 ] = $ data [ 6 ] & 0xf ;
$ data [ 6 ] = $ data [ 6 ] | ( 5 << 4 ) ;
$ data [ 8 ] = $ data [ 8 ] & 127 ;
$ data [ 8 ] = $ data [ 8 ] | 64 ;
my $ uuid = unpack ( "H*" , pack ( "C*" , splice @ data , 0 , 4 ) ) ;
$ uuid . = "-" . unpack ( "H*" , pack ( "C*" , splice @ data , 0 , 2 ) ) ;
$ uuid . = "-" . unpack ( "H*" , pack ( "C*" , splice @ data , 0 , 2 ) ) ;
$ uuid . = "-" . unpack ( "H*" , pack ( "C*" , splice @ data , 0 , 2 ) ) ;
$ uuid . = "-" . unpack ( "H*" , pack ( "C*" , @ data ) ) ;
return $ uuid ;
2010-05-16 18:54:46 +00:00
}
2009-02-04 17:18:44 +00:00
srand ( ) ; #Many note this as bad practice, however, forks are going on..
2008-07-28 13:48:15 +00:00
my $ uuid ;
2009-02-04 17:18:44 +00:00
$ uuid =
sprintf ( "%08x-%04x-4%03x-" ,
int ( rand ( 4294967295 ) ) ,
int ( rand ( 65535 ) ) , int ( rand ( 4095 ) ) ) ;
my $ num = 32768 ;
2008-07-28 13:48:15 +00:00
$ num = $ num | int ( rand ( 16383 ) ) ;
2009-02-04 17:18:44 +00:00
$ uuid . =
sprintf ( "%04x-%04x%08x" , $ num , int ( rand ( 65535 ) ) , int ( rand ( 4294967295 ) ) ) ;
2008-07-28 13:48:15 +00:00
return $ uuid ;
}
2008-05-07 14:51:12 +00:00
#--------------------------------------------------------------------------------
2008-05-13 12:36:13 +00:00
2008-05-07 14:51:12 +00:00
= head3 genpassword
returns a random string of specified length or 8 if none given
Arguments:
length of string requested
Returns:
string of requested length or 8
Globals:
none
Error:
none
Example:
my $ salt = genpassword ( 8 ) ;
Comments:
none
= cut
#--------------------------------------------------------------------------------
2008-05-13 12:36:13 +00:00
sub genpassword
{
#Generate a pseudo-random password of specified length
my $ length = shift ;
unless ( $ length ) { $ length = 8 ; }
my $ password = '' ;
my $ characters =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890' ;
srand ; #have to reseed, rand is not rand otherwise
while ( length ( $ password ) < $ length )
{
$ password . = substr ( $ characters , int ( rand 63 ) , 1 ) ;
2008-05-07 14:51:12 +00:00
}
return $ password ;
}
2007-10-26 22:44:33 +00:00
#--------------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
2007-10-26 22:44:33 +00:00
= head3 quote
Quote a string , taking into account embedded quotes . This function is most
useful when passing string through the shell to another cmd . It handles one
level of embedded double quotes , single quotes , and dollar signs .
Arguments:
string to quote
Returns:
quoted string
Globals:
none
Error:
none
Example:
if ( defined ( $$ opthashref { 'WhereStr' } ) ) {
$ where = xCAT::Utils - > quote ( $$ opthashref { 'WhereStr' } ) ;
}
Comments:
none
= cut
2007-12-20 19:02:45 +00:00
2007-10-26 22:44:33 +00:00
#--------------------------------------------------------------------------------
sub quote
{
my ( $ class , $ str ) = @ _ ;
# if the value has imbedded double quotes, use single quotes. If it also has
# single quotes, escape the double quotes.
if ( ! ( $ str =~ /\"/ ) ) # no embedded double quotes
{
$ str =~ s/\$/\\\$/sg ; # escape the dollar signs
$ str =~ s/\`/\\\`/sg ;
$ str = qq( "$str" ) ;
}
elsif ( ! ( $ str =~ /\'/ ) )
{
$ str = qq( '$str' ) ;
} # no embedded single quotes
else # has both embedded double and single quotes
{
# Escape the double quotes. (Escaping single quotes does not seem to work
# in the shells.)
$ str =~ s/\"/\\\"/sg ; #" this comment helps formating
$ str =~ s/\$/\\\$/sg ; # escape the dollar signs
$ str =~ s/\`/\\\`/sg ;
$ str = qq( "$str" ) ;
}
}
#-------------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
2007-10-26 22:44:33 +00:00
= head3 isAIX
returns 1 if localHost is AIX
Arguments:
none
Returns:
1 - localHost is AIX
0 - localHost is some other platform
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > isAIX ( ) ) { blah ; }
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub isAIX
{
if ( $^O =~ /^aix/i ) { return 1 ; }
else { return 0 ; }
}
2009-08-09 17:46:04 +00:00
#-------------------------------------------------------------------------------
= head3 get_OS_VRMF
Arguments:
none
Returns:
v . r . m . f - if success
undef - if error
Example:
my $ osversion = xCAT::Utils - > get_OS_VRMF ( ) ;
Comments:
Only implemented for AIX for now
= cut
#-------------------------------------------------------------------------------
sub get_OS_VRMF
{
my $ version ;
if ( xCAT::Utils - > isAIX ( ) ) {
my $ cmd = "/usr/bin/lslpp -cLq bos.rte" ;
my $ output = xCAT::Utils - > runcmd ( $ cmd ) ;
chomp ( $ output ) ;
# The third field in the lslpp output is the VRMF
$ version = ( split ( /:/ , $ output ) ) [ 2 ] ;
# not sure if the field would ever contain more than 4 parts?
my ( $ v1 , $ v2 , $ v3 , $ v4 , $ rest ) = split ( /\./ , $ version ) ;
$ version = join ( "." , $ v1 , $ v2 , $ v3 , $ v4 ) ;
}
return ( length ( $ version ) ? $ version : undef ) ;
}
#----------------------------------------------------------------------------
= head3 testversion
Compare version1 and version2 according to the operator and
return True or False .
Arguments:
$ version1
$ operator
$ version2
$ release1
$ release2
Returns:
True or False
Example:
if ( ArchiveUtils - > testversion ( $ ins_ver ,
"<" ,
$ req_ver ,
$ ins_rel ,
$ req_rel ) ) { blah ; }
Comments:
= cut
#-------------------------------------------------------------------------------
sub testversion
{
my ( $ class , $ version1 , $ operator , $ version2 , $ release1 , $ release2 ) = @ _ ;
my @ a1 = split ( /\./ , $ version1 ) ;
my @ a2 = split ( /\./ , $ version2 ) ;
my $ len = ( scalar ( @ a1 ) > scalar ( @ a2 ) ? scalar ( @ a1 ) : scalar ( @ a2 ) ) ;
$# a1 = $ len - 1 ; # make the arrays the same length before appending release
$# a2 = $ len - 1 ;
push @ a1 , split ( /\./ , $ release1 ) ;
push @ a2 , split ( /\./ , $ release2 ) ;
$ len = ( scalar ( @ a1 ) > scalar ( @ a2 ) ? scalar ( @ a1 ) : scalar ( @ a2 ) ) ;
my $ num1 = '' ;
my $ num2 = '' ;
for ( my $ i = 0 ; $ i < $ len ; $ i + + )
{
my ( $ d1 ) = $ a1 [ $ i ] =~ /^(\d*)/ ; # remove any non-numbers on the end
my ( $ d2 ) = $ a2 [ $ i ] =~ /^(\d*)/ ;
my $ diff = length ( $ d1 ) - length ( $ d2 ) ;
if ( $ diff > 0 ) # pad d2
{
$ num1 . = $ d1 ;
$ num2 . = ( '0' x $ diff ) . $ d2 ;
}
elsif ( $ diff < 0 ) # pad d1
{
$ num1 . = ( '0' x abs ( $ diff ) ) . $ d1 ;
$ num2 . = $ d2 ;
}
else # they are the same length
{
$ num1 . = $ d1 ;
$ num2 . = $ d2 ;
}
}
# Remove the leading 0s or perl will interpret the numbers as octal
$ num1 =~ s/^0+// ;
$ num2 =~ s/^0+// ;
#SLES Changes ??
# if $num1="", the "eval '$num1 $operator $num2'" will fail.
# So MUST BE be sure that $num1 is not a "".
if ( length ( $ num1 ) == 0 ) { $ num1 = 0 ; }
if ( length ( $ num2 ) == 0 ) { $ num2 = 0 ; }
#End of SLES Changes
if ( $ operator eq '=' ) { $ operator = '==' ; }
my $ bool = eval "$num1 $operator $num2" ;
if ( length ( $@ ) )
{
# error msg ?
}
return $ bool ;
}
2008-01-21 19:39:09 +00:00
#-------------------------------------------------------------------------------
2008-01-21 19:49:59 +00:00
= head3 xfork
2008-01-21 19:39:09 +00:00
forks , safely coping with open database handles
Argumens:
none
Returns:
same as fork
= cut
2008-02-04 20:02:15 +00:00
2008-03-26 18:20:05 +00:00
#-------------------------------------------------------------------------------
2008-02-04 20:02:15 +00:00
sub xfork
{
my $ rc = fork ;
unless ( defined ( $ rc ) )
{
return $ rc ;
}
unless ( $ rc )
{
#my %drivers = DBI->installed_drivers;
foreach ( values % { $ ::XCAT_DBHS } )
{ #@{$drh->{ChildHandles}}) {
2009-11-10 15:07:16 +00:00
#if ($_) { $_->disconnect(); }
2008-02-04 20:02:15 +00:00
$ _ - > { InactiveDestroy } = 1 ;
undef $ _ ;
2008-01-21 19:39:09 +00:00
}
2008-02-04 20:02:15 +00:00
}
return $ rc ;
2008-01-21 19:39:09 +00:00
}
2008-03-26 18:20:05 +00:00
sub close_all_dbhs
{
foreach ( values % { $ ::XCAT_DBHS } )
{ #@{$drh->{ChildHandles}}) {
$ _ - > disconnect ;
undef $ _ ;
}
2008-03-11 20:27:46 +00:00
}
2008-03-26 18:20:05 +00:00
2007-10-26 22:44:33 +00:00
#-------------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
2007-10-26 22:44:33 +00:00
= head3 isLinux
returns 1 if localHost is Linux
Arguments:
none
Returns:
1 - localHost is Linux
0 - localHost is some other platform
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > isLinux ( ) ) { blah ; }
Comments:
none
= cut
2007-12-20 19:02:45 +00:00
2007-10-26 22:44:33 +00:00
#-------------------------------------------------------------------------------
sub isLinux
{
if ( $^O =~ /^linux/i ) { return 1 ; }
else { return 0 ; }
}
#-------------------------------------------------------------------------------
2008-06-10 16:39:20 +00:00
= head3 Version
Arguments:
2008-09-19 17:39:06 +00:00
Optional 'short' string to request only the version ;
2008-06-10 16:39:20 +00:00
Returns:
xcat Version number
Globals:
none
Error:
none
Example:
$ version = xCAT::Utils - > Version ( ) ;
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub Version
{
2009-02-04 17:18:44 +00:00
my $ version = shift ;
2011-04-26 16:57:13 +00:00
$ version = xCAT::Version - > Version ( ) ;
2009-02-04 17:18:44 +00:00
return $ version ;
2008-06-10 16:39:20 +00:00
}
#-------------------------------------------------------------------------------
2007-10-26 22:44:33 +00:00
= head3 make_node_list_file
2008-04-05 14:53:35 +00:00
Makes a node list file .
2007-10-26 22:44:33 +00:00
Arguments:
( \ @ list_of_nodes ) - reference to an arrary of nodes .
Returns:
$ file_name and sets the global var: $ ::NODE_LIST_FILE
Globals:
the ENV vars: DSH_LIST , RPOWER_LIST , RCONSOLE_LIST
Error:
None documented
Example:
2008-04-05 14:53:35 +00:00
xCAT::Utils - > make_node_list_file ( \ @ nodelist ) ;
2007-10-26 22:44:33 +00:00
Comments:
IMPORTANT:
Make sure to cleanup afterwards with:
xCAT::Utils - > close_delete_file ( $ file_handle , $ file_name )
= cut
#--------------------------------------------------------------------------------
sub make_node_list_file
{
my ( $ class , $ ref_node_list ) = @ _ ;
my @ node_list = @$ ref_node_list ;
srand ( time | $$ ) ; #random number generator start
my $ file = "/tmp/csm_$$" ;
while ( - e $ file )
{
$ file = xCAT::Utils - > CreateRandomName ( $ file ) ;
}
open ( $ ::NODE_LIST_FILE , ">$file" )
2009-01-06 17:58:01 +00:00
or xCAT::MsgUtils - > message ( "E" , "Cannot write to file: $file\n" ) ;
2007-10-26 22:44:33 +00:00
foreach my $ node ( @ node_list )
{
print $ ::NODE_LIST_FILE "$node\n" ;
}
return $ file ;
}
#--------------------------------------------------------------------------------
= head3 CreateRandomName
Create a randome file name .
Arguments:
Prefix of name
Returns:
Prefix with 8 random letters appended
Error:
none
Example:
$ file = xCAT::Utils - > CreateRandomName ( $ namePrefix ) ;
Comments:
None
= cut
#-------------------------------------------------------------------------------
sub CreateRandomName
{
my ( $ class , $ name ) = @ _ ;
my $ nI ;
for ( $ nI = 0 ; $ nI < 8 ; $ nI + + )
{
my $ char = ( 'a' .. 'z' , 'A' .. 'Z' ) [ int ( rand ( 52 ) ) + 1 ] ;
$ name . = $ char ;
}
$ name ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
2007-10-26 22:44:33 +00:00
close_delete_file .
Arguments:
file handle , filename
Returns:
2008-04-05 14:53:35 +00:00
none
2007-10-26 22:44:33 +00:00
Globals:
none
Error:
undef
Example:
xCAT::Utils - > close_delete_file ( $ file_handle , $ file_name ) ;
Comments:
none
= cut
#------------------------------------------------------------------------
sub close_delete_file
{
my ( $ class , $ file_handle , $ file_name ) = @ _ ;
close $ file_handle ;
unlink ( $ file_name ) ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
2010-10-28 19:08:56 +00:00
list_nodes_in_nodegroups
2007-10-26 22:44:33 +00:00
Arguments: nodegroup
2008-04-05 14:53:35 +00:00
2007-10-26 22:44:33 +00:00
Returns:
2008-04-05 14:53:35 +00:00
an array of all define nodes in the node group
2007-10-26 22:44:33 +00:00
Globals:
none
Error:
undef
Example:
2010-10-28 19:08:56 +00:00
@ nodes = xCAT::Utils - > list_nodes_in_nodegroups ( $ group ) ;
2007-10-26 22:44:33 +00:00
Comments:
none
= cut
#------------------------------------------------------------------------
sub list_nodes_in_nodegroups
{
my ( $ class , $ group ) = @ _ ;
2009-02-04 17:18:44 +00:00
my $ req = { } ;
2007-10-26 22:44:33 +00:00
$ req - > { noderange } - > [ 0 ] = $ group ;
2008-04-05 14:53:35 +00:00
my @ nodes = xCAT::NodeRange:: noderange ( $ req - > { noderange } - > [ 0 ] ) ;
2007-10-26 22:44:33 +00:00
return @ nodes ;
}
#-----------------------------------------------------------------------
2010-10-28 19:08:56 +00:00
= head3
isMemberofGroup
Arguments: node , group
Returns:
1 = is a member
0 = not a member
Globals:
none
Error:
undef
Example:
$ ismember = xCAT::Utils - > isMemberofGroup ( $ node , $ group ) ;
Comments:
none
= cut
#------------------------------------------------------------------------
sub isMemberofGroup
{
my ( $ class , $ node , $ group ) = @ _ ;
my $ ismember ;
my @ nodes = xCAT::Utils - > list_nodes_in_nodegroups ( $ group ) ;
2010-11-02 18:16:33 +00:00
if ( grep ( /^$node$/ , @ nodes ) ) {
2010-10-28 19:08:56 +00:00
$ ismember = 1 ;
} else {
$ ismember = 0 ;
}
return $ ismember ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
2007-11-28 19:44:47 +00:00
add_cron_job
This function adds a new cron job .
Arguments:
2008-04-05 14:53:35 +00:00
job - - - string in the crontab job format .
2007-11-28 19:44:47 +00:00
Returns:
( code , message )
Globals:
none
Error:
undef
Example:
xCAT::Utils - > add_cron_job ( "*/5 * * * * /usr/bin/myjob" ) ;
Comments:
none
= cut
2007-12-20 19:02:45 +00:00
2007-11-28 19:44:47 +00:00
#------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
sub add_cron_job
{
2008-07-18 12:30:22 +00:00
my $ newentry = shift ;
2007-12-20 19:02:45 +00:00
if ( $ newentry =~ /xCAT::Utils/ )
{
$ newentry = shift ;
}
#read the cron tab entries
my @ tabs = `/usr/bin/crontab -l 2>/dev/null` ;
my @ newtabs = ( ) ;
foreach ( @ tabs )
{
chomp ( $ _ ) ;
# stop adding if it's already there
if ( $ _ eq $ newentry ) { return ( 0 , "started" ) ; }
#skip headers for Linux
next
if $ _ =~
m/^\#.+(DO NOT EDIT THIS FILE|\(.+ installed on |Cron version )/ ;
push ( @ newtabs , $ _ ) ;
}
#add new entries to the cron tab
push ( @ newtabs , $ newentry ) ;
my $ tabname = "" ;
2008-09-26 23:07:45 +00:00
if ( xCAT::Utils - > isLinux ( ) ) { $ tabname = "-" ; }
2007-12-20 19:02:45 +00:00
open ( CRONTAB , "|/usr/bin/crontab $tabname" )
or return ( 1 , "cannot open crontab." ) ;
foreach ( @ newtabs ) { print CRONTAB $ _ . "\n" ; }
close ( CRONTAB ) ;
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
return ( 0 , "" ) ;
}
2007-11-28 19:44:47 +00:00
#-----------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
2008-04-05 14:53:35 +00:00
= head3
2007-11-28 19:44:47 +00:00
remove_cron_job
This function removes a new cron job .
Arguments:
2008-04-05 14:53:35 +00:00
job - - - a substring that is contained in a crontab entry .
( use crontab - l to see all the job entries . )
2007-11-28 19:44:47 +00:00
Returns:
( code , message )
Globals:
none
Error:
undef
Example:
xCAT::Utils - > remove_cron_job ( "/usr/bin/myjob" ) ;
This will remove any cron job that contains this string .
Comments:
none
= cut
2007-12-20 19:02:45 +00:00
2007-11-28 19:44:47 +00:00
#------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
sub remove_cron_job
{
2008-07-18 12:30:22 +00:00
my $ job = shift ;
2007-12-20 19:02:45 +00:00
if ( $ job =~ /xCAT::Utils/ )
{
$ job = shift ;
}
#read the cron tab entries and remove the one that contains $job
my @ tabs = `/usr/bin/crontab -l 2>/dev/null` ;
my @ newtabs = ( ) ;
foreach ( @ tabs )
{
chomp ( $ _ ) ;
# stop adding if it's already there
next if index ( $ _ , $ job , 0 ) >= 0 ;
#skip headers for Linux
next
if $ _ =~
m/^\#.+(DO NOT EDIT THIS FILE|\(.+ installed on |Cron version )/ ;
push ( @ newtabs , $ _ ) ;
}
#refresh the cron
my $ tabname = "" ;
2008-09-26 23:07:45 +00:00
if ( xCAT::Utils - > isLinux ( ) ) { $ tabname = "-" ; }
2007-12-20 19:02:45 +00:00
open ( CRONTAB , "|/usr/bin/crontab $tabname" )
or return ( 1 , "cannot open crontab." ) ;
foreach ( @ newtabs ) { print CRONTAB $ _ . "\n" ; }
close ( CRONTAB ) ;
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
return ( 0 , "" ) ;
}
2007-11-28 19:44:47 +00:00
2010-05-18 19:30:49 +00:00
#-------------------------------------------------------------------------------
= head3 runcmd3
Run the specified command with optional input and return stderr , stdout , and exit code
Arguments:
command = > [] - Array reference of command to run
input = > [] or string - Data to send to stdin of process like piping input
Returns:
{ exitcode = > number , output = > $ string , errors = > string }
= cut
sub runcmd3 { #a proper runcmd that indpendently returns stdout, stderr, pid and accepts a stdin
my % args = @ _ ;
my @ indata ;
my $ output ;
my $ errors ;
if ( $ args { input } ) {
if ( ref $ args { input } ) { #array ref
@ indata = @ { $ args { input } } ;
} else { #just a string
@ indata = ( $ args { input } ) ;
}
}
my @ cmd ;
if ( ref $ args { command } ) {
@ cmd = @ { $ args { command } } ;
} else {
@ cmd = ( $ args { command } ) ;
}
my $ cmdin ;
my $ cmdout ;
my $ cmderr = gensym ;
my $ cmdpid = open3 ( $ cmdin , $ cmdout , $ cmderr , @ cmd ) ;
2010-05-18 19:54:43 +00:00
my $ cmdsel = IO::Select - > new ( $ cmdout , $ cmderr ) ;
2010-05-18 19:30:49 +00:00
foreach ( @ indata ) {
print $ cmdin $ _ ;
}
2010-05-18 21:01:49 +00:00
close ( $ cmdin ) ;
2010-05-18 19:30:49 +00:00
my @ handles ;
2010-05-19 12:52:52 +00:00
while ( $ cmdsel - > count ( ) ) {
2010-05-19 12:47:07 +00:00
@ handles = $ cmdsel - > can_read ( ) ;
2010-05-18 19:30:49 +00:00
foreach ( @ handles ) {
my $ line ;
my $ done = sysread $ _ , $ line , 180 ;
if ( $ done ) {
if ( $ _ eq $ cmdout ) {
$ output . = $ line ;
} else {
$ errors . = $ line ;
}
} else {
$ cmdsel - > remove ( $ _ ) ;
close ( $ _ ) ;
}
}
}
waitpid ( $ cmdpid , 0 ) ;
my $ exitcode = $? >> 8 ;
return { 'exitcode' = > $ exitcode , 'output' = > $ output , 'errors' = > $ errors }
}
2007-11-27 14:22:04 +00:00
#-------------------------------------------------------------------------------
= head3 runcmd
Run the given cmd and return the output in an array ( already chopped ) .
2008-04-05 14:53:35 +00:00
Alternately , if this function is used in a scalar context , the output
2007-11-27 14:22:04 +00:00
is joined into a single string with the newlines separating the lines .
Arguments:
2011-08-24 18:05:11 +00:00
command , exitcode , reference to output , streaming mode
2007-11-27 14:22:04 +00:00
Returns:
see below
Globals:
2008-04-05 14:53:35 +00:00
$ ::RUNCMD_RC , $ ::CALLBACK
2007-11-27 14:22:04 +00:00
Error:
Normally , if there is an error running the cmd , it will display the
error and exit with the cmds exit code , unless exitcode
is given one of the following values :
0 : display error msg , DO NOT exit on error , but set
$ ::RUNCMD_RC to the exit code .
- 1 : DO NOT display error msg and DO NOT exit on error , but set
$ ::RUNCMD_RC to the exit code .
- 2 : DO the default behavior ( display error msg and exit with cmds
exit code .
number > 0 : Display error msg and exit with the given code
Example:
my $ outref = xCAT::Utils - > runcmd ( $ cmd , - 2 , 1 ) ;
2011-08-25 12:52:19 +00:00
$ ::CALLBACK = your callback ( required for streaming from plugins )
2011-08-24 18:05:11 +00:00
my $ outref = xCAT::Utils - > runcmd ( $ cmd , - 2 , 1 , 1 ) ; streaming
2007-11-27 14:22:04 +00:00
Comments:
If refoutput is true , then the output will be returned as a
reference to an array for efficiency .
= cut
#-------------------------------------------------------------------------------
sub runcmd
{
2011-08-24 18:05:11 +00:00
my ( $ class , $ cmd , $ exitcode , $ refoutput , $ stream ) = @ _ ;
2007-11-27 14:22:04 +00:00
$ ::RUNCMD_RC = 0 ;
2010-05-13 12:15:23 +00:00
# redirect stderr to stdout
if ( ! ( $ cmd =~ /2>&1$/ ) ) { $ cmd . = ' 2>&1' ; }
2007-11-27 14:22:04 +00:00
2011-01-30 17:00:54 +00:00
if ( $ ::VERBOSE )
{
# get this systems name as known by xCAT management node
my $ Sname = xCAT::InstUtils - > myxCATname ( ) ;
my $ msg ;
if ( $ Sname ) {
$ msg = "Running command on $Sname: $cmd" ;
} else {
$ msg = "Running command: $cmd" ;
}
if ( $ ::CALLBACK ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$msg\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
} else {
xCAT::MsgUtils - > message ( "I" , "$msg\n" ) ;
}
}
2010-02-05 16:17:28 +00:00
2007-11-27 14:22:04 +00:00
my $ outref = [] ;
2011-09-28 12:08:15 +00:00
if ( ! defined ( $ stream ) || ( length ( $ stream ) == 0 ) ) { # do not stream
2011-08-24 18:05:11 +00:00
@$ outref = `$cmd` ;
} else { # streaming mode
my @ cmd ;
push @ cmd , $ cmd ;
my $ rsp = { } ;
my $ output ;
my $ errout ;
2011-09-28 12:08:15 +00:00
open ( PIPE , "$cmd |" ) ;
while ( <PIPE> ) {
2012-10-24 15:37:47 +00:00
push @$ outref , $ _ ;
chomp ; # get rid of the newline, because the client will add one
2011-09-28 12:08:15 +00:00
if ( $ ::CALLBACK ) {
$ rsp - > { data } - > [ 0 ] = $ _ ;
$ ::CALLBACK - > ( $ rsp ) ;
} else {
xCAT::MsgUtils - > message ( "D" , "$_" ) ;
2011-08-24 18:05:11 +00:00
}
2012-10-24 15:37:47 +00:00
#$output .= $_;
2011-08-24 18:05:11 +00:00
}
# store the return string
2012-10-24 15:37:47 +00:00
#push @$outref,$output;
2011-08-24 18:05:11 +00:00
}
2011-09-28 12:08:15 +00:00
# now if not streaming process errors
if ( ( $? ) && ( ! defined ( $ stream ) ) )
2007-11-27 14:22:04 +00:00
{
$ ::RUNCMD_RC = $? >> 8 ;
my $ displayerror = 1 ;
my $ rc ;
if ( defined ( $ exitcode ) && length ( $ exitcode ) && $ exitcode != - 2 )
{
if ( $ exitcode > 0 )
{
$ rc = $ exitcode ;
} # if not zero, exit with specified code
elsif ( $ exitcode <= 0 )
{
$ rc = '' ; # if zero or negative, do not exit
if ( $ exitcode < 0 ) { $ displayerror = 0 ; }
}
}
else
{
$ rc = $ ::RUNCMD_RC ;
} # if exitcode not specified, use cmd exit code
if ( $ displayerror )
{
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
2007-11-27 14:22:04 +00:00
my $ errmsg = '' ;
if ( xCAT::Utils - > isLinux ( ) && $ ::RUNCMD_RC == 139 )
{
$ errmsg = "Segmentation fault $errmsg" ;
}
else
{
$ errmsg = join ( '' , @$ outref ) ;
chomp $ errmsg ;
}
2007-12-20 19:02:45 +00:00
if ( $ ::CALLBACK )
{
$ rsp - > { data } - > [ 0 ] =
"Command failed: $cmd. Error message: $errmsg.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
}
else
2007-11-27 14:22:04 +00:00
{
xCAT::MsgUtils - > message ( "E" ,
"Command failed: $cmd. Error message: $errmsg.\n" ) ;
}
$ xCAT:: Utils:: errno = 29 ;
}
}
if ( $ refoutput )
{
chomp ( @$ outref ) ;
return $ outref ;
}
elsif ( wantarray )
{
chomp ( @$ outref ) ;
return @$ outref ;
}
else
{
my $ line = join ( '' , @$ outref ) ;
chomp $ line ;
return $ line ;
}
}
2007-11-28 19:44:47 +00:00
2008-10-06 14:51:33 +00:00
#-------------------------------------------------------------------------------
= head3 runxcmd
Run the given xCAT cmd and return the output in an array .
Alternately , if this function is used in a scalar context , the output
is joined into a single string with newlines separating the lines .
Arguments:
command - string with following format :
< xCAT cmd name > < comma - delimited nodelist > < cmd args >
2008-10-22 15:56:46 +00:00
where the xCAT cmd name is as reqistered in the plugins ,
2008-10-06 14:51:33 +00:00
the nodelist is already flattened and verified
2008-10-22 15:56:46 +00:00
the remainder of the string is passed as args .
The nodelist may be set to the string "NO_NODE_RANGE" to
not pass in any nodes to the command .
2008-10-06 14:51:33 +00:00
OR
command - request hash
reference to xCAT daemon sub_req routine
2012-11-10 12:06:39 +00:00
exitcode - see definitions below
2008-10-06 14:51:33 +00:00
2012-11-10 12:06:39 +00:00
refoutput - type of output to build
Not set - array
1 - reference to an array
2 - returns the response hash as received from the plugin .
2008-10-06 14:51:33 +00:00
2012-10-30 19:21:28 +00:00
2008-10-06 14:51:33 +00:00
Returns:
see below
Globals:
$ ::RUNCMD_RC , $ ::CALLBACK
Error:
Cannot determine error code . If ERROR data set in response
hash , $ ::RUNCMD_RC will be set to 1 .
Normally , if there is an error running the cmd , it will display the
error and exit with the cmds exit code , unless exitcode
is given one of the following values :
2012-11-10 12:06:39 +00:00
0 : display error msg , DO NOT exit on error , but set
2008-10-06 14:51:33 +00:00
$ ::RUNCMD_RC to the exit code .
- 1 : DO NOT display error msg and DO NOT exit on error , but set
$ ::RUNCMD_RC to the exit code .
- 2 : DO the default behavior ( display error msg and exit with cmds
exit code .
number > 0 : Display error msg and exit with the given code
Example:
2012-10-30 19:21:28 +00:00
return output as reference to an array
2008-10-06 14:51:33 +00:00
my $ outref = xCAT::Utils - > runxcmd ( $ cmd , $ sub_req , - 2 , 1 ) ;
2012-10-30 19:21:28 +00:00
2012-11-10 12:06:39 +00:00
return response hash from plugin . Will not display error msg for any
exit_code setting .
my $ outref = xCAT::Utils - > runxcmd ( $ cmd , $ sub_req , - 1 , 2 ) ;
2008-10-06 14:51:33 +00:00
Comments:
2012-10-30 19:21:28 +00:00
If refoutput is 1 , then the output will be returned as a
2008-10-06 14:51:33 +00:00
reference to an array for efficiency .
2012-10-31 19:23:59 +00:00
If refoutput is 2 , then the response hash will be returned
2012-11-10 12:06:39 +00:00
as output . runxcmd will not parse the request structure , nor
will it display the error message despite the exit_code setting .
The caller will need to display the error .
2012-10-30 19:21:28 +00:00
2008-10-22 15:56:46 +00:00
Do not use the scalar string input for xdsh unless you are running
a simple single - word command . When building your request hash ,
the entire command string xdsh runs needs to be a single entry
in the arg array .
2010-02-02 19:47:52 +00:00
The caller to the runxcmd is responsible for filename expansion , that
would have been done if the command was run on the command line .
For example , the xdcp node1 /tmp/ testfile * / tmp command needs to
have the /tmp/ testfile * argument expanded before call xdcp with
runxcmd . The easy way to do this is to use the perl glob function .
@ files = glob "/tmp/testfile*" ;
2008-10-06 14:51:33 +00:00
= cut
#-------------------------------------------------------------------------------
sub runxcmd
{
2009-02-04 17:18:44 +00:00
my $ save_CALLBACK = $ ::CALLBACK ;
2008-10-06 14:51:33 +00:00
my ( $ class , $ cmd , $ subreq , $ exitcode , $ refoutput ) = @ _ ;
$ ::RUNCMD_RC = 0 ;
2010-02-05 16:17:28 +00:00
2008-10-06 14:51:33 +00:00
if ( $ ::VERBOSE )
{
2009-02-04 17:18:44 +00:00
if ( ref ( $ cmd ) eq "HASH" )
{
2010-02-05 16:17:28 +00:00
if ( $ ::CALLBACK ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Running internal xCAT command: $cmd->{command}->[0] ... \n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
} else {
xCAT::MsgUtils - > message ( "I" , "Running internal xCAT command: $cmd->{command}->[0] ... \n" ) ;
}
2009-02-04 17:18:44 +00:00
}
else
{
2010-02-05 16:17:28 +00:00
if ( $ ::CALLBACK ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Running Command: $cmd\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
} else {
xCAT::MsgUtils - > message ( "I" , "Running Command: $cmd\n" ) ;
}
2008-10-27 17:11:23 +00:00
}
2008-10-06 14:51:33 +00:00
}
2010-02-05 16:17:28 +00:00
2008-10-06 14:51:33 +00:00
$ ::xcmd_outref = [] ;
2012-10-31 18:54:37 +00:00
% ::xcmd_outref_hash = ( ) ;
2009-02-04 17:18:44 +00:00
my $ req ;
if ( ref ( $ cmd ) eq "HASH" )
{
$ req = $ cmd ;
}
else
{ # assume scalar, build request hash the way we do in xcatclient
my @ cmdargs = split ( /\s+/ , $ cmd ) ;
my $ cmdname = shift ( @ cmdargs ) ;
$ req - > { command } = [ $ cmdname ] ;
my $ arg = shift ( @ cmdargs ) ;
while ( $ arg =~ /^-/ )
{
push ( @ { $ req - > { arg } } , $ arg ) ;
$ arg = shift ( @ cmdargs ) ;
}
if ( $ arg ne "NO_NODE_RANGE" )
{
my @ nodes = split ( "," , $ arg ) ;
$ req - > { node } = \ @ nodes ;
}
push ( @ { $ req - > { arg } } , @ cmdargs ) ;
}
2012-10-30 19:21:28 +00:00
# call the plugin
2012-10-31 18:54:37 +00:00
my $ outref ;
2012-10-30 19:21:28 +00:00
if ( defined ( $ refoutput ) ) {
if ( $ refoutput != 2 ) {
$ subreq - > ( $ req , \ & runxcmd_output ) ;
2012-10-31 18:54:37 +00:00
$ outref = $ ::xcmd_outref ;
} else { # return response hash
2012-10-30 19:21:28 +00:00
$ subreq - > ( $ req , \ & runxcmd_output2 ) ;
2012-10-31 18:54:37 +00:00
$ outref = $ ::xcmd_outref_hash ;
2012-10-30 19:21:28 +00:00
}
} else {
$ subreq - > ( $ req , \ & runxcmd_output ) ;
2012-10-31 18:54:37 +00:00
$ outref = $ ::xcmd_outref ;
2012-10-30 19:21:28 +00:00
}
2009-02-04 17:18:44 +00:00
$ ::CALLBACK = $ save_CALLBACK ; # in case the subreq call changed it
2012-10-30 19:21:28 +00:00
2008-10-06 14:51:33 +00:00
if ( $ ::RUNCMD_RC )
{
my $ displayerror = 1 ;
2012-11-10 12:06:39 +00:00
# Do not display error for refoutput=2
# we do not parse the returned structure
if ( defined ( $ refoutput ) ) {
if ( $ refoutput == 2 ) {
$ displayerror = 0 ;
}
}
2008-10-06 14:51:33 +00:00
my $ rc ;
if ( defined ( $ exitcode ) && length ( $ exitcode ) && $ exitcode != - 2 )
{
if ( $ exitcode > 0 )
{
$ rc = $ exitcode ;
2009-02-04 17:18:44 +00:00
} # if not zero, exit with specified code
2008-10-06 14:51:33 +00:00
elsif ( $ exitcode <= 0 )
{
2009-02-04 17:18:44 +00:00
$ rc = '' ; # if zero or negative, do not exit
2012-11-10 12:06:39 +00:00
2008-10-06 14:51:33 +00:00
if ( $ exitcode < 0 ) { $ displayerror = 0 ; }
}
}
else
{
$ rc = $ ::RUNCMD_RC ;
} # if exitcode not specified, use cmd exit code
2012-11-10 12:06:39 +00:00
2008-10-06 14:51:33 +00:00
if ( $ displayerror )
{
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
2008-10-06 14:51:33 +00:00
my $ errmsg = join ( '' , @$ outref ) ;
chomp $ errmsg ;
2009-02-04 17:18:44 +00:00
my $ displaycmd = $ cmd ;
if ( ref ( $ cmd ) eq "HASH" )
{
$ displaycmd = $ cmd - > { command } - > [ 0 ] ;
}
2008-10-06 14:51:33 +00:00
if ( $ ::CALLBACK )
{
$ rsp - > { data } - > [ 0 ] =
2008-10-22 15:56:46 +00:00
"Command failed: $displaycmd. Error message: $errmsg.\n" ;
2008-10-06 14:51:33 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
}
else
{
xCAT::MsgUtils - > message ( "E" ,
2009-02-04 17:18:44 +00:00
"Command failed: $displaycmd. Error message: $errmsg.\n" ) ;
2008-10-06 14:51:33 +00:00
}
$ xCAT:: Utils:: errno = 29 ;
}
}
2012-10-30 19:21:28 +00:00
if ( ( defined ( $ refoutput ) ) && ( $ refoutput == 1 ) )
# output is reference to array
2008-10-06 14:51:33 +00:00
{
chomp ( @$ outref ) ;
return $ outref ;
}
2012-10-30 19:21:28 +00:00
elsif ( ( defined ( $ refoutput ) ) && ( $ refoutput == 2 ) )
# output is structure returned from plugin
{
return $ outref ;
}
elsif ( wantarray ) # array
2008-10-06 14:51:33 +00:00
{
chomp ( @$ outref ) ;
return @$ outref ;
}
2012-10-30 19:21:28 +00:00
else # string
2008-10-06 14:51:33 +00:00
{
my $ line = join ( '' , @$ outref ) ;
chomp $ line ;
return $ line ;
}
}
2009-02-04 17:18:44 +00:00
2012-10-31 18:54:37 +00:00
#-------------------------------------------------------------------------------
= head3 runxcmd_output
Internal subroutine for runxcmd to capture the output
from the xCAT daemon subrequest call
Note - only basic info , data , and error responses returned
For more complex node or other return structures , you will need
to write your own wrapper to subreq instead of using runxcmd .
= cut
#-------------------------------------------------------------------------------
2009-02-04 17:18:44 +00:00
sub runxcmd_output
{
my $ resp = shift ;
if ( defined ( $ resp - > { info } ) )
{
push @$ ::xcmd_outref , @ { $ resp - > { info } } ;
}
if ( defined ( $ resp - > { sinfo } ) )
{
push @$ ::xcmd_outref , @ { $ resp - > { sinfo } } ;
}
if ( defined ( $ resp - > { data } ) )
{
push @$ ::xcmd_outref , @ { $ resp - > { data } } ;
}
if ( defined ( $ resp - > { node } ) )
{
my $ node = $ resp - > { node } - > [ 0 ] ;
my $ desc = $ node - > { name } - > [ 0 ] ;
if ( defined ( $ node - > { data } ) )
{
if ( ref ( \ ( $ node - > { data } - > [ 0 ] ) ) eq 'SCALAR' )
{
$ desc = $ desc . ": " . $ node - > { data } - > [ 0 ] ;
}
else
{
if ( defined ( $ node - > { data } - > [ 0 ] - > { desc } ) )
{
$ desc = $ desc . ": " . $ node - > { data } - > [ 0 ] - > { desc } - > [ 0 ] ;
}
if ( defined ( $ node - > { data } - > [ 0 ] - > { contents } ) )
{
$ desc = "$desc: " . $ node - > { data } - > [ 0 ] - > { contents } - > [ 0 ] ;
}
}
}
push @$ ::xcmd_outref , $ desc ;
}
if ( defined ( $ resp - > { error } ) )
{
push @$ ::xcmd_outref , @ { $ resp - > { error } } ;
$ ::RUNCMD_RC = 1 ;
}
if ( defined ( $ resp - > { errorcode } ) )
{
if ( ref ( $ resp - > { errorcode } ) eq 'ARRAY' )
{
foreach my $ ecode ( @ { $ resp - > { errorcode } } )
{
$ ::RUNCMD_RC |= $ ecode ;
}
}
else
{
2008-10-06 14:51:33 +00:00
2009-02-04 17:18:44 +00:00
# assume it is a non-reference scalar
$ ::RUNCMD_RC |= $ resp - > { errorcode } ;
}
}
return 0 ;
}
2012-10-31 18:54:37 +00:00
#-------------------------------------------------------------------------------
= head3 runxcmd_output2
Internal subroutine for runxcmd to capture the output
from the xCAT daemon subrequest call . Returns the response hash
= cut
#-------------------------------------------------------------------------------
2012-10-30 19:21:28 +00:00
sub runxcmd_output2
{
my $ resp = shift ;
2012-10-31 18:54:37 +00:00
if ( defined ( $ resp - > { info } ) )
{
push @ { $ ::xcmd_outref_hash - > { info } } , @ { $ resp - > { info } } ;
}
if ( defined ( $ resp - > { sinfo } ) )
{
push @ { $ ::xcmd_outref_hash - > { sinfo } } , @ { $ resp - > { sinfo } } ;
}
if ( defined ( $ resp - > { data } ) )
{
push @ { $ ::xcmd_outref_hash - > { data } } , @ { $ resp - > { data } } ;
}
if ( defined ( $ resp - > { node } ) )
{
push @ { $ ::xcmd_outref_hash - > { node } } , @ { $ resp - > { node } } ;
}
if ( defined ( $ resp - > { error } ) )
{
push @ { $ ::xcmd_outref_hash - > { error } } , @ { $ resp - > { error } } ;
$ ::RUNCMD_RC = 1 ;
}
if ( defined ( $ resp - > { errorcode } ) )
{
if ( ref ( $ resp - > { errorcode } ) eq 'ARRAY' )
{
push @ { $ ::xcmd_outref_hash - > { errorcode } } , @ { $ resp - > { errorcode } } ;
foreach my $ ecode ( @ { $ resp - > { errorcode } } )
{
$ ::RUNCMD_RC |= $ ecode ;
}
}
else
{
# assume it is a non-reference scalar
$ ::RUNCMD_RC |= $ resp - > { errorcode } ;
}
}
2012-10-30 19:21:28 +00:00
return 0 ;
}
2008-10-06 14:51:33 +00:00
2007-12-20 19:02:45 +00:00
#--------------------------------------------------------------------------------
= head3 getHomeDir
Get the path the user home directory from /etc/ passwd .
2011-10-03 19:03:03 +00:00
If /etc/ passwd returns nothing ( id maybe in LDAP ) then
su - userid - c pwd to figure out where home is
2007-12-20 19:02:45 +00:00
Arguments:
none
Returns:
path to user home directory .
Globals:
none
Error:
none
Example:
$ myHome = xCAT::Utils - > getHomeDir ( ) ;
2011-10-03 19:03:03 +00:00
$ myHome = xCAT::Utils - > getHomeDir ( $ userid ) ;
2007-12-20 19:02:45 +00:00
Comments:
none
= cut
#--------------------------------------------------------------------------------
sub getHomeDir
{
my ( $ class , $ username ) = @ _ ;
2009-03-30 14:13:09 +00:00
my @ user ;
2011-10-03 19:03:03 +00:00
my $ homedir ;
2009-04-03 15:42:59 +00:00
if ( $ username )
{
2009-03-30 14:13:09 +00:00
@ user = getpwnam ( $ username ) ;
2009-04-03 15:42:59 +00:00
}
else
{
2009-03-30 14:13:09 +00:00
@ user = getpwuid ( $> ) ;
2011-10-03 19:03:03 +00:00
$ username = $ user [ 0 ] ;
}
if ( $ user [ 7 ] ) { # if homedir
$ homedir = $ user [ 7 ] ;
} else { # no home
$ homedir = `su - $username -c pwd` ;
chop $ homedir ;
2009-03-30 14:13:09 +00:00
}
2011-10-03 19:03:03 +00:00
return $ homedir ;
2007-12-20 19:02:45 +00:00
}
2008-04-05 14:53:35 +00:00
2012-08-09 03:48:50 +00:00
#-------------------------------------------------------------------------------
2009-02-04 17:18:44 +00:00
2012-08-09 03:48:50 +00:00
= head3 isServiceNode
checks for the /etc/x CATSN file
2007-12-20 19:02:45 +00:00
2012-08-09 03:48:50 +00:00
Arguments:
none
Returns:
1 - localHost is ServiceNode
0 - localHost is not ServiceNode
Globals:
none
Error:
none
Example:
% ::XCATMasterPort defined in the caller .
$ return = ( xCAT::Utils - > isServiceNode ( ) )
Comments:
none
2007-12-20 19:02:45 +00:00
= cut
2012-08-09 03:48:50 +00:00
#-------------------------------------------------------------------------------
sub isServiceNode
2007-12-20 19:02:45 +00:00
{
2012-08-09 03:48:50 +00:00
my $ value ;
if ( - e "/etc/xCATSN" )
2009-02-04 17:18:44 +00:00
{
2012-08-09 03:48:50 +00:00
return 1 ;
2009-02-04 17:18:44 +00:00
}
else
{
2012-08-09 03:48:50 +00:00
return 0 ;
2009-02-04 17:18:44 +00:00
}
2012-08-09 03:48:50 +00:00
}
#-------------------------------------------------------------------------------
= head3 isMN
checks for the /etc/x CATMN file , if it exists it is a Management Server
Arguments:
none
Returns:
1 - localHost is Management Node
0 - localHost is not a Management Node
Globals:
none
Error:
none
Example:
$ return = ( xCAT::Utils - > isMN ( ) )
Comments:
none
= cut
2009-02-04 17:18:44 +00:00
2012-08-09 03:48:50 +00:00
#-------------------------------------------------------------------------------
sub isMN
{
my $ value ;
if ( - e "/etc/xCATMN" )
{
return 1 ;
2009-02-04 17:18:44 +00:00
}
else
{
2012-08-09 03:48:50 +00:00
return 0 ;
2009-02-04 17:18:44 +00:00
}
2012-08-09 03:48:50 +00:00
}
2009-02-04 17:18:44 +00:00
2007-12-20 19:02:45 +00:00
2012-08-09 03:48:50 +00:00
#-----------------------------------------------------------------------------
2007-12-20 19:02:45 +00:00
2012-08-09 03:48:50 +00:00
= head3 exportDBConfig
Reads the /etc/xc at / cfgloc file for the DB configuration and exports it
in $ XCATCFG
= cut
2009-01-14 15:54:57 +00:00
2012-08-09 03:48:50 +00:00
#-----------------------------------------------------------------------------
sub exportDBConfig
{
2007-12-20 19:02:45 +00:00
2012-08-09 03:48:50 +00:00
# export the xcat database configuration
my $ configfile = "/etc/xcat/cfgloc" ;
if ( ! ( $ ENV { 'XCATCFG' } ) )
2009-04-03 15:42:59 +00:00
{
2012-08-09 03:48:50 +00:00
if ( - e ( $ configfile ) )
2009-04-03 15:42:59 +00:00
{
2012-08-09 03:48:50 +00:00
open ( CFGFILE , "<$configfile" )
or xCAT::MsgUtils - > message ( 'S' ,
"Cannot open $configfile for DB access. \n" ) ;
foreach my $ line ( <CFGFILE> )
{
chop $ line ;
my $ exp . = $ line ;
2009-04-03 15:42:59 +00:00
2012-08-09 03:48:50 +00:00
$ ENV { 'XCATCFG' } = $ exp ;
close CFGFILE ;
last ;
}
}
2007-12-20 19:02:45 +00:00
}
2008-04-23 18:14:57 +00:00
return 0 ;
}
2008-04-23 19:11:16 +00:00
#-----------------------------------------------------------------------------
2012-08-09 03:48:50 +00:00
= head3 update_xCATSN
Will add the input service string to /etc/x CATSN to indicate that
the service has been setup by the service node
Input: service ( e . g . tftp , nfs , etc )
Output: 0 = added , 1 = already there
2008-04-24 17:28:35 +00:00
= cut
#-----------------------------------------------------------------------------
2012-08-09 03:48:50 +00:00
sub update_xCATSN
2008-04-24 17:28:35 +00:00
{
2012-08-09 03:48:50 +00:00
my ( $ class , $ service ) = @ _ ;
my $ file = "/etc/xCATSN" ;
my $ rc = 0 ;
my $ cmd = " grep $service $file" ;
xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{ # need to add
`echo $service >> /etc/xCATSN` ;
}
else
2008-04-24 17:28:35 +00:00
{
2012-08-09 03:48:50 +00:00
$ rc = 1 ;
2008-04-24 17:28:35 +00:00
}
2012-08-09 03:48:50 +00:00
return $ rc ;
2008-04-24 17:28:35 +00:00
}
2008-05-06 17:22:15 +00:00
#-----------------------------------------------------------------------------
2012-08-09 03:48:50 +00:00
= head3 isSN
2008-05-06 17:22:15 +00:00
2012-08-09 03:48:50 +00:00
Determines if the input node name is a service node
Reads the servicenode table . nodename must be service node name as
known by the Management node .
2008-05-06 17:22:15 +00:00
2012-08-09 03:48:50 +00:00
returns 1 if input host is a service node
2008-05-06 17:22:15 +00:00
Arguments:
2012-08-09 03:48:50 +00:00
hostname
2008-05-06 17:22:15 +00:00
Returns:
2012-08-09 03:48:50 +00:00
1 - is Service Node
0 - is not a Service Node
2008-05-06 17:22:15 +00:00
Globals:
none
Error:
2012-08-09 03:48:50 +00:00
none
2008-05-06 17:22:15 +00:00
Example:
2012-08-09 03:48:50 +00:00
if ( xCAT::Utils - > isSN ( $ nodename ) ) { blah ; }
2008-05-06 17:22:15 +00:00
Comments:
none
= cut
#-----------------------------------------------------------------------------
2012-08-09 03:48:50 +00:00
sub isSN
2008-05-06 17:22:15 +00:00
{
2011-04-01 14:02:44 +00:00
require xCAT::Table ;
2012-08-09 03:48:50 +00:00
my ( $ class , $ node ) = @ _ ;
2008-05-06 17:22:15 +00:00
# reads all nodes from the service node table
my @ servicenodes ;
2012-08-09 03:48:50 +00:00
my $ servicenodetab = xCAT::Table - > new ( 'servicenode' ) ;
2008-05-06 17:22:15 +00:00
unless ( $ servicenodetab ) # no servicenode table
{
xCAT::MsgUtils - > message ( 'I' , "Unable to open servicenode table.\n" ) ;
2012-08-09 03:48:50 +00:00
return 0 ;
2008-05-06 17:22:15 +00:00
}
2012-08-09 03:48:50 +00:00
my @ nodes = $ servicenodetab - > getAllNodeAttribs ( [ 'tftpserver' ] , undef , prefetchcache = > 1 ) ;
2008-05-06 17:22:15 +00:00
$ servicenodetab - > close ;
2012-08-09 03:48:50 +00:00
foreach my $ nodes ( @ nodes )
2008-05-06 17:22:15 +00:00
{
2012-08-09 03:48:50 +00:00
if ( $ node eq $ nodes - > { node } )
2008-05-06 17:22:15 +00:00
{
2012-08-09 03:48:50 +00:00
return 1 ; # match
2008-05-06 17:22:15 +00:00
}
}
2012-08-09 03:48:50 +00:00
return 0 ;
2009-04-28 09:10:19 +00:00
}
#-------------------------------------------------------------------------------
2008-05-12 19:49:41 +00:00
= head3 isMounted
Checks if the input directory is already mounted
Arguments:
directory
Returns:
1 - directory is mounted
0 - directory is not mounted
Globals:
none
Error:
- 1 error
Example:
if ( xCAT::Utils - > isMounted ( $ directory ) ) { blah ; }
2011-04-20 19:31:39 +00:00
Comments:
2008-05-12 19:49:41 +00:00
none
= cut
#-------------------------------------------------------------------------------
sub isMounted
{
my ( $ class , $ directory ) = @ _ ;
2011-04-20 19:20:53 +00:00
my $ cmd ;
my @ output ;
if ( - e $ directory ) { # does the directory exist
if ( xCAT::Utils - > isLinux ( ) ) {
$ cmd = "df -T -P $directory" ;
@ output = xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
foreach my $ line ( @ output ) {
my ( $ file_sys , $ type , $ blocks , $ used , $ avail , $ per , $ mount_point ) =
split ( ' ' , $ line ) ;
$ type =~ s/\s*//g ; # remove blanks
if ( $ type =~ /^nfs/ )
{
return 1 ;
}
2008-05-12 19:49:41 +00:00
}
2011-04-20 19:20:53 +00:00
} else { #AIX
$ cmd = "/usr/sysv/bin/df -n $directory" ;
@ output = xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
foreach my $ line ( @ output ) {
my ( $ dir , $ colon , $ type ) =
split ( ' ' , $ line ) ;
$ type =~ s/\s*//g ; # remove blanks
if ( $ type =~ /^nfs/ )
{
return 1 ;
}
}
}
2008-05-12 19:49:41 +00:00
}
return 0 ;
}
2009-02-04 17:18:44 +00:00
2008-06-10 16:39:20 +00:00
#-------------------------------------------------------------------------------
2008-05-06 17:22:15 +00:00
2008-09-15 18:15:42 +00:00
= head3 runxcatd
Stops or starts xcatd
Arguments:
xcatstart - start the daemon , restart if already running
xcatstop - stop the daemon
Returns:
0 = not error , 1 = error
Globals:
none
Error:
Example:
my $ rc = xCAT:: runxcatd ( "xcatstart" ) ; ( starts xcatd )
my $ rc = xCAT:: runxcatd ( "xcatstop" ) ; ( stops xcatd )
= cut
#-------------------------------------------------------------------------------
2009-02-04 17:18:44 +00:00
sub runxcatd
2008-09-15 18:15:42 +00:00
{
2009-02-04 17:18:44 +00:00
my ( $ class , $ cmd ) = @ _ ;
if ( ! ( xCAT::Utils - > isAIX ( ) ) )
{ # only runs on AIX
xCAT::MsgUtils - > message ( "E" ,
"This command should only be run on AIX.\n" ) ;
return 1 ;
}
#
# if xcatd already running
# Get the xcatd processes and stop them
#
my @ xpids = xCAT::Utils - > runcmd ( "ps -ef\|grep \"xcatd\"" , 0 ) ;
if ( $# xpids >= 1 )
{ # will have at least "0" for the grep
xCAT::MsgUtils - > message ( 'I' , "Stopping xcatd processes....\n" ) ;
foreach my $ ps ( @ xpids )
2008-09-15 18:15:42 +00:00
{
2009-02-04 17:18:44 +00:00
$ ps =~ s/^\s+// ; # strip any leading spaces
my ( $ uid , $ pid , $ ppid , $ desc ) = split /\s+/ , $ ps ;
# if $ps contains "grep" then it's not one of the daemon processes
if ( $ ps !~ /grep/ )
2008-09-15 18:15:42 +00:00
{
2009-02-04 17:18:44 +00:00
# print "pid=$pid\n";
#my $cmd = "/bin/kill -9 $pid";
my $ cmd = "/bin/kill $pid" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( 'E' ,
"Could not stop xcatd process $pid.\n" ) ;
return 1 ;
}
2008-09-15 18:15:42 +00:00
}
}
}
2009-02-04 17:18:44 +00:00
if ( $ cmd eq "xcatstart" )
{ # start xcatd
xCAT::MsgUtils - > message ( 'I' , "Starting xcatd.....\n" ) ;
my $ xcmd = "$::XCATROOT/sbin/xcatd &" ;
my $ outref = xCAT::Utils - > runcmd ( "$xcmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( 'E' , "Could not start xcatd process.\n" ) ;
return 1 ;
}
2008-09-15 18:15:42 +00:00
}
2009-02-04 17:18:44 +00:00
return 0 ;
2008-09-15 18:15:42 +00:00
}
2008-09-26 23:07:45 +00:00
2008-10-27 16:07:21 +00:00
#-------------------------------------------------------------------------------
= head3 get_image_name
get a name for the install image on AIX and Linux , to be used
by xdsh and sinv for the nodename
Arguments:
path to image .
Returns:
imagename
= cut
#-------------------------------------------------------------------------------
2009-02-04 17:18:44 +00:00
sub get_image_name
{
my ( $ class , $ imagepath ) = @ _ ;
my $ imagename ;
if ( xCAT::Utils - > isLinux ( ) )
{
my @ fields = split ( '/' , $ imagepath ) ;
$ imagename . = $ fields [ 5 ] ;
$ imagename . = "-" ;
$ imagename . = $ fields [ 3 ] ;
$ imagename . = "-" ;
$ imagename . = $ fields [ 4 ] ;
}
else
{ # AIX
my @ fields = split ( '/' , $ imagepath ) ;
my $ name = pop @ fields ;
$ imagename = $ name ;
}
2008-10-27 16:07:21 +00:00
2009-02-04 17:18:44 +00:00
return $ imagename ;
}
2008-09-26 23:07:45 +00:00
2009-01-28 18:49:02 +00:00
#-------------------------------------------------------------------------------
2009-03-16 12:50:22 +00:00
= head3 StartService
2009-03-02 14:27:10 +00:00
Supports AIX and Linux as long as the service is registered with
lssrc or startsrc .
Used by the service node plugin ( AAsn . pm ) to start requested services .
Checks to see if the input service is already started . If it is started
2009-03-16 12:50:22 +00:00
it stops and starts the service . Otherwise
it just starts the service .
2009-03-02 14:27:10 +00:00
Note we are using the system command on the start of the services to see
the output when the xcatd is started on Service Nodes . Do not change this .
Arguments:
servicename
force flag
Returns:
2009-03-16 12:50:22 +00:00
0 - ok
2009-03-02 14:27:10 +00:00
1 - could not start the service
Globals:
none
Error:
1 error
Example:
2009-03-16 12:50:22 +00:00
if ( xCAT::Utils - > startService ( "named" ) { ... }
2009-03-02 14:27:10 +00:00
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub startService
{
2009-03-16 12:50:22 +00:00
my ( $ class , $ service ) = @ _ ;
2009-03-02 14:27:10 +00:00
my $ rc = 0 ;
my @ output ;
my $ cmd ;
if ( xCAT::Utils - > isAIX ( ) )
{
2009-03-16 12:50:22 +00:00
@ output = xCAT::Utils - > runcmd ( "LANG=C /usr/bin/lssrc -s $service" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{ # error so start it
$ cmd = "/usr/bin/stopsrc -s $service" ;
system $ cmd ; # note using system here to see output when
# daemon comes up
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
}
$ cmd = "/usr/bin/startsrc -s $service" ;
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
}
}
else
{
# check to see if running
my ( $ subsys , $ group , $ pid , $ status ) = split ( ' ' , $ output [ 1 ] ) ;
if ( defined ( $ status ) && $ status eq 'active' )
{
# already running, stop and start
2009-03-02 14:27:10 +00:00
$ cmd = "/usr/bin/stopsrc -s $service" ;
system $ cmd ; # note using system here to see output when
# daemon comes up
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
}
$ cmd = "/usr/bin/startsrc -s $service" ;
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
}
2009-03-16 12:50:22 +00:00
return 0 ;
2009-03-02 14:27:10 +00:00
}
2009-03-16 12:50:22 +00:00
else
2009-03-02 14:27:10 +00:00
{
2009-03-16 12:50:22 +00:00
# not running, start it
$ cmd = "/usr/bin/startsrc -s $service" ;
system $ cmd ; # note using system here to see output when
# daemon comes up
if ( $? > 0 )
{
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
2009-03-02 14:27:10 +00:00
}
2009-03-16 12:50:22 +00:00
2009-03-02 14:27:10 +00:00
}
}
2009-03-16 12:50:22 +00:00
}
else # linux
{
my @ output = xCAT::Utils - > runcmd ( "service $service status" , - 1 ) ;
if ( $ ::RUNCMD_RC == 0 )
2009-03-02 14:27:10 +00:00
{
2009-03-24 19:25:31 +00:00
# whether or not an error is returned varies by service
2009-03-16 12:50:22 +00:00
# stop and start the service for those running
if ( ( $ service ne "conserver" ) && ( $ service ne "nfs" ) )
2009-03-02 14:27:10 +00:00
{
2009-03-16 12:50:22 +00:00
$ cmd = "service $service stop" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
}
$ cmd = "service $service start" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
}
return 0 ;
2009-03-02 14:27:10 +00:00
}
2009-03-16 12:50:22 +00:00
if ( ( $ service eq "conserver" ) || ( $ service eq "nfs" ) )
{
# must check output
if ( grep ( /running/ , @ output ) )
2009-03-02 14:27:10 +00:00
{
2009-03-16 12:50:22 +00:00
$ cmd = "service $service stop" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" ,
"Error on command: $cmd\n" ) ;
}
$ cmd = "service $service start" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
{ # error
xCAT::MsgUtils - > message ( "S" ,
"Error on command: $cmd\n" ) ;
return 1 ;
}
2009-03-02 14:27:10 +00:00
return 0 ;
}
2009-03-16 12:50:22 +00:00
else
2009-03-02 14:27:10 +00:00
{
2009-03-16 12:50:22 +00:00
# not running , just start
$ cmd = "service $service start" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
{ # error
2009-03-02 14:27:10 +00:00
xCAT::MsgUtils - > message ( "S" ,
"Error on command: $cmd\n" ) ;
return 1 ;
}
2009-03-16 12:50:22 +00:00
return 0 ;
2009-03-02 14:27:10 +00:00
}
}
}
else
2009-03-16 12:50:22 +00:00
{
2009-03-24 19:25:31 +00:00
# error getting status, check output
2009-03-16 12:50:22 +00:00
# must check output
2009-03-24 19:25:31 +00:00
if ( grep ( /stopped/ , @ output ) ) # stopped
2009-03-16 12:50:22 +00:00
{
$ cmd = "service $service start" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
2009-03-24 19:25:31 +00:00
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
2009-03-16 12:50:22 +00:00
}
2009-03-24 19:25:31 +00:00
}
else
{ # not sure
2009-03-16 12:50:22 +00:00
$ cmd = "service $service stop" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
2009-03-24 19:25:31 +00:00
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
2009-03-16 12:50:22 +00:00
}
$ cmd = "service $service start" ;
2009-09-23 14:09:12 +00:00
print ' ' ; # indent service output to separate it from the xcatd service output
2009-03-16 12:50:22 +00:00
system $ cmd ;
if ( $? > 0 )
2009-03-24 19:25:31 +00:00
{ # error
xCAT::MsgUtils - > message ( "S" , "Error on command: $cmd\n" ) ;
return 1 ;
2009-03-16 12:50:22 +00:00
}
2009-03-02 14:27:10 +00:00
}
}
}
2009-03-16 12:50:22 +00:00
2009-03-02 14:27:10 +00:00
return $ rc ;
}
2009-03-03 19:39:17 +00:00
2009-03-02 14:27:10 +00:00
#-------------------------------------------------------------------------------
2009-02-28 17:05:34 +00:00
= head3 CheckVersion
Checks the two versions numbers to see which one is greater .
Arguments:
ver_a the version number in format of d . d . d . d ...
ver_b the version number in format of d . d . d . d ...
Returns:
1 if ver_a is greater than ver_b
0 if ver_a is eaqual to ver_b
- 1 if ver_a is smaller than ver_b
= cut
#-------------------------------------------------------------------------------
2009-03-03 19:39:17 +00:00
sub CheckVersion
{
my $ ver_a = shift ;
if ( $ ver_a =~ /xCAT::Utils/ )
{
$ ver_a = shift ;
}
my $ ver_b = shift ;
my @ a = split ( /\./ , $ ver_a ) ;
my @ b = split ( /\./ , $ ver_b ) ;
my $ len_a = @ a ;
my $ len_b = @ b ;
my $ index = 0 ;
my $ max_index = ( $ len_a > $ len_b ) ? $ len_a : $ len_b ;
for ( $ index = 0 ; $ index <= $ max_index ; $ index + + )
{
my $ val_a = ( $ len_a < $ index ) ? 0 : $ a [ $ index ] ;
my $ val_b = ( $ len_b < $ index ) ? 0 : $ b [ $ index ] ;
if ( $ val_a > $ val_b ) { return 1 ; }
if ( $ val_a < $ val_b ) { return - 1 ; }
}
2009-02-28 17:05:34 +00:00
return 0 ;
}
2009-03-11 17:22:43 +00:00
#-------------------------------------------------------------------------------
2009-03-18 12:07:50 +00:00
= head3 osver
Returns the os and version of the System you are running on
Arguments:
none
Returns:
0 - ok
Globals:
none
Error:
1 error
Example:
my $ os = ( xCAT::Utils - > osver { ... }
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub osver
{
2009-03-24 19:25:31 +00:00
my $ osver = "unknown" ;
my $ os = '' ;
my $ ver = '' ;
my $ line = '' ;
my @ lines ;
2010-08-06 12:36:39 +00:00
my $ relfile ;
2009-03-24 19:25:31 +00:00
if ( - f "/etc/redhat-release" )
{
2010-08-06 12:36:39 +00:00
open ( $ relfile , "<" , "/etc/redhat-release" ) ;
$ line = <$relfile> ;
close ( $ relfile ) ;
chomp ( $ line ) ;
2009-03-24 19:25:31 +00:00
$ os = "rh" ;
2010-08-06 12:36:39 +00:00
$ ver = $ line ;
$ ver =~ tr /\./ / ;
2009-03-24 19:25:31 +00:00
$ ver =~ s/[^0-9]*([0-9]+).*/$1/ ;
if ( $ line =~ /AS/ ) { $ os = 'rhas' }
elsif ( $ line =~ /ES/ ) { $ os = 'rhes' }
elsif ( $ line =~ /WS/ ) { $ os = 'rhws' }
2009-03-18 12:07:50 +00:00
elsif ( $ line =~ /Server/ ) { $ os = 'rhserver' }
elsif ( $ line =~ /Client/ ) { $ os = 'rhclient' }
2009-03-24 19:25:31 +00:00
elsif ( - f "/etc/fedora-release" ) { $ os = 'rhfc' }
}
elsif ( - f "/etc/SuSE-release" )
{
2010-08-06 12:36:39 +00:00
open ( $ relfile , "<" , "/etc/SuSE-release" ) ;
@ lines = <$relfile> ;
close ( $ relfile ) ;
chomp ( @ lines ) ;
2009-03-24 19:25:31 +00:00
if ( grep /SLES|Enterprise Server/ , @ lines ) { $ os = "sles" }
if ( grep /SLEC/ , @ lines ) { $ os = "slec" }
2010-08-06 12:36:39 +00:00
$ ver = $ lines [ 0 ] ;
$ ver =~ tr /\./ / ;
2009-03-24 19:25:31 +00:00
$ ver =~ s/[^0-9]*([0-9]+).*/$1/ ;
#print "ver: $ver\n";
}
elsif ( - f "/etc/UnitedLinux-release" )
{
$ os = "ul" ;
2010-08-06 12:36:39 +00:00
open ( $ relfile , "<" , "/etc/UnitedLinux-release" ) ;
$ ver = <$relfile> ;
close ( $ relfile ) ;
$ ver =~ tr /\./ / ;
2009-03-24 19:25:31 +00:00
$ ver =~ s/[^0-9]*([0-9]+).*/$1/ ;
}
2011-10-06 17:45:08 +00:00
elsif ( - f "/etc/lsb-release" ) # Possibly Ubuntu
2011-08-15 00:30:40 +00:00
{
2011-10-06 17:45:08 +00:00
if ( open ( $ relfile , "<" , "/etc/lsb-release" ) ) {
my @ text = <$relfile> ;
close ( $ relfile ) ;
chomp ( @ text ) ;
my $ distrib_id = '' ;
my $ distrib_rel = '' ;
foreach ( @ text ) {
if ( $ _ =~ /^\s*DISTRIB_ID=(.*)$/ ) {
$ distrib_id = $ 1 ; # last DISTRIB_ID value in file used
} elsif ( $ _ =~ /^\s*DISTRIB_RELEASE=(.*)$/ ) {
$ distrib_rel = $ 1 ; # last DISTRIB_RELEASE value in file used
}
}
2012-08-09 03:48:50 +00:00
if ( $ distrib_id =~ /^(Ubuntu|"Ubuntu")\s*$/ ) {
$ os = "ubuntu" ;
2009-03-24 19:25:31 +00:00
2012-08-09 03:48:50 +00:00
if ( $ distrib_rel =~ /^(.*?)\s*$/ ) { # eliminate trailing blanks, if any
$ distrib_rel = $ 1 ;
}
if ( $ distrib_rel =~ /^"(.*?)"$/ ) { # eliminate enclosing quotes, if any
$ distrib_rel = $ 1 ;
}
$ ver = $ distrib_rel ;
}
2009-03-24 19:25:31 +00:00
}
}
2012-08-09 03:48:50 +00:00
$ os = "$os" . "$ver" ;
return ( $ os ) ;
2009-03-24 19:25:31 +00:00
}
2009-03-11 17:22:43 +00:00
2009-06-26 14:45:50 +00:00
#-----------------------------------------------------------------------------
= head3 acquire_lock
Get a lock on an arbirtrary named resource . For now , this is only across the scope of one service node /master node, an argument may be added later if/ when 'global' locks are supported . This call will block until the lock is free .
Arguments:
2012-10-22 09:37:09 +00:00
lock_name: A string name for the lock to acquire
nonblock_mode: Whether this is a non - blocking call or not . ( 1 non - blocking , 0 = blocking )
2009-06-26 14:45:50 +00:00
Returns:
false on failure
A reference for the lock being held .
= cut
sub acquire_lock {
2012-10-22 09:37:09 +00:00
my $ class = shift ;
2009-06-26 14:45:50 +00:00
my $ lock_name = shift ;
2012-10-22 09:37:09 +00:00
my $ nonblock_mode = shift ;
2009-06-26 14:45:50 +00:00
use File::Path ;
mkpath ( "/var/lock/xcat/" ) ;
use Fcntl ":flock" ;
my $ tlock ;
$ tlock - > { path } = "/var/lock/xcat/" . $ lock_name ;
open ( $ tlock - > { fd } , ">" , $ tlock - > { path } ) or return undef ;
unless ( $ tlock - > { fd } ) { return undef ; }
2012-10-22 09:37:09 +00:00
if ( $ nonblock_mode ) {
flock ( $ tlock - > { fd } , LOCK_EX | LOCK_NB ) or return undef ;
} else {
flock ( $ tlock - > { fd } , LOCK_EX ) or return undef ;
}
print { $ tlock - > { fd } } $$ ;
$ tlock - > { fd } - > autoflush ( 1 ) ;
2009-06-26 14:45:50 +00:00
return $ tlock ;
}
#---------------------
= head3 release_lock
Release an acquired lock
Arguments:
2012-10-22 09:37:09 +00:00
tlock: reference to lock
nonblock_mode: Whether this is a non - blocking call or not .
2009-06-26 14:45:50 +00:00
Returns:
false on failure , true on success
= cut
sub release_lock {
2012-10-22 09:37:09 +00:00
my $ class = shift ;
2009-06-26 14:45:50 +00:00
my $ tlock = shift ;
2012-10-22 09:37:09 +00:00
my $ nonblock_mode = shift ;
2009-06-26 14:45:50 +00:00
unlink ( $ tlock - > { path } ) ;
2012-10-22 09:37:09 +00:00
if ( $ nonblock_mode ) {
flock ( $ tlock - > { fd } , LOCK_UN | LOCK_NB ) ;
} else {
flock ( $ tlock - > { fd } , LOCK_UN ) ;
}
2009-06-26 14:45:50 +00:00
close ( $ tlock - > { fd } ) ;
}
2012-10-22 09:37:09 +00:00
#-------------------------------------------------------------------------------
= head3 is_locked
Description : Try to see whether current command catagory is locked or not .
Arguments : action - command catagory
Returns :
1 - current command catagory already locked .
0 - not locked yet .
= cut
#-------------------------------------------------------------------------------
sub is_locked
{
my $ class = shift ;
my $ action = shift ;
my $ lock = xCAT::Utils - > acquire_lock ( $ action , 1 ) ;
if ( ! $ lock ) {
return 1 ;
}
xCAT::Utils - > release_lock ( $ lock , 1 ) ;
return 0 ;
}
2009-06-30 09:47:48 +00:00
#----------------------------------------------------------------------------
= head3 parse_selection_string
Parse the selection string and
write the parsed result into % wherehash
Arguments:
$ ss_ref - selection string array from - w flag
\ % wherehash - selection string hash % ::WhereHash
Returns:
0 - parse successfully
1 - parse failed
Globals:
% wherehash
Error:
Example:
Comments:
= cut
#-----------------------------------------------------------------------------
sub parse_selection_string ()
{
my ( $ class , $ ss_ref , $ wherehash_ref ) = @ _ ;
2009-07-06 09:45:22 +00:00
# selection string is specified with one or multiple -w flags
# stored in an array
2009-06-30 09:47:48 +00:00
foreach my $ m ( @ { $ ss_ref } )
{
my $ attr ;
my $ val ;
my $ matchtype ;
2009-07-06 09:45:22 +00:00
if ( $ m =~ /^[^=]*\==/ ) { #attr==val
2009-06-30 09:47:48 +00:00
( $ attr , $ val ) = split /==/ , $ m , 2 ;
$ matchtype = 'match' ;
2009-07-06 09:45:22 +00:00
} elsif ( $ m =~ /^[^=]*=~/ ) { #attr=~val
2009-06-30 09:47:48 +00:00
( $ attr , $ val ) = split /=~/ , $ m , 2 ;
$ val =~ s/^\/// ;
$ val =~ s/\/$// ;
$ matchtype = 'regex' ;
2009-07-06 09:45:22 +00:00
} elsif ( $ m =~ /^[^=]*\!=/ ) { #attr!=val
2009-06-30 09:47:48 +00:00
( $ attr , $ val ) = split /!=/ , $ m , 2 ;
$ matchtype = 'natch' ;
2009-07-06 09:45:22 +00:00
} elsif ( $ m =~ /[^=]*!~/ ) { #attr!~val
2009-06-30 09:47:48 +00:00
( $ attr , $ val ) = split /!~/ , $ m , 2 ;
$ val =~ s/^\/// ;
$ val =~ s/\/$// ;
$ matchtype = 'negex' ;
} elsif ( $ m =~ /^[^=]*=[^=]+$/ ) { # attr=val is the same as attr==val
( $ attr , $ val ) = split /=/ , $ m , 2 ;
$ matchtype = 'match' ;
} else {
return 1 ;
}
if ( ! defined ( $ attr ) || ! defined ( $ val ) )
{
return 1 ;
}
$ wherehash_ref - > { $ attr } - > { 'val' } = $ val ;
$ wherehash_ref - > { $ attr } - > { 'matchtype' } = $ matchtype ;
}
return 0 ;
}
#----------------------------------------------------------------------------
= head3 selection_string_match
Check whether a node matches the selection string
defined in hash % wherehash
Arguments:
\ % objhash - the hash contains the objects definition
$ objname - the object name
$ wherehash_ref - the selection string hash
Returns:
0 - NOT match
1 - match
Globals:
% wherehash
Error:
Example:
Comments:
= cut
#-----------------------------------------------------------------------------
sub selection_string_match ()
{
my ( $ class , $ objhash_ref , $ objname , $ wherehash_ref ) = @ _ ;
my % wherehash = %$ wherehash_ref ;
my $ match = 1 ;
foreach my $ testattr ( keys % wherehash ) {
# access non-exists hash entry will create an empty one
# we should not modify the $objhash_ref
if ( exists ( $ objhash_ref - > { $ objname } ) && exists ( $ objhash_ref - > { $ objname } - > { $ testattr } ) ) {
if ( $ wherehash { $ testattr } { 'matchtype' } eq 'match' ) { #attr==val or attr=val
if ( $ objhash_ref - > { $ objname } - > { $ testattr } ne $ wherehash { $ testattr } { 'val' } ) {
$ match = 0 ;
last ;
}
}
2009-07-06 09:45:22 +00:00
if ( $ wherehash { $ testattr } { 'matchtype' } eq 'natch' ) { #attr!=val
2009-06-30 09:47:48 +00:00
if ( $ objhash_ref - > { $ objname } - > { $ testattr } eq $ wherehash { $ testattr } { 'val' } ) {
$ match = 0 ;
last ;
}
}
if ( $ wherehash { $ testattr } { 'matchtype' } eq 'regex' ) { #attr=~val
if ( $ objhash_ref - > { $ objname } - > { $ testattr } !~ $ wherehash { $ testattr } { 'val' } ) {
$ match = 0 ;
last ;
}
}
if ( $ wherehash { $ testattr } { 'matchtype' } eq 'negex' ) { #attr!~val
if ( $ objhash_ref - > { $ objname } - > { $ testattr } =~ $ wherehash { $ testattr } { 'val' } ) {
$ match = 0 ;
last ;
}
}
} else { #$objhash_ref->{$objname}->{$testattr} does not exist
$ match = 0 ;
last ;
}
}
return $ match ;
}
2009-07-03 08:56:14 +00:00
#-------------------------------------------------------------------------------
= head3 check_deployment_monitoring_settings
Check the deployment retry monitoring settings .
Arguments:
$ request: request hash
$ mstring: The monitoring setting string
specified with the - m flag for rpower or rnetboot
Returns:
0 - ok
1 - failed
Globals:
none
Example:
my $ rc = xCAT::Utils - > check_deployment_monitoring_settings ( $ opt ( m ) )
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub check_deployment_monitoring_settings ()
{
my ( $ class , $ request , $ opt_ref ) = @ _ ;
my $ callback = $ request - > { callback } ;
my @ mstring = @ { $ opt_ref - > { 'm' } } ;
# -r flag is required with -m flag
if ( ! defined ( $ opt_ref - > { 't' } ) ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Flag missing, the -t flag is required" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
foreach my $ m ( @ mstring ) {
if ( $ m eq '' ) {
#No value specified with -m flag
next ;
}
my $ attr ;
my $ val ;
if ( $ m =~ /[^=]*==/ ) {
( $ attr , $ val ) = split /==/ , $ m , 2 ;
} elsif ( $ m =~ /^[^=]*=~/ ) {
( $ attr , $ val ) = split /=~/ , $ m , 2 ;
$ val =~ s/^\/// ;
$ val =~ s/\/$// ;
} else {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Invalid string \"$m\" specified with -m flag" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
# The attr is table.column
if ( $ attr !~ /\..*$/ ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Invalid attribute \"$attr\" specified with -m flag, should be table.column" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
if ( $ val eq '' ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "The value of attribute \"$attr\" can not be NULL" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
}
return 0 ;
}
#-------------------------------------------------------------------------------
= head3 generate_monsettings ( )
Generate installation monitoring settings hash .
Arguments:
$ request: request hash
\ @ monnodes: nodes to be monitored
Returns:
\ % monsettings - the ref of % monsettings hash
Globals:
none
Example:
my $ monsettings_ref = xCAT::Utils - > generate_monsettings ( $ request , \ @ monnodes )
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub generate_monsettings ()
{
my ( $ class , $ request , $ monnodes_ref ) = @ _ ;
my @ monnodes = @$ monnodes_ref ;
my $ callback = $ request - > { callback } ;
my @ mstring = @ { $ request - > { opt } - > { m } } ;
my % monsettings = ( ) ;
#set default value for each attribute,
#to avoid ugly perl syntax error
my % defaultattrs = (
"timeout" = > "10" ,
"retrycount" = > "3"
) ;
#Monitoring settings check already done in parse_args,
#Assume it is correct.
foreach my $ m ( @ mstring ) {
if ( $ m eq '' ) {
# No value specified with -m flag
next ;
}
my $ attr ;
my $ val ;
my $ matchtype ;
if ( $ m =~ /^[^=]*\==/ ) {
( $ attr , $ val ) = split /==/ , $ m , 2 ;
$ matchtype = 'match' ;
} elsif ( $ m =~ /^[^=]*=~/ ) {
( $ attr , $ val ) = split /=~/ , $ m , 2 ;
$ val =~ s/^\/// ;
$ val =~ s/\/$// ;
$ matchtype = 'regex' ;
}
#This is a table.column
my ( $ tab , $ col ) = split '\.' , $ attr ;
$ monsettings { 'monattrs' } { $ tab } { $ col } { 'val' } = $ val ;
$ monsettings { 'monattrs' } { $ tab } { $ col } { 'matchtype' } = $ matchtype ;
}
if ( defined ( $ request - > { opt } - > { r } ) ) {
$ monsettings { 'retrycount' } = $ request - > { opt } - > { r } ;
}
if ( defined ( $ request - > { opt } - > { t } ) ) {
$ monsettings { 'timeout' } = $ request - > { opt } - > { t } ;
}
#Set the default values
foreach my $ attr ( keys % defaultattrs ) {
if ( ( ! defined ( $ monsettings { $ attr } ) ) || ( $ monsettings { $ attr } eq '' ) ) {
$ monsettings { $ attr } = $ defaultattrs { $ attr } ;
}
}
if ( ! defined ( $ monsettings { 'monattrs' } ) || ( scalar ( keys % { $ monsettings { 'monattrs' } } ) == 0 ) ) {
$ monsettings { 'monattrs' } { 'nodelist' } { 'status' } { 'val' } = "booted" ;
$ monsettings { 'monattrs' } { 'nodelist' } { 'status' } { 'matchtype' } = "match" ;
}
#Initialize the %{$monsettings{'nodes'}} hash
foreach my $ node ( @ monnodes ) {
foreach my $ tab ( keys % { $ monsettings { 'monattrs' } } ) {
foreach my $ col ( keys % { $ monsettings { 'monattrs' } { $ tab } } ) {
$ monsettings { 'nodes' } { $ node } { 'status' } { $ tab } { $ col } = '' ;
}
}
}
return \ % monsettings ;
}
#-------------------------------------------------------------------------------
= head3 monitor_installation
Monitoring os installation progress .
Arguments:
$ request: request hash
Returns:
0 - ok
1 - failed
Globals:
none
Example:
my $ rc = xCAT::Utils - > monitor_installation ( $ opt ( m ) )
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub monitor_installation ()
{
2011-04-01 14:02:44 +00:00
require xCAT::Table ;
2009-07-03 08:56:14 +00:00
my ( $ class , $ request , $ monsettings ) = @ _ ;
my $ callback = $ request - > { callback } ;
my $ mstring = $ request - > { opt } - > { m } ;
#This is the first time the monitor_installation is called,
# my $rsp={};
# my $monnodes = join ',', @monitornodes;
# $rsp->{data}->[0] = "Start monitoring the installation progress with settings \"$mstring\" for nodes $monnodes";
# xCAT::MsgUtils->message("I", $rsp, $callback);
$ monsettings - > { 'timeelapsed' } = 0 ;
while ( ( $ monsettings - > { 'timeelapsed' } < $ monsettings - > { 'timeout' } ) && ( scalar ( keys % { $ monsettings - > { 'nodes' } } ) ) ) {
#polling interval is 1 minute,
#do not do the first check until 1 minute after the os installation starts
2009-07-03 09:09:00 +00:00
sleep 60 ;
2009-07-03 08:56:14 +00:00
#update the timeelapsed
$ monsettings - > { 'timeelapsed' } + + ;
my @ monitornodes = keys % { $ monsettings - > { 'nodes' } } ;
# Look up tables, do not look up the same table more than once
my % tabattrs = ( ) ;
foreach my $ tab ( keys % { $ monsettings - > { 'monattrs' } } ) {
foreach my $ col ( keys % { $ monsettings - > { 'monattrs' } - > { $ tab } } ) {
if ( ! grep ( /^$col$/ , @ { $ tabattrs { $ tab } } ) ) {
push @ { $ tabattrs { $ tab } } , $ col ;
}
}
}
foreach my $ node ( keys % { $ monsettings - > { 'nodes' } } ) {
foreach my $ montable ( keys % tabattrs ) {
#Get the new status of the node
my $ montab_ref = xCAT::Table - > new ( $ montable ) ;
if ( $ montab_ref ) {
my @ attrs = @ { $ tabattrs { $ montable } } ;
my $ tabdata = $ montab_ref - > getNodesAttribs ( \ @ monitornodes , \ @ attrs ) ;
foreach my $ attr ( @ { $ tabattrs { $ montable } } ) {
# nodestatus changed, print a message
if ( ( $ monsettings - > { 'nodes' } - > { $ node } - > { 'status' } - > { $ montable } - > { $ attr } ne '' )
&& ( $ monsettings - > { 'nodes' } - > { $ node } - > { 'status' } - > { $ montable } - > { $ attr } ne $ tabdata - > { $ node } - > [ 0 ] - > { $ attr } ) ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$node $montable.$attr: $monsettings->{'nodes'}->{$node}->{'status'}->{$montable}->{$attr} => $tabdata->{$node}->[0]->{$attr}" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
#set the new status
$ monsettings - > { 'nodes' } - > { $ node } - > { 'status' } - > { $ montable } - > { $ attr } = $ tabdata - > { $ node } - > [ 0 ] - > { $ attr } ;
}
$ montab_ref - > close ( ) ;
} else { #can not open the table
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Open table $montable failed" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return ( ) ;
}
}
#expected status??
my $ statusmatch = 1 ;
foreach my $ temptab ( keys % { $ monsettings - > { 'monattrs' } } ) {
foreach my $ tempcol ( keys % { $ monsettings - > { 'monattrs' } - > { $ temptab } } ) {
my $ currentstatus = $ monsettings - > { 'nodes' } - > { $ node } - > { 'status' } - > { $ temptab } - > { $ tempcol } ;
my $ expectedstatus = $ monsettings - > { 'monattrs' } - > { $ temptab } - > { $ tempcol } - > { 'val' } ;
my $ matchtype = $ monsettings - > { 'monattrs' } - > { $ temptab } - > { $ tempcol } - > { 'matchtype' } ;
#regular expression
if ( $ matchtype eq 'match' ) {
if ( $ currentstatus ne $ expectedstatus ) {
$ statusmatch = 0 ;
}
} elsif ( $ matchtype eq 'regex' ) {
if ( $ currentstatus !~ /$expectedstatus/ ) {
$ statusmatch = 0 ;
}
}
} #end foreach
} #end foreach
if ( $ statusmatch == 1 ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$node: Reached the expected status" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
delete $ monsettings - > { 'nodes' } - > { $ node } ;
}
} #end foreach my $node
} #end while
if ( scalar ( keys % { $ monsettings - > { 'nodes' } } ) > 0 )
{
foreach my $ n ( keys % { $ monsettings - > { 'nodes' } } ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "$n: does not transit to the expected status" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
}
return $ monsettings ;
}
2009-07-27 15:28:11 +00:00
2009-07-31 19:45:28 +00:00
#-------------------------------------------------------------------------------
= head3 get_unique_members
Description:
Return an array which have unique members
Arguments:
origarray: the original array to be treated
Returns:
Return an array , which contains unique members .
Globals:
none
Error:
none
Example:
my @ new_array = xCAT::Utils:: get_unique_members ( @ orig_array ) ;
Comments:
= cut
#-------------------------------------------------------------------------------
sub get_unique_members
{
my @ orig_array = @ _ ;
2009-07-31 21:11:48 +00:00
my % tmp_hash = ( ) ;
for my $ ent ( @ orig_array )
2009-07-31 19:45:28 +00:00
{
2009-07-31 21:11:48 +00:00
$ tmp_hash { $ ent } = 1 ;
2009-07-31 19:45:28 +00:00
}
return keys % tmp_hash ;
}
2009-08-05 11:43:46 +00:00
#-------------------------------------------------------------------------------
= head3 updateEtcHosts
Description:
Add nodes and their IP addresses into /etc/ hosts .
Arguments:
$ host_ip: the hostname - IP pairs to be updated in /etc/ hosts
Returns:
1 : Succesfully . 0 : Failed .
Globals:
none
Error:
none
Example:
xCAT::Utils:: updateEtcHosts ( \ % node_to_be_updated )
Comments:
= cut
#-------------------------------------------------------------------------------
# Update /etc/hosts
##########################################################################
sub updateEtcHosts
{
2009-11-13 12:56:37 +00:00
my $ host = shift ;
my $ ip = shift ;
2009-08-05 11:43:46 +00:00
my $ fname = "/etc/hosts" ;
unless ( open ( HOSTS , "<$fname" ) ) {
return undef ;
}
my @ rawdata = <HOSTS> ;
my @ newdata = ( ) ;
close ( HOSTS ) ;
chomp @ rawdata ;
######################################
# Remove old entry
######################################
2009-11-13 12:56:37 +00:00
my $ updated = 0 ;
foreach my $ line ( @ rawdata ) {
if ( $ line =~ /^#/ or $ line =~ /^\s*$/ ) {
next ;
2009-08-05 11:43:46 +00:00
}
2009-11-13 12:56:37 +00:00
if ( $ line =~ /^\s*\Q$ip\E\s+(.*)$/ )
2009-08-05 11:43:46 +00:00
{
2009-11-13 12:56:37 +00:00
$ host = $ 1 ;
$ updated = 1 ;
last ;
2009-08-05 11:43:46 +00:00
}
}
2009-11-13 12:56:37 +00:00
if ( ! $ updated )
{
push @ rawdata , "$ip\t$host" ;
}
2009-08-05 11:43:46 +00:00
######################################
# Rewrite file
######################################
unless ( open ( HOSTS , ">$fname" ) ) {
return undef ;
}
for my $ line ( @ rawdata )
{
print HOSTS "$line\n" ;
}
close ( HOSTS ) ;
2009-11-13 12:56:37 +00:00
return [ $ host , $ ip ] ;
2009-08-05 11:43:46 +00:00
}
2010-01-19 18:48:23 +00:00
#-------------------------------------------------------------------------------
= head3 getDBName
Description:
Returns the current database ( SQLITE , DB2 , MYSQL , PG )
Arguments:
None
Returns:
Return string .
Globals:
none
Error:
none
Example:
2010-04-06 13:17:37 +00:00
my $ DBname = xCAT::Utils - > get_DBName ;
2010-01-19 18:48:23 +00:00
Comments:
= cut
#-------------------------------------------------------------------------------
sub get_DBName
{
my $ name = "SQLITE" ; # default
my $ xcatcfg ;
if ( - r "/etc/xcat/cfgloc" ) {
my $ cfgl ;
open ( $ cfgl , "<" , "/etc/xcat/cfgloc" ) ;
$ xcatcfg = <$cfgl> ;
close ( $ cfgl ) ;
if ( $ xcatcfg =~ /^mysql:/ ) {
$ name = "MYSQL"
} else {
if ( $ xcatcfg =~ /^DB2:/ ) {
$ name = "DB2"
} else {
if ( $ xcatcfg =~ /^Pg:/ ) {
$ name = "PG"
}
}
}
}
return $ name ;
}
2009-11-13 12:56:37 +00:00
2010-01-25 08:59:52 +00:00
#-------------------------------------------------------------------------------
= head3 full_path
Description:
Convert the relative path to full path .
Arguments:
relpath: relative path
cwdir: current working directory , use the cwd ( ) if not specified
Returns:
Return the full path
NULL - Failed to get the full path .
Globals:
none
Error:
none
Example:
my $ fp = xCAT::Utils:: full_path ( './test' , '/home/guest' ) ;
Comments:
= cut
#-------------------------------------------------------------------------------
sub full_path
{
my ( $ class , $ relpath , $ cwdir ) = @ _ ;
my $ fullpath ;
if ( ! $ cwdir ) { #cwdir is not specified
$ fullpath = Cwd:: abs_path ( $ relpath ) ;
} else {
$ fullpath = $ cwdir . "/$relpath" ;
}
return $ fullpath ;
}
2010-02-04 10:24:13 +00:00
2010-03-29 13:19:13 +00:00
#-------------------------------------------------------------------------------
= head3 isStateful
returns 1 if localHost is a Stateful install
Arguments:
none
Returns:
1 - localHost is Stateful
0 - localHost is not Stateful
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > isStateful ( ) ) { }
Comments:
none
= cut
2010-02-26 09:46:29 +00:00
2010-03-29 13:19:13 +00:00
#-------------------------------------------------------------------------------
sub isStateful
{
# check to see if / is a real directory
my $ dir = "\/" ;
my $ cmd = "df -P $dir " ;
my @ output = xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{ # error
xCAT::MsgUtils - > message ( "" , " Could not determine Stateful\n" ) ;
return 0 ;
}
foreach my $ line ( @ output )
{
my ( $ file_sys , $ blocks , $ used , $ avail , $ cap , $ mount_point ) =
split ( ' ' , $ line ) ;
$ mount_point =~ s/\s*//g ; # remove blanks
if ( $ mount_point eq $ dir ) {
if ( - e ( $ file_sys ) )
{
return 1 ;
} else {
return 0 ;
}
}
}
return 0 ;
}
2010-02-26 09:46:29 +00:00
2010-05-05 09:00:15 +00:00
#-----------------------------------------------------------------------------
= head3 setupAIXconserver
Set AIX conserver
= cut
#-------------------------------------------------------------------------------
= head3 setupAIXconserver
Description:
Set AIX conserver
Arguments:
$ verbose:
Returns:
Return result of the operation
Globals:
none
Error:
none
Example:
my $ res = xCAT::Utils:: setupAIXconserver ( $ verbose ) ;
Comments:
= cut
#-----------------------------------------------------------------------------
sub setupAIXconserver
{
my ( $ class , $ verbose ) = @ _ ;
my $ cmd ;
my $ outref ;
my $ msg ;
my $ rc = 0 ;
if ( ! - f "/usr/sbin/conserver" )
{
$ cmd = "ln -sf /opt/freeware/sbin/conserver /usr/sbin/conserver" ;
$ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message (
'E' ,
"Could not ln -sf /opt/freeware/sbin/conserver /usr/sbin/conserver."
) ;
}
else
{
$ msg = "ln -sf /opt/freeware/sbin/conserver /usr/sbin/conserver." ;
2010-05-14 07:41:43 +00:00
if ( $ verbose ) {
2010-05-05 09:00:15 +00:00
xCAT::MsgUtils - > message ( "I" , $ msg ) ;
}
}
}
if ( ! - f "/usr/bin/console" )
{
$ cmd = "ln -sf /opt/freeware/bin/console /usr/bin/console" ;
$ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message (
'E' ,
"Could not ln -sf /opt/freeware/bin/console /usr/bin/console."
) ;
}
else
{
$ msg = "ln -sf /opt/freeware/bin/console /usr/sbin/console." ;
2010-05-14 07:41:43 +00:00
if ( $ verbose ) {
2010-05-05 09:00:15 +00:00
xCAT::MsgUtils - > message ( "I" , $ msg ) ;
}
}
}
$ cmd = "lssrc -a | grep conserver >/dev/null 2>&1" ;
$ outref = xCAT::Utils - > runcmd ( "$cmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ cmd =
"mkssys -p /opt/freeware/sbin/conserver -s conserver -u 0 -S -n 15 -f 15 -a \"-o -O1 -C /etc/conserver.cf\"" ;
$ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( 'E' , "Could not add subsystem conserver." ) ;
}
else
{
xCAT::MsgUtils - > message ( 'I' , "Added subsystem conserver." ) ;
# Remove old setting
my $ rmitab_cmd = 'rmitab conserver > /dev/null 2>&1' ;
$ rc = system ( $ rmitab_cmd ) ;
# add to the /etc/inittab file
my $ mkitab_cmd =
'mkitab "conserver:2:once:/usr/bin/startsrc -s conserver > /dev/console 2>&1" > /dev/null 2>&1' ;
$ rc = system ( $ mkitab_cmd ) ; # may already be there no error check
}
}
else
{ # conserver already a service
# Remove old setting
my $ rmitab_cmd = 'rmitab conserver > /dev/null 2>&1' ;
$ rc = system ( $ rmitab_cmd ) ;
# make sure it is registered in /etc/inittab file
my $ mkitab_cmd =
'mkitab "conserver:2:once:/usr/bin/startsrc -s conserver > /dev/console 2>&1" > /dev/null 2>&1' ;
$ rc = system ( $ mkitab_cmd ) ; # may already be there no error check
}
# now make sure conserver is started
$ rc = xCAT::Utils - > startService ( "conserver" ) ;
return $ rc ;
}
2010-11-02 11:58:45 +00:00
2010-09-14 22:29:41 +00:00
2011-08-22 11:50:44 +00:00
#-------------------------------------------------------------------------------
= head3 isSELINUX
Returns:
returns 0 if SELINUX is enabled
returns 1 if SELINUX is not enabled
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > isSELINUX ( ) ) { blah ; }
Comments:
This is tested on Redhat , may need more for SLES
= cut
#-------------------------------------------------------------------------------
sub isSELINUX
{
if ( - e "/usr/sbin/selinuxenabled" ) {
`/usr/sbin/selinuxenabled` ;
if ( $? == 0 ) {
return 0 ;
} else {
return 1 ;
}
} else {
return 1 ;
}
}
#-------------------------------------------------------------------------------
2010-08-02 08:11:46 +00:00
2012-02-10 20:19:54 +00:00
2012-08-07 14:55:24 +00:00
#-------------------------------------------------------------------------------
= head3 noderangecontainsMN
Returns:
returns nothing , if ManagementNode is not the input noderange
returns name of MN , if Management Node is in the input noderange
Globals:
none
Error:
none
Input:
array of nodes in the noderange
Example:
my $ mn = xCAT::Utils - > noderangecontainsMN ( $ noderange ) ;
Comments:
= cut
#-------------------------------------------------------------------------------
sub noderangecontainsMn
{
my ( $ class , @ noderange ) = @ _ ;
# check if any node in the noderange is the Management Node return the
# name
my $ mname ;
2012-09-10 18:59:47 +00:00
my $ tab = xCAT::Table - > new ( 'nodelist' ) ;
my @ nodelist = $ tab - > getAllNodeAttribs ( [ 'node' , 'groups' ] ) ;
2012-08-07 14:55:24 +00:00
foreach my $ n ( @ nodelist ) {
2012-09-10 18:59:47 +00:00
if ( defined ( $ n - > { 'groups' } ) ) {
2012-11-05 14:48:21 +00:00
my @ groups = split ( "," , $ n - > { 'groups' } ) ;
if ( ( grep ( /__mgmtnode/ , @ groups ) ) ) { # this is the MN
2012-08-07 14:55:24 +00:00
$ mname = $ n - > { 'node' } ;
last ;
}
2012-08-09 16:14:44 +00:00
}
2012-08-07 14:55:24 +00:00
}
2012-10-30 11:10:12 +00:00
if ( $ mname ) { # if Management Node defined in the database
if ( grep ( /$mname/ , @ noderange ) ) { # if MN in the noderange
return $ mname ;
} else {
return ;
}
2012-08-07 14:55:24 +00:00
}
}
2007-12-20 19:02:45 +00:00
1 ;