summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-09-19 11:27:22 +0200
committerSimon Rettberg2018-09-19 11:27:22 +0200
commit6da78493a0bb010a0fff50ac3cc23e018b15e979 (patch)
tree6baaa31e9d985e503e09cd669f11bce65355cd3d
parent[serversetup-bwlp] Pass initrd= on KCL for EFI mode (diff)
downloadslx-admin-6da78493a0bb010a0fff50ac3cc23e018b15e979.tar.gz
slx-admin-6da78493a0bb010a0fff50ac3cc23e018b15e979.tar.xz
slx-admin-6da78493a0bb010a0fff50ac3cc23e018b15e979.zip
[serversetup-bwlp] Differentiate between EFI/BIOS
Different executable/initrd etc. can be given for a simple boot entry of type "exec", or it can be specified that only one of them is supported. For bootentry type "script" there can still be only one entry, since you can just check the ${platform} variable within the script.
-rw-r--r--modules-available/serversetup-bwlp/api.inc.php12
-rw-r--r--modules-available/serversetup-bwlp/inc/bootentry.inc.php113
-rw-r--r--modules-available/serversetup-bwlp/inc/ipxemenu.inc.php8
-rw-r--r--modules-available/serversetup-bwlp/inc/menuentry.inc.php10
-rw-r--r--modules-available/serversetup-bwlp/page.inc.php7
-rw-r--r--modules-available/serversetup-bwlp/templates/ipxe-new-boot-entry.html122
6 files changed, 194 insertions, 78 deletions
diff --git a/modules-available/serversetup-bwlp/api.inc.php b/modules-available/serversetup-bwlp/api.inc.php
index 36f9063c..52f30440 100644
--- a/modules-available/serversetup-bwlp/api.inc.php
+++ b/modules-available/serversetup-bwlp/api.inc.php
@@ -1,5 +1,7 @@
<?php
+// TODO: Check if required arguments are given; if not, spit out according script (identical to what is embedded)
+
$BOOT_METHODS = [
'EXIT' => 'exit 1',
'COMBOOT' => 'chain /tftp/chain.c32 hd0',
@@ -22,12 +24,14 @@ $platform = strtoupper(Request::any('platform', 'PCBIOS', 'string'));
$localboot = false;
$model = false;
if ($uuid !== false && Module::get('statistics') !== false) {
+ // If we have the machine table, we rather try to look up the system model from there, using the UUID
$row = Database::queryFirst('SELECT systemmodel FROM machine WHERE machineuuid = :uuid', ['uuid' => $uuid]);
if ($row !== false && !empty($row['systemmodel'])) {
$model = $row['systemmodel'];
}
}
if ($model === false) {
+ // Otherwise use what iPXE sent us
function modfilt($str)
{
if (empty($str) || preg_match('/product\s+name|be\s+filled|unknown|default\s+string/i', $str))
@@ -70,6 +74,8 @@ if (isset($BOOT_METHODS[$localboot])) {
$BOOT_METHODS = array_reverse($BOOT_METHODS);
}
+// TODO: Feature check for our own iPXE extensions, stay compatible to stock iPXE
+
$output = <<<HERE
#!ipxe
@@ -139,7 +145,7 @@ console --left 55 --top 88 --right 63 --bottom 64 --quick --keep --picture bg-me
HERE;
-$output .= $menu->getMenuDefinition('target');
+$output .= $menu->getMenuDefinition('target', $platform);
$output .= <<<HERE
@@ -151,7 +157,9 @@ goto start
HERE;
-$output .= $menu->getItemsCode();
+$output .= $menu->getItemsCode($platform);
+
+// TODO: Work out memtest stuff. Needs to be put on server (install/update script) -- PCBIOS only? Chain EFI -> BIOS?
/*
:i1
diff --git a/modules-available/serversetup-bwlp/inc/bootentry.inc.php b/modules-available/serversetup-bwlp/inc/bootentry.inc.php
index 930f4413..010b660c 100644
--- a/modules-available/serversetup-bwlp/inc/bootentry.inc.php
+++ b/modules-available/serversetup-bwlp/inc/bootentry.inc.php
@@ -14,7 +14,9 @@ abstract class BootEntry
}
}
- public abstract function toScript($failLabel);
+ public abstract function supportsMode($mode);
+
+ public abstract function toScript($failLabel, $mode);
public abstract function toArray();
@@ -46,9 +48,19 @@ abstract class BootEntry
public static function newStandardBootEntry($initData)
{
- if (empty($initData['executable']))
- return null;
- return new StandardBootEntry($initData);
+ $ret = new StandardBootEntry($initData);
+ $list = [];
+ if ($ret->arch() !== StandardBootEntry::EFI) {
+ $list[] = StandardBootEntry::BIOS;
+ }
+ if ($ret->arch() === StandardBootEntry::EFI || $ret->arch() === StandardBootEntry::BOTH) {
+ $list[] = StandardBootEntry::EFI;
+ }
+ foreach ($list as $mode) {
+ if (empty($initData['executable'][$mode]))
+ return null;
+ }
+ return $ret;
}
public static function newCustomBootEntry($initData)
@@ -83,6 +95,12 @@ class StandardBootEntry extends BootEntry
protected $replace;
protected $autoUnload;
protected $resetConsole;
+ protected $arch; // true == available, false == not available
+
+ const BIOS = 'PCBIOS'; // Only valid for legacy BIOS boot
+ const EFI = 'EFI'; // Only valid for EFI boot
+ const BOTH = 'PCBIOS-EFI'; // Supports both via distinct entry
+ const AGNOSTIC = 'agnostic'; // Supports both via same entry (PCBIOS entry)
public function __construct($data = false)
{
@@ -109,38 +127,70 @@ class StandardBootEntry extends BootEntry
} else {
parent::__construct($data);
}
+ // Convert legacy DB format
+ foreach (['executable', 'initRd', 'commandLine', 'replace', 'autoUnload', 'resetConsole'] as $key) {
+ if (!is_array($this->{$key})) {
+ $this->{$key} = [ 'PCBIOS' => $this->{$key}, 'EFI' => '' ];
+ }
+ }
+ if ($this->arch === null) {
+ $this->arch = self::AGNOSTIC;
+ }
+ }
+
+ public function arch()
+ {
+ return $this->arch;
+ }
+
+ public function supportsMode($mode)
+ {
+ if ($mode === $this->arch || $this->arch === self::AGNOSTIC)
+ return true;
+ if ($mode === self::BIOS || $mode === self::EFI) {
+ return $this->arch === self::BOTH;
+ }
+ error_log('Unknown iPXE platform: ' . $mode);
+ return false;
}
- public function toScript($failLabel)
+ public function toScript($failLabel, $mode)
{
+ if (!$this->supportsMode($mode)) {
+ return "prompt Entry doesn't have an executable for mode $mode\n";
+ }
+ if ($this->arch === self::AGNOSTIC) {
+ $mode = self::BIOS;
+ }
+
$script = '';
- if ($this->resetConsole) {
+ if ($this->resetConsole[$mode]) {
$script .= "console ||\n";
}
- if (!empty($this->initRd)) {
+ if (!empty($this->initRd[$mode])) {
$script .= "imgfree ||\n";
- if (!is_array($this->initRd)) {
- $script .= "initrd {$this->initRd} || goto $failLabel\n";
+ if (!is_array($this->initRd[$mode])) {
+ $script .= "initrd {$this->initRd[$mode]} || goto $failLabel\n";
} else {
- foreach ($this->initRd as $initrd) {
+ foreach ($this->initRd[$mode] as $initrd) {
$script .= "initrd $initrd || goto $failLabel\n";
}
}
}
$script .= "boot ";
- if ($this->autoUnload) {
+ if ($this->autoUnload[$mode]) {
$script .= "-a ";
}
- if ($this->replace) {
+ if ($this->replace[$mode]) {
$script .= "-r ";
}
- $script .= "{$this->executable}";
- $rdBase = basename($this->initRd);
- if (!empty($this->commandLine)) {
- $script .= " initrd=$rdBase {$this->commandLine}";
+ $script .= $this->executable[$mode];
+ $rdBase = basename($this->initRd[$mode]);
+ if (!empty($this->commandLine[$mode])) {
+ $script .= " initrd=$rdBase {$this->commandLine[$mode]}";
}
$script .= " || goto $failLabel\n";
- if ($this->resetConsole) {
+ if ($this->resetConsole[$mode]) {
$script .= "goto start ||\n";
}
return $script;
@@ -148,14 +198,19 @@ class StandardBootEntry extends BootEntry
public function addFormFields(&$array)
{
- $array['entry'] = [
- 'executable' => $this->executable,
- 'initRd' => $this->initRd,
- 'commandLine' => $this->commandLine,
- 'replace_checked' => $this->replace ? 'checked' : '',
- 'autoUnload_checked' => $this->autoUnload ? 'checked' : '',
- 'resetConsole_checked' => $this->resetConsole ? 'checked' : '',
- ];
+ $array[$this->arch . '_selected'] = 'selected';
+ foreach ([self::BIOS, self::EFI] as $mode) {
+ $array['entries'][] = [
+ 'is' . $mode => true,
+ 'mode' => $mode,
+ 'executable' => $this->executable[$mode],
+ 'initRd' => $this->initRd[$mode],
+ 'commandLine' => $this->commandLine[$mode],
+ 'replace_checked' => $this->replace[$mode] ? 'checked' : '',
+ 'autoUnload_checked' => $this->autoUnload[$mode] ? 'checked' : '',
+ 'resetConsole_checked' => $this->resetConsole[$mode] ? 'checked' : '',
+ ];
+ }
$array['exec_checked'] = 'checked';
}
@@ -168,6 +223,7 @@ class StandardBootEntry extends BootEntry
'replace' => $this->replace,
'autoUnload' => $this->autoUnload,
'resetConsole' => $this->resetConsole,
+ 'arch' => $this->arch,
];
}
}
@@ -176,7 +232,12 @@ class CustomBootEntry extends BootEntry
{
protected $script;
- public function toScript($failLabel)
+ public function supportsMode($mode)
+ {
+ return true;
+ }
+
+ public function toScript($failLabel, $mode)
{
return str_replace('%fail%', $failLabel, $this->script) . "\n";
}
diff --git a/modules-available/serversetup-bwlp/inc/ipxemenu.inc.php b/modules-available/serversetup-bwlp/inc/ipxemenu.inc.php
index ed9f0986..56041c20 100644
--- a/modules-available/serversetup-bwlp/inc/ipxemenu.inc.php
+++ b/modules-available/serversetup-bwlp/inc/ipxemenu.inc.php
@@ -36,11 +36,11 @@ class IPxeMenu
}
}
- public function getMenuDefinition($targetVar)
+ public function getMenuDefinition($targetVar, $mode)
{
$str = "menu {$this->title}\n";
foreach ($this->items as $item) {
- $str .= $item->getMenuItemScript("m_{$this->menuid}", $this->defaultEntryId);
+ $str .= $item->getMenuItemScript("m_{$this->menuid}", $this->defaultEntryId, $mode);
}
if ($this->defaultEntryId === null) {
$defaultLabel = "mx_{$this->menuid}_poweroff";
@@ -61,11 +61,11 @@ class IPxeMenu
return $str;
}
- public function getItemsCode()
+ public function getItemsCode($mode)
{
$str = '';
foreach ($this->items as $item) {
- $str .= $item->getBootEntryScript("m_{$this->menuid}", 'fail');
+ $str .= $item->getBootEntryScript("m_{$this->menuid}", 'fail', $mode);
$str .= "goto slx_menu\n";
}
return $str;
diff --git a/modules-available/serversetup-bwlp/inc/menuentry.inc.php b/modules-available/serversetup-bwlp/inc/menuentry.inc.php
index 9d9d4163..03b860e8 100644
--- a/modules-available/serversetup-bwlp/inc/menuentry.inc.php
+++ b/modules-available/serversetup-bwlp/inc/menuentry.inc.php
@@ -58,8 +58,10 @@ class MenuEntry
settype($this->menuentryid, 'int');
}
- public function getMenuItemScript($lblPrefix, $requestedDefaultId)
+ public function getMenuItemScript($lblPrefix, $requestedDefaultId, $mode)
{
+ if ($this->bootEntry !== null && !$this->bootEntry->supportsMode($mode))
+ return '';
$str = 'item ';
if ($this->gap) {
$str .= '--gap ';
@@ -81,9 +83,9 @@ class MenuEntry
return $str . " || prompt Could not create menu item for {$lblPrefix}_{$this->menuentryid}\n";
}
- public function getBootEntryScript($lblPrefix, $failLabel)
+ public function getBootEntryScript($lblPrefix, $failLabel, $mode)
{
- if ($this->bootEntry === null)
+ if ($this->bootEntry === null || !$this->bootEntry->supportsMode($mode))
return '';
$str = ":{$lblPrefix}_{$this->menuentryid}\n";
if (!empty($this->md5pass)) {
@@ -94,7 +96,7 @@ class MenuEntry
. "goto slx_pass_check || goto $failLabel\n"
. ":{$lblPrefix}_ok\n";
}
- return $str . $this->bootEntry->toScript($failLabel);
+ return $str . $this->bootEntry->toScript($failLabel, $mode);
}
/*
diff --git a/modules-available/serversetup-bwlp/page.inc.php b/modules-available/serversetup-bwlp/page.inc.php
index 25a31f06..ba2e5433 100644
--- a/modules-available/serversetup-bwlp/page.inc.php
+++ b/modules-available/serversetup-bwlp/page.inc.php
@@ -279,6 +279,7 @@ class Page_ServerSetup extends Page
$entry->addFormFields($params);
$params['title'] = $row['title'];
$params['oldentryid'] = $params['entryid'] = $row['entryid'];
+ $params['builtin'] = $row['builtin'];
}
Render::addTemplate('ipxe-new-boot-entry', $params);
}
@@ -543,7 +544,7 @@ class Page_ServerSetup extends Page
}
if ($entry === null) {
Message::addError('main.empty-field');
- return;
+ Util::redirect('?do=serversetup&show=bootentry');
}
$params = [
'entryid' => $newId,
@@ -560,10 +561,10 @@ class Page_ServerSetup extends Page
// Edit existing entry
$params['oldid'] = $oldEntryId;
Database::exec('UPDATE serversetup_bootentry SET entryid = :entryid, title = :title, data = :data
- WHERE entryid = :oldid AND builtin = 0', $params);
- // TODO: Redirect to &show=bootentry
+ WHERE entryid = :oldid', $params);
Message::addSuccess('boot-entry-updated', $newId);
}
+ Util::redirect('?do=serversetup&show=bootentry');
}
}
diff --git a/modules-available/serversetup-bwlp/templates/ipxe-new-boot-entry.html b/modules-available/serversetup-bwlp/templates/ipxe-new-boot-entry.html
index fd9e1d72..33de1ee4 100644
--- a/modules-available/serversetup-bwlp/templates/ipxe-new-boot-entry.html
+++ b/modules-available/serversetup-bwlp/templates/ipxe-new-boot-entry.html
@@ -1,5 +1,11 @@
<h2>{{lang_newBootEntryHead}}</h2>
+{{#builtin}}
+ <div class="alert alert-warning">
+ {{lang_editBuiltinWarn}}
+ </div>
+{{/builtin}}
+
<div class="panel panel-default">
<div class="panel-heading">
{{lang_bootEntryData}}
@@ -33,47 +39,69 @@
</label>
<input id="input-title" class="form-control" name="title" value="{{title}}" maxlength="100">
</div>
+ <div class="form-group">
+ <label for="arch-selector">
+ {{lang_archSelector}}
+ </label>
+ <select id="arch-selector" class="form-control" name="entry[arch]">
+ <option value="agnostic" {{agnostic_selected}}>{{lang_archAgnostic}}</option>
+ <option value="PCBIOS" {{PCBIOS_selected}}>{{lang_biosOnly}}</option>
+ <option value="EFI" {{EFI_selected}}>{{lang_efiOnly}}</option>
+ <option value="PCBIOS-EFI" {{PCBIOS-EFI_selected}}>{{lang_archBoth}}</option>
+ </select>
+ </div>
<div class="type-form" id="form-exec">
- <div class="form-group">
- <label for="input-ex">
- {{lang_imageToLoad}}
- </label>
- <input id="input-ex" class="form-control" name="entry[executable]" value="{{entry.executable}}">
- </div>
- <div class="form-group">
- <label for="input-rd">
- {{lang_initRd}}
- </label>
- <input id="input-rd" class="form-control" name="entry[initRd]" value="{{entry.initRd}}">
- </div>
- <div class="form-group">
- <label for="input-cmd">
- {{lang_commandLine}}
- </label>
- <input id="input-cmd" class="form-control" name="entry[commandLine]"
- value="{{entry.commandLine}}">
- </div>
- <div class="form-group">
- <div class="checkbox checkbox-inline">
- <input id="exec-replace" class="form-control" type="checkbox"
- name="entry[replace]" {{entry.replace_checked}}>
- <label for="exec-replace">{{lang_execReplace}}</label>
- </div>
- </div>
- <div class="form-group">
- <div class="checkbox checkbox-inline">
- <input id="exec-au" class="form-control" type="checkbox"
- name="entry[autoUnload]" {{entry.autoUnload_checked}}>
- <label for="exec-au">{{lang_execAutoUnload}}</label>
- </div>
- </div>
- <div class="form-group">
- <div class="checkbox checkbox-inline">
- <input id="exec-reset" class="form-control" type="checkbox"
- name="entry[resetConsole]" {{entry.resetConsole_checked}}>
- <label for="exec-reset">{{lang_execResetConsole}}</label>
- </div>
+ <div class="row">
+ {{#entries}}
+ <div class="mode-class col-md-6" id="col-{{mode}}">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h4 class="arch-heading">{{mode}}</h4>
+ <div class="form-group">
+ <label for="input-ex">
+ {{lang_imageToLoad}}
+ </label>
+ <input id="input-ex" class="form-control" name="entry[executable][{{mode}}]" value="{{executable}}">
+ </div>
+ <div class="form-group">
+ <label for="input-rd">
+ {{lang_initRd}}
+ </label>
+ <input id="input-rd" class="form-control" name="entry[initRd][{{mode}}]" value="{{initRd}}">
+ </div>
+ <div class="form-group">
+ <label for="input-cmd">
+ {{lang_commandLine}}
+ </label>
+ <input id="input-cmd" class="form-control" name="entry[commandLine][{{mode}}]"
+ value="{{commandLine}}">
+ </div>
+ <div class="form-group">
+ <div class="checkbox checkbox-inline">
+ <input id="exec-replace-{{mode}}" class="form-control" type="checkbox"
+ name="entry[replace][{{mode}}]" {{replace_checked}}>
+ <label for="exec-replace-{{mode}}">{{lang_execReplace}}</label>
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="checkbox checkbox-inline">
+ <input id="exec-au-{{mode}}" class="form-control" type="checkbox"
+ name="entry[autoUnload][{{mode}}]" {{autoUnload_checked}}>
+ <label for="exec-au-{{mode}}">{{lang_execAutoUnload}}</label>
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="checkbox checkbox-inline">
+ <input id="exec-reset-{{mode}}" class="form-control" type="checkbox"
+ name="entry[resetConsole][{{mode}}]" {{resetConsole_checked}}>
+ <label for="exec-reset-{{mode}}">{{lang_execResetConsole}}</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ {{/entries}}
</div>
</div>
@@ -104,5 +132,21 @@ document.addEventListener('DOMContentLoaded', function () {
$('#form-' + $(this).val()).show();
});
$('.type-radio[checked]').click();
+ var $as = $('#arch-selector');
+ $as.change(function() {
+ var v = $as.val();
+ if (v === 'agnostic') {
+ v = 'PCBIOS';
+ $('.arch-heading').hide();
+ } else {
+ $('.arch-heading').show();
+ }
+ var vs = v.split('-');
+ var cols = 12 / vs.length;
+ $('.mode-class').hide();
+ for (var i = 0; i < vs.length; ++i) {
+ $('#col-' + vs[i]).attr('class', 'mode-class col-md-' + cols).show();
+ }
+ }).change();
});
// --></script> \ No newline at end of file