2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-21 19:22:05 +00:00

support environment variables in osimage customized files (#5281)

* * osimage table schema change: add a "environvar" col in osimage table to hold environment variables used in osimage customized files
* osimage object schema change: add a environvar attribute, which refers to  osimage.environvar
* the environment variables specified in "environvar" attribute will be exported during invocation of postinstall scripts in genimage

* support variables in synclists

* support environment variables in genimage,mkinstall,getpostscript

* support environment variables for xdcp -i -F in packimage
This commit is contained in:
yangsong 2018-06-15 14:51:41 +08:00 committed by Bin Xu
parent 18c5afc0f4
commit c49e41da99
11 changed files with 190 additions and 16 deletions

View File

@ -804,6 +804,46 @@ sub fork_fanout_dcp
my @dcp_command;
my $rsyncfile;
my %envardict;
foreach my $varstr (split(',',$$target_properties{'envar'})){
if($varstr =~ m/(.*)=(.*)/){
my ($myvar,$myvalue)=($1,$2);
$envardict{$myvar}=$myvalue;
}
}
if(%envardict){
my $dest_srcdict=$$options{'destDir_srcFile'}{$user_target};
for my $dest (keys %{$dest_srcdict}){
my $newdest=$dest;
$newdest=xCAT::Utils->varsubinline($newdest,\%envardict);
for my $label(keys %{$$dest_srcdict{$dest}}){
my $myref;
if('ARRAY' eq ref($$dest_srcdict{$dest}{$label})){
for my $path(@{$$dest_srcdict{$dest}{$label}}){
$path=xCAT::Utils->varsubinline($path,\%envardict);
}
}elsif('HASH' eq ref($$dest_srcdict{$dest}{$label})){
for my $path(keys(%{$$dest_srcdict{$dest}{$label}})){
my $newpath=$path;
$newpath=xCAT::Utils->varsubinline($newpath,\%envardict);
if($newpath ne $path){
$$dest_srcdict{$dest}{$label}{$newpath}=$$dest_srcdict{$dest}{$label}{$path};
delete $$dest_srcdict{$dest}{$label}{$path};
}
}
}
}
if($newdest ne $dest){
$$dest_srcdict{$newdest}=$$dest_srcdict{$dest};
delete $$dest_srcdict{$dest};
}
}
}
if (!$$target_properties{'localhost'}) # this is to a remote host
{
my $target_type = $$target_properties{'type'};
@ -3293,6 +3333,13 @@ sub bld_resolve_nodes_hash
$rsp->{info}->[0] = "Command: $cmd failed. Continuing...";
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
}
my $ostab = xCAT::Table->new('nodetype');
my %oents = %{ $ostab->getNodesAttribs(\@target_list, [qw(provmethod)]) };
foreach my $target (@target_list)
{
@ -3306,12 +3353,27 @@ sub bld_resolve_nodes_hash
if (($mname eq $target) || ($localhostname eq $target)) {
$localhost = $target;
}
my $envar=undef;
my $ent = $oents{$target}->[0];
if ($ent and $ent->{provmethod} and \
($ent->{provmethod} ne 'install') and ($ent->{provmethod} ne 'netboot') and ($ent->{provmethod} ne 'statelite')) {
my $imagename = $ent->{provmethod};
my $osimagetab = xCAT::Table->new('osimage', -create => 1);
(my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'environvar');
if($ref){
$envar=$ref->{'environvar'};
}
}
my %properties = (
'hostname' => $hostname,
'ip-address' => $ip_address,
'localhost' => $localhost,
'user' => $user,
'context' => $context,
'envar' => $envar,
'unresolved' => $target
);
@ -4405,6 +4467,7 @@ sub parse_and_run_dcp
$::XCATROOT = "/opt/xcat";
}
# parse the arguments
Getopt::Long::Configure("posix_default");
Getopt::Long::Configure("no_gnu_compat");
@ -4914,6 +4977,15 @@ sub rsync_to_image
my ($input_file, $image) = @_;
my $rc = 0;
my %osimgenv;
if($ENV{'XCAT_OSIMAGE_ENV'}){
foreach my $myenv(split(',',$ENV{'XCAT_OSIMAGE_ENV'})){
if($myenv =~ /\s*(\S+)\s*=\s*(\S+)\s*/) {
$osimgenv{$1}=$2;
}
}
}
open(INPUTFILE, "< $input_file") || die "File $input_file does not exist\n";
while (my $line = <INPUTFILE>)
{
@ -4923,6 +4995,8 @@ sub rsync_to_image
next;
}
$line=xCAT::Utils->varsubinline($line,\%osimgenv);
# process no more lines, do not exec
# do not execute postscripts when syncing images
if (($line =~ /EXECUTE:/) || ($line =~ /EXECUTEALWAYS:/)

View File

@ -768,7 +768,7 @@ passed as argument rather than by table value',
},
},
osimage => {
cols => [qw(imagename groups profile imagetype description provmethod rootfstype osdistroname osupdatename cfmdir osname osvers osarch synclists postscripts postbootscripts serverrole isdeletable kitcomponents comments disable)],
cols => [qw(imagename groups profile imagetype description provmethod rootfstype osdistroname osupdatename cfmdir osname osvers osarch synclists postscripts postbootscripts serverrole isdeletable kitcomponents environvar comments disable)],
keys => [qw(imagename)],
tablespace => 'XCATTBS32K',
table_desc => 'Basic information about an operating system image that can be used to deploy cluster nodes.',
@ -795,6 +795,7 @@ passed as argument rather than by table value',
serverrole => 'The role of the server created by this osimage. Default roles: mgtnode, servicenode, compute, login, storage, utility.',
isdeletable => 'A flag to indicate whether this image profile can be deleted. This attribute is only used by PCM.',
kitcomponents => 'List of Kit Component IDs assigned to this OS Image definition.',
environvar => 'Comma delimited environment variables for the osimage',
comments => 'Any user-written notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
},
@ -3478,6 +3479,10 @@ push(@{ $defspec{node}->{'attrs'} }, @nodeattrs);
tabentry => 'nimimage.comments',
access_tabentry => 'nimimage.imagename=attr:imagename',
},
{ attr_name => 'environvar',
tabentry => 'osimage.environvar',
access_tabentry => 'osimage.imagename=attr:imagename',
},
);
#########################

