summaryrefslogblamecommitdiffstats
path: root/config-db/slxconfig-demuxer.pl
blob: 74916c734f5d2575a371ce0907a21c64ce073864 (plain) (tree)
1
2
3
4
5
6
7
8
9
                
           




                                                                        
                              
                   
                                          
 
                    
                                                        
 

                                                       
        
          
                

              



                                                            

                
                                             
                         


                                                                           

  





                                                                                  
              
 
                                  
 


                                                                                
 
                                                              




                                                                                 
 
                                                          
               
                                                                     



                                                                                     

 


                                                 


                                                    
                                                                                                                   
 
                               
 
                                                                                 

                        
 




                                                                                



























                                                                                                                                                                                                 




                             

                                   



                                                                                      
                                                                       
                                                                             




                     
                            




                                                                            

                                   


                                                                                



                                     
                                                            



                                                                 
                                                               










                                                                

                                                  


                                   








                                                                                    

                 

                                                           
 
                                        
                                 

                                                                             
         
                                      
                               

                                                                           

         


                                                                    

                                                                 
                                                             

                                                                                     


                                                                                 





                                                                                           
                                                                                






                                                                           

                           


         


































                                                                            



                           
                                        
 













                                                                                               
         

 





                                      


                                                                         
                                                                                      
                                         
 




                                                                                    
 



                                                                     
                                                                      
                                                                                             


         

                             



                                                       
                                                                                      
                                   
 
                                                  
                                                                      

                                                                    
                                                                      

                                                          




                                                                             


                                                                                   
                                                                       


         
                       
 
                                                      
                                    
                        

 
#! /usr/bin/perl
use strict;

# add the folder this script lives in to perl's search path for modules:
use FindBin;
use lib $FindBin::Bin;

use Fcntl qw(:DEFAULT :flock);
use File::Basename;
use Getopt::Long qw(:config pass_through);

use OpenSLX::Basics;
use OpenSLX::ConfigDB qw(:access :aggregation :support);

my $pxeConfigDefaultTemplate = q[# generated by openslx
NOESCAPE 0
PROMPT 0
TIMEOUT 10
DEFAULT menu.c32
IMPLICIT 1
ALLOWOPTIONS 1
MENU TITLE What would you like to do? (use cursor to select)
MENU MASTER PASSWD secret
];

my (
	$dryRun,
		# dryRun won't touch any file
	$systemConfCount,
		# number of system configurations written
	$clientSystemConfCount,
		# number of (system-specific) client configurations written
);

GetOptions(
	'dry-run' => \$dryRun
		# dry-run doesn't write anything, just prints statistic about what
		# would have been written
);

openslxInit();

my $openslxDB = connectConfigDB();

my $clientConfigPath = "$openslxConfig{'private-path'}/config";
if (!-d $clientConfigPath) {
	die _tr("Unable to access client-config-path '%s'!", $clientConfigPath);
}
my $tempPath = "$openslxConfig{'temp-basepath'}/oslx-demuxer";
if (!$dryRun) {
	mkdir $tempPath;
	if (!-d $tempPath) {
		die _tr("Unable to create or access temp-path '%s'!", $tempPath);
	}
}
my $exportPath = "$openslxConfig{'public-path'}/tftpboot";
if (!$dryRun) {
	system("rm -rf $exportPath/client-conf/* $exportPath/pxe/*");
	system("mkdir -p $exportPath/client-conf $exportPath/pxe/pxelinux.cfg");
	if (!-d $exportPath) {
		die _tr("Unable to create or access export-path '%s'!", $exportPath);
	}
}

my $lockFile = "$exportPath/config-demuxer.lock";
lockScript($lockFile);

writeConfigurations();

my $wr = ($dryRun ? "would have written" : "wrote");
print "$wr $systemConfCount systems and $clientSystemConfCount client-configurations to $exportPath/client-conf\n";

disconnectConfigDB($openslxDB);

system("rm -rf $tempPath")		unless $dryRun || length($tempPath) < 12;

unlockScript($lockFile);

exit;

################################################################################
###
################################################################################
sub lockScript
{
	my $lockFile = shift;

	return		if $dryRun;

	# use a lock-file to singularize execution of this script:
	if (-e $lockFile) {
		my $ctime = (stat($lockFile))[10];
		my $now = time();
		if ($now - $ctime > 15*60) {
			# existing lock file is older than 15 minutes, wipe it:
			unlink $lockFile;
		}
	}
	sysopen(LOCKFILE, $lockFile, O_RDWR|O_CREAT|O_EXCL)
		or die _tr(qq[Lock-file <%s> exists, script is already running.\nPlease remove the logfile and try again if you are sure that no one else is executing this script.], $lockFile);
}

