From 3e45ec44d22f03ca6642e08f695c6d7274cecfaf Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Sat, 7 Dec 2019 13:52:54 +0100 Subject: [statistics/rebootcontrol] Add WOL button to statistics module * Overhauled task display in rebootcontrol module * Can only add subnets by CIDR now instead of start and end --- .../rebootcontrol/pages/jumphost.inc.php | 8 +- .../rebootcontrol/pages/subnet.inc.php | 42 ++++---- modules-available/rebootcontrol/pages/task.inc.php | 119 +++++++++++++++------ 3 files changed, 108 insertions(+), 61 deletions(-) (limited to 'modules-available/rebootcontrol/pages') diff --git a/modules-available/rebootcontrol/pages/jumphost.inc.php b/modules-available/rebootcontrol/pages/jumphost.inc.php index 111560ef..7dcdd52c 100644 --- a/modules-available/rebootcontrol/pages/jumphost.inc.php +++ b/modules-available/rebootcontrol/pages/jumphost.inc.php @@ -30,15 +30,9 @@ class SubPage private static function execCheckConnection($hostid) { $host = self::getJumpHost($hostid); - $script = str_replace(['%IP%', '%MACS%'], ['255.255.255.255', '00:11:22:33:44:55'], $host['script']); - $task = RebootControl::runScript([[ - 'clientip' => $host['host'], - 'port' => $host['port'], - 'username' => $host['username'], - ]], $script, 5, $host['sshkey']); + $task = RebootControl::wakeViaJumpHost($host, '255.255.255.255', [['macaddr' => '00:11:22:33:44:55']]); if (!Taskmanager::isTask($task)) return; - TaskmanagerCallback::addCallback($task, 'rbcConnCheck', $hostid); Util::redirect('?do=rebootcontrol&show=task&type=checkhost&what=task&taskid=' . $task['id']); } diff --git a/modules-available/rebootcontrol/pages/subnet.inc.php b/modules-available/rebootcontrol/pages/subnet.inc.php index 946d2d64..c38c7595 100644 --- a/modules-available/rebootcontrol/pages/subnet.inc.php +++ b/modules-available/rebootcontrol/pages/subnet.inc.php @@ -20,23 +20,16 @@ class SubPage private static function addSubnet() { User::assertPermission('subnet.edit'); - $range = []; - foreach (['start', 'end'] as $key) { - $range[$key] = Request::post($key, Request::REQUIRED, 'string'); - $range[$key . '_l'] = ip2long($range[$key]); - if ($range[$key . '_l'] === false) { - Message::addError('invalid-ip-address', $range[$key]); - return; - } - } - if ($range['start_l'] > $range['end_l']) { - Message::addError('invalid-range', $range['start'], $range['end']); + $cidr = Request::post('cidr', Request::REQUIRED, 'string'); + $range = IpUtil::parseCidr($cidr); + if ($range === false) { + Message::addError('invalid-cidr', $cidr); return; } $ret = Database::exec('INSERT INTO reboot_subnet (start, end, fixed, isdirect) VALUES (:start, :end, 1, 0)', [ - 'start' => sprintf('%u', $range['start_l']), - 'end' => sprintf('%u', $range['end_l']), + 'start' => $range['start'], + 'end' => $range['end'], ], true); if ($ret === false) { Message::addError('subnet-already-exists'); @@ -97,15 +90,15 @@ class SubPage User::assertPermission('subnet.*'); $nets = []; $res = Database::simpleQuery('SELECT subnetid, start, end, fixed, isdirect, - lastdirectcheck, lastseen, seencount, Count(hxs.hostid) AS jumphostcount - FROM reboot_subnet + nextdirectcheck, lastseen, seencount, Count(hxs.hostid) AS jumphostcount, Count(sxs.srcid) AS sourcecount + FROM reboot_subnet s LEFT JOIN reboot_jumphost_x_subnet hxs USING (subnetid) + LEFT JOIN reboot_subnet_x_subnet sxs ON (s.subnetid = sxs.dstid AND sxs.reachable <> 0) GROUP BY subnetid, start, end ORDER BY start ASC, end DESC'); $deadline = strtotime('-60 days'); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - $row['start_s'] = long2ip($row['start']); - $row['end_s'] = long2ip($row['end']); + $row['cidr'] = IpUtil::rangeToCidr($row['start'], $row['end']); $row['lastseen_s'] = Util::prettyTime($row['lastseen']); if ($row['lastseen'] && $row['lastseen'] < $deadline) { $row['lastseen_class'] = 'text-danger'; @@ -114,7 +107,6 @@ class SubPage } $data = ['subnets' => $nets]; Render::addTemplate('subnet-list', $data); - Module::isAvailable('js_ip'); } private static function showSubnet() @@ -127,17 +119,29 @@ class SubPage Message::addError('invalid-subnet', $id); return; } + $subnet['cidr'] = IpUtil::rangeToCidr($subnet['start'], $subnet['end']); $subnet['start_s'] = long2ip($subnet['start']); $subnet['end_s'] = long2ip($subnet['end']); + // Get list of jump hosts $res = Database::simpleQuery('SELECT h.hostid, h.host, h.port, hxs.subnetid FROM reboot_jumphost h LEFT JOIN reboot_jumphost_x_subnet hxs ON (h.hostid = hxs.hostid AND hxs.subnetid = :id) ORDER BY h.host ASC', ['id' => $id]); + // Mark those assigned to the current subnet $jh = []; while ($row = $res->fetch(PDO::FETCH_ASSOC)) { $row['checked'] = $row['subnetid'] === null ? '' : 'checked'; $jh[] = $row; } $subnet['jumpHosts'] = $jh; + // Get list of all subnets that can broadcast into this one + $res = Database::simpleQuery('SELECT s.start, s.end FROM reboot_subnet s + INNER JOIN reboot_subnet_x_subnet sxs ON (s.subnetid = sxs.srcid AND sxs.dstid = :id AND sxs.reachable = 1) + ORDER BY s.start ASC', ['id' => $id]); + $sn = []; + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $sn[] = ['cidr' => IpUtil::rangeToCidr($row['start'], $row['end'])]; + } + $subnet['sourceNets'] = $sn; Permission::addGlobalTags($subnet['perms'], null, ['subnet.flag', 'jumphost.view', 'jumphost.assign-subnet']); Render::addTemplate('subnet-edit', $subnet); } @@ -147,4 +151,4 @@ class SubPage } -} \ No newline at end of file +} diff --git a/modules-available/rebootcontrol/pages/task.inc.php b/modules-available/rebootcontrol/pages/task.inc.php index 15449aaf..e52eb981 100644 --- a/modules-available/rebootcontrol/pages/task.inc.php +++ b/modules-available/rebootcontrol/pages/task.inc.php @@ -10,6 +10,12 @@ class SubPage public static function doRender() { + $xxx = Request::get('tasks'); + if (is_array($xxx)) { + $data = array_map(function($item) { return ['id' => $item]; }, $xxx); + Render::addTemplate('status-wol', ['tasks' => $data]); + return; + } $show = Request::get('what', 'tasklist', 'string'); if ($show === 'tasklist') { self::showTaskList(); @@ -21,67 +27,110 @@ class SubPage private static function showTask() { $taskid = Request::get("taskid", Request::REQUIRED, 'string'); - $task = Taskmanager::status($taskid); - - if (!Taskmanager::isTask($task) || !isset($task['data'])) { - Message::addError('no-such-task', $taskid); - return; - } - - $td =& $task['data']; $type = Request::get('type', false, 'string'); - if ($type === false) { - // Try to guess - if (isset($td['locationId']) || isset($td['clients'])) { - $type = 'reboot'; - } elseif (isset($td['result'])) { - $type = 'exec'; + if ($type === 'checkhost') { + // Override + $task = Taskmanager::status($taskid); + if (!Taskmanager::isTask($task) || !isset($task['data'])) { + Message::addError('no-such-task', $taskid); + return; } - } - if ($type === 'reboot') { - $data = [ - 'taskId' => $task['id'], - 'locationId' => $td['locationId'], - 'locationName' => Location::getName($td['locationId']), - ]; - $uuids = array_map(function ($entry) { - return $entry['machineuuid']; - }, $td['clients']); - $data['clients'] = RebootQueries::getMachinesByUuid($uuids); - Render::addTemplate('status-reboot', $data); - } elseif ($type === 'exec') { - $data = [ - 'taskId' => $task['id'], - ]; - Render::addTemplate('status-exec', $data); - } elseif ($type === 'checkhost') { + $td =& $task['data']; $ip = array_key_first($td['result']); $data = [ 'taskId' => $task['id'], 'host' => $ip, ]; Render::addTemplate('status-checkconnection', $data); - } else { + return; + } + if ($type !== false) { Message::addError('unknown-task-type'); } + + $job = RebootControl::getActiveTasks(null, $taskid); + if ($job === false) { + Message::addError('no-such-task', $taskid); + return; + } + if (isset($job['type'])) { + $type = $job['type']; + } + if ($type === RebootControl::TASK_EXEC) { + $template = $perm = 'exec'; + } elseif ($type === RebootControl::TASK_REBOOTCTL) { + $template = 'reboot'; + if ($job['action'] === RebootControl::SHUTDOWN) { + $perm = 'shutdown'; + } else { + $perm = 'reboot'; + } + } elseif ($type == RebootControl::TASK_WOL) { + $template = $perm = 'wol'; + } else { + Message::addError('unknown-task-type', $type); + return; + } + if (!empty($job['locations'])) { + $allowedLocs = User::getAllowedLocations("action.$perm"); + if (!in_array(0, $allowedLocs) && array_diff($job['locations'], $allowedLocs) !== []) { + Message::addError('main.no-permission'); + return; + } + self::expandLocationIds($job['locations']); + } + + // Output + if ($type === RebootControl::TASK_REBOOTCTL) { + $job['clients'] = RebootQueries::getMachinesByUuid(ArrayUtil::flattenByKey($job['clients'], 'machineuuid')); + } elseif ($type === RebootControl::TASK_EXEC) { + $details = RebootQueries::getMachinesByUuid(ArrayUtil::flattenByKey($job['clients'], 'machineuuid'), true); + foreach ($job['clients'] as &$client) { + if (isset($client['machineuuid']) && isset($details[$client['machineuuid']])) { + $client += $details[$client['machineuuid']]; + } + } + } elseif ($type === RebootControl::TASK_WOL) { + // Nothing (yet) + } else { + Util::traceError('oopsie'); + } + Render::addTemplate('status-' . $template, $job); } private static function showTaskList() { + Render::addTemplate('task-header'); // Append list of active reboot/shutdown tasks - $allowedLocs = User::getAllowedLocations("*"); + $allowedLocs = User::getAllowedLocations("action.*"); $active = RebootControl::getActiveTasks($allowedLocs); if (empty($active)) { Message::addInfo('no-current-tasks'); } else { foreach ($active as &$entry) { - $entry['locationName'] = Location::getName($entry['locationId']); + self::expandLocationIds($entry['locations']); + if (isset($entry['clients'])) { + $entry['clients'] = count($entry['clients']); + } } unset($entry); Render::addTemplate('task-list', ['list' => $active]); } } + private static function expandLocationIds(&$lids) + { + foreach ($lids as &$locid) { + if ($locid === 0) { + $name = '-'; + } else { + $name = Location::getName($locid); + } + $locid = ['id' => $locid, 'name' => $name]; + } + $lids = array_values($lids); + } + public static function doAjax() { -- cgit v1.2.3-55-g7522