# 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::PREBOOT_CD.pm # - provides CD-specific implementation of the BootEnvironment API. # ----------------------------------------------------------------------------- package OpenSLX::BootEnvironment::PREBOOT_CD; use strict; use warnings; use base qw(OpenSLX::BootEnvironment::Base); use Clone qw(clone); use File::Basename; use File::Path; use OpenSLX::Basics; use OpenSLX::MakeInitRamFS::Engine::PrebootCD; use OpenSLX::Utils; sub initialize { my $self = shift; my $params = shift; return if !$self->SUPER::initialize($params); $self->{'original-path'} = "$openslxConfig{'public-path'}/preboot-cd"; $self->{'target-path'} = "$openslxConfig{'public-path'}/preboot-cd.new"; if (!$self->{'dry-run'}) { mkpath([$self->{'original-path'}]); rmtree($self->{'target-path'}); mkpath("$self->{'target-path'}/client-config"); } return 1; } sub finalize { my $self = shift; my $delete = shift; return if !$self->{prebootSystemInfo}; return $self->SUPER::finalize($delete); } sub writeBootloaderMenuFor { my $self = shift; my $client = shift; my $externalClientID = shift; my $systemInfos = shift || []; my $prebootSystemInfo = clone($systemInfos->[0]); $self->_createImage($client, $prebootSystemInfo); # $self->_prepareBootloaderConfigFolder() # unless $self->{preparedBootloaderConfigFolder}; # # my $pxePath = $self->{'target-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)); # # # set label for each system # foreach my $info (@$systemInfos) { # 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}; # } # } # $info->{label} = $label; # } # my $slxLabels = ''; # foreach my $info (sort { $a->{label} cmp $b->{label} } @$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"; # $slxLabels .= "\tMENU LABEL ^$info->{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 _createImage { my $self = shift; my $client = shift; my $info = shift; vlog( 0, _tr( "\ncreating CD-image for client %s (based on %s) ...", $client->{name}, $info->{name} ) ); my $imageDir = "$openslxConfig{'public-path'}/images/$client->{name}"; mkpath($imageDir) unless $self->{'dry-run'}; # copy static data and init script my $dataDir = "$openslxConfig{'base-path'}/share/boot-env/preboot-cd"; slxsystem(qq{rsync -rlpt $dataDir/ "$imageDir/"}) unless $self->{'dry-run'}; # copy kernel (take the one from the given system info) my $kernelFile = $info->{'kernel-file'}; my $kernelName = basename($kernelFile); slxsystem(qq{cp -p "$kernelFile" "$imageDir/iso/isolinux/vmlinuz"}) unless $self->{'dry-run'}; # create initramfs my $initramfsName = qq{"$imageDir/iso/isolinux/initramfs"}; $self->_makePrebootInitRamFS($info, $initramfsName); my $mkisoCmd = unshiftHereDoc(<<" End-of-Here"); mkisofs -o "$imageDir/../$client->{name}.iso" -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -r -J -l -boot-info-table -joliet-long -publisher "OpenSLX Project - http://www.openslx.org" -p "OpenSLX Project - openslx-devel\@openslx.org" -V "OpenSLX BootCD" -volset "OpenSLX Project - PreBoot CD for non PXE/TFTP start of a Linux Stateless Client" -c isolinux/boot.cat "$imageDir/iso" End-of-Here $mkisoCmd =~ s{\n\s*}{ }gms; my $logFile = "$imageDir/../$client->{name}.iso.log"; if (slxsystem(qq{$mkisoCmd 2>"$logFile"})) { my $log = slurpFile($logFile); die _tr("unable to create ISO-image - log follows:\n%s", $log); } rmtree($imageDir); return 1; } sub _makePrebootInitRamFS { my $self = shift; my $info = shift; my $initramfs = shift; my $vendorOS = $info->{'vendor-os'}; my $kernelFile = basename(followLink($info->{'kernel-file'})); my $attrs = clone($info->{attrs} || {}); chomp(my $slxVersion = qx{slxversion}); my $params = { 'attrs' => $attrs, 'export-name' => undef, 'export-uri' => undef, 'initramfs' => $initramfs, 'kernel-params' => [ split ' ', ($info->{kernel_params} || '') ], 'kernel-version' => $kernelFile =~ m[-(.+)$] ? $1 : '', 'plugins' => '', 'root-path' => "$openslxConfig{'private-path'}/stage1/$vendorOS->{name}", 'slx-version' => $slxVersion, 'system-name' => $info->{name}, }; # TODO: make debug-level an explicit attribute, it's used in many places! my $kernelParams = $info->{kernel_params} || ''; if ($kernelParams =~ m{debug(?:=(\d+))?}) { my $debugLevel = defined $1 ? $1 : '1'; $params->{'debug-level'} = $debugLevel; } my $makeInitRamFSEngine = OpenSLX::MakeInitRamFS::Engine::PrebootCD->new($params); $makeInitRamFSEngine->execute($self->{'dry-run'}); # copy back kernel-params, as they might have been changed (by plugins) $info->{kernel_params} = join ' ', $makeInitRamFSEngine->kernelParams(); return; } 1;