mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	added statelite support
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@4791 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -137,7 +137,7 @@ sub setdestiny { | ||||
|       if ($ient->{kcmdline}) { $hash->{kcmdline} = $ient->{kcmdline} } | ||||
|       $bptab->setNodeAttribs($_,$hash); | ||||
|      } | ||||
|   } elsif ($state =~ /^install[=\$]/ or $state eq 'install' or $state =~ /^netboot[=\$]/ or $state eq 'netboot' or $state eq "image" or $state eq "winshell" or $state =~ /^osimage/ or $state eq 'statelite') { | ||||
|   } elsif ($state =~ /^install[=\$]/ or $state eq 'install' or $state =~ /^netboot[=\$]/ or $state eq 'netboot' or $state eq "image" or $state eq "winshell" or $state =~ /^osimage/ or $state =~ /^statelite/) { | ||||
|     chomp($state); | ||||
|     my $target; | ||||
|     if ($state =~ /=/) { | ||||
|   | ||||
							
								
								
									
										302
									
								
								xCAT-server/lib/xcat/plugins/litetree.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								xCAT-server/lib/xcat/plugins/litetree.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | ||||
| package xCAT_plugin::litetree; | ||||
| use xCAT::NodeRange; | ||||
| use Data::Dumper; | ||||
| use xCAT::Utils; | ||||
| use Sys::Syslog; | ||||
| use xCAT::GlobalDef; | ||||
| use xCAT::Table; | ||||
| use Getopt::Long; | ||||
| Getopt::Long::Configure("bundling"); | ||||
| Getopt::Long::Configure("pass_through"); | ||||
|  | ||||
| use strict; | ||||
| # synchonize files and directories from mulitple sources.  | ||||
|  | ||||
| # object is to return a list of files to be syncronized. | ||||
| # requesting them.  By default we will do read-write files. | ||||
|  | ||||
|  | ||||
| my $syncdirTab = "litetree"; | ||||
| my $syncfileTab = "litefile"; | ||||
| my $errored = 0; | ||||
|  | ||||
|  | ||||
| sub handled_commands { | ||||
| 	# command is syncmount, syncdir is the perl module to use. | ||||
| 	return { | ||||
| 		litetree => "litetree", | ||||
| 		litefile => "litetree", | ||||
| 		ilitefile => "litetree" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| sub usage { | ||||
| 	my $command = shift; | ||||
| 	my $callback = shift; | ||||
| 	my $error = shift; | ||||
| 	my $msg;	 | ||||
| 	if($command eq "ilitefile"){ | ||||
| 		$msg = "ilitefile <imagename> | ||||
| \texample:\n\tilitefile centos5.3-x86_64-compute" | ||||
| 	}	else{ | ||||
| 		$msg = "some general usage string"; | ||||
| 	} | ||||
|  | ||||
| 	if($error){ | ||||
| 		$callback->({error=>[$msg],errorcode=>[$error]}); | ||||
| 	}else{ | ||||
| 		$callback->({info=>[$msg]}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| sub process_request { | ||||
| 	my $request = shift; | ||||
| 	my $callback = shift; | ||||
| 	my $noderange; | ||||
| 	my $image; | ||||
| 	# the request can come from node or some one running command | ||||
| 	# on xCAT mgmt server | ||||
| 	# argument could also be image... | ||||
|  | ||||
| 	# if request comes from user: | ||||
| 	if($request->{node}){ | ||||
| 		$noderange = $request->{node}; | ||||
| 		 | ||||
| 	# if request comes from node post script .awk file. | ||||
| 	}elsif($request->{'_xcat_clienthost'}){ | ||||
| 		$noderange = $request->{'_xcat_clienthost'}; | ||||
| 	}else{ | ||||
| 		$callback->({error=>["Well Kemosabi, I can't figure out who you are."],errorcode=>[1]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if(!$noderange){ | ||||
| 		my $usage_string="Missing Noderange\n"; | ||||
| 		$callback->({error=>[$usage_string],errorcode=>[1]}); | ||||
| 		$request = {}; | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	my $command = $request->{command}->[0]; | ||||
| 	if($command eq "litetree"){ | ||||
| 		return syncmount("dir",$request,$callback,$noderange); | ||||
| 	}elsif($command eq "litefile"){ | ||||
| 		return syncmount("file",$request, $callback,$noderange); | ||||
| 	}elsif($command eq "ilitefile"){ | ||||
| 			#print Dumper($request); | ||||
| 			unless($request->{arg}){ | ||||
| 				usage($command, $callback,1); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			return syncmount("image",$request, $callback,$request->{arg}); | ||||
| 	}else{ | ||||
| 		$callback->({error=>["error in code..."], errorcode=>[127]}); | ||||
| 		$request = {}; | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| sub syncmount {	 | ||||
| 	my $syncType = shift; | ||||
| 	my $request = shift; | ||||
| 	my $callback = shift; | ||||
| 	# deterimine which node is calling this  | ||||
| 	# then find out what directories to use. | ||||
| 	my $noderange = shift; | ||||
| 	my @nodes = @{$noderange}; | ||||
| 	my $tab; | ||||
| 	if($syncType eq 'dir'){ | ||||
| 		$tab = xCAT::Table->new($syncdirTab,-create=>1); | ||||
| 	}elsif($syncType =~ /file|image/ ){ | ||||
| 		$tab = xCAT::Table->new($syncfileTab,-create=>1); | ||||
| 	}else{ | ||||
| 		$callback->({error=>["error in code..."], errorcode=>[127]}); | ||||
| 		$request = {}; | ||||
| 		return; | ||||
| 	} | ||||
| 	my $ostab; | ||||
| 	my %osents; | ||||
| 	unless($syncType =~ /image/){ | ||||
| 		$ostab = xCAT::Table->new('nodetype'); | ||||
| 		%osents = %{$ostab->getNodesAttribs(\@nodes,['profile','os','arch'])}; | ||||
| 	} | ||||
| 	foreach my $node (@nodes){ | ||||
| 		# node may be an image... | ||||
| 		my $ent; | ||||
| 		if(! $syncType =~ /image/){ | ||||
| 			$ent = $osents{$node}->[0]; | ||||
| 			unless($ent->{os} && $ent->{arch} && $ent->{profile}){ | ||||
| 				$callback->({error=>["$node does not have os, arch, or profile defined in nodetype table"],errorcode=>[1]}); | ||||
| 				$request = {}; | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 		my $fData = getNodeData($syncType,$node,$ent,$tab,$callback);	 | ||||
| 		# now we go through each directory and search for the file. | ||||
| 		showSync($syncType,$callback, $node, $fData);	 | ||||
| 	}	 | ||||
| } | ||||
|  | ||||
|  | ||||
| # In most cases the syncdir will be on the management node so  | ||||
| # want to make sure its not us before we mount things. | ||||
| sub showSync { | ||||
| 	my $syncType = shift; # dir or file	 | ||||
| 	my $callback = shift; | ||||
| 	my $node = shift; | ||||
| 	my $dirs = shift; | ||||
|  | ||||
| 	#print Dumper($dirs); | ||||
| 	# go through each directory in priority order | ||||
| 	#mkdir "/mnt/xcat"; | ||||
| 	if($syncType eq "dir"){ | ||||
| 		foreach my $priority (sort {$a <=> $b} keys %$dirs){ | ||||
| 			# split the nfs server up from the directory: | ||||
| 			my ($server, $dir) = split(/:/,$dirs->{$priority}); | ||||
| 			if(grep /\$/, $dir){ | ||||
| 				$dir = subVar($dir,$node,'dir'); | ||||
| 				$dir =~ s/\/\//\//g; | ||||
| 			} | ||||
|  | ||||
| 			if(grep /\$/, $server){ | ||||
| 				$server = subVar($server,$node,'server'); | ||||
| 			} | ||||
| 			my $mntpnt = $server . ":" . $dir; | ||||
| 			# ok, now we have all the mount points.  Let's go through them all? | ||||
| 			$callback->({info => "$node: $mntpnt"}); | ||||
| 		} | ||||
| 	}elsif($syncType =~ /file|image/){ | ||||
| 		foreach my $file (sort keys %$dirs){ | ||||
| 			my $options	= $dirs->{$file}; | ||||
| 			# persistent,rw | ||||
| 			my $out = sprintf("%s: %-13s %s", $node, $options, $file); | ||||
| 			$callback->({info => $out}); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
| # some directories will have xCAT database values, like: | ||||
| # $nodetype.os.  If that is the case we need to open up | ||||
| # the database and look at them.  We need to make sure | ||||
| # we do this sparingly...  We don't like tons of hits | ||||
| # to the database. | ||||
| sub subVar { | ||||
| 	my $dir = shift; | ||||
| 	my $node = shift; | ||||
| 	my $type = shift; | ||||
| 	# parse all the dollar signs...	 | ||||
| 	# if its a directory then it has a / in it, so you have to parse it. | ||||
| 	# if its a server, it won't have one so don't worry about it. | ||||
| 	my @arr = split("/", $dir); | ||||
| 	my $fdir = ""; | ||||
| 	foreach my $p (@arr){ | ||||
| 		if($p =~ /^\$/){ | ||||
| 			# have to sub here: | ||||
| 			# get rid of the $ sign. | ||||
| 			$p =~ s/\$//g; | ||||
| 			# check if p is just the node name: | ||||
|  | ||||
| 			if($p eq 'node'){ | ||||
| 				# it is so, just return the node. | ||||
| 				$fdir .= "/$node"; | ||||
| 			}else{ | ||||
| 				# ask the xCAT DB what the attribute is. | ||||
| 				my ($table, $col) = split('\.', $p); | ||||
| 				my $tab = xCAT::Table->new($table); | ||||
| 				my $ent = $tab->getNodeAttribs($node,[$col]);		 | ||||
| 				my $val = $ent->{$col}; | ||||
| 				unless($val){ | ||||
| 					# couldn't find the value!! | ||||
| 					$val = "UNDEFINED" | ||||
| 				} | ||||
| 				if($type eq 'dir'){ | ||||
| 					$fdir .= "/$val"; | ||||
| 				}else{ | ||||
| 					$fdir .= $val; | ||||
| 				} | ||||
| 			}	 | ||||
| 		}else{ | ||||
| 			# no substitution here | ||||
| 			$fdir .= "/$p"; | ||||
| 		} | ||||
| 	}	 | ||||
| 	return $fdir; | ||||
| } | ||||
|  | ||||
| # get all the directories or files for given image related to this node. | ||||
| sub getNodeData { | ||||
| 	my $type = shift; | ||||
| 	my $node = shift; | ||||
| 	my $ent = shift; | ||||
| 	my $tab = shift;	 | ||||
| 	my $cb = shift;  # callback to print messages!! | ||||
| 	# the image name will be something like rhels5.4-x86_64-nfsroot | ||||
| 	my $image; | ||||
| 	unless($type =~ /image/){ | ||||
| 		$image = $ent->{os} . "-" . $ent->{arch} . "-" . $ent->{profile}; | ||||
| 	}else{ | ||||
| 		$image = $node; | ||||
| 	} | ||||
| 	my @imageInfo; | ||||
| 	my @attrs; | ||||
| 	if($type eq "dir"){ | ||||
| 		@attrs = ['priority', 'directory']; | ||||
| 	}elsif($type =~ /file|image/){ | ||||
| 		@attrs = ['file','options']; | ||||
| 	}else{ | ||||
| 		print "Yikes! error in the code litefile;getNodeData!"; | ||||
| 		exit 1; | ||||
| 	} | ||||
| 	# get the directories with no names | ||||
| 	push @imageInfo, $tab->getAttribs({image => ''}, @attrs); | ||||
| 	# get the ALL directories | ||||
| 	push @imageInfo, $tab->getAttribs({image => 'ALL'}, @attrs); | ||||
| 	# get for the image specific directories | ||||
| 	push @imageInfo, $tab->getAttribs({image => $image}, @attrs); | ||||
| 	# pass back a reference to the directory | ||||
|  | ||||
| 	# now we need to sort them | ||||
| 	return mergeArrays($type,\@imageInfo,$cb); | ||||
| } | ||||
|  | ||||
| sub mergeArrays { | ||||
| 	my $type = shift; # file or dir? | ||||
| 	my $arr = shift; # array of info from the tables. | ||||
| 	my $cb = shift;  # callback routine | ||||
| 	my $attrs; | ||||
| 	if($type eq "dir"){ | ||||
| 		foreach(@$arr){ | ||||
| 			if($_->{directory} eq ''){ next; } | ||||
| 			$attrs->{$_->{priority}} = $_->{directory}; | ||||
| 		} | ||||
| 	}elsif($type =~ /file|image/){ | ||||
| 		foreach(@$arr){ | ||||
| 			if($_->{file} eq ''){ next; } | ||||
| 			my $o = $_->{options}; | ||||
| 			if(!$o){ | ||||
| 				$o = "tmpfs,rw"; | ||||
| 			} | ||||
| 			# TODO: put some logic in here to make sure that ro is alone. | ||||
| 			# if type is ro and con, then this is wrong silly! | ||||
| 			#if($p eq "ro" and $t eq "con"){ | ||||
| 			#	my $f = $_->{file}; | ||||
| 			#	$cb->({info => "#skipping: $f.  not allowed to be ro and con"}); | ||||
| 			#	next; | ||||
| 			#} | ||||
| 			$attrs->{$_->{file}} = $o; | ||||
| 		} | ||||
| 	}else{ | ||||
| 		print "Yikes!  Error in the code in mergeArrays!\n"; | ||||
| 		exit 1; | ||||
| 	} | ||||
| 	#print "mergeArrays...\n"; | ||||
| 	#print Dumper($attrs); | ||||
| 	return $attrs; | ||||
| } | ||||
|  | ||||
| 1; | ||||
| #vim: set ts=2 | ||||
|  | ||||
							
								
								
									
										319
									
								
								xCAT-server/lib/xcat/plugins/statelite.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								xCAT-server/lib/xcat/plugins/statelite.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | ||||
| package xCAT_plugin::statelite; | ||||
| BEGIN | ||||
| { | ||||
| 	$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
| use xCAT::Table; | ||||
| use Getopt::Long; | ||||
| use File::Basename; | ||||
| use File::Path; | ||||
| use File::Copy; | ||||
| use File::Find; | ||||
| use Cwd; | ||||
| use File::Temp; | ||||
| use xCAT::Utils qw(genpassword); | ||||
| use xCAT::SvrUtils; | ||||
| use Data::Dumper; | ||||
| Getopt::Long::Configure("bundling"); | ||||
| Getopt::Long::Configure("pass_through"); | ||||
|  | ||||
| my $cmdname = "liteimg"; | ||||
| my $statedir = ".statelite"; | ||||
| my $verbose = "0"; | ||||
| sub handled_commands { | ||||
| 	return { | ||||
| 		$cmdname => "statelite" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| # function to handle request.  Basically, get the information | ||||
| # about the image and then do the action on it.  Is that vague enough? | ||||
| sub process_request { | ||||
| 	my $request = shift; | ||||
| 	my $callback = shift; | ||||
| 	my $doreq = shift; | ||||
|  | ||||
| 	my $sitetab = xCAT::Table->new('site'); | ||||
| 	my $ent = $sitetab->getAttribs({key=>'installdir'},['value']); | ||||
| 	my $installroot = "/install"; | ||||
|  | ||||
| 	# get /install directory | ||||
| 	if ($ent and $ent->{value}) { | ||||
| 		$installroot = $ent->{value}; | ||||
| 	} | ||||
| 	# if not defined, error out... or should we set it as default? | ||||
| 	unless ($installroot) { | ||||
| 		$callback->({error=>["No installdir defined in site table"],errorcode=>[1]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	@ARGV = @{$request->{arg}}; | ||||
| 	my $argc = scalar @ARGV; | ||||
| 	if ($argc == 0) { | ||||
| 		$callback->({info=>["$cmdname -h # this help message\n$cmdname -v # version\n$cmdname -V # verbose\n$cmdname [-p profile] [-a architecture] [-o OS]\n$cmdname imagename"]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	my $osver; | ||||
| 	my $arch; | ||||
| 	my $profile; | ||||
| 	my $rootimg_dir; | ||||
| 	my $destdir; | ||||
| 	my $imagename; | ||||
|  | ||||
| 	GetOptions( | ||||
| 		"profile|p=s" => \$profile, | ||||
| 		"arch|a=s" => \$arch, | ||||
| 		"osver|o=s" => \$osver, | ||||
| 		"help|h" => \$help, | ||||
| 		"version|v" => \$version, | ||||
| 		"verbose|V" => \$verbose | ||||
| 	); | ||||
|  | ||||
| 	if ($version) { | ||||
| 		my $version = xCAT::Utils->Version(); | ||||
| 		$callback->({info=>[$version]}); | ||||
| 		return; | ||||
| 	} | ||||
| 	if ($help) { | ||||
| 	#	$callback->({info=>["packimage -h \npackimage -v \npackimage [-p profile] [-a architecture] [-o OS] \npackimage imagename"]}); | ||||
| 		$callback->({info=>["imglite... prep an image to be lite"]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	# if they only gave us the image name: | ||||
| 	if (@ARGV > 0) { | ||||
| 		$imagename=$ARGV[0]; | ||||
|  		if ($arch or $osver or $profile) { | ||||
| 			$callback->({error=>["-o, -p and -a options are not allowed when a image name is specified."],errorcode=>[1]}); | ||||
| 			return; | ||||
| 		} | ||||
| 		#load the module in memory | ||||
| 		eval {require("$::XCATROOT/lib/perl/xCAT/Table.pm")}; | ||||
| 		if ($@) { | ||||
| 			$callback->({error=>[$@],errorcode=>[1]}); | ||||
| 			return; | ||||
| 		} | ||||
| 		#get the info from the osimage and linux  | ||||
|  | ||||
| 		my $osimagetab=xCAT::Table->new('osimage', -create=>1); | ||||
| 		if (!$osimagetab) { | ||||
| 			# os image doesn't exist in table. | ||||
| 			$callback->({error=>["The osimage table cannot be opened."],errorcode=>[1]}); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		# open the linux image table to get more attributes... for later. | ||||
| 		my $linuximagetab=xCAT::Table->new('linuximage', -create=>1); | ||||
| 		if (!$linuximagetab) { | ||||
| 			$callback->({error=>["The linuximage table cannot be opened."],errorcode=>[1]}); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		# get the os, arch, and profile from the image name table. | ||||
| 		(my $ref) = $osimagetab->getAttribs({imagename => $imagename}, 'osvers', 'osarch', 'profile'); | ||||
| 		if (!$ref) { | ||||
| 			$callback->({error=>["Cannot find image \'$imagename\' from the osimage table."],errorcode=>[1]}); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$osver=$ref->{'osvers'}; | ||||
| 		$arch=$ref->{'osarch'}; | ||||
| 		$profile=$ref->{'profile'}; | ||||
| 	} # end of case where they give us osimage. | ||||
|  | ||||
| 	unless ($osver and $arch and $profile ) { | ||||
| 		$callback->({error=>["osimage.osvers, osimage.osarch, and osimage.profile and must be specified for the image $imagename in the database, or you must specify -o os -p profile -a arch."],errorcode=>[1]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$destdir="$installroot/netboot/$osver/$arch/$profile"; | ||||
| 	$rootimg_dir="$destdir/rootimg"; | ||||
| 	my $oldpath=cwd(); | ||||
| 	 | ||||
| 	# now we have all the info we need: | ||||
| 	# - rootimg_dir | ||||
| 	# - osver | ||||
| 	# - arch | ||||
| 	# - profile | ||||
| 	$callback->({info=>["going to modify $rootimg_dir"]}); | ||||
| 	 | ||||
|  | ||||
| 	# now get the files for the node	 | ||||
| 	my @synclist = xCAT::Utils->runcmd("ilitefile $osver-$arch-$profile", 0, 1); | ||||
| 	if(!@synclist){ | ||||
| 		$callback->({error=>["There are no files to sync for $osver-$arch-$profile.  You have to have some files read/write filled out in the synclist table."],errorcode=>[1]}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	# all I care about are the files, not the characteristics at this point: | ||||
| 	my @files; | ||||
| 	foreach my $line (@synclist){ | ||||
| 		foreach (@{$line}){ | ||||
| 			my $f = (split(/\s+/, $_))[2]; | ||||
| 			if($f =~ /^\//){ | ||||
| 				push @files, $f; | ||||
| 			}else{ | ||||
| 				# make sure each file begins with "/" | ||||
| 				$callback->({error=>["$f in litefile does not begin with absolute path!  Need a '/' in the beginning"],errorcode=>[1]}); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	liteMe($rootimg_dir,\@files, $callback); | ||||
| 	 | ||||
| 	 | ||||
| } | ||||
|  | ||||
|  | ||||
| sub liteMe { | ||||
| 	# Arg 1:  root image dir: /install/netboot/centos5.3/x86_64/compute/rootimg | ||||
| 	my $rootimg_dir = shift;  | ||||
| 	my $files = shift; | ||||
| 	# Arg 2: callback ref to make comments... | ||||
| 	my $callback = shift;	 | ||||
| 	unless(-d $rootimg_dir){ | ||||
| 		$callback->({error=>["no rootimage dir"],errorcode=>[1]}); | ||||
| 		return; | ||||
| 	} | ||||
| 	# snapshot directory for tmpfs and persistent data.	 | ||||
| 	$callback->({info=>["creating $rootimg_dir/$statedir"]}); | ||||
| 	mkpath("$rootimg_dir/$statedir/tmpfs"); | ||||
| 	# now make a place for all the files.	 | ||||
|  | ||||
|  | ||||
| 	# this loop creates symbolic links for each of the files in the sync list. | ||||
| 	# 1.  copy original contents if they exist to .default directory | ||||
| 	# 2.  remove file  | ||||
| 	# 3.  create symbolic link to .statelite | ||||
|  | ||||
| 	my $sym = "1"; # sym = 0 means no symlinks, just bindmount | ||||
| 	if($sym){ | ||||
| 		foreach my $f (@$files){ | ||||
| 			# copy the file to /.defaults | ||||
| 			my $rif = $rootimg_dir . $f; | ||||
| 			my $d = dirname($f); | ||||
| 			if( -f "$rif" or -d "$rif"){ | ||||
| 				# if its already a link then leave it alone. | ||||
| 				unless(-l $rif){ | ||||
| 					# mk the directory if it doesn't exist: | ||||
| 					$verbose && $callback->({info=>["mkdir -p $rootimg_dir/.default$d"]}); | ||||
| 					system("mkdir -p $rootimg_dir/.default$d"); | ||||
|  | ||||
| 					# copy the file in place. | ||||
| 					$verbose && $callback->({info=>["cp -a $rif $rootimg_dir/.default$d"]}); | ||||
| 					system("cp -a $rif $rootimg_dir/.default$d"); | ||||
|  | ||||
| 					# remove the real file | ||||
| 					$verbose && $callback->({info=>["rm -rf $rif"]}); | ||||
| 					system("rm -rf $rif"); | ||||
|  | ||||
| 				} | ||||
| 	 | ||||
| 			}else{ | ||||
| 			 | ||||
| 				# in this case the file doesn't exist in the image so we create something to it. | ||||
| 				# here we're modifying the read/only image | ||||
| 				unless(-d "$rootimg_dir$d"){ | ||||
| 					$verbose && $callback->({info=>["mkdir -p $rootimg_dir$d"]}); | ||||
| 					system("mkdir -p $rootimg_dir$d");	 | ||||
| 				} | ||||
|  | ||||
| 				unless(-d "$rootimg_dir/.default$d"){ | ||||
| 					$verbose && $callback->({info=>["mkdir -p $rootimg_dir/.default$d"]}); | ||||
| 					system("mkdir -p $rootimg_dir/.default$d");	 | ||||
| 				} | ||||
| 				 | ||||
| 				# now make touch the file:	 | ||||
| 				if($f =~ /\/$/){ | ||||
| 					# if its a directory, make the directory in .default | ||||
| 					$verbose && $callback->({info=>["mkdir -p $rootimg_dir/.default$f"]}); | ||||
| 					system("mkdir -p $rootimg_dir/.default$f"); | ||||
| 				}else{ | ||||
| 					# if its just a file then link it. | ||||
| 					$verbose && $callback->({info=>["touch $rootimg_dir/.default$f"]}); | ||||
| 					system("touch $rootimg_dir/.default$f"); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			# now create the spot in tmpfs | ||||
| 			$verbose && $callback->({info=>["mkdir -p $rootimg_dir/$statedir/tmpfs$d"]}); | ||||
| 			system("mkdir -p $rootimg_dir/$statedir/tmpfs$d"); | ||||
|  | ||||
| 			# now for each file, create a symbollic link to /.statelite/tmpfs/ | ||||
| 			# strip the last / if its a directory for linking, but be careful! | ||||
| 			# doing ln -sf ../../tmp <blah>../tmp when tmp is a directory creates 50 levels of links. | ||||
| 			# have to do: | ||||
| 			# ln -sf ../../tmp <blah>../../tmp/ <- note the / on the end! | ||||
| 			if($f =~ /\/$/){ | ||||
| 				$f =~ s/\/$//g; | ||||
| 			} | ||||
| 			# now do the links. | ||||
| 			# link the .default file to the .statelite file and the real file to the .statelite file. | ||||
|  | ||||
| 			# ../ for tmpfs | ||||
| 			# ../ for .statelite | ||||
| 			# the rest are for the paths in the file.	 | ||||
| 			my $l = getRelDir($f);	 | ||||
| 			$verbose && $callback->({info=>["ln -sf ../../$l/.default$f $rootimg_dir/$statedir/tmpfs$f"]}); | ||||
| 			system("ln -sfn ../../$l/.default$f $rootimg_dir/$statedir/tmpfs/$f"); | ||||
|  | ||||
| 			$verbose && $callback->({info=>["ln -sf $relPath/$statedir/tmpfs$f $rootimg_dir$f"]}); | ||||
| 			system("ln -sfn $l/$statedir/tmpfs$f $rootimg_dir$f"); | ||||
| 				 | ||||
| 		}	 | ||||
| 	}else{ | ||||
| 		# if we go the bindmount method, create some files | ||||
| 		foreach my $f (@$files){ | ||||
| 			my $rif = $rootimg_dir . $f; | ||||
| 			my $d = dirname($rif); | ||||
| 			unless(-e "$rif"){ | ||||
| 				# if it doesn't exist, create it on base image: | ||||
| 				unless(-d $d){ | ||||
| 					#$callback->({info=>["mkdir -p $d"]}); | ||||
| 					system("mkdir -p $d"); | ||||
| 				} | ||||
| 				if($rif =~ /\/$/){ | ||||
| 					#$callback->({info=>["mkdir -p $rif"]}); | ||||
| 					system("mkdir -p $rif"); | ||||
| 				}else{ | ||||
| 					#$callback->({info=>["touch $rif"]}); | ||||
| 					system("touch $rif"); | ||||
| 				} | ||||
| 			}	 | ||||
| 			else { | ||||
| 					#$callback->({info=>["$rif exists"]}); | ||||
| 			} | ||||
| 				 | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 		 | ||||
| 	# end loop, synclist should now all be in place. | ||||
|  | ||||
| 	# now stick the rc files in: | ||||
| 	# this is actually a pre-rc file because it gets run before the node boots up all the way. | ||||
| 	system("cp -a $::XCATROOT/share/xcat/netboot/add-on/statelite/rc.statelite $rootimg_dir/etc/init.d/statelite"); | ||||
| 	 | ||||
| } | ||||
|  | ||||
| sub getRelDir { | ||||
| 	my $f = shift; | ||||
| 	$f = dirname($f); | ||||
| 	if($f eq "/"){ | ||||
| 		return "."; | ||||
| 	} | ||||
| 	my $l = ""; | ||||
| 	 | ||||
| 	my @arr = split("/", $f); | ||||
| 	foreach (1 .. $#arr){ | ||||
| 		$l .= "../"; | ||||
| 	} | ||||
|  | ||||
| 	chop($l); # get rid of last / | ||||
| 	return $l | ||||
| } | ||||
|  | ||||
| 1; | ||||
		Reference in New Issue
	
	Block a user