From 416ab8a37f1b07dc9f6c0fb3ff1a8ff2036510b5 Mon Sep 17 00:00:00 2001 From: Sebastian Schmelzer Date: Thu, 2 Sep 2010 17:50:49 +0200 Subject: change dir structure --- src/config-db/slxconfig-demuxer | 918 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 918 insertions(+) create mode 100755 src/config-db/slxconfig-demuxer (limited to 'src/config-db/slxconfig-demuxer') diff --git a/src/config-db/slxconfig-demuxer b/src/config-db/slxconfig-demuxer new file mode 100755 index 00000000..b88efeb6 --- /dev/null +++ b/src/config-db/slxconfig-demuxer @@ -0,0 +1,918 @@ +#! /usr/bin/perl +# ----------------------------------------------------------------------------- +# Copyright (c) 2006, 2007 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# slxconfig-demuxer +# - OpenSLX configuration demultiplexer +# ----------------------------------------------------------------------------- +use strict; +use warnings; +use Switch; + + +my $abstract = q[ +slxconfig-demuxer + 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. + + Please use the --man option in order to read the full manual. +]; + +use Config::General; +use Digest::MD5 qw(md5_hex); +use File::Basename; +use File::Find; +use File::Path; +use List::Util qw(first); +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"; +use lib "$FindBin::RealBin"; +# development path to config-db stuff + +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::ConfigFolder; +use OpenSLX::OSPlugin::Roster; +use OpenSLX::Utils; + +my ( + $systemConfCount, + # number of system configurations written + $systemErrCount, + # number of systems that had errors + $bootEnvErrCount, + # number of boot environments that had errors + $clientSystemConfCount, + # number of (system-specific) client configurations written + $initramfsCount, + # number of initramfs that were created + @targetSystems, + # systems to create initramfs for, defaults to all systems + %bootEnvMap, + # objects encapsulating the bootloader specific configurations + %option, + # cmdline option hash +); + +if ($> != 0) { + die _tr("Sorry, this script can only be executed by the superuser!\n"); +} + +GetOptions( + 'dhcp-export-type=s' => \$option{dhcpType}, + 'dry-run' => \$option{dryRun}, + 'help|?' => \$option{helpReq}, + 'man' => \$option{manReq}, + 'version' => \$option{versionReq}, + ) + or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $option{helpReq}; +if ($option{manReq}) { + # avoid dubious problem with perldoc in combination with UTF-8 that + # leads to strange dashes and single-quotes being used + $ENV{LC_ALL} = 'POSIX'; + pod2usage(-verbose => 2); +} +if ($option{versionReq}) { + slxsystem('slxversion'); + exit 1; +} + +openslxInit(); + +my $openslxDB = OpenSLX::ConfigDB->new(); +$openslxDB->connect(); + +my $clientConfigPath = "$openslxConfig{'private-path'}/config"; +# make sure that the default config folders exist: +if (createConfigFolderForDefaultSystem()) { + # this path should have been generated by earlier stage (slxsettings), so + # we indicate that there is some kind of problem: + warn _tr( + "Completed client-config-folder '%s', since at least some parts of it didn't exist!", + $clientConfigPath + ); +} + +# protect against parallel execution of this script +my $demuxerLock = grabLock('slxconfig-demuxer'); + +my $tempPath = "$openslxConfig{'temp-path'}/slxconfig-demuxer"; +if (!$option{dryRun}) { + rmtree($tempPath); + mkpath($tempPath); + if (!-d $tempPath) { + die _tr("Unable to create or access temp-path '%s'!", $tempPath); + } +} + +my $deleteInFinalize = 0; + +my @demuxableSystems + = grep { $_->{name} ne '<<>>' } $openslxDB->fetchSystemByFilter(); +if (@ARGV) { + # create initramfs only for systems given on cmdline + for my $systemName (@ARGV) { + if ($systemName eq '<<>>') { + warn _tr( + 'The default-system can not be demuxed - it will be skipped.' + ); + next; + } + my $system = first { $_->{name} eq $systemName } @demuxableSystems; + if (!$system) { + warn _tr( + 'The system "%s" is unknown and will be ignored.', $systemName + ); + next; + } + push @targetSystems, $system; + } +} +else { + # create initramfs for all systems + @targetSystems = @demuxableSystems; + $deleteInFinalize = 1; +} + +writeConfigurations(); + +my $wr = $option{dryRun} ? 'would have written' : 'wrote'; +my $errCount = $systemErrCount ? $systemErrCount : 'no'; +my $systemStatusString + = $systemErrCount ? "$errCount system(s) had errors" : 'all systems ok'; +$errCount = $bootEnvErrCount ? $bootEnvErrCount : 'no'; +my $bootEnvStatusString + = $bootEnvErrCount + ? "$errCount boot environment(s) had errors" + : 'all boot-environments ok'; +print "\n", unshiftHereDoc(<<"End-of-Here"); + $wr $systemConfCount system-specific and $clientSystemConfCount client-specific configurations + $initramfsCount initramfs were created + $systemStatusString + $bootEnvStatusString +End-of-Here + +$openslxDB->disconnect(); + +rmtree([$tempPath]); + +# allow all boot-environments to clean up and active the new configuration +foreach my $bootEnv (values %bootEnvMap) { + $bootEnv->finalize($deleteInFinalize); +} + +exit; + +################################################################################ +### +################################################################################ +sub folderContainsFiles +{ + my $folder = shift; + + return 0 unless -d $folder; + + my $result = 0; + my $wanted = sub { + if ($result) { + # skip anything else if we have found a file already + $File::Find::prune = 1; + } + $result = 1 if -f; + }; + find({wanted => $wanted, follow_fast => 1}, $folder); + vlog(2, "result for folderContainsFiles($folder): $result\n"); + return $result; +} + +sub digestAttributes +{ # returns a digest-string for the given attribute hash, in order to + # facilitate comparing different attribute hashes. + my $object = shift; + + my $attrs = $object->{attrs} || {}; + my $attrsAsString + = join ';', + map { "$_=$attrs->{$_}" } + sort + grep { defined $attrs->{$_} } + keys %$attrs; + + vlog(3, "Attribute-string: $attrsAsString"); + return md5_hex($attrsAsString); +} + +sub writeAttributesToFile +{ + my $object = shift; + my $fileName = shift; + + return if $option{dryRun}; + + my $content = "# attributes set by slxconfig-demuxer:\n"; + my $attrs = $object->{attrs} || {}; + # filter out any plugin-specific attributes (we only want to handle + # the attributes relevant to the core here) + my @attrs = sort grep { index($_, '::') == -1 } keys %$attrs; + foreach my $attr (@attrs) { + my $attrVal = $attrs->{$attr}; + next if !defined $attrVal; + $content .= qq[$attr="$attrVal"\n]; + } + # Overwrite attribute file even if it exists, to make sure that our users + # will never try to fiddle with machine-setup directly in the file-system. + # The config-DB is the keeper of that info! + spitFile($fileName, $content); + if ($openslxConfig{'log-level'} > 2) { + vlog(0, "--- START OF $fileName ---"); + vlog(0, $content); + vlog(0, "--- END OF $fileName --- "); + } + return; +} + +sub writeSlxConfigToFile +{ + my $slxConf = shift; + my $fileName = shift; + + return if $option{dryRun}; + + my $content = ''; + foreach my $key (sort keys %$slxConf) { + $content .= qq[$key="$slxConf->{$key}"\n]; + } + spitFile($fileName, $content); + return; +} + +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; + my $clientName = shift; # optional + + if ($targetPath !~ m[^$tempPath]) { + # bail if target-path isn't within temp folder, as we do not dare + # executing 'rm -rf' in that case! + die _tr("system-error: illegal target-path <%s>!", $targetPath); + } + return if $option{dryRun}; + + slxsystem("rm -rf $targetPath"); + mkpath $targetPath; + + # first copy default files ... + my $defaultConfigPath = "$clientConfigPath/default"; + vlog(2, "checking $defaultConfigPath for default config..."); + if (-d $defaultConfigPath) { + slxsystem("cp -a $defaultConfigPath/* $targetPath"); + } + # ... now pour system-specific configuration on top (if any) ... + my $systemSpecConfigPath = "$clientConfigPath/$systemName/default"; + vlog(2, "checking $systemSpecConfigPath for system config..."); + if (folderContainsFiles($systemSpecConfigPath)) { + slxsystem("cp -a $systemSpecConfigPath/* $targetPath"); + } + if (defined $clientName) { + # ... and finally pour client-specific configuration on top (if any): + my $clientSpecConfigPath = "$clientConfigPath/$systemName/$clientName"; + vlog(2, "checking $clientSpecConfigPath for client config..."); + if (folderContainsFiles($clientSpecConfigPath)) { + slxsystem("cp -a $clientSpecConfigPath/* $targetPath"); + } + } + return; +} + +sub createTarOfPath +{ + my $buildPath = shift; + my $tarName = shift; + my $destinationPath = shift; + + my $tarFile = "$destinationPath/$tarName"; + vlog(1, _tr('creating tar %s', $tarFile)); + return if $option{dryRun}; + + mkpath $destinationPath; + my $tarCmd = "cd $buildPath && tar czf $tarFile *"; + if (slxsystem("$tarCmd") != 0) { + die _tr("unable to execute shell-command:\n\t%s \n\t(%s)", $tarCmd, $!); + } +} + +sub bootEnvironmentForType +{ + my $bootTypeIn = shift || 'pxe'; + + my %bootTypeMap = ( + 'pxe' => 'PXE', + 'preboot' => 'Preboot', + 'pbs' => 'PBS', + ); + my $bootType = $bootTypeMap{lc($bootTypeIn)} + or die _tr( + "'%s' is not one of the supported boot-types (pxe,preboot)", + $bootTypeIn + ); + + if (!$bootEnvMap{$bootType}) { + my $bootEnv = instantiateClass("OpenSLX::BootEnvironment::$bootType"); + $bootEnv->initialize( { + 'dry-run' => $option{dryRun}, + } ); + $bootEnvMap{$bootType} = $bootEnv; + } + + return $bootEnvMap{$bootType}; +} + + + +################################################################################ +### +################################################################################ +sub writeBootloaderMenus +{ + my @infos = @_; + + # iterate over all clients and write a bootloader configuration for each + my @clients = $openslxDB->fetchClientByFilter(); + foreach my $client (@clients) { + # fetch all infos relevant to this client (including the bootable + # systems) + my %systemIDs; + @systemIDs{$openslxDB->aggregatedSystemIDsOfClient($client)} = (); + my @systemInfos = grep { exists $systemIDs{$_->{id}} } @infos; + + # now write bootloader menu with all bootable systems for this client + my $bootEnv = bootEnvironmentForType($client->{attrs}->{boot_type}); + my $externalID = externalIDForClient($client); + my $success = eval { + $bootEnv->writeBootloaderMenuFor( + $client, $externalID, \@systemInfos + ); + 1; + }; + if (!$success) { + print STDERR $@; + $bootEnvErrCount++; + } + } + return; +} + +sub writeDhcpConfig +{ + vlog(0, _tr("sorry, exporting dhcp data is not implemented yet!")); + my $dhcpModule = "OpenSLX::ConfigExport::DHCP::$option{dhcpType}"; + if (!eval { require $dhcpModule } ) { + die _tr("unable to load DHCP-Export backend '%s'! (%s)\n", + $dhcpModule, $@); + } + my $dhcpBackend = $dhcpModule->new(); + my @clients = $openslxDB->fetchClientByFilter(); + $dhcpBackend->execute(\@clients); + return; +} + +sub writeClientConfigurationsForSystem +{ + my $info = shift; + my $buildPath = shift; + my $attrFile = shift; + my $bootType = shift; + my $clients = shift || []; + + foreach my $client (@$clients) { + next if $client->{name} eq '<<>>'; + # skip default client, as it doesn't need any config-tgz + + next if ($client->{attrs}->{boot_type} || 'pxe') ne $bootType; + # skip clients with non-matching boot type + + my $externalSystemID = $info->{'external-id'}; + my $externalClientName = externalConfigNameForClient($client); + my $clientConfigPath + = "$clientConfigPath/$externalSystemID/$externalClientName"; + + # merge configurations of groups, default client and system into the + # current client (overwriting only values the client does not specify) + $openslxDB->mergeDefaultAndGroupAttributesIntoClient($client); + mergeAttributes($client, $info); + + # compute a digest value of the merged attributes ... + my $clientAttrDigest = digestAttributes($client); + vlog( + 2, + _tr( + "attribute-digest for client '%s' is '%s'", $client->{name}, + $clientAttrDigest + ) + ); + # ... and export client-specific config only if attributes are different + # from system and/or a client-specific config-folder exists: + if ($clientAttrDigest ne $info->{'attr-digest'} + || -d $clientConfigPath) + { + vlog( + 1, + _tr( + "creating config-tgz for client %d:%s", $client->{id}, + $client->{name} + ) + ); + $clientSystemConfCount++; + + # merge default, system and client configuration folders into + # a configuration folder specific to the current client: + copyExternalSystemConfig( + $externalSystemID, $buildPath, $externalClientName + ); + + # add plugin configuration and note if the client adds any active + # plugin (as opposed to current state) + my $activeClientPlugins = writePluginConfigurations( + $info, $buildPath, $client->{attrs} + ); + my @additionalActivePlugins = grep { + my $activeClientPlugin = $_; + ! grep { + $activeClientPlugin eq $_ + } @{$info->{'active-plugins'}}; + } @$activeClientPlugins; + if (@additionalActivePlugins) { + push @{$info->{'active-plugins'}}, @additionalActivePlugins; + my $additionalActivePluginStr + = join ',', @additionalActivePlugins; + vlog(0, _tr( + "client '%s' activates additional plugins: %s", + $client->{name}, $additionalActivePluginStr + )); + } + + # check attributes against illegal values and write them into + # a file if they're ok: + my $attrProblems = OpenSLX::AttributeRoster->findProblematicValues( + $client->{attrs}, $info->{'vendor-os'}->{name}, + $info->{'installed-plugins'} + ); + if ($attrProblems) { + my $complaint = join "\n", @$attrProblems; + $complaint =~ s{^}{client $client->{name}: }gms; + warn $complaint; + } + writeAttributesToFile($client, $attrFile); + + # create a tar containing the external configuration folder + # and client attribute file, this time referring to the client + # via its external ID (the PXE-style MAC), as the TGZ needs to + # be accessed from the client-PC, which doesn't know about the + # name it is referred to in the openslx-config-DB: + my $externalClientID = externalIDForClient($client); + my $bootEnv = bootEnvironmentForType($bootType); + switch ($bootType) { + case 'pxe' { + createTarOfPath( + $buildPath, "${externalClientID}.tgz", + "$bootEnv->{'target-path'}/client-config/$externalSystemID" + ); + } + case 'preboot' { + # for preboot types + my $cname = $client->{name}; + createTarOfPath( + $buildPath, "${cname}.tgz", + "$bootEnv->{'target-path'}/client-config/$externalSystemID" + ); + } + case 'pbs' { + # for preboot types + my $cname = $client->{name}; + createTarOfPath( + $buildPath, "${cname}.tgz", + "$bootEnv->{'target-path'}/client-config/$externalSystemID" + ); + } + } + } + } + return; +} + +sub writePluginConfigurations +{ + my $info = shift || confess 'need to pass in info-hash!'; + my $buildPath = shift || confess 'need to pass in build-path!'; + my $attrs = shift || {}; + + my $pluginConfPath = "$buildPath/initramfs/plugin-conf"; + + my @activePlugins; + foreach my $pluginInfo (@{$info->{'installed-plugins'}}) { + my $pluginName = $pluginInfo->{plugin_name}; + vlog(2, _tr("checking configuration of plugin '%s'", $pluginName)); + + # skip inactive plugins + next unless $attrs->{"${pluginName}::active"}; + push @activePlugins, $pluginName; + + my $plugin = OpenSLX::OSPlugin::Roster->getPlugin($pluginName); + my $requiredPlugins = $plugin->getInfo()->{required} || []; + my @missingPlugins + = grep { + my $required = $_; + ! grep { + $_->{plugin_name} eq $required + } @{$info->{'installed-plugins'}}; + } + @$requiredPlugins; + if (@missingPlugins) { + die _tr( + 'the plugin "%s" requires the following plugins to be installed: "%s"!', + $pluginName, join(',', @missingPlugins) + ); + } + + next if $option{dryRun}; + + mkpath([ $pluginConfPath ]); + + vlog(2, _tr("writing configuration file for plugin '%s'", $pluginName)); + # write plugin configuration to a file: + my $content; + my @pluginAttrs = grep { $_ =~ m{^${pluginName}::} } keys %$attrs; + foreach my $attr (sort @pluginAttrs) { + my $attrVal = $attrs->{$attr}; + if (!defined $attrVal) { + $attrVal = ''; + } + my $attrName = substr($attr, index($attr, '::')+2); + $content .= qq[${pluginName}_$attrName="$attrVal"\n]; + } + my $fileName = "$pluginConfPath/${pluginName}.conf"; + spitFile($fileName, $content); + if ($openslxConfig{'log-level'} > 2) { + vlog(0, "--- START OF $fileName ---"); + vlog(0, $content); + vlog(0, "--- END OF $fileName --- "); + } + } + return \@activePlugins; +} + +sub createBootEnvironmentsForSystem +{ + my $info = shift; + my $buildPath = shift; + my $attrFile = shift; + my $clients = shift || []; + + my %bootTypes; + foreach my $client (@$clients) { + my $type = $client->{attrs}->{boot_type} || 'pxe'; + $bootTypes{$type}++; + } + + foreach my $bootType (sort keys %bootTypes) { + vlog(0, _tr("creating boot environment (system part) for $bootType")); + + my $bootEnv = bootEnvironmentForType($bootType); + + # only create a default.tgz if required by boot environment + if ($bootEnv->requiresDefaultClientConfig()) { + writeAttributesToFile($info, $attrFile); + + my $systemPath + = "$bootEnv->{'target-path'}/client-config/$info->{'external-id'}"; + createTarOfPath($buildPath, "default.tgz", $systemPath); + } + } + + foreach my $bootType (sort keys %bootTypes) { + vlog(0, _tr("creating boot environment (client part) for $bootType")); + + my $bootEnv = bootEnvironmentForType($bootType); + + writeClientConfigurationsForSystem( + $info, $buildPath, $attrFile, $bootType, $clients + ); + + # let boot environment copy the kernel and create the initramfs + $initramfsCount + += $bootEnv->writeFilesRequiredForBooting($info, $buildPath); + } + + return; +} + +sub writeSystemConfiguration +{ + my $info = shift; + my $isTargetSystem = shift; + + $info->{'initramfs-name'} = "initramfs-$info->{id}"; + + # if this is not a target system, we shall not write any configurations, + # but we simply incorporate inherited attributes + if (!$isTargetSystem) { + $openslxDB->mergeDefaultAttributesIntoSystem($info); + return; + } + + # write configuration files for this system + my $buildPath = "$tempPath/build"; + copyExternalSystemConfig(externalIDForSystem($info), $buildPath); + + $openslxDB->mergeDefaultAttributesIntoSystem( + $info, $info->{'installed-plugins'} + ); + $info->{'attr-digest'} = digestAttributes($info); + vlog( + 2, + _tr( + "attribute-digest for system '%s' is '%s'", $info->{name}, + $info->{'attr-digest'} + ) + ); + + # check if uclibc-rootfs in corresponding vendor-OS matches the current + # version and add a warning if it does not: + my $uclibcVersionPath + = "$openslxConfig{'private-path'}/stage1/$info->{'vendor-os'}->{name}/opt/openslx/uclib-rootfs.version"; + chomp(my $uclibcVersion + = slurpFile($uclibcVersionPath, { failIfMissing => 0 } )); + chomp(my $currVersion = qx{slxversion}); + if ($currVersion !~ m{M$} && $uclibcVersion ne $currVersion) { + warn _tr( + "uclibc-rootfs for system '%s' may not be up-to-date - consider updating the vendor-OS!", + $info->{name}, $uclibcVersion, $currVersion + ); + } + + my $attrProblems = OpenSLX::AttributeRoster->findProblematicValues( + $info->{attrs}, $info->{'vendor-os'}->{name}, + $info->{'installed-plugins'} + ); + if ($attrProblems) { + my $complaint = join "\n", @$attrProblems; + $complaint =~ s{^}{system $info->{name}: }gms; + warn $complaint; + } + + my $activePlugins + = writePluginConfigurations($info, $buildPath, $info->{attrs}); + $info->{'active-plugins'} = $activePlugins; + my $activePluginStr + = @$activePlugins ? join ',', @$activePlugins : ''; + vlog(0, _tr("active plugins: %s", $activePluginStr)); + + # create all required (pre-)boot-environments (PXE, CD, ...) + my $attrFile = "$buildPath/initramfs/machine-setup"; + my @clientIDs = $openslxDB->aggregatedClientIDsOfSystem($info); + my @clients = $openslxDB->fetchClientByID(\@clientIDs); + createBootEnvironmentsForSystem($info, $buildPath, $attrFile, \@clients); + + slxsystem("rm -rf $buildPath") unless $option{dryRun}; + + $systemConfCount++; + + return; +} + +sub writeConfigurations +{ + $initramfsCount = $systemConfCount = $systemErrCount + = $clientSystemConfCount = 0; + my @infos; + foreach my $system (@demuxableSystems) { + my $isTargetSystem + = first { $_->{name} eq $system->{name} } @targetSystems; + if ($isTargetSystem) { + vlog( + 0, + _tr("\ndemuxing system %d : %s", $system->{id}, $system->{name}) + ); + } + else { + vlog( + 0, + _tr( + "\nlinking demuxed system %d : %s into bootloader menu", + $system->{id}, $system->{name} + ) + ); + } + + my $success = eval { + my $info = $openslxDB->aggregatedSystemFileInfoFor($system); + $info->{'external-id'} = externalIDForSystem($system); + + writeSystemConfiguration($info, $isTargetSystem); + + push @infos, $info; + 1; + }; + if (!$success) { + print STDERR $@; + $systemErrCount++; + } + } + my $imageBaseDir = "$openslxConfig{'public-path'}/images"; + rmtree($imageBaseDir) unless $option{dryRun}; + writeBootloaderMenus(@infos); + if (defined $option{dhcpType}) { + writeDhcpConfig(); + } + return; +} + +=head1 NAME + +slxconfig-demuxer - OpenSLX configuration demultiplexer + +=head1 SYNOPSIS + +slxconfig-demuxer [options] [ ...] + +=head3 Script Options + + --dry-run avoids writing anything, for testing + +=head3 General Options + + --help brief help message + --man full documentation + --version show version + +=head1 DESCRIPTION + +B 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. + +If you invoke the script with one or more system names, only these systems +will be demuxed. All other systems (which are expected to have been demuxed +before) will just be linked into the bootloader menu. + +The resulting files will be put into the OpenSLX-tftpboot-path. + +=head2 FILE CREATION + +The following set of files will be created: + +=over 8 + +=item B + +The basic PXE files (F, F) will be copied into +F<$SLX_PUBLIC_PATH/tftpboot> to make them available to any PXE-client via tftp. + +=item B + +For each client, a PXE configuration file will be generated and written to +F<$SLX_PUBLIC_PATH/tftpboot/pxelinux.cfg/01->. 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). + +Any client that is not known to OpenSLX (so it will not have a specific +configuration file) will use the configuration from the default client +(appropriately named 'default'). + +=item B + +For each bootable system, that system's kernel will be copied to +F<$SLX_PUBLIC_PATH/tftpboot//kernel and an OpenSLX-specific initramfs +required for booting that particular system is generated (by means of +slxmkramfs) and put into F<$SLX_PUBLIC_PATH/tftpboot//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 + +For each system, an OpenSLX configuration archive will be generated and written +to F<$SLX_PUBLIC_PATH/tftpboot/client-config//default. Furthermore, +every client of that system whose attributes differ from the system's default +will get its own configuration archive generated here, too (e.g. +F<$SLX_PUBLIC_PATH/tftpboot/client-config//01-.tgz>). + +Each of these archives will contain the file F, +specifying all the attributes of that particular system and/or client +(e.g. whether or not it should start the X-server). + +Furthermore, each system-specific archive may contain additional system files +that are required for that system (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/>. + +On top of that, each client may have its own set of system files, too (e.g. +some config files required to install a special kind of hardware available only +on that client). These files are copied from +F<< $SLX_PROVATE_PATH/config//01- >>. + +=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-attribute of the B 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-attribute of that B 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. + +=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 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 SEE ALSO + +slxsettings, slxos-setup, slxos-export, slxconfig + +=head1 GENERAL OPENSLX OPTIONS + +Being a part of OpenSLX, this script supports several other options +which can be used to overrule the OpenSLX settings: + + --db-name= name of database + --db-spec= full DBI-specification of database + --db-type= type of database to connect to + --locale= locale to use for translations + --log-level= level of logging verbosity (0-3) + --logfile= file to write logging output to + --private-path= path to private data + --public-path= path to public (client-accesible) data + --temp-path= path to temporary data + +Please refer to the C-manpage for a more detailed description +of these options. + +=cut -- cgit v1.2.3-55-g7522