mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-30 19:02:27 +00:00 
			
		
		
		
	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:
		| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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] }); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user