2007-10-26 22:44:33 +00:00
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#TODO: delete entries not being refreshed if no noderange
package xCAT_plugin::conserver ;
2008-07-18 22:24:06 +00:00
use strict ;
2007-10-26 22:44:33 +00:00
use xCAT::Table ;
2008-04-24 18:08:41 +00:00
use xCAT::Utils ;
use Getopt::Long ;
use Sys::Hostname ;
2007-10-26 22:44:33 +00:00
use strict ;
use Data::Dumper ;
my @ cservers = qw( mrv cyclades ) ;
my % termservers ; #list of noted termservers
2008-04-24 18:08:41 +00:00
my $ usage_string =
2009-01-23 04:16:03 +00:00
" makeconservercf [ - d | - - delete ] noderange
2008-04-24 18:08:41 +00:00
makeconservercf [ - l | - - local ]
2008-05-07 11:34:17 +00:00
makeconservercf - h | - - help
2008-04-24 18:08:41 +00:00
makeconservercf - v | - - version
- l | - - local The conserver gets set up only on the local host .
2008-05-07 11:34:17 +00:00
The default goes down to all the conservers on
2009-01-23 04:16:03 +00:00
the server nodes and set them up
- d | - - delete Conserver has the relevant entries for the given noderange removed immediately from configuration
2008-04-24 18:08:41 +00:00
- h | - - help Display this usage statement .
- v | - - version Display the version number . " ;
2008-07-07 18:29:55 +00:00
my $ version_string = xCAT::Utils - > Version ( ) ;
2008-04-24 18:08:41 +00:00
2007-10-26 22:44:33 +00:00
sub handled_commands {
return {
makeconservercf = > "conserver"
}
}
2008-05-07 11:34:17 +00:00
sub preprocess_request {
2008-04-24 18:08:41 +00:00
my $ request = shift ;
if ( $ request - > { _xcatdest } ) { return [ $ request ] ; } #exit if preprocessed
my $ callback = shift ;
my @ requests ;
2008-05-13 01:15:53 +00:00
my $ noderange = $ request - > { node } ; #Should be arrayref
2008-04-24 18:08:41 +00:00
2008-05-07 11:34:17 +00:00
#display usage statement if -h
2008-04-24 18:08:41 +00:00
my $ extrargs = $ request - > { arg } ;
my @ exargs = ( $ request - > { arg } ) ;
if ( ref ( $ extrargs ) ) {
@ exargs = @$ extrargs ;
}
@ ARGV = @ exargs ;
my $ isSN = xCAT::Utils - > isServiceNode ( ) ;
my @ hostinfo = xCAT::Utils - > determinehostname ( ) ;
my % iphash = ( ) ;
foreach ( @ hostinfo ) { $ iphash { $ _ } = 1 ; }
$ Getopt:: Long:: ignorecase = 0 ;
#$Getopt::Long::pass_through=1;
if ( ! GetOptions (
'l|local' = > \ $ ::LOCAL ,
'h|help' = > \ $ ::HELP ,
'v|version' = > \ $ ::VERSION ) ) {
$ request = { } ;
return ;
}
2008-05-07 11:34:17 +00:00
if ( $ ::HELP ) {
2008-04-24 18:08:41 +00:00
$ callback - > ( { data = > $ usage_string } ) ;
$ request = { } ;
return ;
}
2008-05-07 11:34:17 +00:00
if ( $ ::VERSION ) {
2008-04-24 18:08:41 +00:00
$ callback - > ( { data = > $ version_string } ) ;
$ request = { } ;
return ;
}
if ( $ ::LOCAL ) {
if ( $ noderange && @$ noderange > 0 ) {
$ callback - > ( { data = > "Invalide option -l or --local when there are nodes specofied." } ) ;
$ request = { } ;
return ;
}
}
2008-05-07 11:34:17 +00:00
2008-04-24 18:08:41 +00:00
# get site master
my $ master = xCAT::Utils - > get_site_Master ( ) ;
if ( ! $ master ) { $ master = hostname ( ) ; }
# get conserver for each node
my % cons_hash = ( ) ;
my $ hmtab = xCAT::Table - > new ( 'nodehm' ) ;
my @ items ;
my $ allnodes = 1 ;
if ( $ noderange && @$ noderange > 0 ) {
$ allnodes = 0 ;
2008-09-12 15:12:03 +00:00
my $ hmcache = $ hmtab - > getNodesAttribs ( $ noderange , [ 'node' , 'serialport' , 'cons' , 'conserver' ] ) ;
2008-04-24 18:08:41 +00:00
foreach my $ node ( @$ noderange ) {
2008-07-07 22:47:38 +00:00
my $ ent = $ hmcache - > { $ node } - > [ 0 ] ; #$hmtab->getNodeAttribs($node,['node', 'serialport','cons', 'conserver']);
2008-05-07 11:34:17 +00:00
push @ items , $ ent ;
2008-04-24 18:08:41 +00:00
}
} else {
$ allnodes = 1 ;
2008-05-02 01:59:50 +00:00
@ items = $ hmtab - > getAllNodeAttribs ( [ 'node' , 'serialport' , 'cons' , 'conserver' ] ) ;
2008-04-24 18:08:41 +00:00
}
my @ nodes = ( ) ;
foreach ( @ items ) {
2008-05-07 11:34:17 +00:00
if ( ( ( ! defined ( $ _ - > { cons } ) ) || ( $ _ - > { cons } eq "" ) ) and ! defined ( $ _ - > { serialport } ) ) { next ; } #skip if 'cons' is not defined for this node, unless serialport suggests otherwise
2008-04-24 18:08:41 +00:00
if ( defined ( $ _ - > { conserver } ) ) { push @ { $ cons_hash { $ _ - > { conserver } } { nodes } } , $ _ - > { node } ; }
else { push @ { $ cons_hash { $ master } { nodes } } , $ _ - > { node } ; }
push @ nodes , $ _ - > { node } ;
}
#send all nodes to the MN
if ( ! $ isSN ) { #
my $ reqcopy = { %$ request } ;
$ reqcopy - > { '_xcatdest' } = $ master ;
$ reqcopy - > { '_allnodes' } = $ allnodes ; # the original command comes with nodes or not
if ( $ allnodes == 1 ) { @ nodes = ( ) ; }
2008-05-07 11:34:17 +00:00
$ reqcopy - > { node } = \ @ nodes ;
2008-04-24 18:08:41 +00:00
push @ requests , $ reqcopy ;
2008-05-07 11:34:17 +00:00
if ( $ ::LOCAL ) { return \ @ requests ; }
}
# send to SN
2008-04-24 18:08:41 +00:00
foreach my $ cons ( keys % cons_hash ) {
#print "cons=$cons\n";
2008-05-07 11:34:17 +00:00
my $ doit = 0 ;
2008-04-24 18:08:41 +00:00
if ( $ isSN ) {
if ( exists ( $ iphash { $ cons } ) ) { $ doit = 1 ; }
} else {
if ( ! exists ( $ iphash { $ cons } ) ) { $ doit = 1 ; }
}
2008-05-07 11:34:17 +00:00
2008-04-24 18:08:41 +00:00
if ( $ doit ) {
my $ reqcopy = { %$ request } ;
$ reqcopy - > { '_xcatdest' } = $ cons ;
2008-04-29 23:45:00 +00:00
$ reqcopy - > { '_allnodes' } = [ $ allnodes ] ; # the original command comes with nodes or not
2008-04-24 18:08:41 +00:00
$ reqcopy - > { node } = $ cons_hash { $ cons } { nodes } ;
my $ no = $ reqcopy - > { node } ;
#print "node=@$no\n";
push @ requests , $ reqcopy ;
}
2008-05-07 11:34:17 +00:00
}
2008-04-24 18:08:41 +00:00
return \ @ requests ;
}
2007-10-26 22:44:33 +00:00
sub process_request {
my $ req = shift ;
my $ cb = shift ;
if ( $ req - > { command } - > [ 0 ] eq "makeconservercf" ) {
makeconservercf ( $ req , $ cb ) ;
}
}
sub docfheaders {
# Put in standard headers common to all conserver.cf files
my $ content = shift ;
my $ numlines = @$ content ;
my @ meat = grep ( ! /^#/ , @$ content ) ;
2008-01-10 01:14:14 +00:00
unless ( grep ( /^config \* {/ , @ meat ) ) {
push @$ content , "config * {\n" ;
2008-01-11 21:31:58 +00:00
push @$ content , " sslrequired yes;\n" ;
2008-05-14 21:09:41 +00:00
push @$ content , " sslauthority /etc/xcat/cert/ca.pem;\n" ;
2008-01-10 01:14:14 +00:00
push @$ content , " sslcredentials /etc/xcat/cert/server-cred.pem;\n" ;
push @$ content , "}\n" ;
}
2007-10-26 22:44:33 +00:00
unless ( grep ( /^default full/ , @ meat ) ) {
push @$ content , "default full { rw *; }\n" ;
}
unless ( grep ( /^default cyclades/ , @ meat ) ) {
push @$ content , "default cyclades { type host; portbase 7000; portinc 1; }\n"
}
unless ( grep ( /^default mrv/ , @ meat ) ) {
push @$ content , "default mrv { type host; portbase 2000; portinc 100; }\n"
}
unless ( grep ( /^access \*/ , @ meat ) ) {
#push @$content,"#xCAT BEGIN ACCESS\n";
push @$ content , "access * {\n" ;
push @$ content , " trusted 127.0.0.1;\n" ;
2008-04-24 18:08:41 +00:00
if ( xCAT::Utils - > isServiceNode ( ) ) {
my $ master = xCAT::Utils - > get_site_Master ( ) ;
push @$ content , " trusted $master;\n" ;
}
2007-10-26 22:44:33 +00:00
push @$ content , "}\n" ;
#push @$content,"#xCAT END ACCESS\n";
}
unless ( grep ( /^default \*/ , @ meat ) ) {
push @$ content , "default * {\n" ;
push @$ content , " logfile /var/log/consoles/&;\n" ;
push @$ content , " timestamp 1hab;\n" ;
push @$ content , " include full;\n" ;
push @$ content , " master localhost;\n" ;
2008-09-10 15:07:26 +00:00
#-- if option "conserverondemand" in site table is set to yes
#-- then start all consoles on demand
#-- this helps eliminate many ssh connections to blade AMM
#-- which seems to kill AMMs occasionally
my $ sitetab = xCAT::Table - > new ( 'site' ) ;
my $ vcon = $ sitetab - > getAttribs ( { key = > "consoleondemand" } , 'value' ) ;
if ( $ vcon and $ vcon - > { "value" } and $ vcon - > { "value" } eq "yes" ) {
push @$ content , " options ondemand;\n" ;
}
2007-10-26 22:44:33 +00:00
push @$ content , "}\n" ;
}
}
sub makeconservercf {
my $ req = shift ;
% termservers = ( ) ; #clear hash of existing entries
my $ cb = shift ;
2009-01-23 04:16:03 +00:00
my $ extrargs = $ req - > { arg } ;
my @ exargs = ( $ req - > { arg } ) ;
if ( ref ( $ extrargs ) ) {
@ exargs = @$ extrargs ;
}
@ ARGV = @ exargs ;
$ Getopt:: Long:: ignorecase = 0 ;
#$Getopt::Long::pass_through=1;
my $ delmode ;
GetOptions ( 'd|delete' = > \ $ delmode ) ;
2007-10-26 22:44:33 +00:00
my $ nodes = $ req - > { node } ;
2008-05-13 01:15:53 +00:00
my $ svboot = 0 ;
if ( exists ( $ req - > { svboot } ) ) { $ svboot = 1 ; }
2007-10-26 22:44:33 +00:00
my $ cfile ;
my @ filecontent ;
open $ cfile , '/etc/conserver.cf' ;
while ( <$cfile> ) {
push @ filecontent , $ _ ;
}
close $ cfile ;
docfheaders ( \ @ filecontent ) ;
2008-04-24 18:08:41 +00:00
my $ isSN = xCAT::Utils - > isServiceNode ( ) ;
my @ hostinfo = xCAT::Utils - > determinehostname ( ) ;
my % iphash = ( ) ;
foreach ( @ hostinfo ) { $ iphash { $ _ } = 1 ; }
#print "process_request nodes=@$nodes\n";
2007-10-26 22:44:33 +00:00
my $ hmtab = xCAT::Table - > new ( 'nodehm' ) ;
2008-07-07 22:47:38 +00:00
my @ cfgents1 ; # = $hmtab->getAllNodeAttribs(['cons','serialport','mgt','conserver','termserver','termport']);
if ( ( $ nodes and @$ nodes > 0 ) or $ req - > { noderange } - > [ 0 ] ) {
@ cfgents1 = $ hmtab - > getNodesAttribs ( $ nodes , [ 'cons' , 'serialport' , 'mgt' , 'conserver' , 'termserver' , 'termport' ] ) ;
2008-10-14 11:19:57 +00:00
#to make the result consistent to getAllNodeAttribs
my @ tmpcfgents1 ;
foreach my $ ent ( @ cfgents1 )
{
foreach my $ nodeent ( keys %$ ent )
{
push @ tmpcfgents1 , $ ent - > { $ nodeent } - > [ 0 ] ;
}
}
@ cfgents1 = @ tmpcfgents1
2008-07-07 22:47:38 +00:00
} else {
@ cfgents1 = $ hmtab - > getAllNodeAttribs ( [ 'cons' , 'serialport' , 'mgt' , 'conserver' , 'termserver' , 'termport' ] ) ;
}
2007-10-26 22:44:33 +00:00
#cfgents should now have all the nodes, so we can fill in our hashes one at a time.
2008-04-29 23:45:00 +00:00
2008-05-02 01:59:50 +00:00
# skip the one that does not have 'cons' defined, unless a serialport setting suggests otherwise
2008-04-29 23:45:00 +00:00
my @ cfgents = ( ) ;
2008-05-07 11:34:17 +00:00
foreach ( @ cfgents1 ) {
if ( $ _ - > { cons } or defined ( $ _ - > { 'serialport' } ) ) { push @ cfgents , $ _ ; }
2008-04-29 23:45:00 +00:00
}
2008-05-07 11:34:17 +00:00
2008-04-29 23:45:00 +00:00
# get the teminal servers and terminal port when cons is mrv or cyclades
2007-10-26 22:44:33 +00:00
foreach ( @ cfgents ) {
2008-05-02 01:59:50 +00:00
unless ( $ _ - > { cons } ) { $ _ - > { cons } = $ _ - > { mgt } ; } #populate with fallback
2008-07-07 22:47:38 +00:00
#my $cmeth=$_->{cons};
#if (grep(/^$cmeth$/,@cservers)) { #terminal server, more attribs needed
# my $node = $_->{node};
# my $tent = $hmtab->getNodeAttribs($node,["termserver","termport"]);
# $_->{termserver} = $tent->{termserver};
# $termservers{$tent->{termserver}} = 1;
# $_->{termport}= $tent->{termport};
#}
2007-10-26 22:44:33 +00:00
}
2008-04-29 23:45:00 +00:00
# nodes defined, it is either on the service node or mkconserver is call with noderange on mn
2007-10-26 22:44:33 +00:00
if ( ( $ nodes and @$ nodes > 0 ) or $ req - > { noderange } - > [ 0 ] ) {
2008-04-24 18:08:41 +00:00
# strip all xCAT configured stuff from config if the original command was for all nodes
2008-04-29 23:45:00 +00:00
if ( ( $ req - > { _allnodes } ) && ( $ req - > { _allnodes } - > [ 0 ] == 1 ) ) { zapcfg ( \ @ filecontent ) ; }
2007-10-26 22:44:33 +00:00
foreach ( @$ nodes ) {
my $ node = $ _ ;
foreach ( @ cfgents ) {
if ( $ _ - > { node } eq $ node ) {
2008-09-06 21:49:25 +00:00
if ( $ _ - > { termserver } and not $ termservers { $ _ - > { termserver } } ) {
2007-10-26 22:44:33 +00:00
dotsent ( $ _ , \ @ filecontent ) ;
2008-09-06 21:49:25 +00:00
$ termservers { $ _ - > { termserver } } = 1 ; #prevent needless cycles being burned
2007-10-26 22:44:33 +00:00
}
2009-01-23 04:16:03 +00:00
donodeent ( $ _ , \ @ filecontent , $ delmode ) ;
2007-10-26 22:44:33 +00:00
}
}
}
} else { #no nodes specified, do em all up
zapcfg ( \ @ filecontent ) ; # strip all xCAT configured stuff from config
2008-05-07 11:34:17 +00:00
2008-04-02 15:10:27 +00:00
# filter out node types without console support
my $ typetab = xCAT::Table - > new ( 'nodetype' ) ;
my % type ;
if ( defined ( $ typetab ) ) {
my @ ents = $ typetab - > getAllNodeAttribs ( [ qw( node nodetype ) ] ) ;
foreach ( @ ents ) {
$ type { $ _ - > { node } } = $ _ - > { nodetype } ;
}
}
2007-10-26 22:44:33 +00:00
foreach ( @ cfgents ) {
2008-04-24 18:08:41 +00:00
my $ keepdoing = 0 ;
2008-05-07 11:34:17 +00:00
if ( $ isSN && $ _ - > { conserver } && exists ( $ iphash { $ _ - > { conserver } } ) ) {
2008-04-24 18:08:41 +00:00
$ keepdoing = 1 ; #only hanlde the nodes that use this SN as the conserver
2007-10-26 22:44:33 +00:00
}
2008-04-24 18:08:41 +00:00
if ( ! $ isSN ) { $ keepdoing = 1 ; } #handle all for MN
if ( $ keepdoing ) {
2008-09-06 21:49:25 +00:00
if ( $ _ - > { termserver } and not $ termservers { $ _ - > { termserver } } ) {
2008-04-24 18:08:41 +00:00
dotsent ( $ _ , \ @ filecontent ) ;
2008-09-06 21:49:25 +00:00
$ termservers { $ _ - > { termserver } } = 1 ; #prevent needless cycles being burned
2008-04-24 18:08:41 +00:00
}
if ( $ type { $ _ - > { node } } !~ /fsp|bpa|hmc|ivm/ ) {
donodeent ( $ _ , \ @ filecontent ) ;
}
2008-04-02 15:10:27 +00:00
}
2007-10-26 22:44:33 +00:00
}
}
open $ cfile , '>' , '/etc/conserver.cf' ;
foreach ( @ filecontent ) {
print $ cfile $ _ ;
}
close $ cfile ;
2008-04-24 18:08:41 +00:00
2008-05-13 01:15:53 +00:00
if ( ! $ svboot ) {
#restart conserver daemon
2008-05-29 18:30:48 +00:00
my $ cmd ;
if ( - f "/var/run/conserver.pid" ) {
2008-10-17 17:59:57 +00:00
$ cmd = "/etc/init.d/conserver restart" ;
2008-05-29 18:30:48 +00:00
} else {
2008-10-17 17:59:57 +00:00
$ cmd = "/etc/init.d/conserver start" ;
2008-05-29 18:30:48 +00:00
}
2008-05-13 01:15:53 +00:00
xCAT::Utils - > runcmd ( $ cmd , - 1 ) ;
}
2007-10-26 22:44:33 +00:00
}
sub dotsent {
my $ cfgent = shift ;
my $ tserv = $ cfgent - > { termserver } ;
my $ content = shift ;
my $ idx = 0 ;
my $ toidx = - 1 ;
my $ skip = 0 ;
my $ skipnext = 0 ;
2008-04-24 18:08:41 +00:00
2007-10-26 22:44:33 +00:00
while ( $ idx < $#$ content ) { # Go through and delete that which would match my entry
if ( $ content - > [ $ idx ] =~ /^#xCAT BEGIN $tserv TS/ ) {
$ toidx = $ idx ; #TODO put it back right where I found it
$ skip = 1 ;
$ skipnext = 1 ;
} elsif ( $ content - > [ $ idx ] =~ /^#xCAT END $tserv TS/ ) {
$ skipnext = 0 ;
}
if ( $ skip ) {
splice ( @$ content , $ idx , 1 ) ;
} else {
$ idx + + ;
}
$ skip = $ skipnext ;
}
push @$ content , "#xCAT BEGIN $tserv TS\n" ;
push @$ content , "default $tserv {\n" ;
push @$ content , " include " . $ cfgent - > { cons } . ";\n" ;
push @$ content , " host $tserv;\n" ;
push @$ content , "}\n" ;
push @$ content , "#xCAT END $tserv TS\n" ;
2008-05-07 11:34:17 +00:00
2007-10-26 22:44:33 +00:00
}
2008-04-24 18:08:41 +00:00
2007-10-26 22:44:33 +00:00
sub donodeent {
my $ cfgent = shift ;
my $ node = $ cfgent - > { node } ;
my $ content = shift ;
2009-01-23 04:16:03 +00:00
my $ delmode = shift ;
2007-10-26 22:44:33 +00:00
my $ idx = 0 ;
my $ toidx = - 1 ;
my $ skip = 0 ;
my $ skipnext = 0 ;
2008-04-24 18:08:41 +00:00
my $ isSN = xCAT::Utils - > isServiceNode ( ) ;
2007-10-26 22:44:33 +00:00
while ( $ idx < $#$ content ) { # Go through and delete that which would match my entry
if ( $ content - > [ $ idx ] =~ /^#xCAT BEGIN $node CONS/ ) {
$ toidx = $ idx ; #TODO put it back right where I found it
$ skip = 1 ;
$ skipnext = 1 ;
} elsif ( $ content - > [ $ idx ] =~ /^#xCAT END $node CONS/ ) {
$ skipnext = 0 ;
}
if ( $ skip ) {
splice ( @$ content , $ idx , 1 ) ;
} else {
$ idx + + ;
}
$ skip = $ skipnext ;
}
2009-01-23 04:16:03 +00:00
if ( $ delmode ) {
return ;
}
2007-10-26 22:44:33 +00:00
push @$ content , "#xCAT BEGIN $node CONS\n" ;
push @$ content , "console $node {\n" ;
2008-05-07 11:34:17 +00:00
#if ($cfgent->{cons}
2007-10-26 22:44:33 +00:00
my $ cmeth = $ cfgent - > { cons } ;
2008-04-04 12:59:36 +00:00
#print $cmeth."\n";
2008-05-07 11:34:17 +00:00
if ( grep ( /^$cmeth$/ , @ cservers ) ) {
2007-10-26 22:44:33 +00:00
push @$ content , " include " . $ cfgent - > { termserver } . ";\n" ;
2008-05-07 11:34:17 +00:00
push @$ content , " port " . $ cfgent - > { termport } . ";\n" ;
2008-05-29 18:53:37 +00:00
if ( ( ! $ isSN ) && ( $ cfgent - > { conserver } ) && xCAT::Utils - > thishostisnot ( $ cfgent - > { conserver } ) ) { # let the master handle it
2008-04-24 18:08:41 +00:00
push @$ content , " master " . $ cfgent - > { conserver } . ";\n" ;
2008-05-07 11:34:17 +00:00
}
2007-10-26 22:44:33 +00:00
} else { #a script method...
push @$ content , " type exec;\n" ;
2008-05-29 18:53:37 +00:00
if ( ( ! $ isSN ) && ( $ cfgent - > { conserver } ) && xCAT::Utils - > thishostisnot ( $ cfgent - > { conserver } ) ) { # let the master handle it
2008-04-24 18:08:41 +00:00
push @$ content , " master " . $ cfgent - > { conserver } . ";\n" ;
} else { # handle it here
2008-05-07 11:34:17 +00:00
my $ locerror = $ isSN ? "PERL_BADLANG=0 " : '' ; # on service nodes, often LC_ALL is not set and perl complains
push @$ content , " exec $locerror" . $ ::XCATROOT . "/share/xcat/cons/" . $ cmeth . " " . $ node . ";\n"
2008-04-24 18:08:41 +00:00
}
2007-10-26 22:44:33 +00:00
}
push @$ content , "}\n" ;
push @$ content , "#xCAT END $node CONS\n" ;
}
sub zapcfg {
my $ content = shift ;
my $ idx = 0 ;
my $ toidx = - 1 ;
my $ skip = 0 ;
my $ skipnext = 0 ;
while ( $ idx <= $#$ content ) { # Go through and delete that which would match my entry
if ( $ content - > [ $ idx ] =~ /^#xCAT BEGIN/ ) {
$ toidx = $ idx ; #TODO put it back right where I found it
$ skip = 1 ;
$ skipnext = 1 ;
} elsif ( $ content - > [ $ idx ] =~ /^#xCAT END/ ) {
$ skipnext = 0 ;
}
if ( $ skip ) {
splice ( @$ content , $ idx , 1 ) ;
} else {
$ idx + + ;
}
$ skip = $ skipnext ;
}
}
2008-04-24 18:08:41 +00:00
2007-10-26 22:44:33 +00:00
1 ;
2008-04-24 18:08:41 +00:00