2008-08-08 13:20:20 +00:00
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.htm
#------------------------------------------------------------------------------
= head1 SINV
= head2 Package Description
This program module file supplies a set of utility programs for
the sinv command .
= cut
#------------------------------------------------------------------------------
package xCAT::SINV ;
use strict ;
use xCAT::MsgUtils ;
2008-10-20 17:12:43 +00:00
use xCAT::NodeRange ;
2009-07-07 17:10:27 +00:00
use xCAT::NodeRange qw/noderange abbreviate_noderange/ ;
2008-08-08 13:20:20 +00:00
use xCAT::Utils ;
use Fcntl qw( :flock ) ;
use Getopt::Long ;
2009-09-30 16:11:56 +00:00
use Data::Dumper ;
2008-09-19 17:32:20 +00:00
my $ tempfile ;
2008-09-24 19:17:35 +00:00
my $ errored = 0 ;
2008-09-19 17:32:20 +00:00
my @ dshresult ;
2008-09-24 19:17:35 +00:00
my $ templatepath ;
my $ processflg ;
2008-10-24 18:39:43 +00:00
my @ cmdresult ;
2008-10-27 19:40:10 +00:00
my @ errresult ;
2008-09-24 19:17:35 +00:00
2008-08-08 13:20:20 +00:00
#
# Subroutines
#
#------------------------------------------------------------------------------
= head3 usage
Display usage message
= cut
#------------------------------------------------------------------------------
sub usage
{
2008-10-27 19:40:10 +00:00
my $ callback = shift ;
2008-08-08 13:20:20 +00:00
## usage message
2008-09-16 12:50:30 +00:00
my $ usagemsg1 =
"The sinv command is designed to check the configuration of nodes in a cluster.\nRun man sinv for more information.\n\nInput parameters are as follows:\n" ;
2009-10-16 11:54:26 +00:00
my $ usagemsg1a = "sinv -h \nsinv -v \nsinv" ;
2008-09-16 13:04:12 +00:00
my $ usagemsg3 =
2009-10-16 11:54:26 +00:00
" -p <template path> [-o output file ] [-t <template count>]\n" ;
2008-11-07 15:34:14 +00:00
my $ usagemsg4 = " [-r remove templates] [-s <seednode>]\n" ;
my $ usagemsg5 = " [-e exactmatch] [-i ignore]\n" ;
2009-10-16 11:54:26 +00:00
my $ usagemsg6 = " {-c <command> | -f <command file>}" ;
my $ usagemsg . = $ usagemsg1 . = $ usagemsg1a . = $ usagemsg3 . = $ usagemsg4 . =
2008-11-07 15:34:14 +00:00
$ usagemsg5 . = $ usagemsg6 ;
2008-08-08 13:20:20 +00:00
### end usage mesage
2008-09-16 14:11:50 +00:00
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = $ usagemsg ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ ::CALLBACK ) ;
2008-08-08 13:20:20 +00:00
return ;
}
#------------------------------------------------------------------------------
= head3 parse_and_run_sinv
Checks input arguments and runs sinv from the plugin
= cut
#------------------------------------------------------------------------------
sub parse_and_run_sinv
{
2008-10-20 17:12:43 +00:00
my ( $ class , $ request , $ callback , $ sub_req ) = @ _ ;
2008-08-08 13:20:20 +00:00
my $ rsp = { } ;
2008-10-24 18:39:43 +00:00
my $ rc = 0 ;
2008-08-08 13:20:20 +00:00
$ ::CALLBACK = $ callback ;
2008-10-24 18:39:43 +00:00
my $ args = $ request - > { arg } ;
2009-01-05 15:00:54 +00:00
if ( ! ( $ args ) ) {
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"No arguments have been supplied to the sinv command. Check the sinv man page for appropriate input. \n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
2008-10-24 18:39:43 +00:00
@ ARGV = @ { $ args } ; # get arguments
2008-08-08 13:20:20 +00:00
my % options = ( ) ;
$ Getopt:: Long:: ignorecase = 0 ; #Checks case in GetOptions
Getopt::Long:: Configure ( "bundling" ) ;
2008-10-24 18:39:43 +00:00
2008-08-08 13:20:20 +00:00
if (
! GetOptions (
2008-09-24 19:17:35 +00:00
'h|help' = > \ $ options { 'help' } ,
't|tc=s' = > \ $ options { 'template_cnt' } ,
'p|tp=s' = > \ $ options { 'template_path' } ,
'r|remove' = > \ $ options { 'remove_template' } ,
'o|output=s' = > \ $ options { 'output_file' } ,
's|seed=s' = > \ $ options { 'seed_node' } ,
'e|exactmatch' = > \ $ options { 'exactmatch' } ,
'i|ignorefirst' = > \ $ options { 'ignorefirst' } ,
2008-10-24 18:39:43 +00:00
'c|cmd=s' = > \ $ options { 'sinv_cmd' } ,
'f|file=s' = > \ $ options { 'sinv_cmd_file' } ,
2008-09-24 19:17:35 +00:00
'v|version' = > \ $ options { 'version' } ,
'V|Verbose' = > \ $ options { 'verbose' } ,
2008-08-08 13:20:20 +00:00
)
)
{
2008-10-27 19:40:10 +00:00
& usage ( $ callback ) ;
2008-08-08 13:20:20 +00:00
exit 1 ;
}
if ( $ options { 'help' } )
{
2008-10-27 19:40:10 +00:00
& usage ( $ callback ) ;
2008-08-08 13:20:20 +00:00
exit 0 ;
}
if ( $ options { 'version' } )
{
my $ version = xCAT::Utils - > Version ( ) ;
2008-09-16 13:04:12 +00:00
$ version . = "\n" ;
2008-09-16 14:11:50 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = $ version ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
2008-08-08 13:20:20 +00:00
exit 0 ;
}
if ( $ options { 'verbose' } )
{
$ ::VERBOSE = "yes" ;
}
2008-10-24 18:39:43 +00:00
# if neither command or file, error
if ( ! ( $ options { 'sinv_cmd' } ) && ( ! ( $ options { 'sinv_cmd_file' } ) ) )
2008-08-08 13:20:20 +00:00
{
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
$ rsp - > { data } - > [ 0 ] =
2008-10-24 18:39:43 +00:00
"Neither the sinv command, nor the sinv command file have been supplied.\n" ;
2008-08-08 13:20:20 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
2008-10-24 18:39:43 +00:00
# if both command and file, error
if ( ( $ options { 'sinv_cmd' } ) && ( ( $ options { 'sinv_cmd_file' } ) ) )
2008-08-08 13:20:20 +00:00
{
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
$ rsp - > { data } - > [ 0 ] =
2008-10-24 18:39:43 +00:00
"Both the sinv command, and the sinv command file have been supplied. Only one or the other is allowed.\n" ;
2008-08-08 13:20:20 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
#
# Get Command to run
#
my $ cmd ;
2008-10-24 18:39:43 +00:00
if ( $ options { 'sinv_cmd' } )
2008-08-08 13:20:20 +00:00
{
2008-10-24 18:39:43 +00:00
$ cmd = $ options { 'sinv_cmd' } ;
2008-08-08 13:20:20 +00:00
}
else
{
# read the command from the file
2008-10-24 18:39:43 +00:00
if ( ! ( - e $ options { 'sinv_cmd_file' } ) )
2008-09-24 19:17:35 +00:00
{ # file does not exist
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2008-10-24 18:39:43 +00:00
"Input command file: $options{'sinv_cmd_file'} does not exist.\n" ;
2008-09-24 19:17:35 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2008-10-28 15:32:58 +00:00
return 1 ;
2008-09-24 19:17:35 +00:00
}
2008-10-24 18:39:43 +00:00
$ cmd = `cat $options{'sinv_cmd_file'}` ;
2008-08-08 13:20:20 +00:00
}
chomp $ cmd ;
2008-10-24 18:39:43 +00:00
#
# the command can be either xdsh or rinv for now
# strip off the program and the noderange
#
2008-10-27 19:40:10 +00:00
my @ nodelist = ( ) ;
my @ cmdparts = split ( ' ' , $ cmd ) ;
my $ cmdtype = shift @ cmdparts ;
my $ noderange = shift @ cmdparts ;
2008-10-28 15:32:58 +00:00
my @ cmd = ( ) ;
2008-10-24 18:39:43 +00:00
if ( $ noderange =~ /^-/ )
{ # no noderange
2008-10-27 19:40:10 +00:00
push @ cmd , $ noderange ; # put flag back on command
}
foreach my $ part ( @ cmdparts )
{
push @ cmd , $ part ; # build rest of command
2008-10-24 18:39:43 +00:00
}
if ( ( $ cmdtype ne "xdsh" ) && ( $ cmdtype ne "rinv" ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Only commands xdsh and rinv are currently supported.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
my $ cmdoutput ;
if ( $ cmdtype eq "xdsh" )
2008-12-10 16:00:35 +00:00
{ # choose output routine to run
2008-10-24 18:39:43 +00:00
$ cmdoutput = "xdshoutput" ;
}
else
2008-10-28 15:32:58 +00:00
{ # rinv
2008-10-24 18:39:43 +00:00
$ cmdoutput = "rinvoutput" ;
}
# this must be a noderange or the flag indicating we are going to the
# install image ( -i) for xdsh, only case where noderange is not required
if ( $ noderange =~ /^-/ )
2008-10-28 15:32:58 +00:00
{ # no noderange, it is a flag
2008-10-24 18:39:43 +00:00
@ nodelist = "NO_NODE_RANGE" ;
# add flag back to arguments
$ args . = $ noderange ;
}
else
2008-10-28 15:32:58 +00:00
{ # get noderange
2008-10-24 18:39:43 +00:00
@ nodelist = noderange ( $ noderange ) ; # expand noderange
if ( nodesmissed )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
"Invalid or missing noderange:" . join ( ',' , nodesmissed ) ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
return ;
}
}
2008-08-08 13:20:20 +00:00
#
2008-09-24 19:17:35 +00:00
# Get exact match request
#
my $ exactmatch = "NO" ;
if ( $ options { 'exactmatch' } )
{
$ exactmatch = "YES" ;
}
#
# Get ignore matches on first template request
2008-08-08 13:20:20 +00:00
#
2008-09-24 19:17:35 +00:00
my $ ignorefirsttemplate = "NO" ;
if ( $ options { 'ignorefirst' } )
{
$ ignorefirsttemplate = "YES" ;
}
2008-08-08 13:20:20 +00:00
2008-09-24 19:17:35 +00:00
#
#
# Get template path
#
my $ admintemplate ;
$ templatepath = $ options { 'template_path' } ;
2008-08-08 13:20:20 +00:00
if ( ! $ templatepath )
{
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
$ rsp - > { data } - > [ 0 ] = "Missing template path on the command.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
2008-09-24 19:17:35 +00:00
else
{
if ( - e ( $ templatepath ) )
{ # the admin has input the template
$ admintemplate = "YES" ;
}
else
{
$ admintemplate = "NO" ;
}
}
2008-08-08 13:20:20 +00:00
chomp $ templatepath ;
#
# Get template count
#
my $ templatecnt = $ options { 'template_cnt' } ;
if ( ! $ templatecnt )
{
2008-09-24 19:17:35 +00:00
$ templatecnt = 0 ; # default
2008-08-08 13:20:20 +00:00
}
chomp $ templatecnt ;
#
# Get remove template value
#
2008-09-24 19:17:35 +00:00
my $ rmtemplate = "NO" ; #default
if ( $ options { 'remove_template' } )
2008-08-08 13:20:20 +00:00
{
2008-09-24 19:17:35 +00:00
$ rmtemplate = "YES" ;
2008-08-08 13:20:20 +00:00
}
chomp $ rmtemplate ;
#
#
# Get where to put the output
#
my $ outputfile = $ options { 'output_file' } ;
if ( ! $ outputfile )
{
2008-11-07 15:34:14 +00:00
$ ::NOOUTPUTFILE = 1 ;
2008-08-08 13:20:20 +00:00
}
2008-11-07 15:34:14 +00:00
else
{
2008-08-08 13:20:20 +00:00
2008-11-07 15:34:14 +00:00
chomp $ outputfile ;
}
# open the file for writing, if it exists
if ( $ outputfile )
2008-08-08 13:20:20 +00:00
{
2008-11-07 15:34:14 +00:00
unless ( open ( OUTPUTFILE , ">$outputfile" ) )
{
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = " Cannot open $outputfile for output.\n" ;
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
exit 1 ;
}
$ ::OUTPUT_FILE_HANDLE = \ * OUTPUTFILE ;
2008-08-08 13:20:20 +00:00
}
#
2008-10-24 18:39:43 +00:00
# For xdsh command
2008-08-08 13:20:20 +00:00
# Get seed node if it exists to build the original template
2008-10-24 18:39:43 +00:00
# if seed node does not exist and the admin did not submit a
2008-09-24 19:17:35 +00:00
# template, the the first node becomes the seed node
2008-10-28 16:34:40 +00:00
# if there is no nodelist then error
2008-09-24 19:17:35 +00:00
my @ seed ;
2008-08-08 13:20:20 +00:00
my $ seednode = $ options { 'seed_node' } ;
if ( $ seednode )
{
chomp $ seednode ;
2008-09-24 19:17:35 +00:00
push @ seed , $ seednode ;
}
else
{
2008-11-03 20:26:11 +00:00
if ( $ admintemplate eq "NO" ) # default the seed node
{ # admin did not generate a template
if ( $ nodelist [ 0 ] ne "NO_NODE_RANGE" )
{
push @ seed , $ nodelist [ 0 ] ; # assign first element as seed
$ seednode = $ nodelist [ 0 ] ;
}
else
{ # error cannot default
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] =
2008-12-10 16:00:35 +00:00
"No template or seed node supplied and no noderange to choose a default.\n" ;
2008-11-03 20:26:11 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback , 1 ) ;
exit 1 ;
2008-10-28 16:34:40 +00:00
}
2008-09-24 19:17:35 +00:00
}
2008-08-08 13:20:20 +00:00
}
my $ tmpnodefile ;
#
2008-11-10 21:40:43 +00:00
# Build Output header
if ( ( $ ::VERBOSE ) || ( $ outputfile ) )
2008-08-08 13:20:20 +00:00
{
2008-11-10 21:40:43 +00:00
#
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Command started with following input.\n" ;
if ( $ cmd )
2008-11-07 15:34:14 +00:00
{
2008-11-10 21:40:43 +00:00
$ rsp - > { data } - > [ 1 ] = "$cmdtype cmd:$cmd.\n" ;
}
else
{
$ rsp - > { data } - > [ 1 ] = "$cmdtype cmd:None.\n" ;
}
$ rsp - > { data } - > [ 2 ] = "Template path:$templatepath.\n" ;
$ rsp - > { data } - > [ 3 ] = "Template cnt:$templatecnt.\n" ;
$ rsp - > { data } - > [ 4 ] = "Remove template:$rmtemplate.\n" ;
if ( $ outputfile )
{
$ rsp - > { data } - > [ 5 ] = "Output file:$outputfile.\n" ;
}
else
{
$ rsp - > { data } - > [ 5 ] = "Output file:None.\n" ;
}
$ rsp - > { data } - > [ 6 ] = "Exactmatch:$exactmatch.\n" ;
$ rsp - > { data } - > [ 7 ] = "Ignorefirst:$ignorefirsttemplate.\n" ;
if ( $ seednode )
{
$ rsp - > { data } - > [ 8 ] = "Seed node:$seednode.\n" ;
}
else
{
$ rsp - > { data } - > [ 8 ] = "Seed node:None.\n" ;
}
if ( $ options { 'sinv_cmd_file' } )
{
$ rsp - > { data } - > [ 9 ] = "file:$options{'sinv_cmd_file'}.\n" ;
}
else
{
$ rsp - > { data } - > [ 9 ] = "file:None.\n" ;
}
#write to output file the header
my $ i = 0 ;
if ( $ ::OUTPUT_FILE_HANDLE )
{
while ( $ i < 10 )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ $ i ] ;
$ i + + ;
}
print $ ::OUTPUT_FILE_HANDLE "\n" ;
}
if ( ! ( $ outputfile ) )
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
2008-11-07 15:34:14 +00:00
}
2008-08-08 13:20:20 +00:00
}
2008-10-24 18:39:43 +00:00
# setup a tempfile for command output
2008-09-24 19:17:35 +00:00
$ tempfile = "/tmp/sinv.$$" ;
2008-08-08 13:20:20 +00:00
#
# if we are to seed the original template,run the dsh command against the
# seed node and save in template_path
2008-10-24 18:39:43 +00:00
# already checked for rinv command above and exited, if seed node
#
2008-08-08 13:20:20 +00:00
if ( $ seednode )
{
2008-09-24 19:17:35 +00:00
2008-10-24 18:39:43 +00:00
# Below code needed to run xdsh or rinv from the plugin
2008-09-24 19:17:35 +00:00
# and still support a hierarchial xdsh
2008-10-24 18:39:43 +00:00
# this will run xdsh or rinv with input, return to
# xdshoutput routine or rinvoutput routine
2008-09-24 19:17:35 +00:00
# and then return inline after this code.
$ processflg = "seednode" ;
2008-11-10 21:40:43 +00:00
@ errresult = ( ) ;
@ cmdresult = ( ) ;
2008-09-24 19:17:35 +00:00
$ sub_req - > (
{
2008-10-24 18:39:43 +00:00
command = > [ $ cmdtype ] ,
2008-09-24 19:17:35 +00:00
node = > \ @ seed ,
2008-10-27 19:40:10 +00:00
arg = > [ @ cmd ]
2008-09-24 19:17:35 +00:00
} ,
2008-10-24 18:39:43 +00:00
\ & $ cmdoutput
2008-09-24 19:17:35 +00:00
) ;
2008-10-27 19:40:10 +00:00
if ( $? > 0 )
{
my $ rsp = { } ;
my $ i = 0 ;
foreach my $ line ( @ cmdresult )
{
$ rsp - > { data } - > [ $ i ] = $ line ;
$ i + + ;
}
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
2008-09-24 19:17:35 +00:00
2009-04-20 13:08:25 +00:00
# write the results to the tempfile after running through xdshcoll
2008-10-27 19:40:10 +00:00
$ rc = & storeresults ( $ callback ) ;
2008-10-24 18:39:43 +00:00
2008-08-08 13:20:20 +00:00
}
2008-09-24 19:17:35 +00:00
$ processflg = "node" ;
2008-08-08 13:20:20 +00:00
2008-10-24 18:39:43 +00:00
# Tell them we are running the command
2008-11-07 15:34:14 +00:00
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-08-08 13:20:20 +00:00
{
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-10-24 18:39:43 +00:00
$ rsp - > { data } - > [ 0 ] = "Running $cmdtype command.\n" ;
2008-08-08 13:20:20 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
2008-09-24 19:17:35 +00:00
2008-10-24 18:39:43 +00:00
# Below code needed to run xdsh/rinv from the plugin
2008-09-19 17:32:20 +00:00
# and still support a hierarchial xdsh
2008-10-24 18:39:43 +00:00
# this will run the command with input, return to cmdoutput routine
2008-09-24 19:17:35 +00:00
# and then return inline after this code.
2008-11-07 16:53:49 +00:00
@ errresult = ( ) ;
@ cmdresult = ( ) ;
2008-09-24 19:17:35 +00:00
$ sub_req - > (
{
2008-10-24 18:39:43 +00:00
command = > [ $ cmdtype ] ,
2008-09-24 19:17:35 +00:00
node = > \ @ nodelist ,
2008-10-27 19:40:10 +00:00
arg = > [ @ cmd ]
2008-09-24 19:17:35 +00:00
} ,
2008-10-24 18:39:43 +00:00
\ & $ cmdoutput
2008-09-24 19:17:35 +00:00
) ;
2008-09-19 17:32:20 +00:00
2008-10-27 19:40:10 +00:00
if ( $? > 0 )
{
my $ rsp = { } ;
my $ i = 0 ;
foreach my $ line ( @ cmdresult )
{
$ rsp - > { data } - > [ $ i ] = $ line ;
$ i + + ;
}
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
return 1 ;
}
2009-04-20 13:08:25 +00:00
# write the results to the tempfile after running through xdshcoll
2008-10-27 19:40:10 +00:00
$ rc = & storeresults ( $ callback ) ;
2008-10-24 18:39:43 +00:00
2008-08-08 13:20:20 +00:00
# Build report and write to output file
2008-09-19 17:32:20 +00:00
# if file exist and has something in it
2008-10-24 18:39:43 +00:00
if ( ( - e $ tempfile ) && ( $ rc == 0 ) )
{ # if cmd returned something
2008-08-08 13:20:20 +00:00
# Tell them we are building the report
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
$ rsp - > { data } - > [ 0 ] = "Building Report.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
xCAT::SINV - > buildreport (
2008-09-24 19:17:35 +00:00
$ outputfile , $ tempfile ,
$ templatepath , $ templatecnt ,
$ rmtemplate , \ @ nodelist ,
$ callback , $ ignorefirsttemplate ,
$ exactmatch , $ admintemplate
2008-08-08 13:20:20 +00:00
) ;
}
else
{
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-10-24 18:39:43 +00:00
$ rsp - > { data } - > [ 0 ] = "No output from $cmdtype.\n" ;
2008-08-08 13:20:20 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
# Finally we need to cleanup and exit
#
2008-10-24 18:39:43 +00:00
if ( - e $ tempfile )
{
2008-11-03 20:26:11 +00:00
2008-10-24 18:39:43 +00:00
system ( "/bin/rm $tempfile" ) ;
}
2008-09-19 17:32:20 +00:00
my $ rsp = { } ;
2008-11-07 15:34:14 +00:00
$ rsp - > { data } - > [ 0 ] = "Command Complete." ;
2008-08-08 13:20:20 +00:00
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
close ( OUTPUTFILE ) ;
$ rsp - > { data } - > [ 0 ] = "Check report in $outputfile.\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
2008-10-24 18:39:43 +00:00
return $ rc ;
2008-08-08 13:20:20 +00:00
}
#------------------------------------------------------------------------------
2008-10-24 18:39:43 +00:00
= head3 buildreport ( note originally written only for xdsh but
now supports rinv also )
2008-08-08 13:20:20 +00:00
This routine will take the input template and compare against
the output of the dsh command and build a report of the differences .
Read a nodes worth of data from the dsh command
Call compareoutput - compares the dsh to the template
Get the template and nodename returned from compareoutput and build hash
Call writereport to take the hash and write the report to the output file
Cleanup
Input ( report file , file containing dsh run , template file , template count
2008-09-24 19:17:35 +00:00
whether to remove the generated templates , original dsh node list ,
ignorefirsttemplate , exactmatch )
If exactmatch is chosen , a diff is done against the template and the output .
If not exactmatch , then each record ( line ) in the template must be
checked against the node ' s output to determine , if it exists .
2008-08-08 13:20:20 +00:00
= cut
#------------------------------------------------------------------------------
sub buildreport
{
2008-09-24 19:17:35 +00:00
my (
$ class , $ outputfile , $ dshrun ,
$ templatepath , $ templatecnt , $ removetemplate ,
$ nodelistin , $ callback , $ ignorefirsttemplate ,
$ exactmatch , $ admintemplate
)
2008-08-08 13:20:20 +00:00
= @ _ ;
2008-09-24 19:17:35 +00:00
my @ nodelist = @$ nodelistin ;
my $ pname = "buildreport" ;
my $ rc = $ ::OK ;
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
# Compare files and build report of nodes that match and those that do not
if ( ! - f "$templatepath" ) # we supplied a template
{ # does it exist
$ rsp - > { data } - > [ 0 ] = "$templatepath does not exist\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
if ( ! - f "$dshrun" )
{ # does it exist
$ rsp - > { data } - > [ 0 ] = "$dshrun does not exist\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
#
# Build an array of template name
#
my @ templatearray ;
my $ i = $ templatecnt ;
push @ templatearray , $ templatepath ; # push first template
for ( $ i = 0 ; $ i <= $ templatecnt ; $ i + + )
{
if ( $ i != 0 )
{ # more template file to read
my $ templatename = $ templatepath . "_" . $ i ;
push @ templatearray , "$templatename" ;
}
}
2008-10-24 18:39:43 +00:00
# Read the output of the dsh or rinv command
2008-08-08 13:20:20 +00:00
if ( ! open ( DSHRESULTS , "<$dshrun" ) )
{
$ rsp - > { data } - > [ 0 ] = "Error reading: $dshrun\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
my @ dsharray = <DSHRESULTS> ;
close ( TEMPLATE ) ;
close ( DSHRESULTS ) ;
#Now we have to analyze the template(s) against the dsh command output
#The matching nodes will be built in one array and the non matching node
#In another array
#
#
# For each node entry for the dsh command
# Build an array of that node's data
# Compare that node's data to the template
# Put node in array that matches template or other if no match
#
my $ match = 0 ;
my $ host ;
my $ label ;
2008-11-03 20:26:11 +00:00
my $ headerlines = 0 ;
2008-08-08 13:20:20 +00:00
my @ processNodearray ;
my $ hostline ;
my $ nodename ;
my $ template ;
my @ Nodearray ;
my $ dshline ;
my % nodehash ;
2008-11-03 20:26:11 +00:00
DSHARRAY: foreach $ dshline ( @ dsharray ) # each line returned from dsh/rinv
2008-08-08 13:20:20 +00:00
{
2008-11-03 20:26:11 +00:00
if ( $ dshline =~ /============/ ) # Host header
2008-08-08 13:20:20 +00:00
{
2008-11-03 20:26:11 +00:00
if ( $ headerlines < 2 )
2008-08-08 13:20:20 +00:00
{
2008-11-03 20:26:11 +00:00
# read until we reach another header
2008-08-08 13:20:20 +00:00
push @ Nodearray , $ dshline ;
2008-11-03 20:26:11 +00:00
$ headerlines + + ;
2008-08-08 13:20:20 +00:00
}
else
2008-11-03 20:26:11 +00:00
{ # Hit next header, process current array
2008-08-08 13:20:20 +00:00
@ processNodearray = @ Nodearray ; # save node data
@ Nodearray = ( ) ; # initialize array
2008-11-03 20:26:11 +00:00
$ headerlines = 1 ; # already read one line
push @ Nodearray , $ dshline ; # save next data
2008-09-24 19:17:35 +00:00
my @ info ;
if ( $ exactmatch eq "YES" )
{ # output matches exactly
@ info =
xCAT::SINV - > diffoutput ( $ outputfile , \ @ templatearray ,
2008-08-08 13:20:20 +00:00
\ @ processNodearray , \ % nodehash , $ callback ) ;
2008-09-24 19:17:35 +00:00
}
else
{ # output is contained in the template
@ info =
xCAT::SINV - > compareoutput ( $ outputfile , \ @ templatearray ,
\ @ processNodearray , \ % nodehash , $ callback ) ;
}
2008-08-08 13:20:20 +00:00
$ nodename = pop @ info ;
$ template = pop @ info ;
2008-11-04 17:26:33 +00:00
if ( $ nodename ne "UNKNOWN" )
{
push @ { $ nodehash { $ template } } , $ nodename ; # add node name
} # to template hash
2008-08-08 13:20:20 +00:00
}
}
else
{
2008-11-04 17:26:33 +00:00
if ( $ dshline !~ /^\s*$/ ) # skip blanks
2008-10-24 18:39:43 +00:00
# skip blanks and stop on the next host
2008-08-08 13:20:20 +00:00
{
2008-10-24 18:39:43 +00:00
push @ Nodearray , $ dshline ; # build the node results
2008-08-08 13:20:20 +00:00
}
}
} # end foreach dshline
# process the last entry
if ( @ Nodearray )
{
2008-09-24 19:17:35 +00:00
my @ info ;
if ( $ exactmatch eq "YES" )
{ # output matches exactly
@ info =
xCAT::SINV - > diffoutput (
$ outputfile , \ @ templatearray ,
\ @ Nodearray , \ % nodehash ,
$ callback
) ;
}
else
{ # output is contained in the template
@ info =
xCAT::SINV - > compareoutput (
$ outputfile , \ @ templatearray ,
\ @ Nodearray , \ % nodehash ,
$ callback
) ;
}
2008-08-08 13:20:20 +00:00
$ nodename = pop @ info ;
$ template = pop @ info ;
2008-11-04 17:26:33 +00:00
if ( $ nodename ne "UNKNOWN" )
{
push @ { $ nodehash { $ template } } , $ nodename ;
}
2008-08-08 13:20:20 +00:00
}
#
# Write the report
#
2008-09-24 19:17:35 +00:00
xCAT::SINV - > writereport ( $ outputfile , \ % nodehash , \ @ nodelist , $ callback ,
$ ignorefirsttemplate ) ;
2008-08-08 13:20:20 +00:00
#
# Cleanup the template files if the remove option was yes
#
2008-09-24 19:17:35 +00:00
$ removetemplate =~ tr /a-z/ A - Z / ; # convert to upper
if ( $ removetemplate eq "YES" )
2008-08-08 13:20:20 +00:00
{
foreach $ template ( @ templatearray ) # for each template
{
2008-09-24 19:17:35 +00:00
if ( - f "$template" )
2008-08-08 13:20:20 +00:00
{
2008-09-24 19:17:35 +00:00
if ( ( $ template ne $ templatepath ) || ( $ admintemplate eq "NO" ) )
# not the first template or the first one was not created by
# admin, it was generated by the code
{
`/bin/rm -f $template 2>&1` ;
}
2008-08-08 13:20:20 +00:00
}
}
}
return ;
}
#------------------------------------------------------------------------------
= head3 compareoutput
The purpose of this routine is to build sets of nodes
that have the same configuration . We will build up
to template_cnt sets . If more nodes are not part of these
sets they will be put in an other list .
foreach template
Open the input template
Compare the template to the input node data
if match
add the node to the matched template hash
end foreach
if no match
if generate and a new template allowed
make this nodes information into a new template
add the node to matched template
else
add the node to "notemplate" list
= cut
#------------------------------------------------------------------------------
sub compareoutput
{
my ( $ class , $ outputfile , $ template_array , $ Node_array , $ Node_hash ,
$ callback ) = @ _ ;
my @ Nodearray = @$ Node_array ;
my @ templatearray = @$ template_array ;
my % nodehash = %$ Node_hash ;
my $ pname = "compareoutput" ;
my $ rc = $ ::OK ;
my $ templateline ;
my $ info ;
my $ nodeline ;
my $ match = 0 ;
my @ info ;
my $ nodename ;
2008-11-03 20:26:11 +00:00
my @ nodenames ;
my @ tmpnodenames ;
2008-08-08 13:20:20 +00:00
my $ line ;
% nodehash = ( ) ;
my $ template ;
my $ matchedtemplate ;
my $ rsp = { } ;
foreach $ template ( @ templatearray ) # for each template
{
2008-11-03 20:26:11 +00:00
my $ skiphostline = 1 ;
2008-08-08 13:20:20 +00:00
if ( - f "$template" )
{ # if it exists
# Read the template file
open ( TEMPLATE , "<$template" ) ;
my @ template = <TEMPLATE> ;
# now compare host data to template
foreach $ templateline ( @ template ) # for each line in the template
{
# skip the header and blanks
2008-11-03 20:26:11 +00:00
if ( $ templateline =~ /============/ )
{ # Host header
next ;
}
2008-11-11 15:30:07 +00:00
if ( $ templateline =~ /UNKNOWN/ )
{ # skip UNKNOWN header
next ;
}
2008-11-03 20:26:11 +00:00
if ( $ skiphostline == 1 )
{
$ skiphostline = 0 ;
next ;
}
if ( $ templateline !~ /^\s*$/ ) # skip blanks
2008-08-08 13:20:20 +00:00
{
$ match = 0 ;
2008-11-03 20:26:11 +00:00
my $ gothosts = 0 ;
2008-08-08 13:20:20 +00:00
foreach $ nodeline ( @ Nodearray ) # for each node line
{
2008-11-03 20:26:11 +00:00
if ( $ nodeline =~ /==========/ )
{
next ;
}
if ( $ gothosts == 0 )
{ # get the hostnames
$ nodename = $ nodeline ;
2008-08-08 13:20:20 +00:00
$ nodename =~ s/\s*//g ; # remove blanks
chomp $ nodename ;
2008-11-04 17:26:33 +00:00
if ( $ nodename eq "UNKNOWN" )
{ # skip this node
@ info [ 0 ] = "NONE" ;
@ info [ 1 ] = "UNKNOWN" ;
return @ info ;
}
2008-11-03 20:26:11 +00:00
$ gothosts = 1 ;
2008-08-08 13:20:20 +00:00
}
else
{
if ( $ nodeline eq $ templateline ) # if we find a match
{ # get out
$ match = 1 ;
$ matchedtemplate = $ template ; # save name
last ;
}
}
} # end foreach nodeline
if ( $ match == 0 )
{
last ; # had a template line not found
}
} # if header
} # end foreach templateline
2008-09-24 19:17:35 +00:00
}
# end check exists
#
# if match found, process no more templates
#
2008-08-08 13:20:20 +00:00
if ( $ match == 1 )
{
last ; # exit template loop
}
2008-09-24 19:17:35 +00:00
}
# end foreach template
#
# if no match
# if generate a new template ( check the list of template file
# to see if there is one that does not exist
# put node data to new template file
#
if ( $ match == 0 )
{
my $ nodesaved = 0 ;
foreach $ template ( @ templatearray )
{
if ( ! - f "$template" )
{
if ( ! open ( NEWTEMPLATE , ">$template" ) )
{
$ rsp - > { data } - > [ 0 ] = "Error opening $template:\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
else
{
print NEWTEMPLATE @ Nodearray ; # build a new template
$ nodesaved = 1 ;
close ( NEWTEMPLATE ) ;
$ matchedtemplate = $ template ;
last ;
}
}
}
if ( $ nodesaved == 0 )
{ # out of templates
$ matchedtemplate = "no template" ; # put in other list
}
}
@ info [ 0 ] = $ matchedtemplate ;
@ info [ 1 ] = $ nodename ;
return @ info ;
}
#------------------------------------------------------------------------------
= head3 diffoutput
The purpose of this routine is to build sets of nodes
that have the same configuration . We will build up
to template_cnt sets . If more nodes are not part of these
sets they will be put in an other list .
foreach template
Open the input template
Compare the template to the input node data
if exact match
add the node to the matched template hash
end foreach
if no match
if generate and a new template allowed
make this nodes information into a new template
add the node to matched template
else
add the node to "notemplate" list
= cut
#------------------------------------------------------------------------------
sub diffoutput
{
my ( $ class , $ outputfile , $ template_array , $ Node_array , $ Node_hash ,
$ callback ) = @ _ ;
my @ Nodearray = @$ Node_array ;
my @ templatearray = @$ template_array ;
my % nodehash = %$ Node_hash ;
my $ pname = "compareoutput" ;
my $ rc = $ ::OK ;
my $ templateline ;
my $ info ;
my $ nodeline ;
my $ match = 0 ;
my @ info ;
my $ nodename ;
my $ line ;
% nodehash = ( ) ;
my $ template ;
my $ matchedtemplate ;
my $ rsp = { } ;
my @ template_noheader = ( ) ;
my @ nodearray_noheader = ( ) ;
2008-11-03 20:26:11 +00:00
my $ hostfound = 0 ;
2008-09-24 19:17:35 +00:00
2008-10-24 18:39:43 +00:00
# build a node array without the header
2009-04-20 13:08:25 +00:00
# skip any UNKNOWN entries added by xdshcoll
2008-09-24 19:17:35 +00:00
foreach $ nodeline ( @ Nodearray ) # for each node line
{
2008-11-03 20:26:11 +00:00
if ( $ nodeline =~ /================/ )
{ # skip
next ;
}
if ( $ hostfound == 0 )
2008-09-24 19:17:35 +00:00
{ # save the hostname
2008-11-03 20:26:11 +00:00
$ nodename = $ nodeline ;
2008-09-24 19:17:35 +00:00
$ nodename =~ s/\s*//g ; # remove blanks
chomp $ nodename ;
2008-11-04 17:26:33 +00:00
if ( $ nodename eq "UNKNOWN" )
{ # skip this node
@ info [ 0 ] = "NONE" ;
@ info [ 1 ] = "UNKNOWN" ;
return @ info ;
}
2008-11-03 20:26:11 +00:00
$ hostfound = 1 ;
next ;
2008-09-24 19:17:35 +00:00
}
2008-11-03 20:26:11 +00:00
# build node array with no header
push ( @ nodearray_noheader , $ nodeline ) ;
2008-09-24 19:17:35 +00:00
} # end foreach nodeline
#
# foreach template
# build a template array with no header
# compare to the node array with no header
#
foreach $ template ( @ templatearray ) # for each template
{
if ( - f "$template" )
{ # if it exists
2008-11-03 20:26:11 +00:00
my $ skiphostline = 1 ;
2008-09-24 19:17:35 +00:00
# Read the template file
open ( TEMPLATE , "<$template" ) ;
my @ template = <TEMPLATE> ;
# now compare host data to template
foreach $ templateline ( @ template ) # for each line in the template
{
# skip the header and blanks
2008-11-03 20:26:11 +00:00
if ( $ templateline =~ /============/ )
{ # Host header
next ;
}
2008-11-11 15:30:07 +00:00
if ( $ templateline =~ /UNKNOWN/ )
{ # skip UNKNOWN HEADER
next ;
}
2008-11-03 20:26:11 +00:00
if ( $ skiphostline == 1 )
{
$ skiphostline = 0 ;
next ;
}
if ( $ templateline !~ /^\s*$/ ) # skip blanks
2008-09-24 19:17:35 +00:00
{
# Build template array with no header
push ( @ template_noheader , $ templateline ) ;
2008-11-03 20:26:11 +00:00
} # if header
2008-09-24 19:17:35 +00:00
} # end foreach templateline
# if nodearray matches template exactly,quit processing templates
2008-11-10 21:40:43 +00:00
my $ are_equal =
compare_arrays ( \ @ nodearray_noheader , \ @ template_noheader ) ;
if ( $ are_equal )
2008-09-24 19:17:35 +00:00
{
$ matchedtemplate = $ template ;
$ match = 1 ;
last ;
}
else # go to next template
{
$ match = 0 ;
@ template_noheader = ( ) ;
}
} # end template exist
} #end foreach template
#
# if no match
# if generate a new template - check the list of template files
# to see if there is one that does not exist
# put node data to new template file
#
2008-08-08 13:20:20 +00:00
if ( $ match == 0 )
{
my $ nodesaved = 0 ;
foreach $ template ( @ templatearray )
{
if ( ! - f "$template" )
{
if ( ! open ( NEWTEMPLATE , ">$template" ) )
{
$ rsp - > { data } - > [ 0 ] = "Error opening $template:\n" ;
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
return ;
}
else
{
print NEWTEMPLATE @ Nodearray ; # build a new template
$ nodesaved = 1 ;
close ( NEWTEMPLATE ) ;
$ matchedtemplate = $ template ;
last ;
}
}
}
if ( $ nodesaved == 0 )
{ # out of templates
$ matchedtemplate = "no template" ; # put in other list
}
}
@ info [ 0 ] = $ matchedtemplate ;
@ info [ 1 ] = $ nodename ;
return @ info ;
}
2009-07-07 17:10:27 +00:00
2008-08-08 13:20:20 +00:00
#------------------------------------------------------------------------------
= head3 writereport
The purpose of this routine is to write the report to the output file
= cut
#------------------------------------------------------------------------------
sub writereport
{
2008-09-24 19:17:35 +00:00
my ( $ class , $ outputfile , $ Node_hash , $ nodelistin , $ callback ,
$ ignorefirsttemplate )
= @ _ ;
2008-08-08 13:20:20 +00:00
my % nodehash = %$ Node_hash ;
2008-09-24 19:17:35 +00:00
my @ dshnodearray = @$ nodelistin ;
2008-08-08 13:20:20 +00:00
my $ pname = "writereport" ;
my $ template ;
my @ nodenames ;
my @ nodearray ;
#
# Header message
#
my $ rsp = { } ;
2008-09-24 19:17:35 +00:00
$ ignorefirsttemplate =~ tr /a-z/ A - Z / ; # convert to upper
2008-10-29 16:10:44 +00:00
my $ firstpass = 0 ;
2008-08-08 13:20:20 +00:00
foreach my $ template ( sort keys % nodehash )
{
# print template name
$ rsp - > { data } - > [ 0 ] = "The following nodes match $template:\n" ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ 0 ] ;
}
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-08-08 13:20:20 +00:00
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
#print list of nodes
@ nodenames = @ { $ nodehash { $ template } } ;
2008-11-03 20:26:11 +00:00
my $ nodelist = "" ;
foreach my $ nodenameline ( @ nodenames )
2008-08-08 13:20:20 +00:00
{
2008-11-03 20:26:11 +00:00
# split apart the list of nodes
my @ longnodenames = split ( ',' , $ nodenameline ) ;
foreach my $ node ( @ longnodenames )
{
my @ shortnodename = split ( /\./ , $ node ) ;
push @ nodearray , $ shortnodename [ 0 ] ; # add to process list
$ nodelist . = $ shortnodename [ 0 ] ; # add to print list
$ nodelist . = ',' ;
}
}
2009-07-07 17:10:27 +00:00
2008-11-03 20:26:11 +00:00
chop $ nodelist ;
2009-07-07 17:10:27 +00:00
# convert to noderanges if possible
my $ nodearray ;
$ nodearray - > { 0 } = \ @ nodearray ;
my $ newnodelist = abbreviate_noderange ( $ nodearray - > { 0 } ) ;
2008-11-03 20:26:11 +00:00
if ( $ ignorefirsttemplate ne "YES" )
{ # report first template
2009-07-07 17:10:27 +00:00
$ rsp - > { data } - > [ 0 ] = "$newnodelist\n" ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ 0 ] ;
}
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-11-03 20:26:11 +00:00
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
}
else
{ # do not report nodes on first template
if ( $ firstpass == 0 )
{
$ rsp - > { data } - > [ 0 ] =
"Not reporting matches on first template.\n" ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ 0 ] ;
}
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-10-29 15:57:35 +00:00
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
2008-11-03 20:26:11 +00:00
$ firstpass = 1 ;
2008-08-08 13:20:20 +00:00
}
}
2008-10-29 15:19:57 +00:00
$ ignorefirsttemplate = "NO" ; # reset for remaining templates
2008-08-08 13:20:20 +00:00
}
#
# Now check to see if we covered all nodes in the dsh
2008-10-28 15:32:58 +00:00
# short names must match long names, ignore NO_NODE_RANGE
2008-08-08 13:20:20 +00:00
#
my $ nodefound = 0 ;
2008-11-03 20:26:11 +00:00
my $ rsp = { } ;
2008-08-08 13:20:20 +00:00
foreach my $ dshnodename ( @ dshnodearray )
{
2008-11-03 20:26:11 +00:00
if ( ( $ dshnodename ne "NO_NODE_RANGE" ) && ( $ dshnodename ne "UNKNOWN" ) )
{ # skip it
2008-10-28 15:32:58 +00:00
my @ shortdshnodename ;
my @ shortnodename ;
chomp $ dshnodename ;
$ dshnodename =~ s/\s*//g ; # remove blanks
foreach my $ nodename ( @ nodearray )
2008-08-08 13:20:20 +00:00
{
2008-10-28 15:32:58 +00:00
@ shortdshnodename = split ( /\./ , $ dshnodename ) ;
@ shortnodename = split ( /\./ , $ nodename ) ;
if ( $ shortdshnodename [ 0 ] eq $ shortnodename [ 0 ] )
{
$ nodefound = 1 ; # we have a match
last ;
}
2008-08-08 13:20:20 +00:00
}
2008-10-28 15:32:58 +00:00
if ( $ nodefound == 0 )
{ # dsh node name missing
# add missing node
2008-11-03 20:26:11 +00:00
$ rsp - > { data } - > [ 0 ] . = $ shortdshnodename [ 0 ] ;
$ rsp - > { data } - > [ 0 ] . = "," ;
2008-08-08 13:20:20 +00:00
}
}
}
2008-11-03 20:26:11 +00:00
if ( $ rsp - > { data } - > [ 0 ] )
{
$ rsp - > { data } - > [ 0 ] = "The following nodes had no output:\n" ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ 0 ] ;
}
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-11-03 20:26:11 +00:00
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
chop $ rsp - > { data } - > [ 0 ] ;
$ rsp - > { data } - > [ 0 ] . = "\n" ;
2008-11-07 15:34:14 +00:00
if ( $ ::OUTPUT_FILE_HANDLE )
{
print $ ::OUTPUT_FILE_HANDLE $ rsp - > { data } - > [ 0 ] ;
}
if ( ( $ ::VERBOSE ) || ( $ ::NOOUTPUTFILE ) )
2008-11-03 20:26:11 +00:00
{
xCAT::MsgUtils - > message ( "I" , $ rsp , $ callback ) ;
}
}
$ nodefound = 0 ;
2008-08-08 13:20:20 +00:00
return ;
}
2008-09-24 19:17:35 +00:00
2008-09-19 17:32:20 +00:00
#------------------------------------------------------------------------------
2008-10-24 18:39:43 +00:00
= head3 xdshoutput
2008-09-19 17:32:20 +00:00
2009-04-20 13:08:25 +00:00
Check xdsh output - get output from command and pipe to xdshcoll
2008-09-19 17:32:20 +00:00
= cut
#------------------------------------------------------------------------------
2008-09-24 19:17:35 +00:00
sub xdshoutput
2008-09-19 17:32:20 +00:00
{
2008-10-24 18:39:43 +00:00
my $ rsp = shift ;
my $ rc = 0 ;
# Handle info structure, like xdsh returns
if ( $ rsp - > { warning } )
{
2008-10-27 19:40:10 +00:00
foreach ( @ { $ rsp - > { warning } } )
{
my $ line = $ _ ;
$ line . = "\n" ;
push ( @ errresult , $ line ) ;
}
}
if ( $ rsp - > { error } )
{
foreach ( @ { $ rsp - > { error } } )
{
my $ line = $ _ ;
$ line . = "\n" ;
push ( @ errresult , $ line ) ;
}
2008-10-24 18:39:43 +00:00
}
if ( $ rsp - > { info } )
{
foreach ( @ { $ rsp - > { info } } )
{
my $ line = $ _ ;
$ line . = "\n" ;
push ( @ cmdresult , $ line ) ;
}
}
2009-09-30 16:11:56 +00:00
if ( $ rsp - > { data } )
{
foreach ( @ { $ rsp - > { data } } )
{
my $ line = $ _ ;
$ line . = "\n" ;
push ( @ cmdresult , $ line ) ;
}
}
2008-10-24 18:39:43 +00:00
return $ rc ;
}
#------------------------------------------------------------------------------
= head3 rinvoutput
Check rinv output - get output from command
= cut
#------------------------------------------------------------------------------
sub rinvoutput
{
my $ rsp = shift ;
2009-09-30 16:11:56 +00:00
#print "I am here \n";
#print Dumper($rsp);
2008-10-24 18:39:43 +00:00
# Handle node structure, like rinv returns
my $ errflg = 0 ;
#if (scalar @{$rsp->{node}})
if ( $ rsp - > { node } )
2008-09-24 19:17:35 +00:00
{
2008-10-24 18:39:43 +00:00
my $ nodes = ( $ rsp - > { node } ) ;
my $ node ;
foreach $ node ( @$ nodes )
{
my $ desc = $ node - > { name } - > [ 0 ] ;
if ( $ node - > { errorcode } )
{
if ( ref ( $ node - > { errorcode } ) eq 'ARRAY' )
{
foreach my $ ecode ( @ { $ node - > { errorcode } } )
{
$ xCAT:: Client:: EXITCODE |= $ ecode ;
}
}
else
{
$ xCAT:: Client:: EXITCODE |= $ node - > { errorcode } ;
} # assume it is a non-reference scalar
}
if ( $ node - > { error } )
{
$ desc . = ": Error: " . $ node - > { error } - > [ 0 ] ;
$ errflg = 1 ;
}
if ( $ node - > { data } )
{
if ( ref ( \ ( $ node - > { data } - > [ 0 ] ) ) eq 'SCALAR' )
{
$ desc = $ desc . ": " . $ node - > { data } - > [ 0 ] ;
}
else
{
if ( $ node - > { data } - > [ 0 ] - > { desc } )
{
$ desc = $ desc . ": " . $ node - > { data } - > [ 0 ] - > { desc } - > [ 0 ] ;
}
if ( $ node - > { data } - > [ 0 ] - > { contents } )
{
$ desc = "$desc: " . $ node - > { data } - > [ 0 ] - > { contents } - > [ 0 ] ;
}
}
}
if ( $ desc )
{
my $ line = $ desc ;
$ line . = "\n" ;
push ( @ cmdresult , $ line ) ;
}
}
2008-09-24 19:17:35 +00:00
}
2008-10-24 18:39:43 +00:00
return 0 ;
}
#------------------------------------------------------------------------------
= head3 storeresults
2009-04-20 13:08:25 +00:00
Runs command output through xdshcoll and stores in /tmp/ <tempfile>
2008-10-24 18:39:43 +00:00
store results in $ tempfile or $ templatepath ( for seed node ) based on
$ processflag = seednode
= cut
#------------------------------------------------------------------------------
sub storeresults
{
2008-10-27 19:40:10 +00:00
my $ callback = shift ;
2008-10-24 18:39:43 +00:00
# open file to write results of xdsh or rinv command
2008-09-24 19:17:35 +00:00
my $ newtempfile = $ tempfile ;
$ newtempfile . = "temp" ;
open ( FILE , ">$newtempfile" ) ;
if ( $? > 0 )
{
2008-10-24 18:39:43 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Could not open $newtempfile\n" ;
2008-10-27 19:40:10 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2008-09-24 19:17:35 +00:00
return 1 ;
}
2008-10-24 18:39:43 +00:00
foreach my $ line ( @ cmdresult )
2008-09-24 19:17:35 +00:00
{
print FILE $ line ;
}
close FILE ;
my $ outputfile ;
if ( $ processflg eq "seednode" )
2008-10-24 18:39:43 +00:00
{ # cmd to seednode
2008-09-24 19:17:35 +00:00
$ outputfile = $ templatepath ;
}
else
2008-10-24 18:39:43 +00:00
{ # cmd to nodelist
2008-09-24 19:17:35 +00:00
$ outputfile = $ tempfile ;
}
2009-04-20 13:08:25 +00:00
# open file to put results of xdshcoll
2008-09-24 19:17:35 +00:00
open ( FILE , ">$outputfile" ) ;
if ( $? > 0 )
{
2008-10-24 18:39:43 +00:00
my $ rsp = { } ;
$ rsp - > { data } - > [ 0 ] = "Could not open $outputfile\n" ;
2008-10-27 19:40:10 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2008-09-24 19:17:35 +00:00
return 1 ;
}
2009-04-20 13:08:25 +00:00
my $ cmd = " /opt/xcat/sbin/xdshcoll <$newtempfile |" ;
2008-09-24 19:17:35 +00:00
2008-11-03 20:26:11 +00:00
open ( XCOLL , "$cmd" ) ;
2008-09-24 19:17:35 +00:00
if ( $? > 0 )
{
2008-10-24 18:39:43 +00:00
my $ rsp = { } ;
2009-04-20 13:08:25 +00:00
$ rsp - > { data } - > [ 0 ] = "Could not call xdshcoll \n" ;
2008-10-27 19:40:10 +00:00
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
2008-09-19 17:32:20 +00:00
return 1 ;
2008-09-24 19:17:35 +00:00
}
my $ line ;
2008-11-03 20:26:11 +00:00
while ( <XCOLL> )
2008-09-24 19:17:35 +00:00
{
$ line = $ _ ;
print FILE $ line
}
2008-11-03 20:26:11 +00:00
close ( XCOLL ) ;
2008-09-24 19:17:35 +00:00
close FILE ;
2008-11-03 20:26:11 +00:00
2009-09-30 16:11:56 +00:00
system ( "/bin/rm $newtempfile" ) ;
2008-09-19 17:32:20 +00:00
2008-10-27 19:40:10 +00:00
# capture errors
2008-11-10 21:40:43 +00:00
#
2008-10-27 19:40:10 +00:00
if ( @ errresult )
{ # if errors
2008-11-07 16:37:05 +00:00
my $ rsp = { } ;
2008-11-10 21:40:43 +00:00
my $ i = 0 ;
2008-10-27 19:40:10 +00:00
foreach my $ line ( @ errresult )
{
2008-11-07 16:53:49 +00:00
$ rsp - > { data } - > [ $ i ] = "$line" ;
2008-11-07 16:37:05 +00:00
$ i + + ;
2008-10-27 19:40:10 +00:00
}
xCAT::MsgUtils - > message ( "E" , $ rsp , $ callback ) ;
}
2008-10-24 18:39:43 +00:00
return ;
2008-09-19 17:32:20 +00:00
}
2008-11-10 21:40:43 +00:00
sub compare_arrays
{
my ( $ first , $ second ) = @ _ ;
return 0 unless @$ first == @$ second ;
for ( my $ i = 0 ; $ i < @$ first ; $ i + + )
{
return 0 if $ first - > [ $ i ] ne $ second - > [ $ i ] ;
}
return 1 ;
}
2008-08-08 13:20:20 +00:00
1 ;