Added the new command "imgcapture" to svn trunk.
please run "man imgcapture" for more information. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@9076 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
309bdb5305
commit
60c15d4c94
101
xCAT-client/pods/man1/imgcapture.1.pod
Normal file
101
xCAT-client/pods/man1/imgcapture.1.pod
Normal file
@ -0,0 +1,101 @@
|
||||
=head1 NAME
|
||||
|
||||
B<imgcapture> - Captures an image from one running diskful Linux node, prepares the rootimg directory, kernel and initial ramdisks for the B<liteimg>/B<packimage> command to generate the statelite/stateless rootimg.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<imgcapture> node [B<-p>|B<--profile> I<profile>] [B<-i> I<nodebootif>] [B<-n> I<nodenetdrivers>] [B<-V>|B<--verbose>]
|
||||
|
||||
B<imgcapture> [B<-h> | B<--help>] | [B<-v> | B<--version>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<imgcapture> command will capture an image from one running diskful Linux node, prepares the rootimg directory, kernel and initial rmadisks for the B<liteimg>/B<packimage> command to generate the statelite/stateless rootimg.
|
||||
|
||||
The B<node> should be one diskful Linux node, managed by the xCAT MN, and the remote shell between MN and the B<node> should have been configured. AIX is not supported.
|
||||
|
||||
The B<osver>, B<arch> and B<profile> attributes for the stateless/statelite image to be created are duplicated from the B<node>'s attribute. If the B<-p|--profile> I<profile> option is specified, the image will be created under "/<I<installroot>>/netboot/<osver>/<arch>/<I<profile>>/rootimg".
|
||||
|
||||
The default files/directories excluded in the image are specified by /opt/xcat/share/xcat/netboot/<os>/<I<profile>>.<osver>.<arch>.imgcapture.exlist; also, you can put your customized file (<I<profile>>.<osver>.<arch>.imgcapture.exlist) to /install/custom/netboot/<osplatform>. The directories in the default I<.imgcapture.exlist> file are necessary to capture image from the diskful Linux node managed by xCAT, please don't remove it.
|
||||
|
||||
The image captured will be extracted into the /<I<installroot>>/netboot/<B<osver>>/<B<arch>>/<B<profile>>/rootimg directory.
|
||||
|
||||
After the B<imgcapture> command returns without any errors, you can customize the rootimg and run the B<liteimg>/B<packimage> command for your own request.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 12
|
||||
|
||||
=item B<-p|--profile> I<profile>
|
||||
|
||||
assign I<profile> as the profile of the image to be created.
|
||||
|
||||
=item B<-i> I<nodebootif>
|
||||
|
||||
The network interface the diskless node will boot over (e.g. eth0), which is used by the B<genimage> command to generate initial ramdisks.
|
||||
|
||||
This is optional.
|
||||
|
||||
=item B<-n> I<nodenetdrivers>
|
||||
|
||||
The driver modules needed for the network interface, which is used by the B<genimage> command to generate initial ramdisks.
|
||||
|
||||
This is optional. By default, the B<genimage> command can provide drivers for the following network interfaces:
|
||||
|
||||
For x86 or x86_64 platform:
|
||||
|
||||
tg3 bnx2 bnx2x e1000 e1000e igb m1x_en
|
||||
|
||||
For ppc64 platform:
|
||||
|
||||
e1000 e1000e igb ibmveth ehea
|
||||
|
||||
For S390x:
|
||||
|
||||
qdio ccwgroup
|
||||
|
||||
If the network interface is not in the above list, you'd better specify the driver modules with this option.
|
||||
|
||||
=item B<-h|--help>
|
||||
|
||||
Display the usage message.
|
||||
|
||||
=item B<-v|--version>
|
||||
|
||||
Display the version.
|
||||
|
||||
=item B<-V|--verbose>
|
||||
|
||||
Verbose output.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RETRUN VALUE
|
||||
|
||||
0 The command completed sucessfully.
|
||||
|
||||
1 An error has occurred.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
B<node1> is one diskful Linux node, which is managed by xCAT.
|
||||
|
||||
1. In order to create the image, run the following command:
|
||||
|
||||
imgcapture node1
|
||||
|
||||
2. In order to create the image with B<hpc> as profile, run the command:
|
||||
|
||||
imgcapture node1 -p hpc
|
||||
|
||||
3. Create the image: its profile is B<hpc>, and the network interface the diskless node will boot over is B<eth0>, the driver modules for this network interface is B<e1000e>.
|
||||
|
||||
imgcapture node1 -p hpc -i eth0 -n e1000e
|
||||
|
||||
=head1 FILES
|
||||
|
||||
/opt/xcat/bin/imgcapture
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<genimage(1)|genimage.1>, L<imgimport(1)|imgimport.1>, L<imgexport(1)|imgexport.1>, L<packimage(1)|packimage.1>, L<liteimg(1)|liteimg.1>
|
@ -143,6 +143,7 @@ ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/lsflexnode
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/rmflexnode
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/mkflexnode
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/lsslp
|
||||
ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/imgcapture
|
||||
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/nodegrpch
|
||||
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/tabdump
|
||||
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/tabprune
|
||||
|
@ -477,6 +477,16 @@ sub get_exlist_file_name {
|
||||
return xCAT::SvrUtils::get_file_name($searchpath, "exlist", @_);
|
||||
}
|
||||
|
||||
# for the "imgcapture" command
|
||||
|
||||
sub get_imgcapture_exlist_file_name {
|
||||
my $searchpath = shift;
|
||||
if ($searchpath and $searchpath =~ m/xCAT::SvrUtils/) {
|
||||
$searchpath = shift;
|
||||
}
|
||||
return xCAT::SvrUtils::get_file_name($searchpath, "imgcapture.exlist", @_);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -615,7 +615,7 @@ sub mknetboot
|
||||
#}
|
||||
# append the mac address
|
||||
my $mac;
|
||||
if( $useifname && $machash->{$node}->[0] && $machash->{$node}->[0]->{'mac'}) {
|
||||
if($machash->{$node}->[0] && $machash->{$node}->[0]->{'mac'}) {
|
||||
# TODO: currently, only "mac" attribute with classic style is used, the "|" delimited string of "macaddress!hostname" format is not used
|
||||
$mac = $machash->{$node}->[0]->{'mac'};
|
||||
if ( (index($mac, "|") eq -1) and (index($mac, "!") eq -1) ) {
|
||||
|
324
xCAT-server/lib/xcat/plugins/imgcapture.pm
Normal file
324
xCAT-server/lib/xcat/plugins/imgcapture.pm
Normal file
@ -0,0 +1,324 @@
|
||||
#!/usr/bin/perl
|
||||
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
package xCAT_plugin::imgcapture;
|
||||
|
||||
BEGIN
|
||||
{
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||||
}
|
||||
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
|
||||
use strict;
|
||||
|
||||
use Data::Dumper; # for debug purpose
|
||||
use Getopt::Long;
|
||||
use xCAT::MsgUtils;
|
||||
use xCAT::Utils;
|
||||
use xCAT::Table;
|
||||
use File::Path qw(mkpath);
|
||||
|
||||
Getopt::Long::Configure("bundling");
|
||||
Getopt::Long::Configure("pass_through");
|
||||
|
||||
my $verbose = 0;
|
||||
my $installroot = "/install";
|
||||
|
||||
sub handled_commands {
|
||||
return { "imgcapture" => "imgcapture" };
|
||||
}
|
||||
|
||||
sub process_request {
|
||||
my $request = shift;
|
||||
my $callback = shift;
|
||||
my $doreq = shift;
|
||||
|
||||
my $node;
|
||||
if (exists $request->{node}) {
|
||||
$node = $request->{node}->[0];
|
||||
}
|
||||
|
||||
$installroot = xCAT::Utils->getInstallDir();
|
||||
@ARGV = @{$request->{arg}} if (defined $request->{arg});
|
||||
my $argc = scalar @ARGV;
|
||||
|
||||
my $usage = "Usage: imgcapture <node> [-p | --profile <profile>] [-i <nodebootif>] [-n <nodenetdrivers>] [-V | --verbose] \n imgcapture [-h|--help] \n imgcapture [-v|--version]";
|
||||
|
||||
my $os;
|
||||
my $arch;
|
||||
my $profile;
|
||||
my $bootif;
|
||||
my $netdriver;
|
||||
my $help;
|
||||
my $version;
|
||||
|
||||
GetOptions(
|
||||
"profile|p=s" => \$profile,
|
||||
"i=s" => \$bootif,
|
||||
'n=s' => \$netdriver,
|
||||
"help|h" => \$help,
|
||||
"version|v" => \$version,
|
||||
"verbose|V" => \$verbose
|
||||
);
|
||||
|
||||
if($version) {
|
||||
my $version = xCAT::Utils->Version();
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = $version;
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($help) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = $usage;
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( ! $node ) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = $usage;
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $nodetypetab = xCAT::Table->new("nodetype");
|
||||
my $ref_nodetype = $nodetypetab->getNodeAttribs($node, ['os','arch','profile']);
|
||||
$os = $ref_nodetype->{os};
|
||||
$arch = $ref_nodetype->{arch};
|
||||
unless($profile) {
|
||||
$profile = $ref_nodetype->{profile};
|
||||
}
|
||||
|
||||
imgcapture($node, $os, $arch, $profile, $bootif, $netdriver, $callback, $doreq);
|
||||
}
|
||||
|
||||
sub imgcapture {
|
||||
my ($node, $os, $arch, $profile, $bootif, $netdriver, $callback, $subreq) = @_;
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "nodename is $node; os is $os; arch is $arch; profile is $profile";
|
||||
$rsp->{data}->[1] = "bootif is $bootif; netdriver is $netdriver";
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
# make sure the "/" partion is on the disk,
|
||||
my $output = xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg =>["stat / -f |grep Type"]}, $subreq, -1, 1);
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{the output of "stat / -f |grep Type" on $node is:};
|
||||
foreach my $o (@$output) {
|
||||
push @{$rsp->{data}}, $o;
|
||||
}
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
if($::RUNCMD_RC) { #failed
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The "xdsh" command fails to run on the $node};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# parse the output of "stat / -f |grep Type",
|
||||
$output->[0] =~ m/Type:\s+(.*)$/;
|
||||
my $fstype = $1;
|
||||
if ($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The file type is $fstype};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
# make sure the rootfs type is not nfs or tmpfs
|
||||
if($fstype eq "nfs" or $fstype eq "tmpfs") {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{This node might not be diskful Linux node, please check it.};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $distname = $os;
|
||||
while ( $distname and ( ! -r "$::XCATROOT/share/xcat/netboot/$distname/") ) {
|
||||
chop($distname);
|
||||
}
|
||||
|
||||
unless($distname) {
|
||||
$callback->({error=>["Unable to find $::XCATROOT/share/xcat/netboot directory for $os"], errorcode => [1]});
|
||||
return;
|
||||
}
|
||||
|
||||
my $exlistloc = xCAT::SvrUtils->get_imgcapture_exlist_file_name("$installroot/custom/netboot/$distname", $profile, $os, $arch);
|
||||
unless ($exlistloc) {
|
||||
$exlistloc = xCAT::SvrUtils->get_imgcapture_exlist_file_name("$::XCATROOT/share/xcat/netboot/$distname", $profile, $os, $arch);
|
||||
}
|
||||
|
||||
my $xcat_imgcapture_tmpfile = "/tmp/xcat_imgcapture.$$";
|
||||
|
||||
my $excludestr = "cd /; find .";
|
||||
|
||||
if($exlistloc) {
|
||||
my $exlist;
|
||||
open $exlist, "<", $exlistloc;
|
||||
|
||||
while(<$exlist>) {
|
||||
$_ =~ s/^\s+//;
|
||||
unless($_ =~ m{^#}) {
|
||||
$excludestr .= qq{ ! -path "$_"};
|
||||
}
|
||||
}
|
||||
|
||||
close $exlist;
|
||||
} else {
|
||||
# the following directories must be exluded when capturing the image
|
||||
my @default_exlist = ("./tmp*", "./proc*", "./sys*", "./dev*", "./xcatpost*", "./install*");
|
||||
foreach my $item (@default_exlist) {
|
||||
$excludestr .= qq{ ! -path "$item"};
|
||||
}
|
||||
}
|
||||
|
||||
$excludestr .= " |cpio -H newc -o |gzip -c - >$xcat_imgcapture_tmpfile";
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The excludestr is "$excludestr"};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
# run the command via "xdsh"
|
||||
|
||||
xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg => ["echo -n >$xcat_imgcapture_tmpfile"]}, $subreq, -1, 1);
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{running "echo -n > $xcat_imgcapture_tmpfile" on $node};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
if($::RUNCMD_RC) { # the xdsh command fails
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The "xdsh" command fails to run "echo -n > $xcat_imgcapture_tmpfile" on $node};
|
||||
xCAT:MsgUtils->message("E", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg => [$excludestr]}, $subreq, -1, 1);
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{running "$excludestr" on $node via the "xdsh" command};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
if($::RUNCMD_RC) { # the xdsh command fails
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The "xdsh" command fails to run "$excludestr" on $node};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
# copy the image captured on $node back via the "scp" command
|
||||
xCAT::Utils->runcmd("scp $node:$xcat_imgcapture_tmpfile $xcat_imgcapture_tmpfile");
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{Running "scp $node:$xcat_imgcapture_tmpfile $xcat_imgcapture_tmpfile"};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
if($::RUNCMD_RC) {
|
||||
my $rsp ={};
|
||||
$rsp->{data}->[0] = qq{The scp command fails};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
# extract the $xcat_imgcapture_tmpfile file to /install/netboot/$os/$arch/$profile/rootimg
|
||||
my $rootimgdir = "$installroot/netboot/$os/$arch/$profile/rootimg";
|
||||
|
||||
# empty the rootimg directory before extracting the image captured on the diskful Linux node
|
||||
if( -d $rootimgdir ) {
|
||||
unlink $rootimgdir;
|
||||
}
|
||||
mkpath($rootimgdir);
|
||||
|
||||
xCAT::Utils->runcmd("cd $rootimgdir; gzip -cd $xcat_imgcapture_tmpfile|cpio -idum");
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{Extracting the image to $rootimgdir};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
if($::RUNCMD_RC) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{fails to run the "gzip -cd xx |cpio -idum" command};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{Creating the spots exluded when capturing on $node...};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
|
||||
my @spotslist = ("/tmp/", "/proc/", "/sys/", "/dev/");
|
||||
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{The spots to be restored in the image are:};
|
||||
foreach (@spotslist) {
|
||||
push @{$rsp->{data}}, $_;
|
||||
}
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
# create the directories listed in @spotslist in the rootimg
|
||||
foreach my $path (@spotslist) {
|
||||
mkpath("$rootimgdir$path");
|
||||
}
|
||||
|
||||
# the next step is to call "genimage"
|
||||
my $platform = getplatform($os);
|
||||
if( -e "$::XCATROOT/share/xcat/netboot/$platform/genimage" ) {
|
||||
my $cmd = "$::XCATROOT/share/xcat/netboot/$platform/genimage -o $os -a $arch -p $profile ";
|
||||
if($bootif) {
|
||||
$cmd .= "-i $bootif ";
|
||||
}
|
||||
if($netdriver) {
|
||||
$cmd .= "-n $netdriver";
|
||||
}
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{Generating kernel and initial ramdisks};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
if($verbose) {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{"The genimage command is: $cmd"};
|
||||
xCAT::MsgUtils->message("D", $rsp, $callback);
|
||||
}
|
||||
xCAT::Utils->runcmd($cmd);
|
||||
} else {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = qq{Can't run the "genimage" command for $os};
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub getplatform {
|
||||
my $os = shift;
|
||||
my $platform;
|
||||
if ($os =~ m/rh.*/) {
|
||||
$platform = "rh";
|
||||
} elsif ($os =~ m/centos.*/) {
|
||||
$platform = "centos";
|
||||
} elsif ($os =~ m/fedora.*/) {
|
||||
$platform = "fedora";
|
||||
} elsif ($os =~ m/SL.*/) {
|
||||
$platform = "SL";
|
||||
} elsif ($os =~ m/sles.*/) {
|
||||
$platform = "sles";
|
||||
} elsif ($os =~ m/suse.*/) {
|
||||
$platform = "suse";
|
||||
}
|
||||
|
||||
return $platform;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user