2007-10-26 22:44:33 +00:00
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
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 ) {
use lib "/usr/opt/perl5/lib/5.8.2/aix-thread-multi" ;
use lib "/usr/opt/perl5/lib/5.8.2" ;
use lib "/usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi" ;
use lib "/usr/opt/perl5/lib/site_perl/5.8.2" ;
}
2008-09-26 23:07:45 +00:00
use lib "$::XCATROOT/lib/perl" ;
2008-04-05 14:53:35 +00:00
require xCAT::Table ;
2008-02-25 14:18:18 +00:00
use POSIX qw( ceil ) ;
2008-02-02 19:39:33 +00:00
use Socket ;
2008-07-18 12:30:22 +00:00
use strict ;
2008-04-05 14:53:35 +00:00
require xCAT::Schema ;
require Data::Dumper ;
require xCAT::NodeRange ;
require DBI ;
2008-05-07 17:35:14 +00:00
2008-05-13 12:36:13 +00:00
our @ ISA = qw( Exporter ) ;
2009-07-22 05:59:11 +00:00
our @ EXPORT_OK = qw( genpassword ) ;
2008-05-07 14:51:12 +00:00
2009-04-17 16:35:54 +00:00
my $ utildata ; #data to persist locally
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
Returns an RFC 4122 compliant UUIDv4
Arguments:
none
Returns:
string representation of a UUDv4 ,
for example: f16196d1 - 7534 - 41 c1 - a0ae - a9633b030583
= 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.
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}}) {
$ _ - > { 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
#The following tag tells the build script where to append build info
my $ version = shift ;
if ( $ version eq 'short' )
{
2009-07-16 14:22:42 +00:00
$ version = '' #XCATVERSIONSUBHERE ;
2009-02-04 17:18:44 +00:00
}
else
{
2009-07-16 14:22:42 +00:00
$ version = 'Version ' #XCATVERSIONSUBHERE #XCATSVNBUILDSUBHERE ;
2009-02-04 17:18:44 +00:00
}
return $ version ;
2009-02-18 19:03:45 +00:00
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
2007-10-26 22:44:33 +00:00
list_all_nodes
Arguments:
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 from the nodelist table
2007-10-26 22:44:33 +00:00
Globals:
none
Error:
undef
Example:
@ nodes = xCAT::Utils - > list_all_nodes ;
Comments:
none
= cut
#------------------------------------------------------------------------
sub list_all_nodes
{
my @ nodes ;
my @ nodelist ;
my $ nodelisttab ;
if ( $ nodelisttab = xCAT::Table - > new ( "nodelist" ) )
{
my @ attribs = ( "node" ) ;
@ nodes = $ nodelisttab - > getAllAttribs ( @ attribs ) ;
foreach my $ node ( @ nodes )
{
push @ nodelist , $ node - > { node } ;
}
}
else
{
xCAT::MsgUtils - > message ( "E" , " Could not read the nodelist table\n" ) ;
}
return @ nodelist ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
2007-10-26 22:44:33 +00:00
list_all_nodegroups
Arguments:
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 node groups from the nodelist table
2007-10-26 22:44:33 +00:00
Globals:
none
Error:
undef
Example:
@ nodegrps = xCAT::Utils - > list_all_nodegroups ;
Comments:
none
= cut
#------------------------------------------------------------------------
sub list_all_node_groups
{
my @ grouplist ;
my @ grouplist2 ;
my @ distinctgroups ;
my $ nodelisttab ;
if ( $ nodelisttab = xCAT::Table - > new ( "nodelist" ) )
{
my @ attribs = ( "groups" ) ;
@ grouplist = $ nodelisttab - > getAllAttribs ( @ attribs ) ;
# build a distinct list of unique group names
foreach my $ group ( @ grouplist )
{
my $ gnames = $ group - > { groups } ;
my @ groupnames = split "," , $ gnames ;
foreach my $ groupname ( @ groupnames )
{
if ( ! grep ( /$groupname/ , @ distinctgroups ) )
{ # not already in list
push @ distinctgroups , $ groupname ;
}
}
}
}
else
{
xCAT::MsgUtils - > message ( "E" , " Could not read the nodelist table\n" ) ;
}
2008-04-22 13:24:38 +00:00
$ nodelisttab - > close ;
2007-10-26 22:44:33 +00:00
return @ distinctgroups ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
2007-10-26 22:44:33 +00:00
list_nodes_in_nodegroup
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:
@ nodes = xCAT::Utils - > list_nodes_in_nodegroup ( $ group ) ;
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 ;
}
#-----------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3
get_site_attribute
2007-10-26 22:44:33 +00:00
Arguments:
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
The value of the attribute requested from the site table
2007-10-26 22:44:33 +00:00
Globals:
none
Error:
undef
Example:
@ attr = xCAT::Utils - > get_site_attribute ( $ attribute ) ;
Comments:
none
= cut
#------------------------------------------------------------------------
sub get_site_attribute
{
my ( $ class , $ attr ) = @ _ ;
my $ values ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
if ( $ sitetab )
{
2008-07-18 12:30:22 +00:00
( my $ ref ) = $ sitetab - > getAttribs ( { key = > $ attr } , 'value' ) ;
2009-03-12 17:54:44 +00:00
if ( $ ref )
2007-10-26 22:44:33 +00:00
{
$ values = $ ref - > { value } ;
}
}
else
{
xCAT::MsgUtils - > message ( "E" , " Could not read the site table\n" ) ;
}
2008-04-22 13:24:38 +00:00
$ sitetab - > close ;
2007-10-26 22:44:33 +00:00
return $ values ;
}
2007-11-27 14:22:04 +00:00
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
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
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:
command , exitcode and reference to output
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 ) ;
Comments:
If refoutput is true , then the output will be returned as a
reference to an array for efficiency .
= cut
#-------------------------------------------------------------------------------
sub runcmd
{
my ( $ class , $ cmd , $ exitcode , $ refoutput ) = @ _ ;
$ ::RUNCMD_RC = 0 ;
if ( ! $ xCAT:: Utils:: NO_STDERR_REDIRECT )
{
if ( ! ( $ cmd =~ /2>&1$/ ) ) { $ cmd . = ' 2>&1' ; }
2008-02-04 20:02:15 +00:00
}
if ( $ ::VERBOSE )
{
xCAT::MsgUtils - > message ( "I" , "Running Command: $cmd\n" ) ;
2007-11-27 14:22:04 +00:00
}
my $ outref = [] ;
@$ outref = `$cmd` ;
if ( $? )
{
$ ::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
exitcode
reference to output
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 :
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 - > runxcmd ( $ cmd , $ sub_req , - 2 , 1 ) ;
Comments:
If refoutput is true , then the output will be returned as a
reference to an array for efficiency .
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 .
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 ;
if ( $ ::VERBOSE )
{
2009-02-04 17:18:44 +00:00
if ( ref ( $ cmd ) eq "HASH" )
{
xCAT::MsgUtils - > message ( "I" ,
"Running internal xCAT command: $cmd->{command}->[0] ... \n" ) ;
}
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
}
$ ::xcmd_outref = [] ;
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 ) ;
}
$ subreq - > ( $ req , \ & runxcmd_output ) ;
$ ::CALLBACK = $ save_CALLBACK ; # in case the subreq call changed it
my $ outref = $ ::xcmd_outref ;
2008-10-06 14:51:33 +00:00
if ( $ ::RUNCMD_RC )
{
my $ displayerror = 1 ;
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
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
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 ;
}
}
if ( $ refoutput )
{
chomp ( @$ outref ) ;
return $ outref ;
}
elsif ( wantarray )
{
chomp ( @$ outref ) ;
return @$ outref ;
}
else
{
my $ line = join ( '' , @$ outref ) ;
chomp $ line ;
return $ line ;
}
}
2009-02-04 17:18:44 +00:00
2008-10-06 14:51:33 +00:00
# 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.
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 } ;
}
}
# my $i=0;
# foreach my $line ($resp->{info}->[$i]) {
# push (@dshresult, $line);
# $i++;
# }
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 .
Arguments:
none
Returns:
path to user home directory .
Globals:
none
Error:
none
Example:
$ myHome = xCAT::Utils - > getHomeDir ( ) ;
Comments:
none
= cut
#--------------------------------------------------------------------------------
sub getHomeDir
{
my ( $ class , $ username ) = @ _ ;
2009-03-30 14:13:09 +00:00
my @ user ;
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 ( $> ) ;
}
return $ user [ 7 ] ;
2007-12-20 19:02:45 +00:00
}
#--------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 setupSSH
2007-12-20 19:02:45 +00:00
2009-02-04 17:18:44 +00:00
Generates if needed and Transfers the ssh keys
fOr a userid to setup ssh to the input nodes .
2007-12-20 19:02:45 +00:00
Arguments:
2008-04-05 14:53:35 +00:00
Array of nodes
2007-12-20 19:02:45 +00:00
Returns:
2008-04-05 14:53:35 +00:00
2009-02-04 17:18:44 +00:00
Env Variables: $ DSH_FROM_USERID , $ DSH_TO_USERID , $ DSH_REMOTE_PASSWORD
the ssh keys are transferred from the $ DSH_FROM_USERID to the $ DSH_TO_USERID
on the node ( s ) . The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID
must be obtained by
the calling script or from the xdsh client
2007-12-20 19:02:45 +00:00
Globals:
2008-04-05 14:53:35 +00:00
$ ::XCATROOT , $ ::CALLBACK
2007-12-20 19:02:45 +00:00
Error:
2008-04-05 14:53:35 +00:00
0 = good , 1 = error
2007-12-20 19:02:45 +00:00
Example:
xCAT::Utils - > setupSSH ( @ target_nodes ) ;
Comments:
Does not setup known_hosts . Assumes automatically
setup by SSH ( ssh config option StrictHostKeyChecking no should
be set in the ssh config file ) .
= cut
#--------------------------------------------------------------------------------
sub setupSSH
{
my ( $ class , $ ref_nodes ) = @ _ ;
my @ nodes = $ ref_nodes ;
my @ badnodes = ( ) ;
2009-04-05 12:18:17 +00:00
my $ n_str = $ nodes [ 0 ] ;
2009-02-09 18:49:48 +00:00
my $ SSHdir = "/install/postscripts/_ssh" ;
2009-02-04 17:18:44 +00:00
if ( ! ( $ ENV { 'DSH_REMOTE_PASSWORD' } ) )
{
my $ rsp = ( ) ;
$ rsp - > { data } - > [ 0 ] =
"User password for the ssh key exchange has not been input. xdsh -K cannot complete.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return ;
}
# setup who the keys are coming from and who they are going to
my $ from_userid ;
my $ to_userid ;
if ( ! ( $ ENV { 'DSH_FROM_USERID' } ) )
{
my $ rsp = ( ) ;
$ rsp - > { data } - > [ 0 ] =
"DSH From Userid has not been input. xdsh -K cannot complete.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return ;
}
else
{
$ from_userid = $ ENV { 'DSH_FROM_USERID' } ;
}
if ( ! ( $ ENV { 'DSH_TO_USERID' } ) )
{
my $ rsp = ( ) ;
$ rsp - > { data } - > [ 0 ] =
"DSH to Userid has not been input. xdsh -K cannot complete.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK , 1 ) ;
return ;
}
else
{
$ to_userid = $ ENV { 'DSH_TO_USERID' } ;
}
2007-12-20 19:02:45 +00:00
if ( $ ::XCATROOT )
{
$ ::REMOTESHELL_EXPECT = "$::XCATROOT/sbin/remoteshell.expect" ;
}
else
{
$ ::REMOTESHELL_EXPECT = "/opt/xcat/sbin/remoteshell.expect" ;
}
2008-01-30 18:49:33 +00:00
$ ::REMOTE_SHELL = "/usr/bin/ssh" ;
2007-12-20 19:02:45 +00:00
2009-04-03 15:42:59 +00:00
#
# if we are running as root
# for non-root users, keys were generated in the xdsh client code
#
2007-12-20 19:02:45 +00:00
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
2009-01-14 15:54:57 +00:00
2009-02-04 17:18:44 +00:00
# Get the home directory
my $ home = xCAT::Utils - > getHomeDir ( $ from_userid ) ;
$ ENV { 'DSH_FROM_USERID_HOME' } = $ home ;
2007-12-20 19:02:45 +00:00
2009-04-03 15:42:59 +00:00
if ( $ from_userid eq "root" )
{
# make the directory to hold keys to transfer to the nodes
if ( ! - d $ SSHdir )
{
mkdir ( "/install" , 0755 ) ;
mkdir ( "/install/postscripts" , 0755 ) ;
mkdir ( "/install/postscripts/_ssh" , 0755 ) ;
}
# generates new keys for root, if they do not already exist
xCAT::Utils - > runcmd ( "$::REMOTESHELL_EXPECT -k" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{ # error
$ rsp - > { data } - > [ 0 ] = "remoteshell.expect failed generating keys." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
2007-12-20 19:02:45 +00:00
2009-04-03 15:42:59 +00:00
}
2007-12-20 19:02:45 +00:00
}
2009-04-03 15:42:59 +00:00
# build the shell copy script, needed Perl not always there
# for root and non-root ids
2009-02-11 17:33:58 +00:00
open ( FILE , ">$home/.ssh/copy.sh" )
or die "cannot open file $home/.ssh/copy.sh\n" ;
print FILE " #!/bin/sh
umask 0077
2009-09-09 14:44:42 +00:00
home = `egrep \"^$to_userid:\" /etc/passwd | cut -f6 -d :`
2009-02-11 17:33:58 +00:00
dest_dir = \ " \ $ home / . ssh \ "
mkdir - p \ $ dest_dir
cat /tmp/ $ to_userid /.ssh/ authorized_keys >> \ $ home /.ssh/ authorized_keys 2 > & 1
cat /tmp/ $ to_userid /.ssh/ authorized_keys2 >> \ $ home /.ssh/ authorized_keys2 2 > & 1
cp /tmp/ $ to_userid /.ssh/i d_rsa \ $ home /.ssh/i d_rsa 2 > & 1
cp /tmp/ $ to_userid /.ssh/i d_dsa \ $ home /.ssh/i d_dsa 2 > & 1
chmod 0600 \ $ home /.ssh/i d_ * 2 > & 1
rm - f /tmp/ $ to_userid /.ssh/ * 2 > & 1
rmdir \ " /tmp/ $ to_userid / . ssh \ "
rmdir \ "/tmp/$to_userid\"" ;
2007-12-20 19:02:45 +00:00
close FILE ;
2009-04-03 15:42:59 +00:00
chmod 0777 , "$home/.ssh/copy.sh" ;
2009-02-04 17:18:44 +00:00
2009-02-18 19:03:45 +00:00
if ( xCAT::Utils - > isMN ( ) )
{ # if on Management Node
if ( $ from_userid eq "root" )
2009-02-04 17:18:44 +00:00
{
2009-04-03 15:42:59 +00:00
2009-02-18 19:03:45 +00:00
my $ rc = xCAT::Utils - > cpSSHFiles ( $ SSHdir ) ;
if ( $ rc != 0 )
{ # error
$ rsp - > { data } - > [ 0 ] = "Error running cpSSHFiles.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return 1 ;
2009-02-04 17:18:44 +00:00
2009-02-18 19:03:45 +00:00
}
# copy the copy install file to the install directory, if from and
# to userid are root
if ( $ to_userid eq "root" )
2009-02-04 17:18:44 +00:00
{
2009-02-18 19:03:45 +00:00
my $ cmd = " cp $home/.ssh/copy.sh $SSHdir/copy.sh" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
my $ rsp = { } ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
2009-02-04 17:18:44 +00:00
}
}
2009-04-03 15:42:59 +00:00
else
{ # from_userid is not root
# build the authorized key files for non-root user
xCAT::Utils - > bldnonrootSSHFiles ( $ from_userid ) ;
}
2007-12-20 19:02:45 +00:00
}
2009-02-04 17:18:44 +00:00
# send the keys to the nodes for root or some other id
2007-12-20 19:02:45 +00:00
#
my $ cmd = "$::REMOTESHELL_EXPECT -s $n_str" ;
2008-04-14 16:58:54 +00:00
my $ rc = system ( "$cmd" ) >> 8 ;
2007-12-20 19:02:45 +00:00
if ( $ rc )
{
2008-04-05 14:53:35 +00:00
$ rsp - > { data } - > [ 0 ] = "remoteshell.expect failed sending keys." ;
2007-12-20 19:02:45 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
}
2009-02-18 19:03:45 +00:00
2009-04-03 15:42:59 +00:00
#remove $home/.ssh/authorized_keys*
#Easy to remote this code, if we want
#The MN to be able to ssh to itself and nodes to ssh to the MN
2009-02-18 19:03:45 +00:00
if ( xCAT::Utils - > isMN ( ) )
2009-02-09 18:49:48 +00:00
{
2009-04-03 15:42:59 +00:00
$ cmd = "rm $home/.ssh/authorized_keys*" ;
2009-02-18 19:03:45 +00:00
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
my $ rsp = { } ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
2009-02-09 18:49:48 +00:00
2009-02-18 19:03:45 +00:00
}
2009-02-09 18:49:48 +00:00
}
2009-02-18 19:03:45 +00:00
2007-12-20 19:02:45 +00:00
# must always check to see if worked, run test
2009-04-05 12:18:17 +00:00
my @ testnodes = split ( "," , $ nodes [ 0 ] ) ;
foreach my $ n ( @ testnodes )
2007-12-20 19:02:45 +00:00
{
my $ cmd = "$::REMOTESHELL_EXPECT -t $::REMOTE_SHELL $n " ;
my @ cmdout = `$cmd 2>&1` ;
chomp ( @ cmdout ) ; # take the newline off
my $ rc = $? >> 8 ;
if ( $ rc )
{
push @ badnodes , $ n ;
}
}
if ( @ badnodes )
{
my $ nstring = join ',' , @ badnodes ;
$ rsp - > { data } - > [ 0 ] =
2008-04-05 14:53:35 +00:00
"SSH setup failed for the following nodes: $nstring." ;
2007-12-20 19:02:45 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return @ badnodes ;
}
else
{
2008-04-05 14:53:35 +00:00
$ rsp - > { data } - > [ 0 ] = "$::REMOTE_SHELL setup is complete." ;
2007-12-20 19:02:45 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
return 0 ;
}
}
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
#--------------------------------------------------------------------------------
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
= head3 cpSSHFiles
2007-11-28 19:44:47 +00:00
2009-02-18 19:03:45 +00:00
Builds authorized_keyfiles from the keys only run on Management Node
and for root and puts them in /install/ postscripts / _ssh
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
Arguments:
2009-04-03 15:42:59 +00:00
install directory path
2007-12-20 19:02:45 +00:00
Returns:
2008-04-05 14:53:35 +00:00
2007-12-20 19:02:45 +00:00
Globals:
2008-04-05 14:53:35 +00:00
$ ::CALLBACK
2007-12-20 19:02:45 +00:00
Error:
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
Example:
2009-04-03 15:42:59 +00:00
xCAT::Utils - > cpSSHFiles ( $ dir ) ;
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
Comments:
none
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
= cut
2007-11-28 19:44:47 +00:00
2007-12-20 19:02:45 +00:00
#--------------------------------------------------------------------------------
sub cpSSHFiles
{
my ( $ class , $ SSHdir ) = @ _ ;
my ( $ cmd , $ rc ) ;
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
2007-12-20 19:02:45 +00:00
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "Copying SSH Keys" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
my $ home = xCAT::Utils - > getHomeDir ( "root" ) ;
if ( ! ( - e "$home/.ssh/identity.pub" )
|| ! ( - e "$home/.ssh/id_rsa.pub" )
|| ! ( - e "$home/.ssh/id_dsa.pub" ) )
{
2009-09-09 16:49:18 +00:00
$ rsp - > { data } - > [ 0 ] = "A public key was missing in the .ssh directory." ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
2007-12-20 19:02:45 +00:00
return 1 ;
}
2009-04-03 15:42:59 +00:00
# copy to install directory
my $ authorized_keys = "$SSHdir/authorized_keys" ;
2007-12-20 19:02:45 +00:00
$ cmd = " cp $home/.ssh/identity.pub $authorized_keys" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2009-04-03 15:42:59 +00:00
# copy to home ssh directory
2009-02-04 17:18:44 +00:00
$ cmd = " cp $home/.ssh/identity.pub $home/.ssh/authorized_keys" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
my $ rsp = { } ;
2007-12-20 19:02:45 +00:00
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
2009-02-04 17:18:44 +00:00
chmod 0600 , "$home/.ssh/authorized_keys" ;
2007-12-20 19:02:45 +00:00
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2009-04-03 15:42:59 +00:00
# copy to install directory
my $ authorized_keys2 = "$SSHdir/authorized_keys2" ;
2007-12-20 19:02:45 +00:00
$ cmd = "cp $home/.ssh/id_rsa.pub $authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2009-04-03 15:42:59 +00:00
# copy to home ssh directory
2009-02-04 17:18:44 +00:00
$ cmd = "cp $home/.ssh/id_rsa.pub $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
2007-12-20 19:02:45 +00:00
2009-02-04 17:18:44 +00:00
}
else
{
chmod 0600 , "$home/.ssh/authorized_keys2" ;
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2009-04-03 15:42:59 +00:00
# add dsa key to install directory
2009-02-04 17:18:44 +00:00
my $ rsp = { } ;
2007-12-20 19:02:45 +00:00
$ cmd = "cat $home/.ssh/id_dsa.pub >> $authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2009-04-03 15:42:59 +00:00
# add dsa key to home ssh directory
my $ rsp = { } ;
$ cmd = "cat $home/.ssh/id_dsa.pub >> $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
2007-12-20 19:02:45 +00:00
if ( ! ( - e "$authorized_keys" ) || ! ( - e "$authorized_keys2" ) )
{
return 1 ;
}
return ( 0 ) ;
}
2008-02-04 20:02:15 +00:00
2009-04-03 15:42:59 +00:00
#--------------------------------------------------------------------------------
= head3 bldnonrootSSHFiles
Builds authorized_keyfiles for the non - root id
It must not only contain the public keys for the non - root id
but also the public keys for root
Arguments:
from_userid - current id running xdsh from the command line
Returns:
Globals:
$ ::CALLBACK
Error:
Example:
xCAT::Utils - > bldnonrootSSHFiles ;
Comments:
none
= cut
#--------------------------------------------------------------------------------
sub bldnonrootSSHFiles
{
my ( $ class , $ from_userid ) = @ _ ;
my ( $ cmd , $ rc ) ;
my $ rsp = { } ;
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "Building SSH Keys for $from_userid" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
my $ home = xCAT::Utils - > getHomeDir ( $ from_userid ) ;
my $ roothome = xCAT::Utils - > getHomeDir ( "root" ) ;
if ( ! ( - e "$home/.ssh/identity.pub" )
|| ! ( - e "$home/.ssh/id_rsa.pub" )
|| ! ( - e "$home/.ssh/id_dsa.pub" ) )
{
return 1 ;
}
$ cmd = " cp $home/.ssh/identity.pub $home/.ssh/authorized_keys" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
my $ rsp = { } ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
chmod 0600 , "$home/.ssh/authorized_keys" ;
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
my $ rsp = { } ;
$ cmd = "cp $home/.ssh/id_rsa.pub $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
chmod 0600 , "$home/.ssh/authorized_keys2" ;
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
my $ rsp = { } ;
$ cmd = "cat $home/.ssh/id_dsa.pub >> $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "$cmd failed.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
# add roots keys
# if cannot access, warn and continue
my $ rsp = { } ;
$ cmd = "cat $roothome/.ssh/identity.pub >> $home/.ssh/authorized_keys" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "Warning: Cannot give $from_userid root ssh authority. \n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
my $ rsp = { } ;
$ cmd = "cat $roothome/.ssh/id_rsa.pub >> $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "Warning: Cannot give $from_userid root ssh authority. \n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
my $ rsp = { } ;
$ cmd = "cat $roothome/.ssh/id_dsa.pub >> $home/.ssh/authorized_keys2" ;
xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
$ rsp - > { data } - > [ 0 ] = "Warning: Cannot give $from_userid root ssh authority. \n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ ::CALLBACK ) ;
return ( 1 ) ;
}
else
{
if ( $ ::VERBOSE )
{
$ rsp - > { data } - > [ 0 ] = "$cmd succeeded.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
}
}
return ( 0 ) ;
}
2008-01-22 14:59:14 +00:00
#-------------------------------------------------------------------------------
= head3 isServiceNode
2008-04-05 14:53:35 +00:00
checks for the /etc/x CATSN file
2008-01-22 14:59:14 +00:00
Arguments:
none
Returns:
2008-04-05 14:53:35 +00:00
1 - localHost is ServiceNode
0 - localHost is not ServiceNode
2008-01-22 14:59:14 +00:00
Globals:
none
Error:
none
Example:
% ::XCATMasterPort defined in the caller .
2008-04-05 14:53:35 +00:00
$ return = ( xCAT::Utils - > isServiceNode ( ) )
2008-01-22 14:59:14 +00:00
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub isServiceNode
{
my $ value ;
2008-02-18 15:10:31 +00:00
if ( - e "/etc/xCATSN" )
2008-01-22 14:59:14 +00:00
{
2008-02-06 17:19:13 +00:00
return 1 ;
2008-02-18 15:10:31 +00:00
}
else
{
2008-02-06 17:19:13 +00:00
return 0 ;
2008-02-18 15:10:31 +00:00
}
2008-02-07 20:11:52 +00:00
}
2008-03-26 18:20:05 +00:00
2008-03-13 12:08:34 +00:00
#-------------------------------------------------------------------------------
2008-03-31 15:52:36 +00:00
= head3 isMN
checks for the /etc/x CATMN file , if it exists it is a Management Server
2008-04-05 14:53:35 +00:00
2008-03-13 12:08:34 +00:00
Arguments:
none
Returns:
2008-07-21 18:03:47 +00:00
1 - localHost is Management Node
0 - localHost is not a Management Node
2008-03-13 12:08:34 +00:00
Globals:
none
Error:
none
Example:
2008-04-05 14:53:35 +00:00
$ return = ( xCAT::Utils - > isMN ( ) )
2008-03-13 12:08:34 +00:00
Comments:
none
= cut
#-------------------------------------------------------------------------------
2008-03-31 15:52:36 +00:00
sub isMN
2008-03-13 12:08:34 +00:00
{
my $ value ;
2008-03-31 15:52:36 +00:00
if ( - e "/etc/xCATMN" )
2008-03-13 12:08:34 +00:00
{
return 1 ;
}
else
{
return 0 ;
}
}
#-------------------------------------------------------------------------------
2008-03-19 15:22:03 +00:00
= head3 classful_networks_for_net_and_mask
2008-04-05 14:53:35 +00:00
2008-03-19 15:22:03 +00:00
Arguments:
network and mask
Returns:
a list of classful subnets that constitute the entire potentially classless arguments
Globals:
none
Error:
none
Example:
Comments:
none
= cut
#-------------------------------------------------------------------------------
2008-03-26 18:20:05 +00:00
sub classful_networks_for_net_and_mask
2008-03-19 15:22:03 +00:00
{
2008-03-26 18:20:05 +00:00
my $ network = shift ;
my $ mask = shift ;
2008-03-19 15:22:03 +00:00
my $ given_mask = 0 ;
2008-03-26 18:20:05 +00:00
if ( $ mask =~ /\./ )
{
$ given_mask = 1 ;
my $ masknumber = unpack ( "N" , inet_aton ( $ mask ) ) ;
$ mask = 32 ;
until ( $ masknumber % 2 )
{
$ masknumber = $ masknumber >> 1 ;
$ mask - - ;
}
}
2008-03-19 15:22:03 +00:00
my @ results ;
my $ bitstoeven = ( 8 - ( $ mask % 8 ) ) ;
if ( $ bitstoeven eq 8 ) { $ bitstoeven = 0 ; }
my $ resultmask = $ mask + $ bitstoeven ;
2008-03-26 18:20:05 +00:00
if ( $ given_mask )
{
$ resultmask =
inet_ntoa ( pack ( "N" , ( 2 ** $ resultmask - 1 ) << ( 32 - $ resultmask ) ) ) ;
2008-03-19 15:22:03 +00:00
}
2008-03-26 18:20:05 +00:00
push @ results , $ resultmask ;
2008-03-19 15:22:03 +00:00
my $ padbits = ( 32 - ( $ bitstoeven + $ mask ) ) ;
my $ numchars = int ( ( $ mask + $ bitstoeven ) / 4 ) ;
my $ curmask = 2 ** $ mask - 1 << ( 32 - $ mask ) ;
my $ nown = unpack ( "N" , inet_aton ( $ network ) ) ;
$ nown = $ nown & $ curmask ;
my $ highn = $ nown + ( ( 2 ** $ bitstoeven - 1 ) << ( 32 - $ mask - $ bitstoeven ) ) ;
while ( $ nown <= $ highn )
{
2008-03-26 18:20:05 +00:00
push @ results , inet_ntoa ( pack ( "N" , $ nown ) ) ;
#$rethash->{substr($nowhex, 0, $numchars)} = $network;
$ nown += 1 << ( 32 - $ mask - $ bitstoeven ) ;
2008-03-19 15:22:03 +00:00
}
return @ results ;
}
#-------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 my_hexnets
2008-03-13 12:08:34 +00:00
Arguments:
none
Returns:
Globals:
none
Error:
none
Example:
Comments:
none
= cut
2008-02-07 20:11:52 +00:00
2008-03-13 12:08:34 +00:00
#-------------------------------------------------------------------------------
2008-02-25 14:18:18 +00:00
sub my_hexnets
{
2008-02-26 19:57:10 +00:00
my $ rethash ;
2008-02-25 14:18:18 +00:00
my @ nets = split /\n/ , `/sbin/ip addr` ;
foreach ( @ nets )
{
my @ elems = split /\s+/ ;
unless ( /^\s*inet\s/ )
{
next ;
}
( my $ curnet , my $ maskbits ) = split /\// , $ elems [ 2 ] ;
2008-02-26 19:57:10 +00:00
my $ bitstoeven = ( 4 - ( $ maskbits % 4 ) ) ;
2008-02-25 14:18:18 +00:00
if ( $ bitstoeven eq 4 ) { $ bitstoeven = 0 ; }
2008-02-26 19:57:10 +00:00
my $ padbits = ( 32 - ( $ bitstoeven + $ maskbits ) ) ;
my $ numchars = int ( ( $ maskbits + $ bitstoeven ) / 4 ) ;
my $ curmask = 2 ** $ maskbits - 1 << ( 32 - $ maskbits ) ;
my $ nown = unpack ( "N" , inet_aton ( $ curnet ) ) ;
2008-02-25 14:18:18 +00:00
$ nown = $ nown & $ curmask ;
2008-02-26 19:57:10 +00:00
my $ highn =
$ nown + ( ( 2 ** $ bitstoeven - 1 ) << ( 32 - $ maskbits - $ bitstoeven ) ) ;
while ( $ nown <= $ highn )
{
my $ nowhex = sprintf ( "%08x" , $ nown ) ;
$ rethash - > { substr ( $ nowhex , 0 , $ numchars ) } = $ curnet ;
$ nown += 1 << ( 32 - $ maskbits - $ bitstoeven ) ;
2008-02-25 14:18:18 +00:00
}
}
return $ rethash ;
}
2008-02-26 19:57:10 +00:00
2009-07-23 20:02:39 +00:00
#-------------------------------------------------------------------------------
= head3 get_host_from_ip
Description:
Get the hostname of an IP addresses . First from hosts table , and then try system resultion .
If there is a shortname , it will be returned . Otherwise it will return long name . If the IP cannot be resolved , return undef ;
Arguments:
$ ip: the IP to get ;
Returns:
Return: the hostname .
For an example
Globals:
none
Error:
none
Example:
xCAT::Utils:: get_host_from_ip ( '192.168.200.1' )
Comments:
= cut
#-----------------------------------------------------------------------
sub get_host_from_ip
{
my $ ip = shift ;
}
#-------------------------------------------------------------------------------
= head3 isPingable
Description:
Check if an IP address can be pinged
Arguments:
$ ip: the IP to ping ;
Returns:
Return: 1 indicates yes ; 0 indicates no .
For an example
Globals:
none
Error:
none
Example:
xCAT::Utils:: isPingable ( '192.168.200.1' )
Comments:
none
= cut
#-----------------------------------------------------------------------
% ::PING_CACHE ;
sub isPingable
{
my $ ip = shift ;
my $ rc ;
if ( exists $ ::PING_CACHE { $ ip } )
{
$ rc = $ ::PING_CACHE { $ ip } ;
}
else
{
my $ res = `LANG=C ping -c 1 -w 5 $ip 2>&1` ;
if ( $ res =~ /100% packet loss/g )
{
$ rc = 1 ;
}
else
{
$ rc = 0 ;
}
$ ::PING_CACHE { $ ip } = $ rc ;
}
return ! $ rc ;
}
#-------------------------------------------------------------------------------
= head3 my_nets
Description:
Return a hash ref that contains all subnet and netmask on the mn ( or sn ) . This subroutine can be invoked on both Linux and AIX .
Arguments:
none .
Returns:
Return a hash ref . Each entry will be: <subnet/mask> = > < existing ip > ;
For an example:
'192.168.200.0/255.255.255.0' = > '192.168.200.246' ;
For an example
Globals:
none
Error:
none
Example:
xCAT::Utils:: my_nets ( ) .
Comments:
none
= cut
#-----------------------------------------------------------------------
2009-06-26 19:29:01 +00:00
sub my_nets
{
my $ rethash ;
2009-07-23 20:02:39 +00:00
my @ nets ;
if ( $^O eq 'aix' )
{
@ nets = split /\n/ , `/usr/sbin/ifconfig -a` ;
}
else
{
@ nets = split /\n/ , `/sbin/ip addr` ; #could use ip route, but to match hexnets...
}
2009-06-26 19:29:01 +00:00
foreach ( @ nets )
{
my @ elems = split /\s+/ ;
unless ( /^\s*inet\s/ )
{
next ;
}
2009-07-23 20:02:39 +00:00
my $ curnet ; my $ maskbits ;
if ( $^O eq 'aix' )
{
$ curnet = $ elems [ 2 ] ;
$ maskbits = formatNetmask ( $ elems [ 4 ] , 2 , 1 ) ;
}
else
{
( $ curnet , $ maskbits ) = split /\// , $ elems [ 2 ] ;
}
2009-06-26 19:29:01 +00:00
my $ curmask = 2 ** $ maskbits - 1 << ( 32 - $ maskbits ) ;
my $ nown = unpack ( "N" , inet_aton ( $ curnet ) ) ;
$ nown = $ nown & $ curmask ;
my $ textnet = inet_ntoa ( pack ( "N" , $ nown ) ) ;
$ textnet . = "/$maskbits" ;
$ rethash - > { $ textnet } = $ curnet ;
}
return $ rethash ;
}
2008-03-21 20:00:07 +00:00
#-------------------------------------------------------------------------------
= head3 my_if_netmap
Arguments:
none
Returns:
hash of networks to interface names
Globals:
none
Error:
none
Comments:
none
= cut
2008-03-26 18:20:05 +00:00
2008-03-21 20:00:07 +00:00
#-------------------------------------------------------------------------------
2008-03-26 18:20:05 +00:00
sub my_if_netmap
{
2008-07-18 12:30:22 +00:00
my $ net ;
2008-03-26 18:20:05 +00:00
if ( scalar ( @ _ ) )
{ #called with the other syntax
$ net = shift ;
}
my @ rtable = split /\n/ , `netstat -rn` ;
if ( $? )
{
return "Unable to run netstat, $?" ;
}
my % retmap ;
foreach ( @ rtable )
{
if ( /^\D/ ) { next ; } #skip headers
if ( /^\S+\s+\S+\s+\S+\s+\S*G/ )
{
next ;
} #Skip networks that require gateways to get to
/^(\S+)\s.*\s(\S+)$/ ;
$ retmap { $ 1 } = $ 2 ;
}
return \ % retmap ;
2008-03-21 20:00:07 +00:00
}
2008-02-04 20:02:15 +00:00
#-------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 my_ip_facing
2009-03-12 15:41:11 +00:00
Returns my ip address
Linux only
2008-02-04 20:02:15 +00:00
Arguments:
2009-03-12 15:41:11 +00:00
nodename
2008-02-04 20:02:15 +00:00
Returns:
Globals:
none
Error:
none
Example:
Comments:
none
= cut
2008-02-18 15:10:31 +00:00
#-------------------------------------------------------------------------------
sub my_ip_facing
{
my $ peer = shift ;
if ( @ _ )
{
$ peer = shift ;
}
2009-07-07 02:07:30 +00:00
return my_ip_facing_aix ( $ peer ) if ( $^O eq 'aix' ) ;
2008-02-18 15:10:31 +00:00
my $ noden = unpack ( "N" , inet_aton ( $ peer ) ) ;
my @ nets = split /\n/ , `/sbin/ip addr` ;
foreach ( @ nets )
{
my @ elems = split /\s+/ ;
unless ( /^\s*inet\s/ )
{
next ;
}
( my $ curnet , my $ maskbits ) = split /\// , $ elems [ 2 ] ;
my $ curmask = 2 ** $ maskbits - 1 << ( 32 - $ maskbits ) ;
my $ curn = unpack ( "N" , inet_aton ( $ curnet ) ) ;
if ( ( $ noden & $ curmask ) == ( $ curn & $ curmask ) )
{
return $ curnet ;
}
}
return undef ;
}
#-------------------------------------------------------------------------------
2009-07-07 02:07:30 +00:00
= head3 my_ip_facing_aix
Returns my ip address
AIX only
Arguments:
nodename
Returns:
Globals:
none
Error:
none
Example:
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub my_ip_facing_aix
{
my $ peer = shift ;
my @ nets = `ifconfig -a` ;
chomp @ nets ;
foreach my $ net ( @ nets )
{
if ( $ net =~ /^\s*inet\s+([\d\.]+)\s+netmask\s+(\w+)\s+broadcast/ )
{
my ( $ curnet , $ netmask ) = ( $ 1 , $ 2 ) ;
if ( isInSameSubnet ( $ peer , $ curnet , $ netmask , 2 ) )
{
return $ curnet ;
}
}
}
return undef ;
}
#-------------------------------------------------------------------------------
= head3 formatNetmask
Description:
Transform netmask to one of 3 formats ( 255.255 .255 .0 , 24 , 0xffffff00 ) .
Arguments:
$ netmask: the original netmask
$ origType: the original netmask type . The valid value can be 0 , 1 , 2 :
Type 0 : 255.255 .255 .0
Type 1 : 24
Type 2 : 0xffffff00
$ newType: the new netmask type , valid values can be 0 , 1 , 2 , as above .
Returns:
Return undef if any error . Otherwise return the netmask in new format .
Globals:
none
Error:
none
Example:
xCAT::Utils:: formatNetmask ( '24' , 1 , 0 ) ; #return '255.255.255.0'.
Comments:
none
= cut
#-----------------------------------------------------------------------
sub formatNetmask
{
my $ mask = shift ;
my $ origType = shift ;
my $ newType = shift ;
my $ maskn ;
if ( $ origType == 0 )
{
$ maskn = unpack ( "N" , inet_aton ( $ mask ) ) ;
}
elsif ( $ origType == 1 )
{
$ maskn = 2 ** $ mask - 1 << ( 32 - $ mask ) ;
}
elsif ( $ origType == 2 )
{
$ maskn = hex $ mask ;
}
else
{
return undef ;
}
if ( $ newType == 0 )
{
return inet_ntoa ( pack ( 'N' , $ maskn ) ) ;
}
if ( $ newType == 1 )
{
my $ bin = unpack ( "B32" , pack ( "N" , $ maskn ) ) ;
my @ dup = ( $ bin =~ /(1{1})0*/g ) ;
return scalar ( @ dup ) ;
}
if ( $ newType == 2 )
{
return sprintf "0x%1x" , $ maskn ;
}
return undef ;
}
#-------------------------------------------------------------------------------
= head3 isInSameSubnet
Description:
Check if 2 given IP addresses are in same subnet
Arguments:
$ ip1: the first IP
$ ip2: the second IP
$ mask: the netmask , here are 3 possible netmask types , following are examples for these 3 types:
Type 0 : 255.255 .255 .0
Type 1 : 24
Type 2 : 0xffffff00
$ masktype: the netmask type , 3 possible values : 0 , 1 , 2 , as indicated above
Returns:
1 : they are in same subnet
2 : not in same subnet
Globals:
none
Error:
none
Example:
xCAT::Utils:: isInSameSubnet ( '192.168.10.1' , '192.168.10.2' , '255.255.255.0' , 0 ) ;
Comments:
none
= cut
#-----------------------------------------------------------------------
sub isInSameSubnet
{
my $ ip1 = shift ;
my $ ip2 = shift ;
my $ mask = shift ;
my $ maskType = shift ;
my $ maskn ;
if ( $ maskType == 0 )
{
$ maskn = unpack ( "N" , inet_aton ( $ mask ) ) ;
}
elsif ( $ maskType == 1 )
{
$ maskn = 2 ** $ mask - 1 << ( 32 - $ mask ) ;
}
elsif ( $ maskType == 2 )
{
$ maskn = hex $ mask ;
}
else
{
return undef ;
}
my $ ip1n = unpack ( "N" , inet_aton ( $ ip1 ) ) ;
my $ ip2n = unpack ( "N" , inet_aton ( $ ip2 ) ) ;
return ( ( $ ip1n & $ maskn ) == ( $ ip2n & $ maskn ) ) ;
}
#-------------------------------------------------------------------------------
2009-04-17 16:35:54 +00:00
= head3 nodeonmynet - checks to see if node is on any network this server is attached to or remote network potentially managed by this system
2008-02-18 15:10:31 +00:00
Arguments:
2008-04-05 14:53:35 +00:00
Node name
2008-02-18 15:10:31 +00:00
Returns: 1 if node is on the network
Globals:
none
Error:
none
Example:
Comments:
none
= cut
2008-02-04 20:02:15 +00:00
#-------------------------------------------------------------------------------
sub nodeonmynet
{
my $ nodetocheck = shift ;
if ( scalar ( @ _ ) )
{
$ nodetocheck = shift ;
}
2008-03-26 18:20:05 +00:00
unless ( inet_aton ( $ nodetocheck ) )
{
return 0 ;
2008-03-20 21:36:49 +00:00
}
2008-02-04 20:02:15 +00:00
my $ nodeip = inet_ntoa ( inet_aton ( $ nodetocheck ) ) ;
unless ( $ nodeip =~ /\d+\.\d+\.\d+\.\d+/ )
{
2008-02-18 15:10:31 +00:00
return 0 ; #Not supporting IPv6 here IPV6TODO
2008-02-04 20:02:15 +00:00
}
my $ noden = unpack ( "N" , inet_aton ( $ nodeip ) ) ;
2009-04-17 16:35:54 +00:00
my @ nets ;
if ( $ utildata - > { nodeonmynetdata } and $ utildata - > { nodeonmynetdata } - > { pid } == $$ ) {
2009-04-17 20:29:52 +00:00
@ nets = @ { $ utildata - > { nodeonmynetdata } - > { nets } } ;
2009-04-17 16:35:54 +00:00
} else {
2009-07-07 02:07:30 +00:00
if ( $^O eq 'aix' )
{
my @ subnets = get_subnet_aix ( ) ;
for my $ net_ent ( @ subnets )
{
my @ ents = split /:/ , $ net_ent ;
push @ nets , $ ents [ 0 ] . '/' . $ ents [ 2 ] . ' dev ' . $ ents [ 1 ] ;
}
}
else
{
@ nets = split /\n/ , `/sbin/ip route` ;
}
2009-04-17 16:35:54 +00:00
my $ nettab = xCAT::Table - > new ( "networks" ) ;
my @ vnets = $ nettab - > getAllAttribs ( 'net' , 'mgtifname' , 'mask' ) ;
foreach ( @ vnets ) {
if ( $ _ - > { mgtifname } eq '!remote!' ) { #global scoped network
my $ curm = unpack ( "N" , inet_aton ( $ _ - > { mask } ) ) ;
my $ bits = 32 ;
until ( $ curm & 1 ) {
$ bits - - ;
$ curm = $ curm >> 1 ;
}
2009-04-17 20:29:52 +00:00
push @ nets , $ _ - > { 'net' } . "/" . $ bits . " dev remote" ;
2009-04-17 16:35:54 +00:00
}
}
$ utildata - > { nodeonmynetdata } - > { pid } = $$ ;
2009-04-17 20:29:52 +00:00
$ utildata - > { nodeonmynetdata } - > { nets } = \ @ nets ;
}
2008-02-04 20:02:15 +00:00
foreach ( @ nets )
{
my @ elems = split /\s+/ ;
unless ( $ elems [ 1 ] =~ /dev/ )
{
next ;
}
( my $ curnet , my $ maskbits ) = split /\// , $ elems [ 0 ] ;
my $ curmask = 2 ** $ maskbits - 1 << ( 32 - $ maskbits ) ;
my $ curn = unpack ( "N" , inet_aton ( $ curnet ) ) ;
if ( ( $ noden & $ curmask ) == $ curn )
{
return 1 ;
}
}
return 0 ;
}
#-------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 thishostisnot
2008-02-18 15:10:31 +00:00
returns 0 if host is not the same
2008-02-04 20:02:15 +00:00
Arguments:
2008-04-05 14:53:35 +00:00
hostname
2008-02-04 20:02:15 +00:00
Returns:
Globals:
none
Error:
none
Example:
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub thishostisnot
{
my $ comparison = shift ;
if ( scalar ( @ _ ) )
{
$ comparison = shift ;
}
2009-07-07 02:07:30 +00:00
my @ ips ;
if ( $^O eq 'aix' )
{
@ ips = split /\n/ , `/usr/sbin/ifconfig -a` ;
}
else
{
@ ips = split /\n/ , `/sbin/ip addr` ;
}
2008-02-04 20:02:15 +00:00
my $ comp = inet_aton ( $ comparison ) ;
2009-02-04 17:18:44 +00:00
if ( $ comp )
{
foreach ( @ ips )
2008-02-04 20:02:15 +00:00
{
2009-02-04 17:18:44 +00:00
if ( /^\s*inet/ )
2008-02-04 20:02:15 +00:00
{
2009-02-04 17:18:44 +00:00
my @ ents = split ( /\s+/ ) ;
my $ ip = $ ents [ 2 ] ;
$ ip =~ s/\/.*// ;
if ( inet_aton ( $ ip ) eq $ comp )
{
return 0 ;
}
2008-02-04 20:02:15 +00:00
2009-02-04 17:18:44 +00:00
#print Dumper(inet_aton($ip));
}
2008-02-04 20:02:15 +00:00
}
}
return 1 ;
}
#-------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 GetMasterNodeName
2008-02-04 20:02:15 +00:00
Reads the database for the Master node name for the input node
Arguments:
Node
Returns:
2008-04-05 14:53:35 +00:00
MasterHostName
2008-02-04 20:02:15 +00:00
Globals:
none
Error:
none
Example:
2008-04-05 14:53:35 +00:00
$ master = ( xCAT::Utils - > GetMasterNodeName ( $ node ) )
2008-02-04 20:02:15 +00:00
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub GetMasterNodeName
{
my ( $ class , $ node ) = @ _ ;
my $ master ;
my $ noderestab = xCAT::Table - > new ( 'noderes' ) ;
my $ typetab = xCAT::Table - > new ( 'nodetype' ) ;
unless ( $ noderestab and $ typetab )
{
xCAT::MsgUtils - > message ( 'S' ,
"Unable to open noderes or nodetype table.\n" ) ;
return 1 ;
}
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
( my $ et ) = $ sitetab - > getAttribs ( { key = > "master" } , 'value' ) ;
if ( $ et and $ et - > { value } )
{
$ master = $ et - > { value } ;
}
$ et = $ noderestab - > getNodeAttribs ( $ node , [ 'xcatmaster' ] ) ;
if ( $ et and $ et - > { 'xcatmaster' } )
{
$ master = $ et - > { 'xcatmaster' } ;
}
unless ( $ master )
{
xCAT::MsgUtils - > message ( 'S' , "Unable to identify master for $node.\n" ) ;
2008-04-22 13:24:38 +00:00
$ sitetab - > close ;
$ noderestab - > close ;
$ typetab - > close ;
2008-02-04 20:02:15 +00:00
return 1 ;
}
2008-04-22 13:24:38 +00:00
$ sitetab - > close ;
$ noderestab - > close ;
$ typetab - > close ;
2008-02-04 20:02:15 +00:00
return $ master ;
2008-02-02 19:39:33 +00:00
}
2008-02-04 20:02:15 +00:00
#-------------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 GetNodeOSARCH
2008-02-04 20:02:15 +00:00
Reads the database for the OS and Arch of the input Node
Arguments:
Node
Returns:
$ et - > { 'os' }
$ et - > { 'arch' }
Globals:
none
Error:
none
Example:
2008-04-05 14:53:35 +00:00
$ master = ( xCAT::Utils - > GetNodeOSARCH ( $ node ) )
2008-02-04 20:02:15 +00:00
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub GetNodeOSARCH
{
my ( $ class , $ node ) = @ _ ;
my $ noderestab = xCAT::Table - > new ( 'noderes' ) ;
my $ typetab = xCAT::Table - > new ( 'nodetype' ) ;
unless ( $ noderestab and $ typetab )
{
xCAT::MsgUtils - > message ( 'S' ,
"Unable to open noderes or nodetype table.\n" ) ;
return 1 ;
2008-02-02 19:39:33 +00:00
}
2008-02-04 20:02:15 +00:00
my $ et = $ typetab - > getNodeAttribs ( $ node , [ 'os' , 'arch' ] ) ;
unless ( $ et and $ et - > { 'os' } and $ et - > { 'arch' } )
{
xCAT::MsgUtils - > message ( 'S' ,
"No os/arch setting in nodetype table for $node.\n" ) ;
return 1 ;
}
return $ et ;
2008-02-18 15:10:31 +00:00
}
#-----------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 exportDBConfig
2008-04-22 13:24:38 +00:00
Reads the /etc/xc at / cfgloc file for the DB configuration and exports it
2008-02-18 15:10:31 +00:00
in $ XCATCFG
= cut
#-----------------------------------------------------------------------------
sub exportDBConfig
{
# export the xcat database configuration
2008-04-22 13:24:38 +00:00
my $ configfile = "/etc/xcat/cfgloc" ;
2008-02-18 15:10:31 +00:00
if ( ! ( $ ENV { 'XCATCFG' } ) )
{
if ( - e ( $ configfile ) )
{
open ( CFGFILE , "<$configfile" )
or xCAT::MsgUtils - > message ( 'S' ,
"Cannot open $configfile for DB access. \n" ) ;
foreach my $ line ( <CFGFILE> )
{
2008-04-22 13:24:38 +00:00
chop $ line ;
2008-07-18 12:30:22 +00:00
my $ exp . = $ line ;
2008-04-22 13:24:38 +00:00
$ ENV { 'XCATCFG' } = $ exp ;
close CFGFILE ;
last ;
2008-02-18 15:10:31 +00:00
}
}
}
return 0 ;
}
#-----------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 readSNInfo
2008-02-18 15:10:31 +00:00
Read resource , NFS server , Master node , OS an ARCH from the database
for the service node
Input: service nodename
Output: Masternode , OS and ARCH
= cut
#-----------------------------------------------------------------------------
sub readSNInfo
{
my ( $ class , $ nodename ) = @ _ ;
my $ rc = 0 ;
my $ et ;
my $ masternode ;
my $ os ;
my $ arch ;
$ rc = xCAT::Utils - > exportDBConfig ( ) ;
if ( $ rc == 0 )
{
if ( $ nodename )
{
$ masternode = xCAT::Utils - > GetMasterNodeName ( $ nodename ) ;
if ( ! ( $ masternode ) )
{
xCAT::MsgUtils - > message ( 'S' ,
2008-02-25 13:03:17 +00:00
"Could not get Master for node $nodename\n" ) ;
2008-02-18 15:10:31 +00:00
return 1 ;
}
$ et = xCAT::Utils - > GetNodeOSARCH ( $ nodename ) ;
2009-02-04 17:18:44 +00:00
if ( $ et == 1 )
{
2008-11-21 12:44:39 +00:00
xCAT::MsgUtils - > message ( 'S' ,
"Could not get OS/ARCH for node $nodename\n" ) ;
return 1 ;
2009-02-04 17:18:44 +00:00
}
2008-02-18 15:10:31 +00:00
if ( ! ( $ et - > { 'os' } || $ et - > { 'arch' } ) )
{
xCAT::MsgUtils - > message ( 'S' ,
2008-02-25 13:03:17 +00:00
"Could not get OS/ARCH for node $nodename\n" ) ;
2008-02-18 15:10:31 +00:00
return 1 ;
}
}
$ et - > { 'master' } = $ masternode ;
return $ et ;
}
return $ rc ;
}
#-----------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 isServiceReq
2008-02-18 15:10:31 +00:00
2008-02-28 19:46:39 +00:00
2008-05-06 15:41:58 +00:00
Checks the service node table in the database to see
2009-03-02 14:27:10 +00:00
if input Service should be setup on the
2008-02-18 15:10:31 +00:00
input service node
2008-04-05 14:53:35 +00:00
2009-03-02 14:27:10 +00:00
Input:servicenodename , ipaddres ( s ) and hostnames of service node
2008-04-05 14:53:35 +00:00
Output:
2009-03-02 14:27:10 +00:00
array of services to setup for this service node
2008-02-18 15:10:31 +00:00
Globals:
2009-03-02 14:27:10 +00:00
$ ::RUNCMD_RC = 0 ; good
$ ::RUNCMD_RC = 1 ; error
2008-02-18 15:10:31 +00:00
Error:
none
Example:
2009-03-02 14:27:10 +00:00
@ servicestosetup = xCAT::Utils - > isServiceReq ( $ servicenodename , @ serviceip ) { blah ; }
2008-02-18 15:10:31 +00:00
= cut
#-----------------------------------------------------------------------------
sub isServiceReq
{
2009-03-02 14:27:10 +00:00
my ( $ class , $ servicenodename , $ serviceip ) = @ _ ;
# list of all services from service node table
# note this must be updated if more services added
my @ services = (
"nameserver" , "dhcpserver" , "tftpserver" , "nfsserver" ,
"conserver" , "monserver" , "ldapserver" , "ntpserver" ,
"ftpserver"
) ;
2008-04-22 13:24:38 +00:00
my @ ips = @$ serviceip ; # list of service node ip addresses and names
2008-03-26 18:20:05 +00:00
my $ rc = 0 ;
2008-03-06 18:42:32 +00:00
$ rc = xCAT::Utils - > exportDBConfig ( ) ; # export DB env
if ( $ rc != 0 )
2008-02-28 19:46:39 +00:00
{
2008-03-06 18:42:32 +00:00
xCAT::MsgUtils - > message ( 'S' , "Unable export DB environment.\n" ) ;
2009-03-02 14:27:10 +00:00
$ ::RUNCMD_RC = 1 ;
return ;
2008-03-06 18:42:32 +00:00
2008-02-29 14:06:01 +00:00
}
2008-02-28 19:46:39 +00:00
2008-05-06 15:41:58 +00:00
# get handle to servicenode table
my $ servicenodetab = xCAT::Table - > new ( 'servicenode' ) ;
unless ( $ servicenodetab )
2008-02-28 19:46:39 +00:00
{
2008-05-06 15:41:58 +00:00
xCAT::MsgUtils - > message ( 'S' , "Unable to open servicenode table.\n" ) ;
2009-03-02 14:27:10 +00:00
$ ::RUNCMD_RC = 1 ;
return ; # do not setup anything
2008-02-28 19:46:39 +00:00
}
2008-05-07 17:35:14 +00:00
2009-03-02 14:27:10 +00:00
my @ process_service_list = ( ) ;
# read all the nodes from the table, for each service
foreach my $ service ( @ services )
2008-02-28 19:46:39 +00:00
{
2009-03-02 14:27:10 +00:00
my @ snodelist = $ servicenodetab - > getAllNodeAttribs ( [ $ service ] ) ;
2008-05-07 17:35:14 +00:00
2009-03-02 14:27:10 +00:00
foreach $ serviceip ( @ ips ) # check the table for this servicenode
2008-02-18 19:00:29 +00:00
{
2009-03-02 14:27:10 +00:00
foreach my $ node ( @ snodelist )
{
if ( $ serviceip eq $ node - > { 'node' } )
{ # match table entry
if ( $ node - > { $ service } )
{ # returns service, only if set
my $ value = $ node - > { $ service } ;
$ value =~ tr /a-z/ A - Z / ; # convert to upper
# value 1 or yes then we setup the service
if ( ( $ value eq "1" ) || ( $ value eq "YES" ) )
{
push @ process_service_list ,
$ service ; # found service to setup
}
2008-05-13 12:36:13 +00:00
}
2008-05-07 17:35:14 +00:00
}
2008-02-18 19:00:29 +00:00
}
2008-02-26 19:57:10 +00:00
}
2008-02-18 15:10:31 +00:00
}
2009-03-02 14:27:10 +00:00
$ servicenodetab - > close ;
2008-02-18 15:10:31 +00:00
2009-03-02 14:27:10 +00:00
$ ::RUNCMD_RC = 0 ;
return @ process_service_list ;
2008-05-06 15:41:58 +00:00
2008-02-02 19:39:33 +00:00
}
2008-02-18 19:00:29 +00:00
2008-02-21 18:21:41 +00:00
#-----------------------------------------------------------------------------
2008-03-06 18:42:32 +00:00
= head3 determinehostname and ip address ( s )
2008-04-05 14:53:35 +00:00
2008-03-06 18:42:32 +00:00
Used on the service node to figure out what hostname and ip address ( s )
2008-04-22 13:24:38 +00:00
are valid names and addresses
2008-04-05 14:53:35 +00:00
Input: None
Output: ipaddress ( s ) , nodename
2008-02-21 18:21:41 +00:00
= cut
#-----------------------------------------------------------------------------
sub determinehostname
{
my $ hostname ;
my $ hostnamecmd = "/bin/hostname" ;
2008-03-06 18:42:32 +00:00
my @ thostname = xCAT::Utils - > runcmd ( $ hostnamecmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
2008-02-21 18:21:41 +00:00
{ # could not get hostname
2008-03-06 18:42:32 +00:00
xCAT::MsgUtils - > message ( "S" ,
"Error $::RUNCMD_RC from $hostnamecmd command\n" ) ;
exit $ ::RUNCMD_RC ;
2008-02-21 18:21:41 +00:00
}
$ hostname = $ thostname [ 0 ] ;
2008-03-06 18:42:32 +00:00
2009-07-29 17:43:04 +00:00
#get all potentially valid abbreviations, and pick the one that is ok
#by 'noderange'
my @ hostnamecandidates ;
my $ nodename ;
while ( $ hostname =~ /\./ ) {
push @ hostnamecandidates , $ hostname ;
$ hostname =~ s/\.[^\.]*// ;
}
push @ hostnamecandidates , $ hostname ;
my $ checkhostnames = join ( ',' , @ hostnamecandidates ) ;
my @ validnodenames = xCAT::NodeRange:: noderange ( $ checkhostnames ) ;
unless ( scalar @ validnodenames ) { #If the node in question is not in table, take output literrally.
push @ validnodenames , $ hostnamecandidates [ 0 ] ;
}
#now, noderange doesn't guarantee the order, so we search the preference order, most to least specific.
foreach ( @ hostnamecandidates ) {
if ( grep /^$_$/ , @ validnodenames ) {
$ nodename = $ _ ;
last ;
}
}
2008-03-06 18:42:32 +00:00
my @ ips = xCAT::Utils - > gethost_ips ;
2009-07-29 17:43:04 +00:00
my @ hostinfo = ( @ ips , $ nodename ) ;
2008-03-06 18:42:32 +00:00
2008-02-21 18:21:41 +00:00
return @ hostinfo ;
}
2008-02-25 13:03:17 +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
2008-04-05 14:53:35 +00:00
Input: service ( e . g . tftp , nfs , etc )
2008-02-25 13:03:17 +00:00
Output: 0 = added , 1 = already there
= cut
#-----------------------------------------------------------------------------
sub update_xCATSN
{
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
{
$ rc = 1 ;
}
return $ rc ;
}
2008-03-06 18:42:32 +00:00
#-----------------------------------------------------------------------------
2009-03-02 14:27:10 +00:00
= head3 gethost_ips ( AIX and Linux )
2008-04-05 14:53:35 +00:00
Will use ifconfig to determine all possible ip addresses for the
2008-04-22 13:24:38 +00:00
host it is running on and then gethostbyaddr to get all possible hostnames
2008-03-06 18:42:32 +00:00
2008-04-05 14:53:35 +00:00
input:
2008-04-22 13:24:38 +00:00
output: array of ipaddress ( s ) and hostnames
2008-03-06 18:42:32 +00:00
example: @ ips = xCAT:: gethost_ips ( ) ;
= cut
#-----------------------------------------------------------------------------
sub gethost_ips
{
my ( $ class ) = @ _ ;
my $ cmd ;
my @ ipaddress ;
$ cmd = "ifconfig" . " -a" ;
$ cmd = $ cmd . "| grep \"inet \"" ;
my @ result = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( "S" , "Error from $cmd\n" ) ;
exit $ ::RUNCMD_RC ;
}
foreach my $ addr ( @ result )
{
2009-03-02 14:27:10 +00:00
my @ ip ;
if ( xCAT::Utils - > isLinux ( ) )
{
my ( $ inet , $ addr1 , $ Bcast , $ Mask ) = split ( " " , $ addr ) ;
@ ip = split ( ":" , $ addr1 ) ;
push @ ipaddress , $ ip [ 1 ] ;
}
else
{ #AIX
my ( $ inet , $ addr1 , $ netmask , $ mask1 , $ Bcast , $ bcastaddr ) =
split ( " " , $ addr ) ;
push @ ipaddress , $ addr1 ;
}
2008-03-06 18:42:32 +00:00
}
2008-04-22 13:24:38 +00:00
my @ names = @ ipaddress ;
foreach my $ ipaddr ( @ names )
{
my $ packedaddr = inet_aton ( $ ipaddr ) ;
my $ hostname = gethostbyaddr ( $ packedaddr , AF_INET ) ;
if ( $ hostname )
{
my @ shorthost = split ( /\./ , $ hostname ) ;
push @ ipaddress , $ shorthost [ 0 ] ;
}
}
2008-03-06 18:42:32 +00:00
return @ ipaddress ;
}
2008-03-26 18:20:05 +00:00
2008-03-12 19:16:44 +00:00
#-----------------------------------------------------------------------------
= head3 create_postscripts_tar
2008-04-05 14:53:35 +00:00
2008-03-12 19:16:44 +00:00
This routine will tar and compress the /install/ postscripts directory
and place in /install/ autoinst / xcat_postscripts . Z
2008-04-05 14:53:35 +00:00
input: none
output:
2008-03-12 19:16:44 +00:00
example: $ rc = xCAT:: create_postscripts_tar ( ) ;
= cut
#-----------------------------------------------------------------------------
2008-03-26 18:20:05 +00:00
sub create_postscripts_tar
2008-03-12 19:16:44 +00:00
{
my ( $ class ) = @ _ ;
my $ cmd ;
2008-03-26 18:20:05 +00:00
if ( ! ( - e "/install/autoinst" ) )
{
mkdir ( "/install/autoinst" ) ;
2008-03-19 21:09:38 +00:00
}
2008-04-22 13:24:38 +00:00
$ cmd =
2008-05-01 13:10:57 +00:00
"cd /install/postscripts; tar -cf /install/autoinst/xcatpost.tar * .ssh/* _xcat/*; gzip -f /install/autoinst/xcatpost.tar" ;
2008-03-12 19:16:44 +00:00
my @ result = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( "S" , "Error from $cmd\n" ) ;
2008-03-26 18:20:05 +00:00
return $ ::RUNCMD_RC ;
2008-03-12 19:16:44 +00:00
}
2008-03-06 18:42:32 +00:00
2008-05-06 17:22:15 +00:00
# for AIX add an entry to the /etc/tftpaccess.ctrl file so
# we can tftp the tar file from the node
if ( xCAT::Utils - > isAIX ( ) )
{
my $ tftpctlfile = "/etc/tftpaccess.ctl" ;
my $ entry = "allow:/install/autoinst/xcatpost.tar.gz" ;
2008-05-03 13:01:21 +00:00
2008-05-06 17:22:15 +00:00
# see if there is already an entry
my $ cmd = "cat $tftpctlfile | grep xcatpost" ;
my @ result = xCAT::Utils - > runcmd ( "$cmd" , - 1 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
2008-05-03 13:01:21 +00:00
2008-05-06 17:22:15 +00:00
# not found so add it
unless ( open ( TFTPFILE , ">>$tftpctlfile" ) )
{
xCAT::MsgUtils - > message ( "S" , "Could not open $tftpctlfile.\n" ) ;
return $ ::RUNCMD_RC ;
}
2008-05-03 13:01:21 +00:00
2008-05-06 17:22:15 +00:00
print TFTPFILE $ entry ;
2008-05-03 13:01:21 +00:00
2008-05-06 17:22:15 +00:00
close ( TFTPFILE ) ;
}
}
2008-05-03 13:01:21 +00:00
return 0 ;
2008-03-12 19:16:44 +00:00
}
2008-03-26 18:20:05 +00:00
#-----------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 get_site_Master
2008-03-26 18:20:05 +00:00
Reads the site table for the Master attribute and returns it .
input: none
output : value of site . Master attribute , blank is an error
example: $ Master = xCAT:: get_site_Master ( ) ;
= cut
#-----------------------------------------------------------------------------
sub get_site_Master
{
my $ Master ;
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
( my $ et ) = $ sitetab - > getAttribs ( { key = > "master" } , 'value' ) ;
if ( $ et and $ et - > { value } )
{
$ Master = $ et - > { value } ;
}
else
{
xCAT::MsgUtils - > message ( 'E' ,
"Unable to read site table for Master attribute.\n" ) ;
}
return $ Master ;
}
#-----------------------------------------------------------------------------
2008-04-05 14:53:35 +00:00
= head3 get_ServiceNode
2008-03-26 18:20:05 +00:00
Will get the Service node ( name or ipaddress ) as known by the Management
2008-04-23 18:14:57 +00:00
Server or Node for the input nodename or ipadress of the node
2008-03-26 18:20:05 +00:00
2008-04-15 14:37:26 +00:00
input: list of nodenames and / or node ipaddresses ( array ref )
2008-04-05 14:53:35 +00:00
service name
2008-03-31 15:52:36 +00:00
"MN" or "Node" determines if you want the Service node as known
by the Management Node or by the node .
2008-03-26 18:20:05 +00:00
recognized service names: xcat , tftpserver ,
nfsserver , conserver , monserver
service "xcat" is used by command like xdsh that need to know the
2008-04-05 14:53:35 +00:00
service node that will process the command but are not tied to a
2008-03-26 18:20:05 +00:00
specific service like tftp
Todo: Handle dhcpserver and nameserver from the networks table
2008-04-24 17:28:35 +00:00
output: A hash ref of arrays , the key is the service node pointing to
2008-04-05 14:53:35 +00:00
an array of nodes that are serviced by that service node
2008-03-26 18:20:05 +00:00
Globals:
2008-04-05 14:53:35 +00:00
$ ::ERROR_RC
2008-03-26 18:20:05 +00:00
Error:
2008-04-05 14:53:35 +00:00
$ ::ERROR_RC = 0 no error $ ::ERROR_RC = 1 error
2008-03-26 18:20:05 +00:00
2008-04-15 14:37:26 +00:00
example: $ sn = xCAT::Utils - > get_ServiceNode ( \ @ nodes , $ service , "MN" ) ;
2009-03-03 19:39:17 +00:00
$ sn = xCAT::Utils - > get_ServiceNode ( \ @ nodes , $ service , "Node" ) ;
2008-03-26 18:20:05 +00:00
= cut
#-----------------------------------------------------------------------------
2008-03-31 15:19:42 +00:00
sub get_ServiceNode
2008-03-26 18:20:05 +00:00
{
my ( $ class , $ node , $ service , $ request ) = @ _ ;
my @ node_list = @$ node ;
my $ cmd ;
my % snhash ;
2009-03-03 19:39:17 +00:00
my $ nodehash ;
2008-03-26 18:20:05 +00:00
my $ sn ;
my $ nodehmtab ;
my $ noderestab ;
my $ snattribute ;
$ ::ERROR_RC = 0 ;
2008-03-31 15:52:36 +00:00
# determine if the request is for the service node as known by the MN
2008-03-27 12:35:01 +00:00
# or the node
2008-03-26 18:20:05 +00:00
2008-03-31 15:52:36 +00:00
if ( $ request eq "MN" )
2008-03-27 12:35:01 +00:00
{
2008-03-26 18:20:05 +00:00
$ snattribute = "servicenode" ;
}
2008-03-27 12:35:01 +00:00
else # Node
{
2008-03-26 18:20:05 +00:00
$ snattribute = "xcatmaster" ;
}
my $ master =
xCAT::Utils - > get_site_Master ( ) ; # read the site table, master attrib
$ noderestab = xCAT::Table - > new ( 'noderes' ) ;
unless ( $ noderestab ) # no noderes table, use default site.master
{
xCAT::MsgUtils - > message ( 'I' ,
"Unable to open noderes table. Using site->Master.\n" ) ;
if ( $ master ) # use site Master value
{
foreach my $ node ( @ node_list )
{ # no noderes table, all use site Master
push @ { $ snhash { $ master } } , $ node ;
}
}
else
{
xCAT::MsgUtils - > message ( 'E' , "Unable to read site Master value.\n" ) ;
$ ::ERROR_RC = 1 ;
}
return \ % snhash ;
}
if ( $ service eq "xcat" )
2008-03-27 12:35:01 +00:00
{ # find all service nodes for the nodes in the list
2009-03-03 19:39:17 +00:00
$ nodehash = $ noderestab - > getNodesAttribs ( \ @ node_list , [ $ snattribute ] ) ;
2008-03-26 18:20:05 +00:00
foreach my $ node ( @ node_list )
{
2009-03-03 19:39:17 +00:00
foreach my $ rec ( @ { $ nodehash - > { $ node } } )
{
if ( $ rec and $ rec - > { $ snattribute } )
{
my $ key = $ rec - > { $ snattribute } ;
push @ { $ snhash { $ key } } , $ node ;
}
else
{ # use site.master
push @ { $ snhash { $ master } } , $ node ;
}
2008-03-26 18:20:05 +00:00
}
}
2009-03-03 19:39:17 +00:00
2008-04-22 13:24:38 +00:00
$ noderestab - > close ;
2008-03-26 18:20:05 +00:00
return \ % snhash ;
}
else
{
if (
( $ service eq "tftpserver" ) # all from noderes table
|| ( $ service eq "nfsserver" ) || ( $ service eq "monserver" )
)
{
2009-03-03 19:39:17 +00:00
$ nodehash =
$ noderestab - > getNodesAttribs ( \ @ node_list ,
[ $ service , $ snattribute ] ) ;
2008-03-26 18:20:05 +00:00
foreach my $ node ( @ node_list )
{
2009-03-03 19:39:17 +00:00
foreach my $ rec ( @ { $ nodehash - > { $ node } } )
2008-03-26 18:20:05 +00:00
{
2009-03-03 19:39:17 +00:00
if ( $ rec and $ rec - > { $ service } )
2008-03-27 12:35:01 +00:00
{
2009-03-03 19:39:17 +00:00
# see if both MN and Node address in attribute
2009-03-09 17:37:21 +00:00
my ( $ msattr , $ nodeattr ) = split ':' , $ rec - > { $ service } ;
2009-03-03 19:39:17 +00:00
my $ key = $ msattr ;
if ( $ request eq "Node" )
2008-03-27 12:35:01 +00:00
{
2009-03-03 19:39:17 +00:00
if ( $ nodeattr ) # override with Node, if it exists
{
$ key = $ nodeattr ;
}
2008-03-27 12:35:01 +00:00
}
2008-03-26 18:20:05 +00:00
push @ { $ snhash { $ key } } , $ node ;
}
else
2009-03-03 19:39:17 +00:00
{
if ( $ rec and $ rec - > { $ snattribute } ) # if it exists
{
my $ key = $ rec - > { $ snattribute } ;
push @ { $ snhash { $ key } } , $ node ;
}
else
{ # use site.master
push @ { $ snhash { $ master } } , $ node ;
}
2008-03-26 18:20:05 +00:00
}
}
}
2009-03-03 19:39:17 +00:00
2008-04-22 13:24:38 +00:00
$ noderestab - > close ;
2008-03-26 18:20:05 +00:00
return \ % snhash ;
}
else
{
if ( $ service eq "conserver" )
{
2009-03-03 19:39:17 +00:00
# read the nodehm table
2008-03-26 18:20:05 +00:00
$ nodehmtab = xCAT::Table - > new ( 'nodehm' ) ;
2009-03-03 19:39:17 +00:00
unless ( $ nodehmtab ) # no nodehm table
2008-03-26 18:20:05 +00:00
{
xCAT::MsgUtils - > message ( 'I' ,
"Unable to open nodehm table.\n" ) ;
2009-03-03 19:39:17 +00:00
# use servicenode
$ nodehash =
$ noderestab - > getNodesAttribs ( \ @ node_list , [ $ snattribute ] ) ;
2008-03-26 18:20:05 +00:00
foreach my $ node ( @ node_list )
{
2009-03-03 19:39:17 +00:00
foreach my $ rec ( @ { $ nodehash - > { $ node } } )
2008-03-26 18:20:05 +00:00
{
2009-03-03 19:39:17 +00:00
if ( $ rec and $ rec - > { $ snattribute } )
{
my $ key = $ rec - > { $ snattribute } ;
push @ { $ snhash { $ key } } , $ node ;
}
else
{ # use site.master
push @ { $ snhash { $ master } } , $ node ;
}
2008-03-26 18:20:05 +00:00
}
}
2009-03-03 19:39:17 +00:00
$ noderestab - > close ;
2008-03-26 18:20:05 +00:00
return \ % snhash ;
}
2008-03-27 12:35:01 +00:00
# can read the nodehm table
2009-03-03 19:39:17 +00:00
$ nodehash =
$ nodehmtab - > getNodesAttribs ( \ @ node_list , [ 'conserver' ] ) ;
2008-03-26 18:20:05 +00:00
foreach my $ node ( @ node_list )
{
2009-03-03 19:39:17 +00:00
foreach my $ rec ( @ { $ nodehash - > { $ node } } )
2008-03-26 18:20:05 +00:00
{
2009-03-03 19:39:17 +00:00
if ( $ rec and $ rec - > { 'conserver' } )
2008-03-27 12:35:01 +00:00
{
2009-03-03 19:39:17 +00:00
# see if both MN and Node address in attribute
2009-03-09 17:37:21 +00:00
my ( $ msattr , $ nodeattr ) = split ':' ,
2009-03-03 19:39:17 +00:00
$ rec - > { 'conserver' } ;
my $ key = $ msattr ;
if ( $ request eq "Node" )
2008-03-27 12:35:01 +00:00
{
2009-03-03 19:39:17 +00:00
if ( $ nodeattr
) # override with Node, if it exists
{
$ key = $ nodeattr ;
}
2008-03-27 12:35:01 +00:00
}
2008-03-26 18:20:05 +00:00
push @ { $ snhash { $ key } } , $ node ;
}
else
2009-03-03 19:39:17 +00:00
{ # use service node for this node
$ sn =
$ noderestab - > getNodeAttribs ( $ node ,
[ $ snattribute ] ) ;
if ( $ sn and $ sn - > { $ snattribute } )
{
my $ key = $ sn - > { $ snattribute } ;
push @ { $ snhash { $ key } } , $ node ;
}
else
{ # no service node use master
push @ { $ snhash { $ master } } , $ node ;
}
2008-03-26 18:20:05 +00:00
}
}
}
2008-04-22 13:24:38 +00:00
$ noderestab - > close ;
$ nodehmtab - > close ;
2008-03-26 18:20:05 +00:00
return \ % snhash ;
}
else
{
xCAT::MsgUtils - > message ( 'E' ,
"Invalid service=$service input.\n" ) ;
$ ::ERROR_RC = 1 ;
}
}
}
return \ % snhash ;
}
2008-04-23 18:14:57 +00:00
#-----------------------------------------------------------------------------
2009-08-05 11:53:05 +00:00
= head3 getSNformattedhash
Will call get_ServiceNode to get the Service node ( name or ipaddress )
as known by the Management
Server or Node for the input nodename or ipadress of the node
It will then format the output into a single servicenode key with values
the list of nodes service by that service node . This routine will
break up pools of service nodes into individual node in the hash unlike
get_ServiceNode which leaves the pool as the key .
input: Same as get_ServiceNode to call get_ServiceNode
list of nodenames and / or node ipaddresses ( array ref )
service name
"MN" or "Node" determines if you want the Service node as known
by the Management Node or by the node .
recognized service names: xcat , tftpserver ,
nfsserver , conserver , monserver
service "xcat" is used by command like xdsh that need to know the
service node that will process the command but are not tied to a
specific service like tftp
output: A hash ref of arrays , the key is a single service node
pointing to
a list of nodes that are serviced by that service node
'rra000-m' = > [ 'blade01' , 'testnode' ]
'sn1' = > [ 'blade01' , 'testnode' ]
'sn2' = > [ 'blade01' ]
'sn3' = > [ 'testnode' ]
Globals:
$ ::ERROR_RC
Error:
$ ::ERROR_RC = 0 no error $ ::ERROR_RC = 1 error
example: $ sn = xCAT::Utils - > getSNformattedhash ( \ @ nodes , $ service , "MN" ) ;
$ sn = xCAT::Utils - > getSNformattedhash ( \ @ nodes , $ service , "Node" ) ;
= cut
#-----------------------------------------------------------------------------
sub getSNformattedhash
{
my ( $ class , $ node , $ service , $ request ) = @ _ ;
my @ node_list = @$ node ;
my $ cmd ;
my % newsnhash ;
my $ sn = xCAT::Utils - > get_ServiceNode ( \ @ node_list , $ service , $ request ) ;
# get the keys which are the service nodes and break apart any pool lists
# format into individual service node keys pointing to node lists
if ( $ sn )
{
foreach my $ snkey ( keys %$ sn )
{
# split the key if pool of service nodes
#push my @nodes, $sn->{$snkey}->[0];
push my @ tmpnodes , $ sn - > { $ snkey } ;
my @ nodes ;
for my $ i ( 0 .. $# tmpnodes ) {
for my $ j ( 0 .. $# { $ tmpnodes [ $ i ] } ) {
my $ check = $ tmpnodes [ $ i ] [ $ j ] ;
push @ nodes , $ check ;
}
}
my @ servicenodes = split /,/ , $ snkey ;
# now build new hash of individual service nodes
foreach my $ newsnkey ( @ servicenodes ) {
push @ { $ newsnhash { $ newsnkey } } , @ nodes ;
}
}
}
return \ % newsnhash ;
}
#-----------------------------------------------------------------------------
2008-04-23 18:14:57 +00:00
= head3 toIP
IPv4 function to convert hostname to IP address
= cut
#-----------------------------------------------------------------------------
2008-04-22 13:24:38 +00:00
sub toIP
{
2009-02-04 17:18:44 +00:00
2008-07-18 13:44:38 +00:00
# does not support IPV6 IPV6TODO
2008-04-22 13:24:38 +00:00
if ( $ _ [ 0 ] =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/ )
{
return ( [ 0 , $ _ [ 0 ] ] ) ;
}
2009-04-07 10:03:58 +00:00
$! = undef ;
2008-04-22 13:24:38 +00:00
my $ packed_ip = gethostbyname ( $ _ [ 0 ] ) ;
if ( ! $ packed_ip or $! )
{
return ( [ 1 , "Cannot Resolve: $_[0]\n" ] ) ;
}
return ( [ 0 , inet_ntoa ( $ packed_ip ) ] ) ;
}
2008-04-02 19:39:39 +00:00
2008-04-23 18:14:57 +00:00
#-----------------------------------------------------------------------------
= head3 isSN
Determines if the input node name is a service node
2008-05-06 15:41:58 +00:00
Reads the servicenode table . nodename must be service node name as
known by the Management node .
2008-04-23 18:14:57 +00:00
returns 1 if input host is a service node
Arguments:
hostname
Returns:
1 - is Service Node
0 - is not a Service Node
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > isSN ( $ nodename ) ) { blah ; }
Comments:
none
= cut
#-----------------------------------------------------------------------------
sub isSN
{
my ( $ class , $ node ) = @ _ ;
2008-05-06 15:41:58 +00:00
# reads all nodes from the service node table
my @ servicenodes ;
my $ servicenodetab = xCAT::Table - > new ( 'servicenode' ) ;
unless ( $ servicenodetab ) # no servicenode table
{
xCAT::MsgUtils - > message ( 'I' , "Unable to open servicenode table.\n" ) ;
return 0 ;
}
2008-07-18 12:30:22 +00:00
my @ nodes = $ servicenodetab - > getAllNodeAttribs ( [ 'tftpserver' ] ) ;
2008-05-06 15:41:58 +00:00
$ servicenodetab - > close ;
foreach my $ nodes ( @ nodes )
2008-04-23 18:14:57 +00:00
{
2008-05-06 15:41:58 +00:00
if ( $ node eq $ nodes - > { node } )
2008-04-23 18:14:57 +00:00
{
2008-05-07 17:35:14 +00:00
return 1 ; # match
2008-04-23 18:14:57 +00:00
}
}
2008-05-06 15:41:58 +00:00
2008-04-23 18:14:57 +00:00
return 0 ;
}
2008-04-23 19:11:16 +00:00
#-----------------------------------------------------------------------------
2008-04-24 17:28:35 +00:00
= head3 getAllSN
2008-04-23 19:11:16 +00:00
2008-05-06 15:41:58 +00:00
Returns an array of all service nodes from service node table
2008-04-23 19:11:16 +00:00
Arguments:
none
Returns:
array of Service Nodes or empty array , if none
Globals:
none
Error:
1 - error
Example:
@ allSN = xCAT::Utils - > get_AllSN
Comments:
none
= cut
#-----------------------------------------------------------------------------
2008-04-24 17:28:35 +00:00
sub getAllSN
2008-04-23 19:11:16 +00:00
{
2008-05-06 15:41:58 +00:00
# reads all nodes from the service node table
2008-04-23 19:11:16 +00:00
my @ servicenodes ;
2008-05-06 15:41:58 +00:00
my $ servicenodetab = xCAT::Table - > new ( 'servicenode' ) ;
2008-05-07 17:35:14 +00:00
unless ( $ servicenodetab ) # no servicenode table
2008-04-23 19:11:16 +00:00
{
2008-05-07 17:35:14 +00:00
xCAT::MsgUtils - > message ( 'I' , "Unable to open servicenode table.\n" ) ;
$ servicenodetab - > close ;
return @ servicenodes ;
}
my @ nodes = $ servicenodetab - > getAllNodeAttribs ( [ 'tftpserver' ] ) ;
foreach my $ nodes ( @ nodes )
{
push @ servicenodes , $ nodes - > { node } ;
2008-04-23 19:11:16 +00:00
}
2008-05-06 15:41:58 +00:00
$ servicenodetab - > close ;
2008-04-23 19:11:16 +00:00
return @ servicenodes ;
}
2008-04-24 17:28:35 +00:00
#-----------------------------------------------------------------------------
2008-05-06 15:41:58 +00:00
= head3 getSNandNodes
Returns an hash - array of all service nodes and the nodes they service
Arguments:
none
#-----------------------------------------------------------------------------
2008-04-24 17:28:35 +00:00
= head3 getSNandNodes
Returns an hash - array of all service nodes and the nodes they service
Arguments:
none
Returns:
Service Nodes and the nodes they service or empty , if none
Globals:
none
Error:
1 - error
Example:
$ sn = xCAT::Utils - > getSNandNodes ( )
Comments:
none
= cut
#-----------------------------------------------------------------------------
sub getSNandNodes
{
# read all the nodes from the nodelist table
# call get_ServiceNode to find which Service Node
# the node belongs to.
my % sn ;
my @ nodes ;
my $ nodelisttab = xCAT::Table - > new ( 'nodelist' ) ;
my $ recs = $ nodelisttab - > getAllEntries ( ) ;
foreach ( @$ recs )
{
push @ nodes , $ _ - > { node } ;
}
$ nodelisttab - > close ;
2008-07-18 12:30:22 +00:00
my $ sn = xCAT::Utils - > get_ServiceNode ( \ @ nodes , "xcat" , "MN" ) ;
2008-04-24 17:28:35 +00:00
return $ sn ;
}
2008-05-06 17:22:15 +00:00
#-----------------------------------------------------------------------------
= head3 getSNList
2008-05-07 17:35:14 +00:00
Reads the servicenode table . Will return all the enabled Service Nodes
2008-05-06 17:22:15 +00:00
that will setup the input Service ( e . g tftpserver , nameserver , etc )
If service is blank , then will return the list of all enabled Service
Nodes .
Arguments:
Servicename ( xcat , tftpserver , dhcpserver , conserver , etc )
Returns:
Array of service node names
Globals:
none
Error:
1 - error
Example:
$ sn = xCAT::Utils - > getSNList ( $ servicename ) { blah ; }
$ sn = xCAT::Utils - > getSNList ( ) { blah ; }
Comments:
none
= cut
#-----------------------------------------------------------------------------
sub getSNList
{
my ( $ class , $ service ) = @ _ ;
# reads all nodes from the service node table
my @ servicenodes ;
2009-02-04 17:18:44 +00:00
my $ servicenodetab = xCAT::Table - > new ( 'servicenode' , - create = > 1 ) ;
2008-05-06 17:22:15 +00:00
unless ( $ servicenodetab ) # no servicenode table
{
xCAT::MsgUtils - > message ( 'I' , "Unable to open servicenode table.\n" ) ;
2008-05-20 17:56:53 +00:00
return ( ) ;
2008-05-06 17:22:15 +00:00
}
2008-05-07 17:35:14 +00:00
my @ nodes = $ servicenodetab - > getAllNodeAttribs ( [ $ service ] ) ;
2008-05-06 17:22:15 +00:00
$ servicenodetab - > close ;
foreach my $ node ( @ nodes )
{
2008-05-07 17:35:14 +00:00
if ( $ service eq "" ) # want all the service nodes
2008-05-06 17:22:15 +00:00
{
push @ servicenodes , $ node - > { node } ;
}
else
2008-05-07 17:35:14 +00:00
{ # looking for a particular service
if ( $ node - > { $ service } )
{ # if null then do not add node
my $ value = $ node - > { $ service } ;
$ value =~ tr /a-z/ A - Z / ; # convert to upper
# value 1 or yes or blank then we setup the service
if ( ( $ value == 1 ) || ( $ value eq "YES" ) )
{
push @ servicenodes , $ node - > { node } ;
2008-05-06 17:22:15 +00:00
2008-05-07 17:35:14 +00:00
}
2008-05-06 17:22:15 +00:00
}
}
}
return @ servicenodes ;
}
2008-05-13 12:36:13 +00:00
2008-05-12 19:49:41 +00:00
#-------------------------------------------------------------------------------
2009-04-28 09:10:19 +00:00
= head3 validate_ip
Validate list of IPs
Arguments:
List of IPs
Returns:
1 - Invalid IP address in the list
0 - IP addresses are all valid
Globals:
none
Error:
none
Example:
if ( xCAT::Utils - > validate_ip ( $ IP ) ) { }
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub validate_ip
{
my ( $ class , @ IPs ) = @ _ ;
foreach ( @ IPs ) {
my $ ip = $ _ ;
###################################
# Length is 4 for IPv4 addresses
###################################
my ( @ octets ) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ ;
if ( scalar ( @ octets ) != 4 ) {
return ( [ 1 , "Invalid IP address1: $ip" ] ) ;
}
foreach my $ octet ( @ octets ) {
if ( ( $ octet < 0 ) or ( $ octet > 255 ) ) {
return ( [ 1 , "Invalid IP address2: $ip" ] ) ;
}
}
}
return ( [ 0 ] ) ;
}
#-------------------------------------------------------------------------------
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 ; }
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub isMounted
{
my ( $ class , $ directory ) = @ _ ;
2008-07-18 12:30:22 +00:00
my $ cmd = "df -P $directory" ;
2008-05-12 19:49:41 +00:00
my @ output = xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
foreach my $ line ( @ output )
{
my ( $ file_sys , $ blocks , $ used , $ avail , $ cap , $ mount_point ) =
split ( ' ' , $ line ) ;
if ( $ mount_point eq $ directory )
{
return 1 ;
}
}
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
#-------------------------------------------------------------------------------
= head3 logEventsToDatabase
Logs the given events info to the xCAT 's ' eventlog ' database
Arguments:
arrayref - - A pointer to an array . Each element is a hash that contains an events .
The hash should contain the at least one of the following keys :
eventtime - - The format is "mm-dd-yyyy hh:mm:ss" .
If omitted , the current date and time will be used .
monitor - - The name of the monitor that monitors this event .
monnode - - The node that monitors this event .
node - - The node where the event occurred .
application - - The application that reports the event .
component - - The component where the event occurred .
id - - The location or the resource name where the event occurred .
severity - - The severity of the event . Valid values are: informational , warning , critical .
message - - The full description of the event .
rawdata - - The data that associated with the event .
Returns:
( ret code , error message )
2009-01-29 02:41:02 +00:00
Example:
my @ a = ( ) ;
my $ event = {
eventtime = > "07-28-2009 23:02:03" ,
node = > 'node1' ,
rawdata = > 'kjdlkfajlfjdlksaj' ,
} ;
push ( @ a , $ event ) ;
my $ event1 = {
node = > 'cu03cp' ,
monnode = > 'cu03sv' ,
application = > 'RMC' ,
component = > 'IBM.Sensor' ,
id = > 'AIXErrorLogSensor' ,
severity = > 'warning' ,
} ;
push ( @ a , $ event1 ) ;
xCAT::Utils - > logEventsToDatabase ( \ @ a ) ;
2009-01-28 18:49:02 +00:00
= cut
#-------------------------------------------------------------------------------
2009-02-04 17:18:44 +00:00
sub logEventsToDatabase
{
my $ pEvents = shift ;
if ( ( $ pEvents ) && ( $ pEvents =~ /xCAT::Utils/ ) )
{
$ pEvents = shift ;
}
2009-02-03 17:13:20 +00:00
2009-02-04 17:18:44 +00:00
if ( ( $ pEvents ) && ( @$ pEvents > 0 ) )
{
my $ currtime ;
my $ tab = xCAT::Table - > new ( "eventlog" , - create = > 1 , - autocommit = > 0 ) ;
if ( ! $ tab )
{
return ( 1 , "The evnetlog table cannot be opened." ) ;
}
2009-02-03 17:13:20 +00:00
2009-02-04 17:18:44 +00:00
foreach my $ event ( @$ pEvents )
{
2009-02-03 17:13:20 +00:00
2009-02-04 17:18:44 +00:00
#create event time if it does not exist
if ( ! exists ( $ event - > { eventtime } ) )
{
if ( ! $ currtime )
{
my (
$ sec , $ min , $ hour , $ mday , $ mon ,
$ year , $ wday , $ yday , $ isdst
)
= localtime ( time ) ;
$ currtime = sprintf ( "%02d-%02d-%04d %02d:%02d:%02d" ,
$ mon + 1 , $ mday , $ year + 1900 ,
$ hour , $ min , $ sec ) ;
}
$ event - > { eventtime } = $ currtime ;
}
my @ ret = $ tab - > setAttribs ( undef , $ event ) ;
if ( @ ret > 1 ) { return ( 1 , $ ret [ 1 ] ) ; }
}
$ tab - > commit ;
}
2009-02-03 17:13:20 +00:00
2009-02-04 17:18:44 +00:00
return ( 0 , "" ) ;
2009-02-03 17:13:20 +00:00
}
2009-02-28 17:05:34 +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
#-------------------------------------------------------------------------------
= head3 getFacingIP
Gets the ip address of the adapter of the localhost that is facing the
the given node .
Arguments:
The name of the node that is facing the localhost .
Returns:
The ip address of the adapter that faces the node .
= cut
#-------------------------------------------------------------------------------
2009-03-16 12:50:22 +00:00
sub getFacingIP
{
2009-03-11 17:22:43 +00:00
my ( $ class , $ node ) = @ _ ;
my $ ip ;
my $ cmd ;
my @ ipaddress ;
my $ nodeip = inet_ntoa ( inet_aton ( $ node ) ) ;
unless ( $ nodeip =~ /\d+\.\d+\.\d+\.\d+/ )
{
return 0 ; #Not supporting IPv6 here IPV6TODO
}
$ cmd = "ifconfig" . " -a" ;
$ cmd = $ cmd . "| grep \"inet \"" ;
my @ result = xCAT::Utils - > runcmd ( $ cmd , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
xCAT::MsgUtils - > message ( "S" , "Error from $cmd\n" ) ;
exit $ ::RUNCMD_RC ;
}
2009-03-16 12:50:22 +00:00
2009-03-11 17:22:43 +00:00
# split node address
my ( $ n1 , $ n2 , $ n3 , $ n4 ) = split ( '\.' , $ nodeip ) ;
foreach my $ addr ( @ result )
{
my $ ip ;
my $ mask ;
if ( xCAT::Utils - > isLinux ( ) )
{
my ( $ inet , $ addr1 , $ Bcast , $ Mask ) = split ( " " , $ addr ) ;
2009-03-16 12:50:22 +00:00
if ( ( ! $ addr1 ) || ( ! $ Mask ) ) { next ; }
my @ ips = split ( ":" , $ addr1 ) ;
my @ masks = split ( ":" , $ Mask ) ;
$ ip = $ ips [ 1 ] ;
$ mask = $ masks [ 1 ] ;
2009-03-11 17:22:43 +00:00
}
else
{ #AIX
2009-03-16 12:50:22 +00:00
my ( $ inet , $ addr1 , $ netmask , $ mask1 , $ Bcast , $ bcastaddr ) =
split ( " " , $ addr ) ;
if ( ( ! $ addr1 ) && ( ! $ mask1 ) ) { next ; }
$ ip = $ addr1 ;
$ mask1 =~ s/0x// ;
$ mask =
`printf "%d.%d.%d.%d" \$(echo "$mask1" | sed 's/../0x& /g')` ;
}
if ( $ ip && $ mask )
{
# split interface IP
my ( $ h1 , $ h2 , $ h3 , $ h4 ) = split ( '\.' , $ ip ) ;
# split mask
my ( $ m1 , $ m2 , $ m3 , $ m4 ) = split ( '\.' , $ mask ) ;
# AND this interface IP with the netmask of the network
my $ a1 = ( ( int $ h1 ) & ( int $ m1 ) ) ;
my $ a2 = ( ( int $ h2 ) & ( int $ m2 ) ) ;
my $ a3 = ( ( int $ h3 ) & ( int $ m3 ) ) ;
my $ a4 = ( ( int $ h4 ) & ( int $ m4 ) ) ;
# AND node IP with the netmask of the network
my $ b1 = ( ( int $ n1 ) & ( int $ m1 ) ) ;
my $ b2 = ( ( int $ n2 ) & ( int $ m2 ) ) ;
my $ b3 = ( ( int $ n3 ) & ( int $ m3 ) ) ;
my $ b4 = ( ( int $ n4 ) & ( int $ m4 ) ) ;
if ( ( $ b1 == $ a1 ) && ( $ b2 == $ a2 ) && ( $ b3 == $ a3 ) && ( $ b4 == $ a4 ) )
{
return $ ip ;
}
}
2009-03-11 17:22:43 +00:00
}
xCAT::MsgUtils - > message ( "S" , "Cannot find master for the node $node\n" ) ;
2009-03-16 12:50:22 +00:00
return 0 ;
2009-03-11 17:22:43 +00:00
}
2009-03-24 19:25:31 +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 ;
if ( - f "/etc/redhat-release" )
{
chomp ( $ line = `head -n 1 /etc/redhat-release` ) ;
$ os = "rh" ;
chomp ( $ ver = `tr -d '.' < /etc/redhat-release | head -n 1` ) ;
$ 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" )
{
chomp ( @ lines = `cat /etc/SuSE-release` ) ;
if ( grep /SLES|Enterprise Server/ , @ lines ) { $ os = "sles" }
if ( grep /SLEC/ , @ lines ) { $ os = "slec" }
chomp ( $ ver = `tr -d '.' < /etc/SuSE-release | head -n 1 ` ) ;
$ ver =~ s/[^0-9]*([0-9]+).*/$1/ ;
#print "ver: $ver\n";
}
elsif ( - f "/etc/UnitedLinux-release" )
{
$ os = "ul" ;
chomp ( $ ver = `tr -d '.' < /etc/UnitedLinux-release | head -n 1 ` ) ;
$ ver =~ s/[^0-9]*([0-9]+).*/$1/ ;
}
$ os = "$os" . "$ver" ;
return ( $ os ) ;
2009-03-18 12:07:50 +00:00
}
2009-03-24 19:25:31 +00:00
#-------------------------------------------------------------------------------
2009-03-25 12:09:22 +00:00
= head3 checkCredFiles
2009-03-24 19:25:31 +00:00
Checks the various credential files on the Management Node to
make sure the permission are correct for using and transferring
to the nodes and service nodes .
Also removes /install/ postscripts /etc/xc at / cfgloc if found
Arguments:
$ callback
Returns:
0 - ok
Globals:
none
Error:
warnings of possible missing files and directories
Example:
my $ rc = xCAT::Utils - > checkCreds
Comments:
none
= cut
#-------------------------------------------------------------------------------
2009-03-25 12:09:22 +00:00
sub checkCredFiles
2009-03-24 19:25:31 +00:00
{
2009-03-25 12:09:22 +00:00
my $ lib = shift ;
2009-03-24 19:25:31 +00:00
my $ cb = shift ;
my $ dir = "/install/postscripts/_xcat" ;
if ( - d $ dir )
{
my $ file = "$dir/ca.pem" ;
if ( - e $ file )
{
my $ cmd = "/bin/chmod 0644 $file" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{ # ca.pem missing
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-03-24 19:25:31 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
2009-03-25 12:09:22 +00:00
my $ dir = "/etc/xcat/cert" ;
if ( - d $ dir )
{
2009-04-03 15:42:59 +00:00
my $ file = "$dir/server-cred.pem" ; # from getcredentials
2009-03-25 12:09:22 +00:00
if ( ! ( - e $ file ) )
{
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. run xcatconfig (no force)" ;
2009-03-25 12:09:22 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
2009-03-24 19:25:31 +00:00
my $ dir = "/install/postscripts/ca" ;
if ( - d $ dir )
{
my $ file = "$dir/ca-cert.pem" ;
if ( - e $ file )
{
my $ cmd = "/bin/chmod 0644 $file" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{ # ca_cert.pem missing
2009-03-25 12:09:22 +00:00
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-03-25 12:09:22 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
# todo, I think next release this directory can be removed and
# copycerts modified because ca.pem is gotten by getcredentials from
# /etc/xcat/cert
my $ dir = "/install/postscripts/cert" ;
if ( - d $ dir )
{
my $ file = "$dir/ca.pem" ;
if ( - e $ file )
{
2009-04-03 15:42:59 +00:00
my $ file2 = "$dir/*" ;
my $ cmd = "/bin/chmod 0644 $file2" ;
2009-03-25 12:09:22 +00:00
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{ # ca.pem missing
2009-03-24 19:25:31 +00:00
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-03-24 19:25:31 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
# ssh hostkeys
my $ dir = "/install/postscripts/hostkeys" ;
if ( - d $ dir )
{
my $ file = "$dir/ssh_host_key.pub" ;
if ( - e $ file )
{
my $ file2 = "$dir/*.pub" ; # all public keys
my $ cmd = "/bin/chmod 0644 $file2" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{ # hostkey missing
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-03-24 19:25:31 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
2009-05-11 12:27:30 +00:00
# ssh hostkeys
my $ dir = "/etc/xcat/hostkeys" ;
if ( - d $ dir )
{
my $ file = "$dir/ssh_host_key.pub" ;
if ( - e $ file )
{
my $ file2 = "$dir/*.pub" ; # all public keys
my $ cmd = "/bin/chmod 0644 $file2" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{ # hostkey missing
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-05-11 12:27:30 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
# ssh directory
my $ dir = "/install/postscripts/_ssh" ;
2009-03-24 19:25:31 +00:00
# ssh directory
my $ dir = "/install/postscripts/_ssh" ;
if ( - d $ dir )
{
my $ file = "$dir/authorized_keys" ;
if ( - e $ file )
{
my $ file2 = "$dir/authorized_keys*" ;
my $ cmd = "/bin/chmod 0644 $file2" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
# make install script executable
$ file2 = "$dir/copy.sh" ;
if ( - e $ file2 )
{
my $ cmd = "/bin/chmod 0744 $file2" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
}
else
{ # authorized keys missing
my $ rsp = { } ;
2009-05-11 13:02:34 +00:00
$ rsp - > { data } - > [ 0 ] = "Error: $file is missing. Run xcatconfig (no force)" ;
2009-03-24 19:25:31 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
else
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error: $dir is missing." ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
# remove any old cfgloc files
my $ file = "/install/postscripts/etc/xcat/cfgloc" ;
if ( - e $ file )
{
my $ cmd = "/bin/rm $file" ;
my $ outref = xCAT::Utils - > runcmd ( "$cmd" , 0 ) ;
if ( $ ::RUNCMD_RC != 0 )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Error on command: $cmd" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ cb ) ;
}
}
}
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:
A string name for the lock to acquire
Returns:
false on failure
A reference for the lock being held .
= cut
sub acquire_lock {
my $ lock_name = shift ;
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 ; }
flock ( $ tlock - > { fd } , LOCK_EX ) or return undef ;
return $ tlock ;
}
#---------------------
= head3 release_lock
Release an acquired lock
Arguments:
reference to lock
Returns:
false on failure , true on success
= cut
sub release_lock {
my $ tlock = shift ;
unlink ( $ tlock - > { path } ) ;
flock ( $ tlock - > { fd } , LOCK_UN ) ;
close ( $ tlock - > { fd } ) ;
}
2009-06-19 08:32:47 +00:00
#-----------------------------------------------------------------------------
= head3 getrootimage
Get the directory of root image for a node ;
Note: This subroutine only works for diskless node
Arguments:
$ node
Returns:
string - directory of the root image
undef - this is not a diskless node or the root image does not existed
Globals:
none
Error:
Example:
my $ node_syncfile = xCAT::Utils - > getrootimage ( $ node ) ;
= cut
#-----------------------------------------------------------------------------
sub getrootimage ()
{
my $ node = shift ;
if ( ( $ node ) && ( $ node =~ /xCAT::Utils/ ) )
{
$ node = shift ;
}
# get the os,arch,profile attributes for the nodes
my $ nodetype_t = xCAT::Table - > new ( 'nodetype' ) ;
unless ( $ nodetype_t ) {
return ;
}
my $ nodetype_v = $ nodetype_t - > getNodeAttribs ( $ node , [ 'profile' , 'os' , 'arch' ] ) ;
my $ profile = $ nodetype_v - > { 'profile' } ;
my $ os = $ nodetype_v - > { 'os' } ;
my $ arch = $ nodetype_v - > { 'arch' } ;
if ( $^O eq "linux" ) {
my $ rootdir = "/install/netboot/$os/$arch/$profile/rootimg/" ;
if ( - d $ rootdir ) {
return $ rootdir ;
} else {
return undef ;
}
} else {
# For AIX
}
}
2009-06-04 15:33:44 +00:00
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 ()
{
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-07 02:07:30 +00:00
#-------------------------------------------------------------------------------
= head3 get_subnet_aix
Description:
To get present subnet configuration by parsing the output of 'netstat' . Only designed for AIX .
Arguments:
None
Returns:
@ aix_nrn : An array with entries in format "net:nic:netmask:flag" . Following is an example entry:
9.114 .47 .224 : en0:27:U
Globals:
none
Error:
none
Example:
my @ nrn = xCAT::Utils:: get_subnet_aix
Comments:
none
= cut
#-------------------------------------------------------------------------------
sub get_subnet_aix
{
my @ netstat_res = `/usr/bin/netstat -rn` ;
chomp @ netstat_res ;
my @ aix_nrn ;
for my $ entry ( @ netstat_res )
{
#We need to find entries like:
#Destination Gateway Flags Refs Use If Exp Groups
#9.114.47.192/27 9.114.47.205 U 1 1 en0
if ( $ entry =~ /^\s*([\d\.]+)\/(\d+)\s+[\d\.]+\s+(\w+)\s+\d+\s+\d+\s(\w+)/ )
{
my ( $ net , $ netmask , $ flag , $ nic ) = ( $ 1 , $ 2 , $ 3 , $ 4 ) ;
my @ dotsec = split /\./ , $ net ;
for ( my $ i = 4 ; $ i > scalar ( @ dotsec ) ; $ i - - )
{
$ net . = '.0' ;
}
push @ aix_nrn , "$net:$nic:$netmask:$flag" if ( $ net ne '127.0.0.0' ) ;
}
}
return @ aix_nrn ;
}
2009-07-23 20:02:39 +00:00
#-------------------------------------------------------------------------------
= head3 isIpaddr
returns 1 if parameter is has a valid IP address form .
Arguments:
dot qulaified IP address: e . g . 1.2 .3 .4
Returns:
1 - if legal IP address
0 - if not legal IP address .
Globals:
none
Error:
none
Example:
if ( $ ipAddr ) { blah ; }
Comments:
Doesn ' t test if the IP address is on the network ,
just tests its form .
= cut
#-------------------------------------------------------------------------------
sub isIpaddr
{
my $ addr = shift ;
#print "addr=$addr\n";
if ( $ addr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ )
{
return 0 ;
}
if ( $ 1 > 255 || $ 1 == 0 || $ 2 > 255 || $ 3 > 255 || $ 4 > 255 )
{
return 0 ;
}
else
{
return 1 ;
}
}
2009-07-27 15:28:11 +00:00
#-------------------------------------------------------------------------------
= head3 getNodeNetworkCfg
Description:
Get node network configuration , including "IP, hostname(the nodename),and netmask" by this node ' s name .
Arguments:
node: the nodename
Returns:
Return an array , which contains ( IP , hostname , gateway , netmask ' ) .
undef - Failed to get the network configuration info
Globals:
none
Error:
none
Example:
my ( $ ip , $ host , undef , $ mask ) = xCAT::Utils:: getNodeNetworkCfg ( 'node1' ) ;
Comments:
Presently gateway is always blank . Need to be improved .
= cut
#-------------------------------------------------------------------------------
sub getNodeNetworkCfg
{
my $ node = shift ;
my $ nets = xCAT::Utils:: my_nets ( ) ;
my $ ip = inet_ntoa ( inet_aton ( $ node ) ) ;
my $ mask = undef ;
for my $ net ( keys %$ nets )
{
my $ netname ;
( $ netname , $ mask ) = split /\// , $ net ;
last if ( xCAT::Utils:: isInSameSubnet ( $ netname , $ ip , $ mask , 1 ) ) ;
}
return ( $ ip , $ node , undef , xCAT::Utils:: formatNetmask ( $ mask , 1 , 0 ) ) ;
}
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
{
my $ host_ip = shift ;
my $ fname = "/etc/hosts" ;
unless ( open ( HOSTS , "<$fname" ) ) {
return undef ;
}
my @ rawdata = <HOSTS> ;
my @ newdata = ( ) ;
close ( HOSTS ) ;
chomp @ rawdata ;
######################################
# Remove old entry
######################################
foreach my $ host ( keys %$ host_ip ) {
my $ ip = $ host_ip - > { $ host } ;
my $ updated = 0 ;
foreach my $ line ( @ rawdata ) {
if ( $ line =~ /^#/ or $ line =~ /^\s*$/ ) {
next ;
}
if ( $ line =~ /^\s*\Q$ip\E\s+/ )
{
if ( $ line =~ /\s+\Q$host\E\s+/ or
$ line =~ /\s+\Q$host\E$/ )
{
}
else
{
$ line . = "\t$host" ;
}
$ updated = 1 ;
last ;
}
}
if ( ! $ updated )
{
push @ rawdata , "$ip\t$host" ;
}
}
######################################
# Rewrite file
######################################
unless ( open ( HOSTS , ">$fname" ) ) {
return undef ;
}
for my $ line ( @ rawdata )
{
print HOSTS "$line\n" ;
}
close ( HOSTS ) ;
return 1 ;
}
2007-12-20 19:02:45 +00:00
1 ;