diff options
author | Simon Rettberg | 2019-10-17 14:41:03 +0200 |
---|---|---|
committer | Simon Rettberg | 2019-10-17 14:41:03 +0200 |
commit | 193b765f07543b4824950fe08d337211c2ef8a1c (patch) | |
tree | 4cb54d445e53df797bbf69297c8d360068f94fb7 /modules-available | |
parent | [serversetup-bwlp-ipxe/minilinux] Implement minilinux hook for ipxe (diff) | |
download | slx-admin-193b765f07543b4824950fe08d337211c2ef8a1c.tar.gz slx-admin-193b765f07543b4824950fe08d337211c2ef8a1c.tar.xz slx-admin-193b765f07543b4824950fe08d337211c2ef8a1c.zip |
[serversetup-bwlp-ipxe/minilinux] Further improvements
* Distinction between BIOS and EFI for ipxe hook in minilinux
* Debug KCL modifier customizable by update meta data
* Bugfixes, minor refactoring...
Diffstat (limited to 'modules-available')
10 files changed, 135 insertions, 78 deletions
diff --git a/modules-available/minilinux/hooks/ipxe-bootentry.inc.php b/modules-available/minilinux/hooks/ipxe-bootentry.inc.php index 090a14da..944cdfa3 100644 --- a/modules-available/minilinux/hooks/ipxe-bootentry.inc.php +++ b/modules-available/minilinux/hooks/ipxe-bootentry.inc.php @@ -59,9 +59,9 @@ class LinuxBootEntryHook extends BootEntryHook * @param $id * @return BootEntry the actual boot entry instance for given entry, false if invalid id */ - public function getBootEntryInternal($data) + public function getBootEntryInternal($localData) { - $id = $data['id']; + $id = $localData['id']; if ($id === 'default') { // Special case $effectiveId = Property::get(MiniLinux::PROPERTY_DEFAULT_BOOT_EFFECTIVE); } else { @@ -72,51 +72,67 @@ class LinuxBootEntryHook extends BootEntryHook return BootEntry::newCustomBootEntry(['script' => 'prompt Invalid minilinux boot entry id: ' . $id]); } if ($res['installed'] == 0) { - return BootEntry::newCustomBootEntry(['script' => 'prompt Selected version not currently installed on server: ' . $id]); + return BootEntry::newCustomBootEntry(['script' => 'prompt Selected version not currently installed on server: ' . $effectiveId]); } + $remoteData = json_decode($res['data'], true); + $bios = $efi = false; + if (!@is_array($remoteData['agnostic']) && !@is_array($remoteData['efi']) && !@is_array($remoteData['bios'])) { + $remoteData['agnostic'] = []; // We got nothing at all so fake this entry, resulting in a generic default entry + } + if (@is_array($remoteData['agnostic'])) { + $bios = $this->generateExecData($effectiveId, $remoteData['agnostic'], $localData); + $arch = BootEntry::AGNOSTIC; + } else { + if (@is_array($remoteData['efi'])) { + $efi = $this->generateExecData($effectiveId, $remoteData['efi'], $localData); + } + if (@is_array($remoteData['bios'])) { + $bios = $this->generateExecData($effectiveId, $remoteData['bios'], $localData); + } + if ($bios && $efi) { + $arch = BootEntry::BOTH; + } elseif ($bios) { + $arch = BootEntry::BIOS; + } else { + $arch = BootEntry::EFI; + } + } + return BootEntry::newStandardBootEntry($bios, $efi, $arch); + } + + private function generateExecData($effectiveId, $remoteData, $localData) + { $exec = new ExecData(); // Defaults - $root = '/boot/' . $id . '/'; + $root = '/boot/' . $effectiveId . '/'; $exec->executable = 'kernel'; $exec->initRd = ['initramfs-stage31']; $exec->imageFree = true; $exec->commandLine = 'slxbase=boot/%ID% slxsrv=${serverip} quiet splash ${ipappend1} ${ipappend2}'; // Overrides - $remoteData = json_decode($res['data'], true); - // TODO: agnostic hard coded, support EFI and PCBIOS - if (isset($remoteData['agnostic']) && is_array($remoteData['agnostic'])) { - foreach (['executable', 'commandLine', 'initRd', 'imageFree'] as $key) { - if (isset($remoteData['agnostic'][$key])) { - $exec->{$key} = $remoteData['agnostic'][$key]; - } + foreach (['executable', 'commandLine', 'initRd', 'imageFree'] as $key) { + if (isset($remoteData[$key])) { + $exec->{$key} = $remoteData[$key]; } } - unset($rd); // KCL hacks - if (isset($data['debug']) && $data['debug']) { - if (!isset($data['kcl-extra'])) { - $data['kcl-extra'] = ''; - } - $data['kcl-extra'] = '-quiet -splash -loglevel loglevel=7 ' . $data['kcl-extra']; + if (isset($localData['debug']) && $localData['debug']) { + $exec->commandLine = IPxe::modifyCommandLine($exec->commandLine, + isset($remoteData['debugCommandLineModifier']) + ? $remoteData['debugCommandLineModifier'] + : '-vga -quiet -splash -loglevel loglevel=7' + ); } - if (isset($data['kcl-extra'])) { - $items = preg_split('/\s+/', $data['kcl-extra'], -1, PREG_SPLIT_NO_EMPTY); - // TODO: Make this a function, somewhere in serversetup-ipxe, this could be useful for other stuff - foreach ($items as $item) { - if ($item{0} === '-') { - $item = preg_quote(substr($item, 1), '/'); - $exec->commandLine = preg_replace('/(^|\s)' . $item . '(=\S*)?($|\s)/', ' ', $exec->commandLine); - } else { - $exec->commandLine .= ' ' . $item; - } - } + if (isset($localData['kcl-extra'])) { + $exec->commandLine = IPxe::modifyCommandLine($exec->commandLine, $localData['kcl-extra']); } - $exec->commandLine = str_replace('%ID%', $id, $exec->commandLine); + $exec->commandLine = str_replace('%ID%', $effectiveId, $exec->commandLine); $exec->executable = $root . $exec->executable; foreach ($exec->initRd as &$rd) { $rd = $root . $rd; } - return BootEntry::newStandardBootEntry($exec, false, 'agnostic'); + unset($rd); + return $exec; } public function isValidId($id) diff --git a/modules-available/minilinux/inc/minilinux.inc.php b/modules-available/minilinux/inc/minilinux.inc.php index e940380c..54536096 100644 --- a/modules-available/minilinux/inc/minilinux.inc.php +++ b/modules-available/minilinux/inc/minilinux.inc.php @@ -62,7 +62,7 @@ class MiniLinux EventLog::warning('Cannot download Linux version meta data for ' . $sourceid); $lastupdate = 'lastupdate'; } else { - if (isset($data['systems']) && is_array($data['systems'])) { + if (@is_array($data['systems'])) { self::addBranches($sourceid, $data['systems']); } $lastupdate = 'UNIX_TIMESTAMP()'; @@ -70,6 +70,12 @@ class MiniLinux Database::exec("UPDATE minilinux_source SET lastupdate = $lastupdate, taskid = NULL WHERE sourceid = :sourceid AND taskid = :taskid", ['sourceid' => $sourceid, 'taskid' => $taskId]); + // Clean up -- delete orphaned versions that are not installed + $orphaned = Database::queryColumnArray('SELECT versionid FROM minilinux_version WHERE orphan > 4 AND installed = 0'); + if (!empty($orphaned)) { + Database::exec('DELETE FROM minilinux_version WHERE versionid IN (:list)', ['list' => $orphaned]); + } + Database::exec('DELETE FROM minilinux_branch', [], true); } private static function addBranches($sourceid, $systems) @@ -88,7 +94,7 @@ class MiniLinux 'title' => $title, 'description' => $description, ]); - if (isset($system['versions']) && is_array($system['versions'])) { + if (@is_array($system['versions'])) { self::addVersions($branchid, $system['versions']); } } diff --git a/modules-available/minilinux/install.inc.php b/modules-available/minilinux/install.inc.php index 5387542e..b859671a 100644 --- a/modules-available/minilinux/install.inc.php +++ b/modules-available/minilinux/install.inc.php @@ -34,7 +34,7 @@ $result[] = tableCreate('minilinux_version', " "); $result[] = tableAddConstraint('minilinux_version', 'branchid', 'minilinux_branch', 'branchid', - 'ON UPDATE CASCADE ON DELETE CASCADE'); + 'ON UPDATE CASCADE ON DELETE RESTRICT'); $result[] = tableAddConstraint('minilinux_branch', 'sourceid', 'minilinux_source', 'sourceid', 'ON UPDATE CASCADE ON DELETE SET NULL'); diff --git a/modules-available/minilinux/lang/de/module.json b/modules-available/minilinux/lang/de/module.json index da6ea4bb..687b4a71 100644 --- a/modules-available/minilinux/lang/de/module.json +++ b/modules-available/minilinux/lang/de/module.json @@ -7,7 +7,7 @@ "file-size-mismatch": "Dateigr\u00f6\u00dfe stimmt nicht", "ipxe-debug": "Debug-Ausgaben statt Bootlogo", "ipxe-kcl-extra": "Modifikation der Kernel-Command-Line", - "module_name": "bwLehrpool MiniLinux", + "module_name": "Netboot Grundsystem", "not_installed_hint": "(nicht installiert)", "page_title": "Linuxvarianten f\u00fcr Netboot verwalten" }
\ No newline at end of file diff --git a/modules-available/minilinux/page.inc.php b/modules-available/minilinux/page.inc.php index 53632699..7c7e3d36 100644 --- a/modules-available/minilinux/page.inc.php +++ b/modules-available/minilinux/page.inc.php @@ -80,7 +80,7 @@ class Page_MiniLinux extends Page $eff = Property::get(MiniLinux::PROPERTY_DEFAULT_BOOT_EFFECTIVE); foreach ($versions as &$version) { $version['dateline_s'] = Util::prettyTime($version['dateline']); - $version['orphan'] = ($version['orphan'] > 5); + $version['orphan'] = ($version['orphan'] > 2); $version['downloading'] = $version['taskid'] && Taskmanager::isRunning(Taskmanager::status($version['taskid'])); if ($version['installed'] && $version['versionid'] !== $def) { $version['showsetdefault'] = true; diff --git a/modules-available/minilinux/templates/branches.html b/modules-available/minilinux/templates/branches.html index 64adda16..5f3c4e50 100644 --- a/modules-available/minilinux/templates/branches.html +++ b/modules-available/minilinux/templates/branches.html @@ -1,18 +1,20 @@ <h3>{{lang_branchesHeading}}</h3> -{{#branches}} -<div id="ibm-mainframe" class="panel panel-default"> - <div class="panel-heading"> - <div class="pull-right"> - {{sourceid}} {{branchid}} +<div id="ibm-mainframe"> + {{#branches}} + <div class="panel panel-default"> + <div class="panel-heading"> + <div class="pull-right"> + {{sourceid}} {{branchid}} + </div> + <b>{{title}}</b> </div> - <b>{{title}}</b> - </div> - <div class="panel-body"> - {{description}} + <div class="panel-body"> + {{description}} + </div> + {{{versionlist}}} </div> - {{{versionlist}}} + {{/branches}} </div> -{{/branches}} <script> document.addEventListener('DOMContentLoaded', function () { diff --git a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php index 174f4459..dec70528 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php @@ -3,6 +3,15 @@ abstract class BootEntry { + /** Supports both via same entry (stored in PCBIOS entry) */ + const AGNOSTIC = 'agnostic'; + /** Only valid for legacy BIOS boot */ + const BIOS = 'PCBIOS'; + /** Only valid for EFI boot */ + const EFI = 'EFI'; + /** Supports both via distinct entry */ + const BOTH = 'PCBIOS-EFI'; + public abstract function supportsMode($mode); public abstract function toScript($failLabel, $mode); @@ -57,11 +66,11 @@ abstract class BootEntry { $ret = new StandardBootEntry($initData, $efi, $arch); $list = []; - if ($ret->arch() !== StandardBootEntry::EFI) { - $list[] = StandardBootEntry::BIOS; + if ($ret->arch() !== self::EFI) { + $list[] = self::BIOS; } - if ($ret->arch() === StandardBootEntry::EFI || $ret->arch() === StandardBootEntry::BOTH) { - $list[] = StandardBootEntry::EFI; + if ($ret->arch() === self::EFI || $ret->arch() === self::BOTH) { + $list[] = self::EFI; } $data = $ret->toArray(); foreach ($list as $mode) { @@ -129,11 +138,6 @@ class StandardBootEntry extends BootEntry protected $arch; // Constants below - 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) - const KEYS = ['executable', 'initRd', 'commandLine', 'replace', 'imageFree', 'autoUnload', 'resetConsole', 'dhcpOptions']; public function __construct($data, $efi = false, $arch = false) @@ -157,18 +161,21 @@ class StandardBootEntry extends BootEntry } else { $this->arch = $data['arch']; } - if (isset($data[self::BIOS]) || isset($data[self::EFI])) { + if (isset($data[BootEntry::BIOS]) || isset($data[BootEntry::EFI])) { // Current format $this->fromCurrentFormat($data); } else { // Convert legacy DB format $this->fromLegacyFormat($data); } + } elseif ($arch == BootEntry::EFI && $efi instanceof ExecData) { + $this->efi = $efi; + $this->arch = $arch; } else { error_log('Invalid StandardBootEntry constructor call'); } - if (!in_array($this->arch, [self::BIOS, self::EFI, self::BOTH, self::AGNOSTIC])) { - $this->arch = self::AGNOSTIC; + if (!in_array($this->arch, [BootEntry::BIOS, BootEntry::EFI, BootEntry::BOTH, BootEntry::AGNOSTIC])) { + $this->arch = BootEntry::AGNOSTIC; } } @@ -176,12 +183,12 @@ class StandardBootEntry extends BootEntry { $ok = false; foreach (self::KEYS as $key) { - if (isset($data[$key][self::BIOS])) { - $this->pcbios->{$key} = $data[$key][self::BIOS]; + if (isset($data[$key][BootEntry::BIOS])) { + $this->pcbios->{$key} = $data[$key][BootEntry::BIOS]; $ok = true; } - if (isset($data[$key][self::EFI])) { - $this->efi->{$key} = $data[$key][self::EFI]; + if (isset($data[$key][BootEntry::EFI])) { + $this->efi->{$key} = $data[$key][BootEntry::EFI]; $ok = true; } } @@ -198,11 +205,11 @@ class StandardBootEntry extends BootEntry private function fromCurrentFormat($data) { foreach (self::KEYS as $key) { - if (isset($data[self::BIOS][$key])) { - $this->pcbios->{$key} = $data[self::BIOS][$key]; + if (isset($data[BootEntry::BIOS][$key])) { + $this->pcbios->{$key} = $data[BootEntry::BIOS][$key]; } - if (isset($data[self::EFI][$key])) { - $this->efi->{$key} = $data[self::EFI][$key]; + if (isset($data[BootEntry::EFI][$key])) { + $this->efi->{$key} = $data[BootEntry::EFI][$key]; } } } @@ -241,10 +248,10 @@ class StandardBootEntry extends BootEntry public function supportsMode($mode) { - if ($mode === $this->arch || $this->arch === self::AGNOSTIC) + if ($mode === $this->arch || $this->arch === BootEntry::AGNOSTIC) return true; - if ($mode === self::BIOS || $mode === self::EFI) { - return $this->arch === self::BOTH; + if ($mode === BootEntry::BIOS || $mode === BootEntry::EFI) { + return $this->arch === BootEntry::BOTH; } error_log('Unknown iPXE platform: ' . $mode); return false; @@ -255,7 +262,7 @@ class StandardBootEntry extends BootEntry if (!$this->supportsMode($mode)) { return "prompt Entry doesn't have an executable for mode $mode\n"; } - if ($this->arch === self::AGNOSTIC || $mode == self::BIOS) { + if ($this->arch === BootEntry::AGNOSTIC || $mode == BootEntry::BIOS) { $entry = $this->pcbios; } else { $entry = $this->efi; @@ -319,16 +326,16 @@ class StandardBootEntry extends BootEntry public function addFormFields(&$array) { $array[$this->arch . '_selected'] = 'selected'; - $array['entries'][] = $this->pcbios->toFormFields(self::BIOS); - $array['entries'][] = $this->efi->toFormFields(self::EFI); + $array['entries'][] = $this->pcbios->toFormFields(BootEntry::BIOS); + $array['entries'][] = $this->efi->toFormFields(BootEntry::EFI); $array['exec_checked'] = 'checked'; } public function toArray() { return [ - self::BIOS => $this->pcbios->toArray(), - self::EFI => $this->efi->toArray(), + BootEntry::BIOS => $this->pcbios->toArray(), + BootEntry::EFI => $this->efi->toArray(), 'arch' => $this->arch, ]; } diff --git a/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php index f89031a3..cf180006 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/bootentryhook.inc.php @@ -53,7 +53,7 @@ abstract class BootEntryHook * @param $id * @return BootEntry|null the actual boot entry instance for given entry, null if invalid id */ - public abstract function getBootEntryInternal($data); + public abstract function getBootEntryInternal($localData); public final function getBootEntry($data) { diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php index 6caecc65..4c2a7678 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxe.inc.php @@ -527,4 +527,30 @@ boot -a -r /boot/default/kernel initrd=initramfs-stage31 ${slxextra} slxbase=boo return md5(md5($plainpass) . '-' . $salt); } + /** + * Modify a kernel command line. Add or remove items to a given command line. The $modifier + * string is a list of space separated arguments. If the argument starts with a '-', all + * according occurrences of the given option will be removed from the command line. It is assumed + * that options are either of format "option" or "option=value", so a modifier of "-option" will + * remove any occurrence of either "option" or "option=something". If the argument starts with a + * '+', it will be added to the command line after removing the '+'. If the argument starts with any + * other character, it will also be added to the command line. + * @param string $cmdLine command line to modify + * @param string $modifier modification string of space separated arguments + * @return string the modified command line + */ + public static function modifyCommandLine($cmdLine, $modifier) + { + $items = preg_split('/\s+/', $modifier, -1, PREG_SPLIT_NO_EMPTY); + foreach ($items as $item) { + if ($item{0} === '-') { + $item = preg_quote(substr($item, 1), '/'); + $cmdLine = preg_replace('/(^|\s)' . $item . '(=\S*)?($|\s)/', ' ', $cmdLine); + } else { + $cmdLine .= ' ' . $item; + } + } + return $cmdLine; + } + } diff --git a/modules-available/serversetup-bwlp-ipxe/page.inc.php b/modules-available/serversetup-bwlp-ipxe/page.inc.php index f14c1e57..81f15922 100644 --- a/modules-available/serversetup-bwlp-ipxe/page.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/page.inc.php @@ -434,13 +434,13 @@ class Page_ServerSetup extends Page if (!array_key_exists('arch', $bootentry['data'])) continue; // Naming and agnostic - if ($bootentry['data']['arch'] === StandardBootEntry::BIOS) { + if ($bootentry['data']['arch'] === BootEntry::BIOS) { $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_biosOnly', true); unset($bootentry['data']['EFI']); - } elseif ($bootentry['data']['arch'] === StandardBootEntry::EFI) { + } elseif ($bootentry['data']['arch'] === BootEntry::EFI) { $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_efiOnly', true); unset($bootentry['data']['PCBIOS']); - } elseif ($bootentry['data']['arch'] === StandardBootEntry::AGNOSTIC) { + } elseif ($bootentry['data']['arch'] === BootEntry::AGNOSTIC) { $bootentry['data']['arch'] = Dictionary::translateFile('template-tags','lang_archAgnostic', true); unset($bootentry['data']['EFI']); } else { |