summaryrefslogtreecommitdiffstats
path: root/src/boot-env/OpenSLX/BootEnvironment/Preboot.pm
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot-env/OpenSLX/BootEnvironment/Preboot.pm')
-rw-r--r--src/boot-env/OpenSLX/BootEnvironment/Preboot.pm209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/boot-env/OpenSLX/BootEnvironment/Preboot.pm b/src/boot-env/OpenSLX/BootEnvironment/Preboot.pm
new file mode 100644
index 00000000..b06de7d2
--- /dev/null
+++ b/src/boot-env/OpenSLX/BootEnvironment/Preboot.pm
@@ -0,0 +1,209 @@
+# 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.pm
+# - provides general preboot implementation of the BootEnvironment API.
+# -----------------------------------------------------------------------------
+package OpenSLX::BootEnvironment::Preboot;
+
+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::ConfigDB qw(:support);
+use OpenSLX::Utils;
+
+sub initialize
+{
+ my $self = shift;
+ my $params = shift;
+
+ return if !$self->SUPER::initialize($params);
+
+ $self->{'original-path'} = "$openslxConfig{'public-path'}/preboot";
+ $self->{'target-path'} = "$openslxConfig{'public-path'}/preboot.new";
+
+ $self->{'requires-default-client-config'} = 0;
+ # we do not need a default.tgz since there's always an explicit client
+
+ if (!$self->{'dry-run'}) {
+ mkpath([$self->{'original-path'}]);
+ rmtree($self->{'target-path'});
+ mkpath("$self->{'target-path'}/client-config");
+ }
+
+ return 1;
+}
+
+sub writeBootloaderMenuFor
+{
+ my $self = shift;
+ my $client = shift;
+ my $externalClientID = shift;
+ my $systemInfos = shift || [];
+
+ $self->_prepareBootloaderConfigFolder()
+ unless $self->{preparedBootloaderConfigFolder};
+
+ my $prebootSystemInfo
+ = clone($self->_pickSystemWithNewestKernel($systemInfos));
+
+ $self->_createImages($client, $prebootSystemInfo);
+
+ my $externalClientName = externalConfigNameForClient($client);
+ my $bootloaderPath = "$self->{'target-path'}/bootloader";
+ my $bootloaderConfigPath = "$bootloaderPath/$externalClientName";
+ mkpath($bootloaderConfigPath) unless $self->{'dry-run'};
+ my $menuFile = "$bootloaderConfigPath/bootmenu.dialog";
+
+ my $clientAppend = $client->{attrs}->{kernel_params_client} || '';
+ vlog(1, _tr("writing bootmenu %s", $menuFile));
+
+ # set label for each system
+ foreach my $info (@$systemInfos) {
+ my $label = $info->{label} || '';
+ if (!length($label) || $label eq $info->{name}) {
+ $label = $info->{name};
+ }
+ $info->{label} = $label;
+ }
+ my $bootmenuEntries = '';
+ my $entryState = 'on';
+ my $counter = 1;
+ 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->{attrs}->{kernel_params} || '';
+ $append .= " $clientAppend";
+ $bootmenuEntries .= qq{ "$counter" "$info->{label}" };
+ $entryState = 'off';
+
+ # create a file containing the boot-configuration for this system
+ my $systemDescr = unshiftHereDoc(<<" End-of-Here");
+ label="$info->{label}"
+ kernel="$vendorOSName/$kernelName"
+ initramfs="$vendorOSName/$info->{'initramfs-name'}"
+ append="$append"
+ End-of-Here
+ my $systemFile = "$bootloaderConfigPath/$info->{name}";
+ spitFile(
+ $systemFile, $systemDescr, { 'io-layer' => 'encoding(iso8859-1)' }
+ ) unless $self->{'dry-run'};
+ slxsystem(qq{ln -sf $info->{name} $bootloaderConfigPath/$counter});
+ $counter++;
+ }
+
+ my $entryCount = @$systemInfos;
+ my $bootmenu = unshiftHereDoc(<<" End-of-Here");
+ --no-cancel --menu "OpenSLX Boot Menu" 20 65 $entryCount $bootmenuEntries
+ End-of-Here
+
+ if (!$self->{'dry-run'}) {
+ # default to iso encoding, let's see how uclibc copes with it ...
+ spitFile($menuFile, $bootmenu, { 'io-layer' => 'encoding(iso8859-1)' });
+
+ # copy the preboot script into the folder to be tared
+ my $prebootBasePath
+ = "$openslxConfig{'base-path'}/share/boot-env/preboot";
+ slxsystem(qq{cp $prebootBasePath/preboot.sh $bootloaderConfigPath/});
+ slxsystem(qq{cp -r $prebootBasePath/preboot-scripts $bootloaderConfigPath/});
+ slxsystem(qq{chmod a+x $bootloaderConfigPath/preboot.sh});
+
+ # create a tar which can/will be downloaded by prebooting clients
+ my $tarCMD
+ = qq{cd $bootloaderConfigPath; tar -czf "${bootloaderConfigPath}.env" *};
+ slxsystem($tarCMD);
+ rmtree($bootloaderConfigPath);
+ }
+
+ return 1;
+}
+
+sub _createImages
+{
+ my $self = shift;
+ my $client = shift;
+ my $info = shift;
+
+ my %mediaMap = (
+ 'cd' => 'CD',
+ );
+ my $prebootMedia = $client->{attrs}->{preboot_media} || '';
+ if (!$prebootMedia) {
+ warn _tr(
+ "no preboot-media defined for client %s, no images will be generated!",
+ $client->{name}
+ );
+ return 0;
+ }
+ foreach my $mediumName (split m{, }, $prebootMedia) {
+ my $moduleName = $mediaMap{$mediumName}
+ or die _tr(
+ "'%s' is not one of the supported preboot-medias (cd)",
+ $mediumName
+ );
+
+ my $prebootMedium = instantiateClass(
+ "OpenSLX::BootEnvironment::Preboot::$moduleName"
+ );
+ $prebootMedium->initialize($self);
+ $prebootMedium->createImage($client, $info);
+ }
+
+ return 1;
+}
+
+sub _prepareBootloaderConfigFolder
+{
+ my $self = shift;
+
+ my $bootloaderPath = "$self->{'target-path'}/bootloader";
+ if (!$self->{'dry-run'}) {
+ rmtree($bootloaderPath);
+ mkpath($bootloaderPath);
+ }
+
+ $self->{preparedBootloaderConfigFolder} = 1;
+
+ return 1;
+}
+
+sub _pickSystemWithNewestKernel
+{
+ my $self = shift;
+ my $systemInfos = shift;
+
+ my $systemWithNewestKernel;
+ my $newestKernelFileSortKey = '';
+ foreach my $system (@$systemInfos) {
+ next unless $system->{'kernel-file'} =~ m{
+ (?:vmlinuz|x86)-(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?-(\d+(?:\.\d+)?)
+ }x;
+ my $sortKey
+ = sprintf("%02d.%02d.%02d.%02d-%2.1f", $1, $2, $3, $4||0, $5);
+ if ($newestKernelFileSortKey lt $sortKey) {
+ $systemWithNewestKernel = $system;
+ $newestKernelFileSortKey = $sortKey;
+ }
+ }
+
+ if (!defined $systemWithNewestKernel) {
+ die _tr("unable to pick a system to be used for preboot!");
+ }
+ return $systemWithNewestKernel;
+}
+
+1;