$group]); } if (!$filterOverridden || !Module::isAvailable('rebootcontrol')) return $list; return array_filter($list, function (int $lid) { $mode = Scheduler::getLocationOptions($lid)['ra-mode']; return ($mode !== Scheduler::RA_NEVER && ($mode !== Scheduler::RA_SELECTIVE || !OpeningTimes::isRoomOpen($lid, 5, 5))); }); } public static function ensureMachinesRunning() { if (!Module::isAvailable('rebootcontrol')) { error_log("Not waking remote access machines: rebootcontrol missing"); return; } $res = Database::simpleQuery("SELECT rg.groupid, rg.groupname, rg.wolcount, GROUP_CONCAT(rxl.locationid) AS locs FROM remoteaccess_group rg INNER JOIN remoteaccess_x_location rxl USING (groupid) WHERE rg.active = 1 GROUP BY groupid"); // Consider machines we tried to wake in the past 90 seconds as online $wolDeadline = time() - 90; foreach ($res as $row) { $wantNum = $row['wolcount']; // This can't really be anything but a CSV list, but better be safe $locs = preg_replace('/[^0-9,]/', '', $row['locs']); if (!empty($locs)) { // Filter out locations for which remote-access is disabled $locArray = explode(',', $locs); $locArray = array_filter($locArray, function (int $lid) { $mode = Scheduler::getLocationOptions($lid)['ra-mode']; return ($mode !== Scheduler::RA_NEVER && ($mode !== Scheduler::RA_SELECTIVE || !OpeningTimes::isRoomOpen($lid, 5, 5))); }); $locs = implode(',', $locArray); } if ($wantNum > 0 && !empty($locs)) { $active = Database::queryFirst("SELECT Count(*) AS cnt FROM machine m INNER JOIN remoteaccess_machine rm USING (machineuuid) WHERE m.locationid IN ($locs) AND (m.state = 'IDLE' OR rm.woltime > $wolDeadline)"); $active = ($active['cnt'] ?? 0); $wantNum -= $active; } if ($wantNum > 0) { $numFailed = self::tryWakeMachines($locs, $wantNum); } else { $numFailed = 0; } Database::exec("UPDATE remoteaccess_group SET unwoken = :num WHERE groupid = :groupid", ['num' => $numFailed, 'groupid' => $row['groupid']]); } } private static function tryWakeMachines(string $locs, int $num): int { if (empty($locs)) return $num; $res = Database::simpleQuery("SELECT m.machineuuid, m.macaddr, m.clientip, m.locationid FROM machine m LEFT JOIN remoteaccess_machine rm USING (machineuuid) WHERE m.locationid IN ($locs) AND m.state IN ('OFFLINE', 'STANDBY') ORDER BY rm.woltime ASC"); $NOW = time(); while ($num > 0) { $list = []; for ($i = 0; $i < $num && ($row = $res->fetch()); ++$i) { $list[] = $row; Database::exec("INSERT INTO remoteaccess_machine (machineuuid, password, woltime) VALUES (:uuid, NULL, :now) ON DUPLICATE KEY UPDATE woltime = VALUES(woltime)", ['uuid' => $row['machineuuid'], 'now' => $NOW]); } if (empty($list)) break; // No more clients in this location RebootControl::wakeMachines($list, $fails); $num -= (count($list) - count($fails)); if (!empty($fails)) { $failIds = ArrayUtil::flattenByKey($fails, 'machineuuid'); // Reduce time so they won't be marked as wol_in_progress Database::exec('UPDATE remoteaccess_machine SET woltime = :faketime WHERE machineuuid IN (:fails)', ['faketime' => $NOW - 95, 'fails' => $failIds]); } } return $num; } }