summaryrefslogtreecommitdiffstats
path: root/config-db/slxconfig-demuxer
diff options
context:
space:
mode:
authorOliver Tappe2006-10-28 16:23:49 +0200
committerOliver Tappe2006-10-28 16:23:49 +0200
commit1417b305c990fb428f4089052826a5ba1329c7cf (patch)
tree9193fc1af8da1f66c41b4b555e113d702fafd8be /config-db/slxconfig-demuxer
parentDon't overwrite an existing settings.local file. (diff)
downloadcore-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-xconfig-db/slxconfig-demuxer651
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