View File

@ -5004,4 +5004,32 @@ sub console_sleep {
sleep($time);
}
1;
# replace the variables in $line with the values in dict ref $refvardict
# return the substitued $line
sub varsubinline{
my $class=shift;
my $line=shift;
my $refvardict=shift;
my @varsinline= $line =~ /\$\{?(\w+)\}?/g;
my @unresolvedvars;
foreach my $var(@varsinline){
if(exists $refvardict->{$var}){
$line=~ s/\$\{$var\}/$refvardict->{$var}/g;
$line=~ s/\$$var/$refvardict->{$var}/g;
}else{
push @unresolvedvars,$var;
}
}
return $line;
}
#remove the left and right white spaces from string
sub strim{
my $class=shift;
my $str=shift;
$str =~ s/^\s+|\s+$//g;
return $str;
}

View File

@ -13,7 +13,7 @@ use File::Basename;
use Cwd;
use Socket;
#use Data::Dumper;
use Data::Dumper;
use Getopt::Long;
require xCAT::MsgUtils;
require xCAT::DSHCLI;
@ -195,6 +195,11 @@ if ($ENV{'DSH_VERIFY'})
push(@{ $cmdref->{env} }, "DSH_VERIFY=$ENV{'DSH_VERIFY'}");
}
if ($ENV{'XCAT_OSIMAGE_ENV'})
{
push(@{ $cmdref->{env} }, "XCAT_OSIMAGE_ENV=$ENV{'XCAT_OSIMAGE_ENV'}");
}
xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response);
exit $xCAT::Client::EXITCODE;

View File

