xcat-core/xCAT-server/lib/xcat/plugins/litetree.pm
vallard 33f84c6b8c added statelite support
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4791 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
2009-12-15 20:38:34 +00:00

303 lines
7.5 KiB
Perl

package xCAT_plugin::litetree;
use xCAT::NodeRange;
use Data::Dumper;
use xCAT::Utils;
use Sys::Syslog;
use xCAT::GlobalDef;
use xCAT::Table;
use Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
use strict;
# synchonize files and directories from mulitple sources.
# object is to return a list of files to be syncronized.
# requesting them. By default we will do read-write files.
my $syncdirTab = "litetree";
my $syncfileTab = "litefile";
my $errored = 0;
sub handled_commands {
# command is syncmount, syncdir is the perl module to use.
return {
litetree => "litetree",
litefile => "litetree",
ilitefile => "litetree"
}
}
sub usage {
my $command = shift;
my $callback = shift;
my $error = shift;
my $msg;
if($command eq "ilitefile"){
$msg = "ilitefile <imagename>
\texample:\n\tilitefile centos5.3-x86_64-compute"
} else{
$msg = "some general usage string";
}
if($error){
$callback->({error=>[$msg],errorcode=>[$error]});
}else{
$callback->({info=>[$msg]});
}
}
sub process_request {
my $request = shift;
my $callback = shift;
my $noderange;
my $image;
# the request can come from node or some one running command
# on xCAT mgmt server
# argument could also be image...
# if request comes from user:
if($request->{node}){
$noderange = $request->{node};
# if request comes from node post script .awk file.
}elsif($request->{'_xcat_clienthost'}){
$noderange = $request->{'_xcat_clienthost'};
}else{
$callback->({error=>["Well Kemosabi, I can't figure out who you are."],errorcode=>[1]});
return;
}
if(!$noderange){
my $usage_string="Missing Noderange\n";
$callback->({error=>[$usage_string],errorcode=>[1]});
$request = {};
return;
}
my $command = $request->{command}->[0];
if($command eq "litetree"){
return syncmount("dir",$request,$callback,$noderange);
}elsif($command eq "litefile"){
return syncmount("file",$request, $callback,$noderange);
}elsif($command eq "ilitefile"){
#print Dumper($request);
unless($request->{arg}){
usage($command, $callback,1);
return 1;
}
return syncmount("image",$request, $callback,$request->{arg});
}else{
$callback->({error=>["error in code..."], errorcode=>[127]});
$request = {};
return;
}
}
sub syncmount {
my $syncType = shift;
my $request = shift;
my $callback = shift;
# deterimine which node is calling this
# then find out what directories to use.
my $noderange = shift;
my @nodes = @{$noderange};
my $tab;
if($syncType eq 'dir'){
$tab = xCAT::Table->new($syncdirTab,-create=>1);
}elsif($syncType =~ /file|image/ ){
$tab = xCAT::Table->new($syncfileTab,-create=>1);
}else{
$callback->({error=>["error in code..."], errorcode=>[127]});
$request = {};
return;
}
my $ostab;
my %osents;
unless($syncType =~ /image/){
$ostab = xCAT::Table->new('nodetype');
%osents = %{$ostab->getNodesAttribs(\@nodes,['profile','os','arch'])};
}
foreach my $node (@nodes){
# node may be an image...
my $ent;
if(! $syncType =~ /image/){
$ent = $osents{$node}->[0];
unless($ent->{os} && $ent->{arch} && $ent->{profile}){
$callback->({error=>["$node does not have os, arch, or profile defined in nodetype table"],errorcode=>[1]});
$request = {};
return;
}
}
my $fData = getNodeData($syncType,$node,$ent,$tab,$callback);
# now we go through each directory and search for the file.
showSync($syncType,$callback, $node, $fData);
}
}
# In most cases the syncdir will be on the management node so
# want to make sure its not us before we mount things.
sub showSync {
my $syncType = shift; # dir or file
my $callback = shift;
my $node = shift;
my $dirs = shift;
#print Dumper($dirs);
# go through each directory in priority order
#mkdir "/mnt/xcat";
if($syncType eq "dir"){
foreach my $priority (sort {$a <=> $b} keys %$dirs){
# split the nfs server up from the directory:
my ($server, $dir) = split(/:/,$dirs->{$priority});
if(grep /\$/, $dir){
$dir = subVar($dir,$node,'dir');
$dir =~ s/\/\//\//g;
}
if(grep /\$/, $server){
$server = subVar($server,$node,'server');
}
my $mntpnt = $server . ":" . $dir;
# ok, now we have all the mount points. Let's go through them all?
$callback->({info => "$node: $mntpnt"});
}
}elsif($syncType =~ /file|image/){
foreach my $file (sort keys %$dirs){
my $options = $dirs->{$file};
# persistent,rw
my $out = sprintf("%s: %-13s %s", $node, $options, $file);
$callback->({info => $out});
}
}
}
# some directories will have xCAT database values, like:
# $nodetype.os. If that is the case we need to open up
# the database and look at them. We need to make sure
# we do this sparingly... We don't like tons of hits
# to the database.
sub subVar {
my $dir = shift;
my $node = shift;
my $type = shift;
# parse all the dollar signs...
# if its a directory then it has a / in it, so you have to parse it.
# if its a server, it won't have one so don't worry about it.
my @arr = split("/", $dir);
my $fdir = "";
foreach my $p (@arr){
if($p =~ /^\$/){
# have to sub here:
# get rid of the $ sign.
$p =~ s/\$//g;
# check if p is just the node name:
if($p eq 'node'){
# it is so, just return the node.
$fdir .= "/$node";
}else{
# ask the xCAT DB what the attribute is.
my ($table, $col) = split('\.', $p);
my $tab = xCAT::Table->new($table);
my $ent = $tab->getNodeAttribs($node,[$col]);
my $val = $ent->{$col};
unless($val){
# couldn't find the value!!
$val = "UNDEFINED"
}
if($type eq 'dir'){
$fdir .= "/$val";
}else{
$fdir .= $val;
}
}
}else{
# no substitution here
$fdir .= "/$p";
}
}
return $fdir;
}
# get all the directories or files for given image related to this node.
sub getNodeData {
my $type = shift;
my $node = shift;
my $ent = shift;
my $tab = shift;
my $cb = shift; # callback to print messages!!
# the image name will be something like rhels5.4-x86_64-nfsroot
my $image;
unless($type =~ /image/){
$image = $ent->{os} . "-" . $ent->{arch} . "-" . $ent->{profile};
}else{
$image = $node;
}
my @imageInfo;
my @attrs;
if($type eq "dir"){
@attrs = ['priority', 'directory'];
}elsif($type =~ /file|image/){
@attrs = ['file','options'];
}else{
print "Yikes! error in the code litefile;getNodeData!";
exit 1;
}
# get the directories with no names
push @imageInfo, $tab->getAttribs({image => ''}, @attrs);
# get the ALL directories
push @imageInfo, $tab->getAttribs({image => 'ALL'}, @attrs);
# get for the image specific directories
push @imageInfo, $tab->getAttribs({image => $image}, @attrs);
# pass back a reference to the directory
# now we need to sort them
return mergeArrays($type,\@imageInfo,$cb);
}
sub mergeArrays {
my $type = shift; # file or dir?
my $arr = shift; # array of info from the tables.
my $cb = shift; # callback routine
my $attrs;
if($type eq "dir"){
foreach(@$arr){
if($_->{directory} eq ''){ next; }
$attrs->{$_->{priority}} = $_->{directory};
}
}elsif($type =~ /file|image/){
foreach(@$arr){
if($_->{file} eq ''){ next; }
my $o = $_->{options};
if(!$o){
$o = "tmpfs,rw";
}
# TODO: put some logic in here to make sure that ro is alone.
# if type is ro and con, then this is wrong silly!
#if($p eq "ro" and $t eq "con"){
# my $f = $_->{file};
# $cb->({info => "#skipping: $f. not allowed to be ro and con"});
# next;
#}
$attrs->{$_->{file}} = $o;
}
}else{
print "Yikes! Error in the code in mergeArrays!\n";
exit 1;
}
#print "mergeArrays...\n";
#print Dumper($attrs);
return $attrs;
}
1;
#vim: set ts=2