Author: jfthomps Date: Fri Nov 13 15:44:38 2009 New Revision: 835884 URL: http://svn.apache.org/viewvc?rev=835884&view=rev Log: initial add
Added: incubator/vcl/sandbox/xcat2partimageng/partimageng.pm Added: incubator/vcl/sandbox/xcat2partimageng/partimageng.pm URL: http://svn.apache.org/viewvc/incubator/vcl/sandbox/xcat2partimageng/partimageng.pm?rev=835884&view=auto ============================================================================== --- incubator/vcl/sandbox/xcat2partimageng/partimageng.pm (added) +++ incubator/vcl/sandbox/xcat2partimageng/partimageng.pm Fri Nov 13 15:44:38 2009 @@ -0,0 +1,559 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_plugin::partimageng; +use Storable qw(dclone); +use Sys::Syslog; +use Thread qw(yield); +use POSIX qw(WNOHANG nice); +use xCAT::Table; +use xCAT::Utils; +use xCAT::MsgUtils; +use xCAT::Yum; +use xCAT::Template; +use xCAT::Postage; +use Data::Dumper; +use Getopt::Long; +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); +use File::Path; +use File::Copy; +my $cpiopid; + +sub handled_commands +{ + return { + mkinstall => "nodetype:os=image", + mkimage => "nodetype:os=image", + }; +} + +sub preprocess_request +{ + my $req = shift; + my $callback = shift; + if ($req->{command}->[0] eq 'copycd') + { #don't farm out copycd + return [$req]; + } + + my $stab = xCAT::Table->new('site'); + my $sent; + ($sent) = $stab->getAttribs({key => 'sharedtftp'}, 'value'); + unless ( $sent + and defined($sent->{value}) + and ($sent->{value} =~ /no/i or $sent->{value} =~ /0/)) + { + + #unless requesting no sharedtftp, don't make hierarchical call + return [$req]; + } + + my %localnodehash; + my %dispatchhash; + my $nrtab = xCAT::Table->new('noderes'); + foreach my $node (@{$req->{node}}) + { + my $nodeserver; + my $tent = $nrtab->getNodeAttribs($node, ['tftpserver']); + if ($tent) { $nodeserver = $tent->{tftpserver} } + unless ($tent and $tent->{tftpserver}) + { + $tent = $nrtab->getNodeAttribs($node, ['servicenode']); + if ($tent) { $nodeserver = $tent->{servicenode} } + } + if ($nodeserver) + { + $dispatchhash{$nodeserver}->{$node} = 1; + } + else + { + $localnodehash{$node} = 1; + } + } + my @requests; + my $reqc = {%$req}; + $reqc->{node} = [keys %localnodehash]; + if (scalar(@{$reqc->{node}})) { push @requests, $reqc } + + foreach my $dtarg (keys %dispatchhash) + { #iterate dispatch targets + my $reqcopy = {%$req}; #deep copy + $reqcopy->{'_xcatdest'} = $dtarg; + $reqcopy->{node} = [keys %{$dispatchhash{$dtarg}}]; + push @requests, $reqcopy; + } + return \...@requests; +} + +sub process_request +{ + my $request = shift; + my $callback = shift; + my $doreq = shift; + + if ($request->{command}->[0] eq 'mkinstall') + { + return mkinstall($request, $callback, $doreq); + } + elsif ($request->{command}->[0] eq 'mkimage') + { + return mkimage($request, $callback, $doreq); + } +} + +sub mkinstall +{ + my $request = shift; + my $callback = shift; + my $doreq = shift; + my @nodes = @{$request->{node}}; + my $installroot; + $installroot = "/install"; + + my $node; + my $ostab = xCAT::Table->new('nodetype'); + foreach $node (@nodes) + { + my $osinst; + my $ent = $ostab->getNodeAttribs($node, ['profile', 'os', 'arch']); + my @missingparms; + unless ($ent->{os}) { + push @missingparms,"nodetype.os"; + } + unless ($ent->{arch}) { + push @missingparms,"nodetype.arch"; + } + unless ($ent->{profile}) { + push @missingparms,"nodetype.profile"; + } + unless ($ent->{os} and $ent->{arch} and $ent->{profile}) + { + $callback->( + { + error => ["Missing ".join(',',@missingparms)." for $node"], + errorcode => [1] + } + ); + next; #No profile + } + my $os = $ent->{os}; + my $arch = $ent->{arch}; + my $profile = $ent->{profile}; + # check for /install/image/$arch/$profile + unless (-r "$installroot/image/$arch/$profile.img" or + -r "$installroot/image/$arch/$profile.gz" or + -r "$installroot/image/$arch/$profile-parta1.gz") + { + $callback->( + { + error => [ + "No image file found for $profile in $installroot/image/$arch" + ], + errorcode => [1] + } + ); + next; + } + + #Call the Template class to do substitution to produce a kickstart file in the autoinst dir + my $tmperr = + "Unable to find template in $::XCATROOT/share/xcat/install/image (for $profile/$os/$arch combination)"; + if (-r $::XCATROOT + . "/share/xcat/install/image/$profile.$arch.tmpl") + { + $tmperr = + xCAT::Template->subvars( + $::XCATROOT + . "/share/xcat/install/image/$profile.$arch.tmpl", + "$installroot/autoinst/" . $node, + $node + ); + } + elsif (-r $::XCATROOT + . "/share/xcat/install/image/$profile.tmpl") + { + $tmperr = + xCAT::Template->subvars( + $::XCATROOT + . "/share/xcat/install/image/$profile.tmpl", + "$installroot/autoinst/" . $node, + $node + ); + } + elsif (-r $::XCATROOT + . "/share/xcat/install/image/default.tmpl") + { + $tmperr = + xCAT::Template->subvars( + $::XCATROOT + . "/share/xcat/install/image/default.tmpl", + "$installroot/autoinst/" . $node, + $node + ); + } + if ($tmperr) + { + $callback->( + { + node => + [{name => [$node], error => [$tmperr], errorcode => [1]}] + } + ); + next; + } + + # copy partimageng script to the node-specific post scripts area + #mkpath "$installroot/postscripts/$node"; + #xCAT::Postage->writescript($node,"/install/postscripts/".$node, "install", $callback); + #copy("$installroot/postscripts/partimageng", + # "/$installroot/postscripts/$node/"); + + if ( + -r "/tftpboot/xcat/image/$arch/vmlinuz" + and -r "/tftpboot/xcat/image/$arch/initrd.img" + and -r "$installroot/image/$arch/installer_files/rootimg.gz" + ) + { + + #We have a shot... + my $restab = xCAT::Table->new('noderes'); + my $bptab = xCAT::Table->new('bootparams',-create=>1); + my $hmtab = xCAT::Table->new('nodehm'); + my $ent = + $restab->getNodeAttribs($node, + ['nfsserver', 'primarynic', 'installnic', 'kcmdline']); + my $sent = + $hmtab->getNodeAttribs( + $node, + [ + 'serialport', 'serialspeed', 'serialflow' + ] + ); + unless ($ent and $ent->{nfsserver}) + { + $callback->( + { + error => ["No noderes.nfsserver defined for " . $node], + errorcode => [1] + } + ); + next; + } + + + # determine image server, if tftpserver use it, else use xcatmaster + # else use site.Master, last resort use self + my $imgsrv; + my $ient; + $ient = $restab->getNodeAttribs($node, ['tftpserver']); + if ($ient and $ient->{tftpserver}) + { + $imgsrv = $ient->{tftpserver}; + } + else + { + $ient = $restab->getNodeAttribs($node, ['xcatmaster']); + if ($ient and $ient->{xcatmaster}) + { + $imgsrv = $ient->{xcatmaster}; + } + else + { + $ient = $sitetab->getAttribs({key => master}, value); + if ($ient and $ient->{value}) + { + $imgsrv = $ient->{value}; + } + else + { + my $ipfn = xCAT::Utils->my_ip_facing($node); + if ($ipfn) + { + $imgsrv = $ipfn; #guessing self is second best + + } + } + } + } + unless ($imgsrv) + { + $callback->( + { + error => [ + "Unable to determine or reasonably guess the image server for $node" + ], + errorcode => [1] + } + ); + next; + } + + my $kcmdline = "imgurl=http://$imgsrv/$installroot/image/$arch/installer_files/rootimg.gz image=$installroot/image/$arch/$profile.img blocks=512 action=restore reboot " . $ent->{kcmdline}; + + if (defined($sent->{serialport})) + { + unless ($sent->{serialspeed}) + { + $callback->( + { + error => [ + "serialport defined, but no serialspeed for $node in nodehm table" + ], + errorcode => [1] + } + ); + next; + } + $kcmdline .= + " console=ttyS" + . $sent->{serialport} . "," + . $sent->{serialspeed}; + if ($sent->{serialflow} =~ /(hard|cts|ctsrts)/) + { + $kcmdline .= "n8r"; + } + } + $kcmdline .= " noipv6"; + + $bptab->setNodeAttribs( + $node, + { + kernel => "xcat/image/$arch/vmlinuz", + initrd => "xcat/image/$arch/initrd.img", + kcmdline => $kcmdline + } + ); + } + else + { + $callback->( + { + error => ["vmlinuz and initrd.img not found at /tftpboot/xcat/image/$arch"], + errorcode => [1] + } + ); + } + } + #my $rc = xCAT::Utils->create_postscripts_tar(); + #if ($rc != 0) + #{ + # xCAT::MsgUtils->message("S", "Error creating postscripts tar file."); + #} +} + +sub mkimage +{ + my $request = shift; + my $callback = shift; + my $doreq = shift; + my @nodes = @{$request->{node}}; + my $installroot; + $installroot = "/install"; + + my $node; + my $ostab = xCAT::Table->new('nodetype'); + foreach $node (@nodes) + { + my $osinst; + my $ent = $ostab->getNodeAttribs($node, ['profile', 'os', 'arch']); + my @missingparms; + unless ($ent->{os}) { + push @missingparms,"nodetype.os"; + } + unless ($ent->{arch}) { + push @missingparms,"nodetype.arch"; + } + unless ($ent->{profile}) { + push @missingparms,"nodetype.profile"; + } + unless ($ent->{os} and $ent->{arch} and $ent->{profile}) + { + $callback->( + { + error => ["Missing ".join(',',@missingparms)." for $node"], + errorcode => [1] + } + ); + next; #No profile + } + my $os = $ent->{os}; + my $arch = $ent->{arch}; + my $profile = $ent->{profile}; + # check for /install/image/$arch/$profile + if (-r "$installroot/image/$arch/$profile.img") + { + $callback->( + { + error => [ + "Image file already exists for $profile in $installroot/image/$arch" + ], + errorcode => [1] + } + ); + next; + } + + #Call the Template class to do substitution to produce a kickstart file in the autoinst dir + my $tmperr = + "Unable to find template $::XCATROOT/share/xcat/install/image/createimage.$arch.tmpl"; + if (-r $::XCATROOT + . "/share/xcat/install/image/createimage.$arch.tmpl") + { + $tmperr = + xCAT::Template->subvars( + $::XCATROOT + . "/share/xcat/install/image/createimage.$arch.tmpl", + "$installroot/autoinst/" . $node, + $node + ); + } + if ($tmperr) + { + $callback->( + { + node => + [{name => [$node], error => [$tmperr], errorcode => [1]}] + } + ); + next; + } + + # copy partimageng script to the node-specific post scripts area + #mkpath "$installroot/postscripts/$node"; + #xCAT::Postage->writescript($node,"/install/postscripts/".$node, "install", $callback); + #copy("$installroot/postscripts/partimageng", + # "/$installroot/postscripts/$node/"); + + if ( + -r "/tftpboot/xcat/image/$arch/vmlinuz" + and -r "/tftpboot/xcat/image/$arch/initrd.img" + and -r "$installroot/image/$arch/installer_files/rootimg.gz" + ) + { + + #We have a shot... + my $restab = xCAT::Table->new('noderes'); + my $bptab = xCAT::Table->new('bootparams',-create=>1); + my $hmtab = xCAT::Table->new('nodehm'); + my $ent = + $restab->getNodeAttribs($node, + ['nfsserver', 'primarynic', 'installnic', 'kcmdline']); + my $sent = + $hmtab->getNodeAttribs( + $node, + [ + 'serialport', 'serialspeed', 'serialflow' + ] + ); + unless ($ent and $ent->{nfsserver}) + { + $callback->( + { + error => ["No noderes.nfsserver defined for " . $node], + errorcode => [1] + } + ); + next; + } + + + # determine image server, if tftpserver use it, else use xcatmaster + # else use site.Master, last resort use self + my $imgsrv; + my $ient; + $ient = $restab->getNodeAttribs($node, ['tftpserver']); + if ($ient and $ient->{tftpserver}) + { + $imgsrv = $ient->{tftpserver}; + } + else + { + $ient = $restab->getNodeAttribs($node, ['xcatmaster']); + if ($ient and $ient->{xcatmaster}) + { + $imgsrv = $ient->{xcatmaster}; + } + else + { + $ient = $sitetab->getAttribs({key => master}, value); + if ($ient and $ient->{value}) + { + $imgsrv = $ient->{value}; + } + else + { + my $ipfn = xCAT::Utils->my_ip_facing($node); + if ($ipfn) + { + $imgsrv = $ipfn; #guessing self is second best + + } + } + } + } + unless ($imgsrv) + { + $callback->( + { + error => [ + "Unable to determine or reasonably guess the image server for $node" + ], + errorcode => [1] + } + ); + next; + } + + my $kcmdline = "imgurl=http://$imgsrv/$installroot/image/$arch/installer_files/rootimg.gz image=$installroot/image/$arch/$profile.img blocks=512 action=save reboot " . $ent->{kcmdline}; + + if (defined($sent->{serialport})) + { + unless ($sent->{serialspeed}) + { + $callback->( + { + error => [ + "serialport defined, but no serialspeed for $node in nodehm table" + ], + errorcode => [1] + } + ); + next; + } + $kcmdline .= + " console=ttyS" + . $sent->{serialport} . "," + . $sent->{serialspeed}; + if ($sent->{serialflow} =~ /(hard|cts|ctsrts)/) + { + $kcmdline .= "n8r"; + } + } + $kcmdline .= " noipv6"; + + $bptab->setNodeAttribs( + $node, + { + kernel => "xcat/image/$arch/vmlinuz", + initrd => "xcat/image/$arch/initrd.img", + kcmdline => $kcmdline + } + ); + } + else + { + $callback->( + { + error => ["vmlinuz and initrd.img not found at /tftpboot/xcat/image/$arch"], + errorcode => [1] + } + ); + } + } + #my $rc = xCAT::Utils->create_postscripts_tar(); + #if ($rc != 0) + #{ + # xCAT::MsgUtils->message("S", "Error creating postscripts tar file."); + #} +} + +1;