2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-30 01:26:38 +00:00

Merge pull request #2036 from immarvin/ongenimage

add lock in rh/genimage to avoid multiple genimage processes on same rootimg directory;add guard code before umount/remove mount points under rootimg directory
This commit is contained in:
neo954 2016-11-03 02:41:30 -05:00 committed by GitHub
commit 062ed1385a
4 changed files with 125 additions and 21 deletions

View File

@ -32,6 +32,7 @@ else {
use IPC::Open3;
use IO::Select;
use xCAT::GlobalDef;
use Digest::MD5 qw(md5_hex);
eval {
require xCAT::RemoteShellExp;
};
@ -2394,19 +2395,21 @@ sub acquire_lock {
use Fcntl ":flock";
my $tlock;
$tlock->{path} = "/var/lock/xcat/" . $lock_name;
open($tlock->{fd}, ">", $tlock->{path}) or return undef;
sysopen($tlock->{fd}, $tlock->{path}, POSIX::O_CREAT | POSIX::O_WRONLY) or return undef;
unless ($tlock->{fd}) { return undef; }
if ($nonblock_mode) {
flock($tlock->{fd}, LOCK_EX | LOCK_NB) or return undef;
} else {
flock($tlock->{fd}, LOCK_EX) or return undef;
}
print { $tlock->{fd} } $$;
truncate $tlock->{fd},0;
syswrite $tlock->{fd} ,$$;
$tlock->{fd}->autoflush(1);
return $tlock;
}
#---------------------
=head3 release_lock
@ -4781,4 +4784,45 @@ sub get_nmapversion {
return $nmap_version;
}
#--------------------------------------------------------------------------------
=head3 acquire_lock_imageop
acquire lock for the image related operations on specific rootimg dir
the image related operation includes genimage,packimage,rmimage...
Arguments:
$rootimg_dir: the full path of osimage rootimage dir
lock mode: 0-block, 1-non-block
Returns:
a list with format (<error code>, <error messgae> or <lock handler>)
the <error code>: 0 on success, 1 on fail
the <error message>: available on fail
the <lock handler>: available on success
=cut
#--------------------------------------------------------------------------------
sub acquire_lock_imageop {
my $self=shift;
my $rootimg_dir=shift;
my $NON_BLOCK=shift;
$NON_BLOCK=1 unless(defined $NON_BLOCK);
my $mylockfile=Cwd::realpath($rootimg_dir);
my $mymd5=md5_hex($mylockfile);
$mylockfile=~s/\//./g;
$mylockfile=$mylockfile.".".$mymd5;
my $lock = xCAT::Utils->acquire_lock("$mylockfile", $NON_BLOCK);
unless ($lock){
my $pidfd;
open($pidfd,"<","/var/run/lock/xcat/$mylockfile");
my $pid=<$pidfd>;
close($pidfd);
return (1, "failed to acquire lock, seems there is another genimage/packimage/rmimage process $pid running on root image dir \"$rootimg_dir\"");
}
return (0,$lock);
}
1;

View File

@ -37,6 +37,8 @@ use File::Path;
use xCAT::Utils;
use xCAT::TableUtils;
use xCAT::SvrUtils;
use Digest::MD5 qw(md5_hex);
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
@ -97,7 +99,8 @@ sub process_request {
my $provmethod;
my $help;
my $version;
my $lock;
GetOptions(
"profile|p=s" => \$profile,
"arch|a=s" => \$arch,
@ -199,6 +202,14 @@ sub process_request {
}
$rootimg_dir = "$destdir/rootimg";
my $retcode;
($retcode,$lock)=xCAT::Utils->acquire_lock_imageop($rootimg_dir);
if($retcode){
$callback->({ error => ["$lock"], errorcode => [1]});
return 1;
}
my $distname = $osver;
until (-r "$::XCATROOT/share/xcat/netboot/$distname/" or not $distname) {
chop($distname);

View File

@ -10,9 +10,11 @@ BEGIN
use lib "$::XCATROOT/lib/perl";
use Getopt::Long;
use File::Path;
use Cwd qw(realpath);
use xCAT::Utils;
use xCAT::TableUtils;
use xCAT::DBobjUtils;
use Digest::MD5 qw(md5_hex);
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
@ -41,7 +43,8 @@ sub process_request {
my $xcatdef;
my $imagename;
my $imagedir;
my $lock;
if (!xCAT::Utils->isLinux()) {
$callback->({ error => ["The rmimage command is only supported on Linux."], errorcode => [1] });
return;
@ -175,8 +178,17 @@ sub process_request {
$callback->({ error => ["Image directory $imagedir does not exist"], errorcode => [1] });
return;
}
# Doing this extra check now because we now have a method and arch from either the node or the image name.
my $retcode;
($retcode,$lock)=xCAT::Utils->acquire_lock_imageop("$imagedir/rootimg");
if($retcode){
$callback->({ error => ["$lock"], errorcode => [1]});
return 1;
}
# Doing this extra check now because we now have a method and arch from either the node or the image namee
if (($method eq "sysclone") && ($arch ne "s390x")) {
# Only supporting removing sysclone images for s390x at this time.
@ -184,17 +196,28 @@ sub process_request {
return;
}
my @filestoremove = ("$imagedir/rootimg.gz", "$imagedir/kernel", "$imagedir/initrd-stateless.gz", "$imagedir/initrd-statelite.gz");
my @filestoremove = ("$imagedir/kernel", "$imagedir/initrd-stateless.gz", "$imagedir/initrd-statelite.gz");
my @rootimgtars=glob "$imagedir/rootimg.{tar,cpio}.{xz,gz}";
push @filestoremove,@rootimgtars;
#unmount all the mount points under rootimg directory
#to avoid removing the directory/files on management node by mistake
$realimagedir=realpath("$imagedir/rootimg");
my @mntptlist;
my $FILEHD=undef;
open($FILEHD,"<","/proc/mounts");
while(<$FILEHD>){
my @arr=split / /;
push @mntptlist,$arr[1] if(substr($arr[1],0,length($realimagedir)) eq $realimagedir);
}
close($FILEHD);
foreach my $mntpt (@mntptlist){
system("umount -l $mntpt >/dev/null 2>&1")
}
#some rpms like atftp mount the rootimg/proc to /proc, we need to make sure rootimg/proc is free of junk
`umount -l $imagedir/rootimg/proc 2>&1 1>/dev/null`;
# also umount the rootimg/sys
`umount -l $imagedir/rootimg/sys 2>&1 1>/dev/null`;
# umount the rootimg/dev
my $devmount = `cat /proc/mounts |grep "$imagedir/rootimg/dev"`;
if ($devmount) {
my $devmount = system("findmnt $imagedir/rootimg/dev/ >/dev/null 2>&1");
if (!$devmount) {
xCAT::Utils->runcmd("umount -l $imagedir/rootimg/dev");
if ($?) {
$callback->({ error => ["$imagedir/rootimg/dev mount on /dev, and can't umount. remove $imagename will lead to unpredictable result, please umount manualy before try again"], errorcode => [1] });

View File

@ -19,6 +19,8 @@ use File::Temp qw/mkdtemp/;
use FindBin;
use lib "$FindBin::Bin/../imgutils";
use imgutils;
use xCAT::Utils;
use Digest::MD5 qw(md5_hex);
#use strict;
Getopt::Long::Configure("bundling");
@ -66,6 +68,8 @@ my $tempfile;
my $prompt;
my $ignorekernelchk;
my $noupdate;
my $lock;
sub xdie {
@ -112,17 +116,30 @@ sub mount_chroot {
sub umount_chroot {
my $rootimage_dir = shift;
if ($rootimage_dir eq "") {
$rootimage_dir=realpath($rootimage_dir);
if ($rootimage_dir eq "/") {
print "\n\n\n\nWARNING: /proc and /sys may still be mounted in the rootimgdir\n\n\n\n";
return 1;
}
#unmount all the mount points under rootimg directory
#to avoid removing the direcoty/files on managemment node by mistake
my @mntptlist;
my $FILEHD=undef;
open($FILEHD,"<","/proc/mounts");
while(<$FILEHD>){
my @arr=split / /;
push @mntptlist,$arr[1] if(substr($arr[1],0,length($rootimage_dir)) eq $rootimage_dir);
}
close($FILEHD);
foreach my $mntpt (@mntptlist){
system("umount -l $mntpt >/dev/null 2>&1")
}
if (majversion($osver) > 6) {
system("umount -l $rootimage_dir/proc");
system("umount -l $rootimage_dir/sys");
#system("umount -l $rootimage_dir/dev");
system("rm -rf $rootimage_dir/dev/*");
#only remove the /dev in rootimg directory if it is not a mount point
system("findmnt $rootimage_dir/dev/ >/dev/null 2>&1 || rm -rf $rootimage_dir/dev/*");
}
}
@ -194,6 +211,7 @@ $srcdir_otherpkgs = "$installroot/post/otherpkgs/$osver/$arch" unless ($srcdir_o
$destdir = "$installroot/netboot/$osver/$arch/$profile" unless ($destdir);
$updates{'rootimgdir'} = $destdir if ($tempfile);
$rootimg_dir = "$destdir/rootimg";
$kerneldir = "$installroot/kernels" unless ($kerneldir); # the default directory for 3rd-party kernel is "$installroot/kernels";
@ -348,6 +366,14 @@ unless ($onlyinitrd) {
exit 1;
}
my $retcode;
($retcode,$lock)=xCAT::Utils->acquire_lock_imageop($rootimg_dir);
if($retcode){
print "$lock";
exit 1;
}
mount_chroot($rootimg_dir);
my %pkg_hash = imgutils::get_package_names($pkglist);