sub unlockScript
{
	my $lockFile = shift;

	return		if $dryRun;

	unlink $lockFile;
}

sub writeAttributesToFile
{
	my $attrHash = shift;
	my $fileName = shift;

	return		if $dryRun;

	open(ATTRS, "> $fileName")		or die "unable to write to $fileName";
	my @attrs = sort grep { isAttribute($_) } keys %$attrHash;
	foreach my $attr (@attrs) {
		if (length($attrHash->{$attr}) > 0) {
			my $externalAttrName = externalAttrName($attr);
			print ATTRS "$externalAttrName=$attrHash->{$attr}\n";
		}
	}
	close(ATTRS);
}

sub copyExternalSystemConfig
{	# copies local configuration extensions of given system from private
	# config folder (var/lib/openslx/config/...) into a temporary folder
	my $systemName = shift;
	my $targetPath = shift;

	return		if $dryRun;

	if ($targetPath !~ m[$tempPath]) {
		die _tr("system-error: illegal target-path <%s>!", $targetPath);
	}
	system("rm -rf $targetPath");
	mkdir $targetPath;

	# first copy default files...
	my $defaultConfigPath = "$clientConfigPath/default";
	if (-d $defaultConfigPath) {
		system("cp -r $defaultConfigPath/* $targetPath");
	}
	# now pour system-specific configuration on top (if any):
	my $systemConfigPath = "$clientConfigPath/$systemName";
	if (-d $systemConfigPath) {
		system("cp -r $systemConfigPath/* $targetPath");
	}
}

sub createTarOfPath
{
	my $buildPath = shift;
	my $tarName = shift;
	my $destinationPath = shift;

	my $tarFile = "$destinationPath/$tarName";
	vlog 1, _tr('creating tar %s', $tarFile);
	return		if $dryRun;

	mkdir $destinationPath;
	my $tarCmd = "cd $buildPath && tar czf $tarFile *";
	if (system("$tarCmd") != 0) {
		die _tr("unable to execute shell-command:\n\t%s \n\t($!)", $tarCmd);
	}
}

################################################################################
###
################################################################################
sub writePXEMenus
{
	my $pxePath = "$exportPath/pxe";
	my $pxeConfigPath = "$exportPath/pxe/pxelinux.cfg";

	if (!-e "$pxePath/pxelinux.0") {
		my $pxelinux0Path
			= "$openslxConfig{'share-path'}/tftpboot/pxelinux.0";
		system(qq[cp -a "$pxelinux0Path" $pxePath/]);
	}
	if (!-e "$pxePath/menu.c32") {
		my $menuc32Path
			= "$openslxConfig{'share-path'}/tftpboot/menu.c32";
		system(qq[cp -a "$menuc32Path" $pxePath/]);
	}

	my @clients = fetchClientsByFilter($openslxDB);
	foreach my $client (@clients) {
		my $externalClientID = externalIDForClient($client);
		my $pxeFile = "$pxeConfigPath/$externalClientID";
		my $clientAppend = $client->{kernel_params};
		vlog 1, _tr("writing PXE-file %s", $pxeFile);
		open(PXE, "> $pxeFile")		or die "unable to write to $pxeFile";
		print PXE $pxeConfigDefaultTemplate;
		my @systemIDs = aggregatedSystemIDsOfClient($openslxDB, $client);
		my @systems = fetchSystemsByID($openslxDB, \@systemIDs);
		foreach my $system (@systems) {
			my @infos = aggregatedSystemFileInfosOfSystem($openslxDB, $system);
			foreach my $info (@infos) {
				my $extSysID = externalIDForSystem($info);
				my $append = $system->{kernel_params};
				$append .= " initrd=$extSysID/initialramfs";
				$append .= " $clientAppend";
				$append .= " rootfs=$info->{'export-uri'} file";
				print PXE "LABEL openslx-$extSysID\n";
#				print PXE "\tMENU DEFAULT\n";
				print PXE "\tMENU LABEL ^$info->{label}\n";
				print PXE "\tKERNEL $extSysID/kernel\n";
				print PXE "\tAPPEND $append\n";
				print PXE "\tIPAPPEND 1\n";
			}
		}
		close(PXE);
 	}
}

