diff options
author | Oliver Tappe | 2006-10-28 16:23:49 +0200 |
---|---|---|
committer | Oliver Tappe | 2006-10-28 16:23:49 +0200 |
commit | 1417b305c990fb428f4089052826a5ba1329c7cf (patch) | |
tree | 9193fc1af8da1f66c41b4b555e113d702fafd8be /config-db/slxconfig-demuxer | |
parent | Don't overwrite an existing settings.local file. (diff) | |
download | core-1417b305c990fb428f4089052826a5ba1329c7cf.tar.gz core-1417b305c990fb428f4089052826a5ba1329c7cf.tar.xz core-1417b305c990fb428f4089052826a5ba1329c7cf.zip |
* renamed several scripts to our new convention: no .pl for
user-executable stuff...
git-svn-id: http://svn.openslx.org/svn/openslx/trunk@475 95ad53e4-c205-0410-b2fa-d234c58c8868
Diffstat (limited to 'config-db/slxconfig-demuxer')
-rwxr-xr-x | config-db/slxconfig-demuxer | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/config-db/slxconfig-demuxer b/config-db/slxconfig-demuxer new file mode 100755 index 00000000..62780f17 --- /dev/null +++ b/config-db/slxconfig-demuxer @@ -0,0 +1,651 @@ +#! /usr/bin/perl +# +# slxconfig-demuxer.pl - OpenSLX configuration demultiplexer +# +# (c) 2006 - OpenSLX.com +# +# Oliver Tappe <ot@openslx.com> +# +use strict; + +my $abstract = q[ +slxconfig-demuxer.pl + This script will read information about all systems, clients and + groups from the OpenSLX configuration database, mix & match the individual + configurational attributes and then demultiplex the resulting information + to a set of configuration files. These files are used by any OpenSLX-client + during boot to find out which systems to offer for booting. + + The resulting files will be put into the OpenSLX-tftpboot-path (you can use + the option --tftpboot-path to override the default taken from the OpenSLX + default settings). + + Please use the --man option in order to read the full manual. +]; + +use Fcntl qw(:DEFAULT :flock); +use File::Basename; +use Getopt::Long qw(:config pass_through); +use Pod::Usage; + +# add the lib-folder and the folder this script lives in to perl's search +# path for modules: +use FindBin; +use lib "$FindBin::RealBin/../lib"; + # production path +use lib "$FindBin::RealBin"; + # development path + +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 + $helpReq, + $manReq, + $versionReq, +); + +GetOptions( + 'dry-run' => \$dryRun, + # dry-run doesn't write anything, just prints statistic about what + # would have been written + 'help|?' => \$helpReq, + 'man' => \$manReq, + 'version' => \$versionReq, +) or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $helpReq; +pod2usage(-verbose => 2) if $manReq; +if ($versionReq) { + system('slxversion'); + exit 1; +} + +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-path'}/slxconfig-demuxer"; +if (!$dryRun) { + mkdir $tempPath; + if (!-d $tempPath) { + die _tr("Unable to create or access temp-path '%s'!", $tempPath); + } +} +my $tftpbootPath = $openslxConfig{'tftpboot-path'}; +if (!$dryRun) { + system("rm -rf $tftpbootPath/client-config/* $tftpbootPath/pxe/*"); + system("mkdir -p $tftpbootPath/client-config $tftpbootPath/pxe/pxelinux.cfg"); + if (!-d $tftpbootPath) { + die _tr("Unable to create or access tftpboot-path '%s'!", $tftpbootPath); + } +} + +my $lockFile = "$tftpbootPath/config-demuxer.lock"; +lockScript($lockFile); + +writeConfigurations(); + +my $wr = ($dryRun ? "would have written" : "wrote"); +print "$wr $systemConfCount systems and $clientSystemConfCount client-configurations to $tftpbootPath/client-config\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; + } + } + if (!sysopen(LOCKFILE, $lockFile, O_RDWR|O_CREAT|O_EXCL)) { + if ($! == 13) { + die _tr(qq[Unable to create lock-file <%s>, exiting!\n], $lockFile); + } else { + die _tr(qq[Lock-file <%s> exists, script is already running. +Please remove the logfile and try again if you are sure that no one else +is executing this script.\n], $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(%s)", $tarCmd, $!); + } +} + +################################################################################ +### +################################################################################ +sub writePXEMenus +{ + my $pxePath = "$tftpbootPath/pxe"; + my $pxeConfigPath = "$tftpbootPath/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/initramfs"; + $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/initramfs', $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/initramfs -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 = "$tftpbootPath/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", + "$tftpbootPath/client-config/$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 = "$tftpbootPath/client-config/$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(); +} + +__END__ + +=head1 NAME + +slxconfig-demuxer.pl - OpenSLX configuration demultiplexer + +=head1 SYNOPSIS + +slxconfig-demuxer.pl [options] + + Script Options: + --dry-run avoids writing anything, for testing + + OpenSLX Options: + --base-path=<string> basic path to project files + --bin-path=<string> path to binaries and scripts + --config-path=<string> path to configuration files + --db-basepath=<string> basic path to openslx database + --db-datadir=<string> data folder created under db-basepath + --db-name=<string> name of database + --db-spec=<string> full DBI-specification of database + --db-type=<string> type of database to connect to + --export-path=<string> path to root of all exported filesystems + --locale=<string> locale to use for translations + --logfile=<string> file to write logging output to + --private-path=<string> path to private data + --public-path=<string> path to public (client-accesible) data + --share-path=<string> path to sharable data + --temp-path=<string> path to temporary data + --tftpboot-path=<string> path to root of tftp-server + --verbose-level=<int> level of logging verbosity (0-3) + + General Options: + --help brief help message + --man full documentation + --version show version + +=head1 OPTIONS + +=head3 Script Options + +=over 8 + +=item B<--dry-run> + +Runs the script but avoids writing anything. This is useful for testing, as +you can learn from the logging output what would have been done. + +=back + +=head3 OpenSLX Options + +=over 8 + +=item B<--base-path=<string>> + +Sets basic path to project files. + +Default is $SLX_BASE_PATH (usually F</opt/openslx>). + +=item B<--bin-path=<string>> + +Sets path to binaries and scripts. + +Default is $SLX_BASE_PATH/bin (usually F</opt/openslx/bin>). + +=item B<--config-path=<string>> + +Sets path to configuration files. + +Default is $SLX_CONFIG_PATH (usually F</etc/opt/openslx>). + +=item B<--db-basepath=<string>> + +Sets basic path to openslx database. + +Default is $SLX_DB_PATH (usually F</var/opt/openslx/db>). + +=item B<--db-datadir=<string>> + +Sets data folder created under db-basepath. + +Default is $SLX_DB_DATADIR (usually empty as it depends on db-type +whether or not such a directory is required at all). + +=item B<--db-name=<string>> + +Gives the name of the database to connect to. + +Default is $SLX_DB_NAME (usually C<openslx>). + +=item B<--db-spec=<string>> + +Gives the full DBI-specification of database to connect to. Content depends +on the db-type. + +Default is $SLX_DB_SPEC (usually empty as it will be built automatically). + +=item B<--db-type=<string>> + +Sets the type of database to connect to (CSV, SQLite, mysql, ...). + +Default $SLX_DB_TYPE (usually C<CSV>). + +=item B<--export-path=<string>> + +Sets path to root of all exported filesystems. For each type of export (NFS, +NBD, ...) a separate folder will be created in here. + +Default is $SLX_EXPORT_PATH (usually F</srv/openslx/export>. + +=item B<--locale=<string>> + +Sets the locale to use for translations. + +Defaults to the system's standard locale. + +=item B<--logfile=<string>> + +Specifies a file where logging output will be written to. + +Default is to log to STDERR. + +=item B<--private-path=<string>> + +Sets path to private data, where the config-db, vendor_oses and configurational +extensions will be stored. + +Default is $SLX_PRIVATE_PATH (usually F</var/opt/openslx>. + +=item B<--public-path=<string>> + +Sets path to public (client-accesible) data. + +Default is $SLX_PUBLIC_PATH (usually F</srv/openslx>. + +=item B<--share-path=<string>> + +Sets path to sharable data, where distro-specs and functionality templates +will be stored. + +Default is $SLX_SHARE_PATH (usually F</opt/openslx/share>. + +=item B<--temp-path=<string>> + +Sets path to temporary data. + +Default is $SLX_TEMP_PATH (usually F</tmp>. + +=item B<--tftpboot-path=<string>> + +Sets path to root of tftp-server from which clients will access their files. + +Default is $SLX_TFTPBOOT_PATH (usually F</srv/openslx/tftpboot>. + +=item B<--verbose-level=<int>> + +Sets the level of logging verbosity (0-3). + +Default is $SLX_VERBOSE_LEVEL (usually 0, no logging). + +=back + +=head3 General Options + +=over 8 + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--version> + +Prints the version and exits. + +=back + +=head1 DESCRIPTION + +B<slxconfig-demuxer.pl> will read information about all systems, clients and +groups from the OpenSLX configuration database, mix & match the individual +configurational attributes and then demultiplex the resulting information +to a set of configuration files. These files are used by any OpenSLX-client +during boot to find out which systems to offer for booting. + +The resulting files will be put into the OpenSLX-tftpboot-path (you can use the +option B<--tftpboot-path> to override the default taken from the OpenSLX +default settings). + +=head2 FILE CREATION + +The following set of files will be created: + +=over 8 + +=item B<Basic PXE Setup> + +The basic PXE files (F<menu.c32>, F<pxelinux.0>) will be copied into +F<$SLX_TFTPBOOT_PATH/pxe> to make them available to any PXE-client via tftp. + +=item B<PXE Client Configurations> + +For each client, a PXE configuration file will be generated and written to +F<$SLX_TFTPBOOT_PATH/pxe/pxelinux.cfg/01-<MAC-of-client>>. This file will +contain information about the systems this client shall offer for booting. +For each of these systems, the kernel cmdline options required for that +particular system setup is specified (via PXE's APPEND option). + +=item B<System Kernels and Initialram-Filesystems> + +For each bootable system, that system's kernel will be copied to +F<$SLX_TFTPBOOT_PATH/pxe/<system-name>/kernel and an OpenSLX-specific initramfs +required for booting that particular system is generated (by means of +slxmkramfs) and put into F<$SLX_TFTPBOOT_PATH/pxe/<system-name>/initramfs. + +These two files (kernel & initramfs) will be referenced by the PXE client +configuration of all clients that offer this specific system for booting. + +=item B<OpenSLX Client Configurations> + +For each combination of system and client, an OpenSLX configuration archive +will be generated and written to +F<$SLX_TFTPBOOT_PATH/client-config/<system-name>/01-<MAC-of-client>.tgz>. +This archive will contain the file F<initramfs/machine-setup>, specifying all +the attributes of that particular client (e.g. whether or not it should start +the X-server). + +Furthermore, the archive may contain additional system files that are +required for the client (e.g. a special PAM-module required for LDAP +authentication). These files are copied from F<$SLX_PRIVATE_PATH/config/default> +and F<$SLX_PROVATE_PATH/config/<system-name>>. + +=back + +=head2 MIXING & MATCHING (THE DEMUXER) + +In the OpenSLX configuration database, each system, group and client may have +several configurational attributes set to a specific value that will cause +a client booting that system to behave in a certain way. The mixing of all +these different attributes into one set that is relevant for a specific client +booting one specific system is one important task of the slxconfig-demuxer. + +As an example, let's assume one system setup that is configured to boot directly +into a special application that demands a rather low screen-resolution of +1024x768 pixels, as otherwise the text would be unreadable due to very small +fonts being used by that app. In order to achieve this, the administrator can +set the I<hw_monitor>-attribute of the B<system> to '1024x768'. +Let's say one of the clients, however, is connected to a very old monitor that +has problems with this resolution and only supports 800x600 pixels. In that +case, the administrator can set the I<hw_monitor>-attribute of that B<client> to +'800x600'. The mixing & matching process would make sure that this specific +client would run that system with a resolution of 800x600, while all other +clients would run that system in 1024x768. + +So the slxconfig-demuxer demultiplexes the individual configurational attributes +into a concrete set of configuration settings for specific clients and their +offered systems, making sure that each client/system combination uses the +appropriate settings. + +=cut |