# Copyright (c) 2008 - 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/ # ----------------------------------------------------------------------------- # BootEnvironment::PXE.pm # - provides PXE-specific implementation of the BootEnvironment API. # ----------------------------------------------------------------------------- package OpenSLX::BootEnvironment::PXE; use strict; use warnings; use base qw(OpenSLX::BootEnvironment::Base); use File::Basename; use File::Path; use OpenSLX::Basics; use OpenSLX::Utils; sub prepareBootloaderConfigFolder { my $self = shift; my $basePath = $openslxConfig{'base-path'}; my $pxePath = $self->{'build-path'}; my $pxeConfigPath = "$pxePath/pxelinux.cfg"; if (!$self->{'dry-run'}) { rmtree($pxeConfigPath); mkpath($pxeConfigPath); for my $file ('pxelinux.0', 'menu.c32', 'vesamenu.c32') { if (!-e "$pxePath/$file") { slxsystem(qq[cp -p "$basePath/share/tftpboot/$file" $pxePath/]); } } } return 1; } sub writeBootloaderMenuFor { my $self = shift; my $client = shift; my $externalClientID = shift; my $systemInfos = shift; my $pxePath = $self->{'build-path'}; my $pxeConfigPath = "$pxePath/pxelinux.cfg"; my $pxeConfig = $self->_getTemplate(); my $pxeFile = "$pxeConfigPath/$externalClientID"; my $clientAppend = $client->{kernel_params} || ''; vlog(1, _tr("writing PXE-file %s", $pxeFile)); my $slxLabels = ''; foreach my $info (@$systemInfos) { my $vendorOSName = $info->{'vendor-os'}->{name}; my $kernelName = basename($info->{'kernel-file'}); my $append = $info->{kernel_params}; $append .= " initrd=$vendorOSName/$info->{'initramfs-name'}"; $append .= " $clientAppend"; $slxLabels .= "LABEL openslx-$info->{'external-id'}\n"; my $label = $info->{label} || ''; if (!length($label) || $label eq $info->{name}) { if ($info->{name} =~ m{^(.+)::(.+)$}) { my $system = $1; my $exportType = $2; $label = $system . ' ' x (40-length($system)) . $exportType; } else { $label = $info->{name}; } } $slxLabels .= "\tMENU LABEL ^$label\n"; $slxLabels .= "\tKERNEL $vendorOSName/$kernelName\n"; $slxLabels .= "\tAPPEND $append\n"; $slxLabels .= "\tIPAPPEND 1\n"; my $helpText = $info->{description} || ''; if (length($helpText)) { # make sure that text matches the given margin my $margin = $openslxConfig{'pxe-theme-menu-margin'} || 0; my $marginAsText = ' ' x $margin; $helpText =~ s{^}{$marginAsText}gms; $slxLabels .= "\tTEXT HELP\n$helpText\n\tENDTEXT\n"; } } # now add the slx-labels (inline or appended) and write the config file if (!($pxeConfig =~ s{\@\@\@SLX_LABELS\@\@\@}{$slxLabels})) { $pxeConfig .= $slxLabels; } # PXE uses 'cp850' (codepage 850) but our string is in utf-8, we have # to convert in order to avoid showing gibberish on the client side... spitFile($pxeFile, $pxeConfig, { 'io-layer' => 'encoding(cp850)' } ); return 1; } sub _getTemplate { my $self = shift; return $self->{'pxe-template'} if $self->{'pxe-template'}; my $pxeDefaultTemplate = unshiftHereDoc(<<' End-of-Here'); NOESCAPE 0 PROMPT 0 TIMEOUT 10 DEFAULT menu.c32 IMPLICIT 1 ALLOWOPTIONS 1 MENU TITLE Was möchten Sie tun (Auswahl mittels Cursortasten)? MENU MASTER PASSWD secret End-of-Here utf8::decode($pxeDefaultTemplate); my ($sec, $min, $hour, $day, $mon, $year) = (localtime); $mon++; $year += 1900; my $callDate = sprintf('%04d-%02d-%02d', $year, $mon, $day); my $callTime = sprintf('%02d:%02d:%02d', $hour, $min, $sec); # fetch PXE-template, if any my $pxeTemplate = "# generated by slxconfig-demuxer (on $callDate at $callTime)\n"; my $pxeTemplateFile = "$openslxConfig{'config-path'}/PXE-template"; if (-e $pxeTemplateFile) { $pxeTemplate .= slurpFile($pxeTemplateFile); } else { $pxeTemplate .= $pxeDefaultTemplate; } # now append (and thus override) the PXE-template with the settings of the # selected PXE-theme, if any my $basePath = $openslxConfig{'base-path'}; my $pxeTheme = $openslxConfig{'pxe-theme'}; if (defined $pxeTheme) { my $pxeThemeConfig = "$basePath/share/themes/${pxeTheme}/pxe/theme.conf"; if (-e $pxeThemeConfig) { $pxeTemplate .= slurpFile($pxeThemeConfig); } } # fetch info about margin and replace the corresponding placeholders my $margin = $openslxConfig{'pxe-theme-menu-margin'} || 0; my $marginAsText = ' ' x $margin; $pxeTemplate =~ s{\@\@\@MENU_MARGIN\@\@\@}{$margin}g; my $separatorLine = '-' x (78 - 4 - 2 * $margin); $pxeTemplate =~ s{\@\@\@SEPARATOR_LINE\@\@\@}{$separatorLine}g; # pick out the last background picture and copy it over my $pic; while ($pxeTemplate =~ m{^\s*MENU BACKGROUND (\S+?)\s*$}gims) { chomp($pic = $1); } if (defined $pic) { my $pxeBackground = defined $pxeTheme ? "$basePath/share/themes/${pxeTheme}/pxe/$pic" : $pic; if (-e $pxeBackground && !$self->{'dry-run'}) { slxsystem(qq[cp "$pxeBackground" $self->{'build-path'}/]); } } $self->{'pxe-template'} = $pxeTemplate; return $pxeTemplate; } 1;