diff options
Diffstat (limited to 'modules-available/rebootcontrol/page.inc.php')
-rw-r--r-- | modules-available/rebootcontrol/page.inc.php | 241 |
1 files changed, 115 insertions, 126 deletions
diff --git a/modules-available/rebootcontrol/page.inc.php b/modules-available/rebootcontrol/page.inc.php index 3a438504..80eff842 100644 --- a/modules-available/rebootcontrol/page.inc.php +++ b/modules-available/rebootcontrol/page.inc.php @@ -3,7 +3,10 @@ class Page_RebootControl extends Page { - private $action = false; + /** + * @var bool whether we have a SubPage from the pages/ subdir + */ + private $haveSubpage = false; /** * Called before any page rendering happens - early hook to check parameters etc. @@ -17,62 +20,87 @@ class Page_RebootControl extends Page Util::redirect('?do=Main'); // does not return } - $this->action = Request::any('action', 'show', 'string'); - - - if ($this->action === 'reboot' || $this->action === 'shutdown') { - - $requestedClients = Request::post('clients', false, 'array'); - if (!is_array($requestedClients) || empty($requestedClients)) { - Message::addError('no-clients-selected'); - Util::redirect(); - } + if (User::hasPermission('jumphost.*')) { + Dashboard::addSubmenu('?do=rebootcontrol&show=jumphost', Dictionary::translate('jumphosts')); + } + if (User::hasPermission('subnet.*')) { + Dashboard::addSubmenu('?do=rebootcontrol&show=subnet', Dictionary::translate('subnets')); + } - $actualClients = RebootQueries::getMachinesByUuid($requestedClients); - if (count($actualClients) !== count($requestedClients)) { - // We could go ahead an see which ones were not found in DB but this should not happen anyways unless the - // user manipulated the request - Message::addWarning('some-machine-not-found'); + $section = Request::any('show', false, 'string'); + if ($section !== false) { + $section = preg_replace('/[^a-z]/', '', $section); + if (file_exists('modules/rebootcontrol/pages/' . $section . '.inc.php')) { + require_once 'modules/rebootcontrol/pages/' . $section . '.inc.php'; + $this->haveSubpage = true; + SubPage::doPreprocess(); + } else { + Message::addError('main.invalid-action', $section); + return; } - // Filter ones with no permission - foreach (array_keys($actualClients) as $idx) { - if (!User::hasPermission('action.' . $this->action, $actualClients[$idx]['locationid'])) { - Message::addWarning('locations.no-permission-location', $actualClients[$idx]['locationid']); - unset($actualClients[$idx]); + } else { + $action = Request::post('action', 'show', 'string'); + + if ($action === 'reboot' || $action === 'shutdown') { + $this->execRebootShutdown($action); + } elseif ($action === 'toggle-wol') { + User::assertPermission('woldiscover'); + $enabled = Request::post('enabled', false); + $c2c = Request::post('enabled-c2c', false); + $port = Request::post('port', 9, 'int'); + $dbcast = Request::post('dbcast', '', 'string'); + Property::set(RebootControl::KEY_AUTOSCAN_DISABLED, !$enabled); + Property::set(RebootControl::KEY_SCAN_CLIENT_TO_CLIENT, $c2c); + Property::set(RebootControl::KEY_UDP_PORT, $port); + Property::set(RebootControl::KEY_BROADCAST_ADDRESS, $dbcast); + if ($enabled) { + Message::addInfo('woldiscover-enabled'); } else { - $locationId = $actualClients[$idx]['locationid']; + Message::addInfo('woldiscover-disabled'); } + $section = 'subnet'; // For redirect below } - // See if anything is left - if (!is_array($actualClients) || empty($actualClients)) { - Message::addError('no-clients-selected'); - Util::redirect(); - } - usort($actualClients, function($a, $b) { - $a = ($a['state'] === 'IDLE' || $a['state'] === 'OCCUPIED'); - $b = ($b['state'] === 'IDLE' || $b['state'] === 'OCCUPIED'); - if ($a === $b) - return 0; - return $a ? -1 : 1; - }); - if ($this->action === 'shutdown') { - $mode = 'SHUTDOWN'; - $minutes = Request::post('s-minutes', 0, 'int'); - } elseif (Request::any('quick', false, 'string') === 'on') { - $mode = 'KEXEC_REBOOT'; - $minutes = Request::post('r-minutes', 0, 'int'); - } else { - $mode = 'REBOOT'; - $minutes = Request::post('r-minutes', 0, 'int'); - } - $task = RebootControl::execute($actualClients, $mode, $minutes, $locationId); - if (Taskmanager::isTask($task)) { - Util::redirect("?do=rebootcontrol&taskid=" . $task["id"]); + } + + if (Request::isPost()) { + Util::redirect('?do=rebootcontrol' . ($section ? '&show=' . $section : '')); + } elseif ($section === false) { + if (User::hasPermission('action.*')) { + Util::redirect('?do=rebootcontrol&show=task'); + } elseif (User::hasPermission('jumphost.*')) { + Util::redirect('?do=rebootcontrol&show=jumphost'); } else { - Util::redirect("?do=rebootcontrol"); + Util::redirect('?do=rebootcontrol&show=subnet'); } } + } + private function execRebootShutdown($action) + { + $requestedClients = Request::post('clients', false, 'array'); + if (!is_array($requestedClients) || empty($requestedClients)) { + Message::addError('no-clients-selected'); + return; + } + + $actualClients = RebootUtils::getFilteredMachineList($requestedClients, 'action.' . $action); + if ($actualClients === false) + return; + RebootUtils::sortRunningFirst($actualClients); + if ($action === 'shutdown') { + $mode = 'SHUTDOWN'; + $minutes = Request::post('s-minutes', 0, 'int'); + } elseif (Request::any('quick', false, 'string') === 'on') { + $mode = 'KEXEC_REBOOT'; + $minutes = Request::post('r-minutes', 0, 'int'); + } else { + $mode = 'REBOOT'; + $minutes = Request::post('r-minutes', 0, 'int'); + } + $task = RebootControl::execute($actualClients, $mode, $minutes); + if (Taskmanager::isTask($task)) { + Util::redirect("?do=rebootcontrol&show=task&what=task&taskid=" . $task["id"]); + } } /** @@ -81,94 +109,55 @@ class Page_RebootControl extends Page protected function doRender() { - if ($this->action === 'show') { - - $data = []; - $task = Request::get("taskid", false, 'string'); - if ($task !== false) { - $task = Taskmanager::status($task); - } - - if (Taskmanager::isTask($task)) { - - $data['taskId'] = $task['id']; - $data['locationId'] = $task['data']['locationId']; - $data['locationName'] = Location::getName($task['data']['locationId']); - $uuids = array_map(function($entry) { - return $entry['machineuuid']; - }, $task['data']['clients']); - $data['clients'] = RebootQueries::getMachinesByUuid($uuids); - Render::addTemplate('status', $data); - - } else { - - //location you want to see, default are "not assigned" clients - $requestedLocation = Request::get('location', false, 'int'); - $allowedLocs = User::getAllowedLocations("action.*"); - if (empty($allowedLocs)) { - User::assertPermission('action.*'); - } - - if ($requestedLocation === false) { - if (in_array(0, $allowedLocs)) { - $requestedLocation = 0; - } else { - $requestedLocation = reset($allowedLocs); - } - } - - $data['locations'] = Location::getLocations($requestedLocation, 0, true); - - // disable each location user has no permission for - foreach ($data['locations'] as &$loc) { - if (!in_array($loc["locationid"], $allowedLocs)) { - $loc["disabled"] = "disabled"; - } elseif ($loc["locationid"] == $requestedLocation) { - $data['location'] = $loc['locationname']; - } - } - // Always show public key (it's public, isn't it?) - $data['pubKey'] = SSHKey::getPublicKey(); - - // Only enable shutdown/reboot-button if user has permission for the location - Permission::addGlobalTags($data['perms'], $requestedLocation, ['newkeypair', 'action.shutdown', 'action.reboot']); - - Render::addTemplate('header', $data); - - // only fill table if user has at least one permission for the location - if (!in_array($requestedLocation, $allowedLocs)) { - Message::addError('locations.no-permission-location', $requestedLocation); - } else { - $data['data'] = RebootQueries::getMachineTable($requestedLocation); - Render::addTemplate('_page', $data); - } - - // Append list of active reboot/shutdown tasks - $active = RebootControl::getActiveTasks($allowedLocs); - if (!empty($active)) { - foreach ($active as &$entry) { - $entry['locationName'] = Location::getName($entry['locationId']); - } - unset($entry); - Render::addTemplate('task-list', ['list' => $active]); - } - - } + $port = (int)Property::get(RebootControl::KEY_UDP_PORT); + if ($port < 1 || $port > 65535) { + $port = 9; + } + // Always show public key (it's public, isn't it?) + $data = [ + 'pubkey' => SSHKey::getPublicKey(), + 'wol_auto_checked' => Property::get(RebootControl::KEY_AUTOSCAN_DISABLED) ? '' : 'checked', + 'wol_c2c_checked' => Property::get(RebootControl::KEY_SCAN_CLIENT_TO_CLIENT) ? 'checked' : '', + 'port' => $port, + 'dbcast' => Property::get(RebootControl::KEY_BROADCAST_ADDRESS), + ]; + Permission::addGlobalTags($data['perms'], null, ['newkeypair', 'woldiscover']); + Render::addTemplate('header', $data); + + if ($this->haveSubpage) { + SubPage::doRender(); } } - function doAjax() + protected function doAjax() { - $this->action = Request::post('action', false, 'string'); - if ($this->action === 'generateNewKeypair') { + $action = Request::post('action', false, 'string'); + if ($action === 'generateNewKeypair') { User::assertPermission("newkeypair"); Property::set("rebootcontrol-private-key", false); echo SSHKey::getPublicKey(); + } elseif ($action === 'clientstatus') { + $clients = Request::post('clients'); + if (is_array($clients)) { + // XXX No permission check here, should we consider this as leaking sensitive information? + $machines = RebootUtils::getMachinesByUuid(array_values($clients), false, ['machineuuid', 'state']); + $ret = []; + foreach ($machines as $machine) { + switch ($machine['state']) { + case 'OFFLINE': $val = 'glyphicon-off'; break; + case 'IDLE': $val = 'glyphicon-ok green'; break; + case 'OCCUPIED': $val = 'glyphicon-user red'; break; + case 'STANDBY': $val = 'glyphicon-off green'; break; + default: $val = 'glyphicon-question-sign'; break; + } + $ret[$machine['machineuuid']] = $val; + } + Header('Content-Type: application/json; charset=utf-8'); + echo json_encode($ret); + } } else { echo 'Invalid action.'; } } - - } |