summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2020-07-10 16:40:06 +0200
committerSimon Rettberg2020-07-10 16:40:06 +0200
commit8cdccaeb71a167c6a16b715e65967da3be8a040a (patch)
treeb8239c2a701b7d05b75a5a19f93f93ffc03e4f7e
parent[minilinux] Lower update disable to 5 mins (was 10) (diff)
downloadslx-admin-8cdccaeb71a167c6a16b715e65967da3be8a040a.tar.gz
slx-admin-8cdccaeb71a167c6a16b715e65967da3be8a040a.tar.xz
slx-admin-8cdccaeb71a167c6a16b715e65967da3be8a040a.zip
[serversetup-bwlp-ipxe] Progress on new structure (+bash)
-rw-r--r--modules-available/minilinux/inc/linuxbootentryhook.inc.php4
-rw-r--r--modules-available/serversetup-bwlp-ipxe/api.inc.php22
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php2
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php4
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php33
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php97
-rw-r--r--modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php50
7 files changed, 180 insertions, 32 deletions
diff --git a/modules-available/minilinux/inc/linuxbootentryhook.inc.php b/modules-available/minilinux/inc/linuxbootentryhook.inc.php
index 324ffc7e..19acedd9 100644
--- a/modules-available/minilinux/inc/linuxbootentryhook.inc.php
+++ b/modules-available/minilinux/inc/linuxbootentryhook.inc.php
@@ -117,7 +117,9 @@ class LinuxBootEntryHook extends BootEntryHook
$exec->executable = 'kernel';
$exec->initRd = ['initramfs-stage31'];
$exec->imageFree = true;
- $exec->commandLine = 'slxbase=boot/%ID% slxsrv=${serverip} quiet splash ${ipappend1} ${ipappend2}';
+ $exec->commandLine = 'slxbase=boot/%ID% slxsrv=${serverip} quiet splash ${ipappend1} ${ipappend2}'
+ . ' ipv4.ip=${ip} ipv4.router=${gateway} ipv4.dns=${dns} ipv4.hostname=${hostname} ipv4.domain=${domain} ipv4.search=${dnssl}'
+ . ' ipv4.if=${mac} ipv4.ntpsrv=${ntpsrv} ipv4.subnet=${netmask}';
// Overrides
foreach (['executable', 'commandLine', 'initRd', 'imageFree'] as $key) {
if (isset($remoteData[$key])) {
diff --git a/modules-available/serversetup-bwlp-ipxe/api.inc.php b/modules-available/serversetup-bwlp-ipxe/api.inc.php
index 303f1560..dd559efa 100644
--- a/modules-available/serversetup-bwlp-ipxe/api.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/api.inc.php
@@ -1,12 +1,26 @@
<?php
(function() {
- $builder = new ScriptBuilderIpxe();
+ $type = Request::any('type');
+ if ($type === 'bash') {
+ $builder = new ScriptBuilderBash();
+ } else {
+ $builder = new ScriptBuilderIpxe();
+ }
+ $bootEntryId = Request::get('beid', false, 'string');
$entryId = Request::get('entryid', false, 'int');
- if ($entryId !== false) {
- $data = $builder->getMenuEntry($entryId);
+ if ($bootEntryId !== false) {
+ $entry = BootEntry::fromDatabaseId($bootEntryId);
+ $data = $builder->getBootEntry($entry);
+ } elseif ($entryId !== false) {
+ $entry = MenuEntry::get($entryId);
+ $data = $builder->getMenuEntry($entry);
} else {
- $data = $builder->fallback();
+ $data = $builder->bootstrapLive();
+ if ($data === false) {
+ $menu = IPxeMenu::forClient($builder->clientIp(), $builder->uuid());
+ $data = $builder->getMenu($menu, true);
+ }
}
$builder->output($data);
})();
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php
index 7b8fb4b5..614f5ee4 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/bootentry.inc.php
@@ -323,6 +323,8 @@ class CustomBootEntry extends BootEntry
{
if ($builder instanceof ScriptBuilderIpxe)
return $this->ipxe;
+ if ($builder instanceof ScriptBuilderBash)
+ return $this->bash;
return '';
}
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php
index 15766227..d4705be5 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php
@@ -94,7 +94,7 @@ class IPxeMenu
*
*/
- public static function forLocation($locationId)
+ public static function forLocation($locationId) : IPxeMenu
{
$chain = null;
if (Module::isAvailable('locations')) {
@@ -132,7 +132,7 @@ class IPxeMenu
return new IPxeMenu($menu);
}
- public static function forClient($ip, $uuid)
+ public static function forClient($ip, $uuid) : IPxeMenu
{
$locationId = 0;
if (Module::isAvailable('locations')) {
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
index c6adc953..b9867ed9 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbase.inc.php
@@ -11,6 +11,8 @@ abstract class ScriptBuilderBase
protected $clientIp;
+ protected $uuid;
+
/**
* @var bool Running iPXE has slx-extensions
*/
@@ -26,6 +28,16 @@ abstract class ScriptBuilderBase
return $this->platform;
}
+ public function uuid()
+ {
+ return $this->uuid;
+ }
+
+ public function clientIp()
+ {
+ return $this->clientIp;
+ }
+
public function getLabel()
{
return 'b' . mt_rand(100, 999) . 'x' . (++$this->lblId);
@@ -42,11 +54,11 @@ abstract class ScriptBuilderBase
if ($this->platform !== false) {
$this->platform = strtoupper($this->platform);
}
- Header('X-Popo: ' . $this->platform);
if ($this->platform !== 'EFI' && $this->platform !== 'PCBIOS') {
$this->platform = '';
}
$this->hasExtension = $slxExtensions ?? (bool)Request::any('slx-extensions', false, 'int');
+ $this->uuid = Request::any('uuid', false, 'string');
}
/**
@@ -55,13 +67,24 @@ abstract class ScriptBuilderBase
*/
public abstract function output($string);
- public abstract function getMenu($menuId);
+ public abstract function bootstrapLive();
- public abstract function getMenuEntry($menuEntryId);
+ public abstract function getMenu(IPxeMenu $menu, bool $bootstrap);
- public abstract function getSpecial($special);
+ /**
+ * @param MenuEntry|null $menuEntry The according menu entry, or null if invalid.
+ * @param bool $honorPassword Whether we should generate a password dialog if protected, or skip
+ * @return string generated script/code/...
+ */
+ public abstract function getMenuEntry($menuEntry, $honorPassword = true);
- public abstract function fallback();
+ /**
+ * @param BootEntry|null|false $bootEntry
+ * @return string
+ */
+ public abstract function getBootEntry($bootEntry);
+
+ public abstract function getSpecial($special);
/**
* @param IPxeMenu|null $menu
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php
new file mode 100644
index 00000000..86b2931f
--- /dev/null
+++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderbash.inc.php
@@ -0,0 +1,97 @@
+<?php
+
+class ScriptBuilderBash extends ScriptBuilderBase
+{
+
+ public function output($string)
+ {
+ echo $string;
+ }
+
+ public function bootstrapLive() { return false; }
+
+ public function getMenu(IPxeMenu $menu, bool $bootstrap)
+ {
+ return $this->menuToScript($menu);
+ }
+
+ public function getBootEntry($entry)
+ {
+ if (!$entry) {
+ return "echo 'Invalid boot entry id'\nread -n1 -r _\n";
+ }
+ return $entry->toScript($this);
+ }
+
+ public function getMenuEntry($entry, $honorPassword = true)
+ {
+ if ($entry === null)
+ return "echo 'Invalid menu entry id - press any key to continue'\nread -n1 -r _\n";
+ return $entry->getBootEntryScript($this);
+ }
+
+ public function getSpecial($special)
+ {
+ return ''; // We can't really do localboot here I guess
+ }
+
+ public function menuToScript($menu)
+ {
+ $output = "declare -A items_name items_gap hotkey_item\ndeclare menu_default menu_timeout menu_title\n";
+ foreach ($menu->items as $entry) {
+ $id = $entry->menuentryid;
+ if ($entry->bootEntry === null || (!empty($this->platform) && !$entry->bootEntry->supportsMode($this->platform)))
+ continue;
+ if (!$entry->hidden) {
+ $output .= 'items_name[' . $id . ']=' . $this->bashString($entry->title) . "\n";
+ if ($entry->gap) {
+ $output .= 'items_gap[' . $id . "]=1\n";
+ }
+ }
+ if ($entry->hotkey !== false) {
+ $output .= 'hotkey_item[' . $entry->hotkey . ']=' . $id . "\n";
+ }
+ if ($id == $menu->defaultEntryId) {
+ $output .= "menu_default={$id}\n";
+ }
+ }
+ return $output . "menu_timeout=" . $menu->timeoutMs
+ . "\nmenu_title=" . $this->bashString($menu->title) . "\n";
+ }
+
+ public function execDataToScript($agnostic, $bios, $efi) : string
+ {
+ if ($agnostic !== null)
+ return $this->execDataToScriptInternal($agnostic);
+ if ($bios !== null && $this->platform === BootEntry::BIOS)
+ return $this->execDataToScriptInternal($bios);
+ if ($efi !== null && $this->platform === BootEntry::EFI)
+ return $this->execDataToScriptInternal($efi);
+ return $this->execDataToScriptInternal($bios ?? $efi ?? new ExecData());
+ }
+
+ private function execDataToScriptInternal(ExecData $entry) : string
+ {
+ $entry->sanitize();
+ $script = "declare -a initrd\ndeclare kernel kcl\n";
+ if (!empty($entry->initRd)) {
+ foreach ($entry->initRd as $initrd) {
+ if (empty($initrd))
+ continue;
+ $script .= 'initrd+=( ' . $this->bashString($initrd) . " )\n";
+ }
+ }
+ $script .= 'kernel=' . $this->bashString($entry->executable) . "\n";
+ $script .= 'kcl="' . str_replace('"', '"\\""', $entry->commandLine) . "\"\n"; // Allow expansion
+ return $script;
+ }
+
+ private function bashString($string)
+ {
+ if (strpos($string, "'") === false) {
+ return "'$string'";
+ }
+ return "'" . str_replace("'", "'\\''", $string) . "'";
+ }
+
+}
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
index 23c4bd70..1b33a1ac 100644
--- a/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
+++ b/modules-available/serversetup-bwlp-ipxe/inc/scriptbuilderipxe.inc.php
@@ -86,32 +86,39 @@ HERE;
return $output;
}
- public function fallback()
+ /**
+ * Called when we handle a real client request, and don't just generate static data
+ * for whatever use-case that might have. In the latter case, it wouldn't make much sense
+ * to generate a redirect code snippet.
+ * @return string
+ */
+ public function bootstrapLive()
{
// Check if required arguments are given; if not, spit out according script and chain to self
- $uuid = Request::any('uuid', false, 'string');
- error_log("Got UUID='$uuid' PLATF='" . $this->platform . "'");
- if ($uuid === false || $this->platform === '') {
+ if ($this->uuid === false || $this->platform === '') {
// REQUIRED so we can hide incompatible entries
return $this->redirect();
}
+ return false;
+ }
- $menu = IPxeMenu::forClient($this->clientIp, $uuid);
- $out = $this->menuCheckAutostart($menu);
- if (!empty($out))
- return "#!ipxe\nimgfree ||\n" . $out;
-
- return "#!ipxe\nimgfree ||\n" . $this->menuToScript($menu);
+ public function getBootEntry($entry)
+ {
+ if (!$entry) {
+ return "#!ipxe\nprompt --timeout 5000 Invalid boot entry id\n";
+ }
+ return $entry->toScript($this);
}
- public function getMenu($menuId)
+ public function getMenu(IPxeMenu $menu, bool $bootstrap)
{
- $menu = IPxeMenu::get($menuId, true);
+ if ($bootstrap) {
+ return "#!ipxe\nimgfree ||\n" . $this->menuToScript($menu);
+ }
$base = $this->getUrlFull($he);
return "#!ipxe\nset self {$base} ||\n" . $this->menuToScript($menu);
}
-
/**
* @param IPxeMenu $menu
*/
@@ -144,7 +151,7 @@ cpair --foreground 7 --background 9 0
console --left 55 --top 88 --right 63 --bottom 64 $slxConsoleUpdate --keep --picture bg-menu ||
-menu -- {$menu->title} || prompt Error creating menu ||
+menu -- {$menu->title} || prompt --timeout 5000 Error creating menu ||
HERE;
foreach ($menu->items as $item) {
@@ -306,7 +313,6 @@ console ||
$localboot || goto fail
BLA;
-
//
} else {
$output = "prompt --timeout 5000 Unknown special command '$special' ||\nchain -ar \${self}\n";
@@ -381,12 +387,12 @@ chain -a \${self}&entryid={$entry->menuentryid}##params || goto fail ||
HERE;
}
- public function getMenuEntry($menuEntryId)
+ public function getMenuEntry($entry, $honorPassword = true)
{
- $entry = MenuEntry::get($menuEntryId);
if ($entry === null)
- return "#!ipxe\nprompt --timeout 10000 Invalid menu entry id: $menuEntryId\n";
+ return "#!ipxe\nprompt --timeout 10000 Invalid menu entry id\n";
$base = $this->getUrlBase();
+ $meid = $entry->menuEntryId();
// Make sure legacy variables are set; they might get used
$output = <<<HERE
#!ipxe
@@ -395,10 +401,11 @@ set ipappend2 BOOTIF=01-\${mac:hexhyp}
set serverip {$this->serverIp} ||
iseq \${idx} \${} && set idx:string X ||
iseq \${self} \${} && set self {$base}? ||
+set menuentryid $meid ||
HERE;
// Check for password
- if (!empty($entry->md5pass)) { // TODO: This should be split out so we can unconditionally get entry code
+ if ($honorPassword && !empty($entry->md5pass)) {
$pwh = Request::post('pwhash', false, 'string');
$pwp = Request::post('pwplain', false, 'string');
if ($pwh === false && $pwp === false) {
@@ -459,6 +466,9 @@ HERE;
return $output . "goto fail\n";
}
// static, we know in advance
+ if ($efi !== null && $this->platform === BootEntry::EFI)
+ return $this->execDataToScriptInternal($efi) . "\ngoto fail\n";
+ // Should be BIOS at this point
return $this->execDataToScriptInternal($bios ?? $efi ?? new ExecData()) . "\ngoto fail\n";
}
@@ -510,7 +520,7 @@ HERE;
}
}
if (!empty($entry->commandLine)) {
- $script .= ' ' . $entry->commandLine;
+ $script .= ' ' . $entry->commandLine . ' slx.ipxe.id=${menuentryid}';
}
$script .= " || goto fail\n";
if ($entry->resetConsole) {