sub generateInitalRamFS
{
	my $setup = shift;
	my $vendorOS = shift;
	my $pxeSysPath = shift;

	vlog 1, _tr('generating initialramfs %s/initialramfs', $pxeSysPath);
	my $cmd = "$openslxConfig{'bin-path'}/slxmkramfs ";
	if ($setup->{ramfs_use_glibc}) {
		$cmd .= '-g ';
	}
	if ($setup->{ramfs_use_busybox}) {
		$cmd .= '-b ';
	}
	my $debugLevel = $setup->{ramfs_debug_level};
	if ($debugLevel) {
		$cmd .= qq[-d $debugLevel ];
	}
	if (length($setup->{ramfs_nicmods}) > 0) {
		$cmd .= qq[-n "$setup->{ramfs_nicmods}" ];
	}
	if (length($setup->{ramfs_fsmods}) > 0) {
		$cmd .= qq[-f "$setup->{ramfs_fsmods}" ];
	}
	my $rootPath
		= "$openslxConfig{'private-path'}/stage1/$vendorOS->{path}";
	$cmd .= "-i $pxeSysPath/initialramfs -r $rootPath";

	$ENV{'SLX_PRIVATE_PATH'} = $openslxConfig{'private-path'};
	$ENV{'SLX_PUBLIC_PATH'} = $openslxConfig{'public-path'};
	$ENV{'SLX_SHARE_PATH'} = $openslxConfig{'share-path'};
	vlog 2, _tr('executing %s', $cmd);
	system($cmd)		unless $dryRun;
}

sub writeSystemPXEFiles
{
	my $system = shift;

	my $pxePath = "$exportPath/pxe";

	my $vendorOS = fetchVendorOSesByID($openslxDB, $system->{vendor_os_id});
	my @infos = aggregatedSystemFileInfosOfSystem($openslxDB, $system);
	foreach my $info (@infos) {
		my $kernelFile = $info->{'kernel-file'};
		my $extSysID = externalIDForSystem($info);
		my $pxeSysPath = "$pxePath/$extSysID";
		if (-e $pxeSysPath) {
			die _tr('PXE-system %s already exists!', $pxeSysPath);
		}
		mkdir $pxeSysPath;
		vlog 1, _tr('copying kernel %s to %s/kernel', $kernelFile, $pxeSysPath);
		system(qq[cp -a "$kernelFile" $pxeSysPath/kernel])		unless $dryRun;

		generateInitalRamFS($info, $vendorOS, $pxeSysPath);
	}
}

sub writeClientConfigurationsForSystem
{
	my $system = shift;
	my $buildPath = shift;
	my $attrFile = shift;

	my @clientIDs = aggregatedClientIDsOfSystem($openslxDB, $system);
	my @clients = fetchClientsByID($openslxDB, \@clientIDs);
	foreach my $client (@clients) {
		vlog 2, _tr("exporting client %d:%s", $client->{id}, $client->{name});
		$clientSystemConfCount++;

		# merge configurations of client, it's groups, default client and
		# system and write the resulting attributes to a configuration file:
		mergeDefaultAndGroupAttributesIntoClient($openslxDB, $client);
		mergeAttributes($client, $system);
		writeAttributesToFile($client, $attrFile);

		# create tar containing external system configuration
		# and client attribute file:
		my $externalClientID = externalIDForClient($client);
		my $externalSystemID = externalIDForSystem($system);
		createTarOfPath($buildPath, "${externalClientID}.tgz",
						"$exportPath/client-conf/$externalSystemID");
	}
}

sub writeSystemConfigurations
{
	my @systems = fetchSystemsByFilter($openslxDB);
	foreach my $system (@systems) {
		next 	unless $system->{id} > 0;

		vlog 2, _tr('exporting system %d:%s', $system->{id}, $system->{name});
		$systemConfCount++;

		my $buildPath = "$tempPath/build";
		copyExternalSystemConfig($system->{name}, $buildPath);

		my $attrFile = "$buildPath/initramfs/machine-setup";
		mergeDefaultAttributesIntoSystem($openslxDB, $system);
		writeAttributesToFile($system, $attrFile);

		my $externalSystemID = externalIDForSystem($system);
		my $systemPath = "$exportPath/client-conf/$externalSystemID";
		createTarOfPath($buildPath, "default.tgz", $systemPath);

		writeSystemPXEFiles($system);

		writeClientConfigurationsForSystem($system, $buildPath, $attrFile);

		system("rm -rf $buildPath")		unless $dryRun;
	}
}

sub writeConfigurations
{
	$systemConfCount = $clientSystemConfCount = 0;
	writeSystemConfigurations();
	writePXEMenus();
}