@ -18,6 +18,7 @@ use xCAT::Template;
use xCAT::SvrUtils;
use xCAT::Zone;
use Data::Dumper;
use File::Basename;
use Socket;
use strict;
@ -319,7 +320,7 @@ sub makescript {
#%image_hash is used to store the attributes in linuximage and nimimage tabs
my %image_hash;
getImage(\%image_hash);
getImage(\%image_hash);
# get postscript and postscript from postscripts and osimage tabs
my $script_hash = xCAT::Postage::getScripts($nodes, \%image_hash);
@ -512,6 +513,16 @@ sub makescript {
$osimgname = $provmethod;
}
if($image_hash{$osimgname}{'environvar'}){
my $myenvstr=$image_hash{$osimgname}{'environvar'};
foreach my $myenv(split(',',$myenvstr)){
if($myenv =~ /\s*(\S+)\s*=\s*(\S+)\s*/) {
$ENV{$1}=$2;
}
}
}
my $osimage_vars;
$osimage_vars = getImageitems_for_node($node, \%image_hash, $nodesetstate);
@ -1114,7 +1125,7 @@ sub getImage
if ($^O =~ /^linux/i) {
my $linuximagetab = xCAT::Table->new('linuximage', -create => 1);
my @et2 = $linuximagetab->getAllAttribs('imagename', 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir');
my @et2 = $linuximagetab->getAllAttribs('imagename', 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir','environvar');
if (@et2) {
foreach my $tmp_et2 (@et2) {
my $imagename = $tmp_et2->{imagename};
@ -1122,6 +1133,7 @@ sub getImage
$image_hash->{$imagename}->{pkgdir} = $tmp_et2->{pkgdir};
$image_hash->{$imagename}->{otherpkglist} = $tmp_et2->{otherpkglist};
$image_hash->{$imagename}->{otherpkgdir} = $tmp_et2->{otherpkgdir};
$image_hash->{$imagename}->{environvar} = $tmp_et2->{environvar};
}
}
}
@ -1190,6 +1202,11 @@ sub getImageitems_for_node
$result .= "export OTHERPKGDIR\n";
}
}
if ($ref1->{'environvar'}){
foreach my $myenvar(split(',',$ref1->{'environvar'})){
$result .='export '.$myenvar."\n";
}
}
}
}
else
@ -1813,6 +1830,8 @@ sub includefile
my $file = shift;
my $idir = shift;
my @text = ();
$file=xCAT::Utils->varsubinline($file,\%ENV);
unless ($file =~ /^\//)
{
$file = $idir . "/" . $file;
@ -1948,7 +1967,7 @@ sub getScripts
$script_hash{default_postboot} = $et->{'postbootscripts'};
my @et2 = $ostab->getAllAttribs('imagename', 'postscripts', 'postbootscripts', 'osvers', 'osarch', 'profile', 'provmethod', 'synclists', 'kitcomponents');
my @et2 = $ostab->getAllAttribs('imagename', 'postscripts', 'postbootscripts', 'osvers', 'osarch', 'profile', 'provmethod', 'synclists', 'kitcomponents','environvar');
if (@et2) {
foreach my $tmp_et2 (@et2) {
my $imagename = $tmp_et2->{imagename};
@ -1959,6 +1978,7 @@ sub getScripts
$image_hash->{$imagename}->{profile} = $tmp_et2->{profile};
$image_hash->{$imagename}->{provmethod} = $tmp_et2->{provmethod};
$image_hash->{$imagename}->{synclists} = $tmp_et2->{synclists};
$image_hash->{$imagename}->{environvar} = $tmp_et2->{environvar};
$image_hash->{$imagename}->{kitcomponents} = $tmp_et2->{kitcomponents} if ($tmp_et2->{kitcomponents});
}
}

View File

@ -1489,6 +1489,7 @@ sub includefile
#2 means pattern list, pattern list starts with @,
#3 means remove package list, packages to be removed start with -.
my $text = "";
$file=xCAT::Utils->varsubinline($file,\%ENV);
unless ($file =~ /^\//) {
$file = $idir . "/" . $file;
}

View File

@ -18,7 +18,6 @@ use xCAT::MsgUtils;
use xCAT::SvrUtils;
use xCAT::Yum;
#use Data::Dumper;
use Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
@ -952,12 +951,13 @@ sub mkinstall
if (!$osimagetab) {
$osimagetab = xCAT::Table->new('osimage', -create => 1);
}
(my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'osupdatename');
(my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'osupdatename','environvar');
if ($ref) {
$img_hash{$imagename}->{osver} = $ref->{'osvers'};
$img_hash{$imagename}->{osarch} = $ref->{'osarch'};
$img_hash{$imagename}->{profile} = $ref->{'profile'};
$img_hash{$imagename}->{provmethod} = $ref->{'provmethod'};
$img_hash{$imagename}->{environvar} = $ref->{'environvar'};
if (!$linuximagetab) {
$linuximagetab = xCAT::Table->new('linuximage', -create => 1);
}
@ -1163,6 +1163,15 @@ sub mkinstall
} else {
$tmperr = "Unable to find template in /install/custom/install/$platform or $::XCATROOT/share/xcat/install/$platform (for $profile/$os/$arch combination)";
}
if($img_hash{$imagename}->{environvar}){
foreach my $myenv(split(',',$img_hash{$imagename}->{'environvar'})){
if($myenv =~ /\s*(\S+)\s*=\s*(\S+)\s*/) {
$ENV{$1}=$2;
}
}
}
if (-r "$tmplfile")
{
$tmperr =

View File

@ -73,6 +73,7 @@ sub process_request {
my $dryrun;
my $ignorekernelchk;
my $noupdate;
my $envar;
GetOptions(
'a=s' => \$arch,
@ -138,7 +139,7 @@ sub process_request {
return 1;
}
(my $ref_osimage_tab) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod');
(my $ref_osimage_tab) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod','environvar');
unless ($ref_osimage_tab) {
$callback->({ error => ["Cannot find image \'$imagename\' from the osimage table."], errorcode => [1] });
return 1;
@ -153,6 +154,7 @@ sub process_request {
$osver = $ref_osimage_tab->{'osvers'};
$arch = $ref_osimage_tab->{'osarch'};
$profile = $ref_osimage_tab->{'profile'};
$envar = $ref_osimage_tab->{'environvar'};
my $provmethod = $ref_osimage_tab->{'provmethod'}; # TODO: not necessary, and need to update both statelite and stateless modes
unless ($osver and $arch and $profile and $provmethod) {
@ -318,7 +320,7 @@ sub process_request {
if ($kerneldir) { $cmd .= " --kerneldir $kerneldir"; }
if ($interactive) { $cmd .= " --interactive" }
if ($onlyinitrd) { $cmd .= " --onlyinitrd" }
if ($envar) { $cmd .= " --env $envar"; }
if ($srcdir) { $cmd .= " --srcdir \"$srcdir\""; }
if ($pkglist) { $cmd .= " --pkglist $pkglist"; }
if ($srcdir_otherpkgs) { $cmd .= " --otherpkgdir \"$srcdir_otherpkgs\""; }

View File

@ -99,6 +99,7 @@ sub process_request {
my $imagename;
my $dotorrent;
my $provmethod;
my $envars;
my $help;
my $version;
my $lock;
@ -153,7 +154,7 @@ sub process_request {
$callback->({ error => ["The linuximage table cannot be opened."], errorcode => [1] });
return 1;
}
(my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'synclists');
(my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'synclists','environvar');
unless ($ref) {
$callback->({ error => ["Cannot find image \'$imagename\' from the osimage table."], errorcode => [1] });
return 1;
@ -169,6 +170,7 @@ sub process_request {
$profile = $ref->{'profile'};
$syncfile = $ref->{'synclists'};
$provmethod = $ref->{'provmethod'};
$envars = $ref->{'environvar'};
unless ($osver and $arch and $profile and $provmethod) {
$callback->({ error => ["osimage.osvers, osimage.osarch, osimage.profile and osimage.provmethod must be specified for the image $imagename in the database."], errorcode => [1] });
@ -422,8 +424,12 @@ sub process_request {
# sync fils configured in the synclist to the rootimage
$syncfile = xCAT::SvrUtils->getsynclistfile(undef, $osver, $arch, $profile, "netboot", $imagename);
if ( defined($syncfile) && -f $syncfile && -d $rootimg_dir) {
my $myenv='';
if($envars){
$myenv.=" XCAT_OSIMAGE_ENV=$envars";
}
print "Syncing files from $syncfile to root image dir: $rootimg_dir\n";
system("$::XCATROOT/bin/xdcp -i $rootimg_dir -F $syncfile");
system("$myenv $::XCATROOT/bin/xdcp -i $rootimg_dir -F $syncfile");
}
} else {
print "Bypass of syncfiles requested, will not sync files to root image directory.\n";

View File

@ -10,6 +10,24 @@ use File::Basename;
use File::Path;
use Cwd qw(realpath);
sub varsubinline{
my $line=shift;
my $refvardict=shift;
my @varsinline= $line =~ /\$\{?(\w+)\}?/g;
my @unresolvedvars;
foreach my $var(@varsinline){
if(exists $refvardict->{$var}){
$line=~ s/\$\{$var\}/$refvardict->{$var}/g;
$line=~ s/\$$var/$refvardict->{$var}/g;
}else{
push @unresolvedvars,$var;
}
}
return $line;
}
sub get_profile_def_filename {
my $osver = shift;
my $profile = shift;
@ -54,6 +72,8 @@ sub include_file
my $file = shift;
my $idir = shift;
my @text = ();
$file=varsubinline($file,\%ENV);
unless ($file =~ /^\//) {
$file = $idir . "/" . $file;
}
@ -117,7 +137,6 @@ sub get_package_names {
$pkgtext =~ s/#INCLUDE:([^#^\n]+)#/include_file($1,$idir)/eg;
}
}
#print "\n\npkgtext=$pkgtext\n\n";
my @tmp = split(',', $pkgtext);
my $pass = 1;
@ -169,7 +188,6 @@ sub get_package_names {
}
}
}
return %pkgnames;
}

View File

@ -69,7 +69,7 @@ my $prompt;
my $ignorekernelchk;
my $noupdate;
my $lock;
my $envar;
sub xdie {
@ -186,6 +186,7 @@ GetOptions(
'onlyinitrd' => \$onlyinitrd,
'ignorekernelchk' => \$ignorekernelchk,
'noupdate' => \$noupdate,
'env=s' => \$envar,
);
if (@ARGV > 0) {
@ -376,6 +377,11 @@ unless ($onlyinitrd) {
exit 1;
}
my @envarlist=split(',',$envar);
foreach my $entry (@envarlist){
my ($key,$value)=split('=',$entry);
$ENV{xCAT::Utils->strim($key)}=xCAT::Utils->strim($value);
}
mount_chroot($rootimg_dir);
my %pkg_hash = imgutils::get_package_names($pkglist);
@ -784,6 +790,7 @@ if ($postinstall_filename) {
$ENV{IMG_OTHERPKGLIST}=$otherpkglist if("" ne $otherpkglist);
$ENV{IMG_OTHERPKGDIR}=$srcdir_otherpkgs if("" ne $srcdir_otherpkgs);
$ENV{IMG_ROOTIMGDIR}=$rootimg_dir if("" ne $rootimg_dir);
foreach my $postinstall (split /,/, $postinstall_filename) {
if (!-x $postinstall) {
@ -1944,7 +1951,6 @@ sub generic_post { #This function is meant to leave the image in a state approxi
print $cfgfile "tmpfs /dev/shm tmpfs defaults 0 0\n";
print $cfgfile "proc /proc proc defaults 0 0\n";
print $cfgfile "sysfs /sys sysfs defaults 0 0\n";
if (!&using_systemd($osver)) {
if ($tmplimit) {
print $cfgfile "tmpfs /tmp tmpfs defaults,size=$tmplimit 0 2\n";