diff options
Diffstat (limited to 'modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php')
-rw-r--r-- | modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php | 189 |
1 files changed, 111 insertions, 78 deletions
diff --git a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php index f87d15c2..3ffecba1 100644 --- a/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php +++ b/modules-available/serversetup-bwlp-ipxe/inc/ipxemenu.inc.php @@ -3,84 +3,71 @@ class IPxeMenu { + /** + * @var int ID of this menu, from DB + */ protected $menuid; - protected $timeoutMs; - protected $title; - protected $defaultEntryId; + /** + * @var int 0 = disabled, otherwise, launch default option after timeout + */ + public $timeoutMs; + /** + * @var string title to display above menu + */ + public $title; + /** + * @var int menu entry id from DB + */ + public $defaultEntryId; /** * @var MenuEntry[] */ - protected $items = []; + public $items = []; - public function __construct($menu) + public static function get(int $menuId, bool $emptyFallback = false): ?IPxeMenu + { + $menu = Database::queryFirst("SELECT menuid, timeoutms, title, defaultentryid FROM serversetup_menu + WHERE menuid = :menuid LIMIT 1", ['menuid' => $menuId]); + if ($menu !== false) + return new IPxeMenu($menu); + if (!$emptyFallback) + return null; + return new EmptyIPxeMenu(); + } + + /** + * IPxeMenu constructor. + * + * @param array $menu array for according menu row + */ + public function __construct(array $menu) { - if (!is_array($menu)) { - $menu = Database::queryFirst("SELECT menuid, timeoutms, title, defaultentryid FROM serversetup_menu - WHERE menuid = :menuid LIMIT 1", ['menuid' => $menu]); - if (!is_array($menu)) { - $menu = ['menuid' => 'foo', 'title' => 'Invalid Menu ID: ' . (int)$menu]; - } - } $this->menuid = (int)$menu['menuid']; $this->timeoutMs = (int)$menu['timeoutms']; - $this->title = $menu['title']; - $this->defaultEntryId = $menu['defaultentryid']; - $res = Database::simpleQuery("SELECT e.menuentryid, e.entryid, e.refmenuid, e.hotkey, e.title, e.hidden, e.sortval, e.md5pass, - b.module, b.data AS bootentry + $this->title = (string)$menu['title']; + $defaultEntryId = $menu['defaultentryid']; + $res = Database::simpleQuery("SELECT e.menuentryid, e.entryid, e.refmenuid, e.hotkey, e.title, + e.hidden, e.sortval, e.md5pass, b.module, b.data AS bootentry, b.title AS betitle FROM serversetup_menuentry e LEFT JOIN serversetup_bootentry b USING (entryid) WHERE e.menuid = :menuid ORDER BY e.sortval ASC, e.title ASC", ['menuid' => $menu['menuid']]); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + foreach ($res as $row) { $this->items[] = new MenuEntry($row); } // Make sure we have a default entry if the menu isn't empty - if ($this->defaultEntryId === null && !empty($this->items)) { - $this->defaultEntryId = $this->items[0]->menuEntryId(); - } - } - - public function getMenuDefinition($targetVar, $mode, $slxExtensions) - { - $str = "menu -- {$this->title}\n"; - foreach ($this->items as $item) { - $str .= $item->getMenuItemScript("m_{$this->menuid}", $this->defaultEntryId, $mode, $slxExtensions); - } - if ($this->defaultEntryId === null) { - $defaultLabel = "mx_{$this->menuid}_poweroff"; - } else { - $defaultLabel = "m_{$this->menuid}_{$this->defaultEntryId}"; - } - $str .= "choose"; - if ($this->timeoutMs > 0) { - $str .= " --timeout {$this->timeoutMs}"; + if ($defaultEntryId === null && !empty($this->items)) { + $defaultEntryId = $this->items[0]->menuEntryId(); } - $str .= " $targetVar || goto $defaultLabel || goto fail\n"; - if ($this->defaultEntryId === null) { - $str .= "goto skip_{$defaultLabel}\n" - . ":{$defaultLabel}\n" - . "poweroff || goto fail\n" - . ":skip_{$defaultLabel}\n"; - } - return $str; - } - - public function getItemsCode($mode) - { - $str = ''; - foreach ($this->items as $item) { - $str .= $item->getBootEntryScript("m_{$this->menuid}", 'fail', $mode); - $str .= "goto slx_menu\n"; - } - return $str; + $this->defaultEntryId = (int)$defaultEntryId; } - public function title() + public function title(): string { return $this->title; } - public function timeoutMs() + public function timeoutMs(): int { return $this->timeoutMs; } @@ -88,52 +75,89 @@ class IPxeMenu /** * @return int Number of items in this menu */ - public function itemCount() + public function itemCount(): int { return count($this->items); } /** - * @return string|false Return script label of default entry, false if not set + * @return MenuEntry|null Return preselected menu entry */ - public function getDefaultScriptLabel() + public function defaultEntry(): ?MenuEntry { - if ($this->defaultEntryId !== null) - return "m_{$this->menuid}_{$this->defaultEntryId}"; - return false; + foreach ($this->items as $item) { + if ($item->menuEntryId() === $this->defaultEntryId) + return $item; + } + return null; + } + + private function maybeOverrideDefault(string $uuid) + { + $e = $this->defaultEntry(); + // Shortcut - is already bwlp and timeout is reasonable (1-15s), do nothing + $defIsMl = $e !== null && substr($e->internalId(), 0, 3) === 'ml-'; + $timeoutOk = $this->timeoutMs > 0 && $this->timeoutMs <= 15000; + if ($timeoutOk && $defIsMl) + return; + // No runmode module anyways + if (!Module::isAvailable('runmode')) + return; + $rm = RunMode::getRunMode($uuid); + // No runmode for this client, cannot be PVSmgr + if ($rm === false) + return; + // Is not pvsmgr + if ($rm['module'] !== 'roomplanner') + return; + // See if it's a dedicated station, if so make sure it boots into bwLehrpool + $data = json_decode($rm['modedata'], true); + if ($data['dedicatedmgr'] ?? false) { + if (!$defIsMl) { + $this->overrideDefaultToMinilinux(); + } + if (!$timeoutOk) { + $this->timeoutMs = 5000; + } + } } /** - * @return MenuEntry|null Return preselected menu entry + * Patch the menu to make sure bwLehrpool/"MiniLinux" is the default + * boot option, and set timeout to something reasonable. This is used + * for dedicated PVS managers, as they might not have a keyboard + * connected. */ - public function defaultEntry() + private function overrideDefaultToMinilinux() { foreach ($this->items as $item) { - if ($item->menuEntryId() == $this->defaultEntryId) - return $item; + if (substr($item->internalId(), 0, 3) === 'ml-') { + $this->defaultEntryId = $item->menuEntryId(); + return; + } } - return null; } /* * */ - public static function forLocation($locationId) + public static function forLocation(int $locationId): IPxeMenu { $chain = null; if (Module::isAvailable('locations')) { $chain = Location::getLocationRootChain($locationId); } if (!empty($chain)) { - $res = Database::simpleQuery("SELECT m.menuid, m.timeoutms, m.title, IFNULL(ml.defaultentryid, m.defaultentryid) AS defaultentryid, ml.locationid - FROM serversetup_menu m - INNER JOIN serversetup_menu_location ml USING (menuid) - WHERE ml.locationid IN (:chain)", ['chain' => $chain]); + $res = Database::simpleQuery("SELECT m.menuid, m.timeoutms, m.title, + IFNULL(ml.defaultentryid, m.defaultentryid) AS defaultentryid, ml.locationid + FROM serversetup_menu m + INNER JOIN serversetup_menu_location ml USING (menuid) + WHERE ml.locationid IN (:chain)", ['chain' => $chain]); if ($res->rowCount() > 0) { // Make the location id key, preserving order (closest location is first) $chain = array_flip($chain); - while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + foreach ($res as $row) { // Overwrite the value (numeric ascending values, useless) with menu array of according location $chain[(int)$row['locationid']] = $row; } @@ -156,13 +180,19 @@ class IPxeMenu return new IPxeMenu($menu); } - public static function forClient($ip, $uuid) + public static function forClient(string $ip, ?string $uuid): IPxeMenu { $locationId = 0; if (Module::isAvailable('locations')) { $locationId = Location::getFromIpAndUuid($ip, $uuid); } - return self::forLocation($locationId); + $menu = self::forLocation($locationId); + if ($uuid !== null) { + // Super specialcase hackery: If this is a dedicated PVS, force the default to + // be bwlp/"minilinux" + $menu->maybeOverrideDefault($uuid); + } + return $menu; } } @@ -170,11 +200,14 @@ class IPxeMenu class EmptyIPxeMenu extends IPxeMenu { - /** @noinspection PhpMissingParentConstructorInspection */ public function __construct() { - $this->title = 'No menu defined'; - $this->menuid = -1; + parent::__construct([ + 'menuid' => -1, + 'timeoutms' => 120, + 'defaultentryid' => null, + 'title' => 'No menu defined', + ]); $this->items[] = new MenuEntry([ 'title' => 'Please create a menu in Server-Setup first' ]); |