summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Hofmaier2021-03-16 20:03:58 +0100
committerChristian Hofmaier2021-03-16 20:03:58 +0100
commit834b95629832fc3735756727b6c7cb1826d0e9d8 (patch)
treeff465ef0063c59d92f8c77e89f15a2a7a2405977
parent[sysconfig] yes -> true (diff)
downloadslx-admin-834b95629832fc3735756727b6c7cb1826d0e9d8.tar.gz
slx-admin-834b95629832fc3735756727b6c7cb1826d0e9d8.tar.xz
slx-admin-834b95629832fc3735756727b6c7cb1826d0e9d8.zip
[rebootcontrol] Handle scheduler overlaps
- Overlaps < 5 min are ignored, < 15 triggers reboot - Database: Make 1 line out of 2
-rw-r--r--modules-available/locations/pages/details.inc.php34
-rw-r--r--modules-available/locations/templates/ajax-opening-location.html8
-rw-r--r--modules-available/rebootcontrol/hooks/cron.inc.php6
-rw-r--r--modules-available/rebootcontrol/inc/scheduler.inc.php112
-rw-r--r--modules-available/rebootcontrol/install.inc.php9
5 files changed, 102 insertions, 67 deletions
diff --git a/modules-available/locations/pages/details.inc.php b/modules-available/locations/pages/details.inc.php
index 2f444157..fd45646b 100644
--- a/modules-available/locations/pages/details.inc.php
+++ b/modules-available/locations/pages/details.inc.php
@@ -89,25 +89,25 @@ class SubPage
array('locationid' => $locationid, 'openingtime' => $openingTimes));
if (Module::isAvailable('rebootcontrol')) {
- if ($wol) {
+ if ($wol || $sd) {
$options = array();
+
// Sanity checks
if ($woloffset > 15) $woloffset = 15;
else if ($woloffset < 0) $woloffset = 0;
- $options['wol-offset'] = $woloffset;
- Scheduler::updateSchedule($locationid, 'wol', $options, $openingTimes);
- } else {
- Scheduler::deleteSchedule($locationid, 'wol');
- }
- if ($sd) {
- $options = array();
- // Sanity checks
if ($sdoffset > 15) $sdoffset = 15;
else if ($sdoffset < 0) $sdoffset = 0;
+
+ // Set options
+ $options['wol'] = $wol;
+ $options['wol-offset'] = $woloffset;
+ $options['sd'] = $sd;
$options['sd-offset'] = $sdoffset;
- Scheduler::updateSchedule($locationid, 'sd', $options, $openingTimes);
+
+ Scheduler::updateSchedule($locationid, $options, $openingTimes);
+
} else {
- Scheduler::deleteSchedule($locationid, 'sd');
+ Scheduler::deleteSchedule($locationid);
}
}
}
@@ -423,16 +423,8 @@ class SubPage
$rebootcontrol = Module::isAvailable('rebootcontrol');
$data['rebootcontrol'] = $rebootcontrol;
if ($rebootcontrol) {
- $wol = Database::queryFirst("SELECT options FROM `reboot_scheduler` WHERE locationid = :id AND action = 'wol'", array('id' => $id));
- if ($wol !== false) {
- $data['wol'] = true;
- $data['wol-options'] = json_decode($wol['options']);
- }
- $sd = Database::queryFirst("SELECT options FROM `reboot_scheduler` WHERE locationid = :id AND action = 'sd'", array('id' => $id));
- if ($sd !== false) {
- $data['sd'] = true;
- $data['sd-options'] = json_decode($sd['options']);
- }
+ $res = Database::queryFirst("SELECT * FROM `reboot_scheduler` WHERE locationid = :id", array('id' => $id));
+ if ($res !== false) $data['scheduler-options'] = json_decode($res['options']);
}
echo Render::parse('ajax-opening-location', $data);
diff --git a/modules-available/locations/templates/ajax-opening-location.html b/modules-available/locations/templates/ajax-opening-location.html
index a2bb357d..b1aea2e2 100644
--- a/modules-available/locations/templates/ajax-opening-location.html
+++ b/modules-available/locations/templates/ajax-opening-location.html
@@ -128,14 +128,14 @@
<div class="row wol">
<div class="col-sm-4">
<div class="checkbox checkbox-inline">
- <input id="wol-check-{{id}}" name="wol" type="checkbox" {{#wol}}checked{{/wol}}>
+ <input id="wol-check-{{id}}" name="wol" type="checkbox" {{#scheduler-options.wol}}checked{{/scheduler-options.wol}}>
<label for="wol-check-{{id}}">{{lang_wakeonlan}}</label>
</div>
</div>
<div class="col-sm-8">
<div class="input-group">
<input disabled type="number" id="wol-offset-{{id}}" name="wol-offset" class="form-control"
- value="{{wol-options.wol-offset}}" placeholder="0" min="0" max="15">
+ value="{{scheduler-options.wol-offset}}" placeholder="0" min="0" max="15">
<span class="input-group-addon slx-ga2">
<label for="wol-offset-{{id}}">{{lang_offsetEarly}}</label>
</span>
@@ -145,14 +145,14 @@
<div class="row shutdown">
<div class="col-sm-4">
<div class="checkbox checkbox-inline">
- <input id="sd-check-{{id}}" name="sd" type="checkbox" {{#sd}}checked{{/sd}}>
+ <input id="sd-check-{{id}}" name="sd" type="checkbox" {{#scheduler-options.sd}}checked{{/scheduler-options.sd}}>
<label for="sd-check-{{id}}">{{lang_shutdown}}</label>
</div>
</div>
<div class="col-sm-8">
<div class="input-group">
<input disabled type="number" id="sd-offset-{{id}}" name="sd-offset" class="form-control"
- value="{{sd-options.sd-offset}}" placeholder="0" min="0" max="15">
+ value="{{scheduler-options.sd-offset}}" placeholder="0" min="0" max="15">
<span class="input-group-addon slx-ga2">
<label for="sd-offset-{{id}}">{{lang_offsetLate}}</label>
</span>
diff --git a/modules-available/rebootcontrol/hooks/cron.inc.php b/modules-available/rebootcontrol/hooks/cron.inc.php
index 3651c779..9c6cbaaf 100644
--- a/modules-available/rebootcontrol/hooks/cron.inc.php
+++ b/modules-available/rebootcontrol/hooks/cron.inc.php
@@ -14,10 +14,11 @@ if (in_array((int)date('G'), [6, 7, 9, 12, 15]) && in_array(date('i'), ['00', '0
$now = time();
$res = Database::simpleQuery("SELECT * FROM reboot_scheduler WHERE nextexecution < :now", ['now' => $now]);
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $options = json_decode($row['options'], true);
// Calculate next_execution for the event.
$location = Database::queryFirst("SELECT openingtime FROM `location` WHERE locationid = :lid", array('lid' => $row['locationid']));
- Scheduler::updateSchedule($row['locationid'], $row['action'], $row['options'], $location['openingtime']);
+ Scheduler::updateSchedule($row['locationid'], $options, $location['openingtime']);
if ($row['nextexecution'] + 1200 < $now) continue;
@@ -27,10 +28,9 @@ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
settype($machine['locationid'], 'int');
$machines[] = $machine;
}
- // Options not yet used.
- $options = json_decode($row['options']);
if ($row['action'] === 'sd') RebootControl::execute($machines, RebootControl::SHUTDOWN, 0);
else if ($row['action'] === 'wol') RebootControl::wakeMachines($machines);
+ else if ($row['action'] === 'rb') RebootControl::execute($machines, RebootControl::REBOOT, 0);
}
/*
diff --git a/modules-available/rebootcontrol/inc/scheduler.inc.php b/modules-available/rebootcontrol/inc/scheduler.inc.php
index 27a22646..0928d20f 100644
--- a/modules-available/rebootcontrol/inc/scheduler.inc.php
+++ b/modules-available/rebootcontrol/inc/scheduler.inc.php
@@ -3,63 +3,97 @@
class Scheduler
{
- public static function updateSchedule($locationid, $action, $options, $openingTimes) {
+ public static function updateSchedule($locationid, $options, $openingTimes) {
if ($openingTimes == '') {
- self::deleteSchedule($locationid, $action);
+ self::deleteSchedule($locationid);
return false;
}
- $nextexec = self::calcNextexec($action, $options, $openingTimes);
+ $nextexec = self::calculateNext($options, $openingTimes);
$json_options = json_encode($options);
- self::upsert($locationid, $action, $nextexec, $json_options);
+ if ($nextexec !== false) self::upsert($locationid, $nextexec['action'], $nextexec['time'], $json_options);
+ else {
+ // All times are getting ignored because they are within 5 minutes of each other, delete possible db entries.
+ self::deleteSchedule($locationid);
+ }
return true;
}
- public static function deleteSchedule($locationid, $action) {
+ public static function deleteSchedule($locationid) {
Database::exec("DELETE FROM `reboot_scheduler`
- WHERE locationid = :lid AND action = :act", array(
- 'lid' => $locationid,
- 'act' => $action
- ));
+ WHERE locationid = :lid", array('lid' => $locationid));
}
- private static function calcNextexec($action, $options, $openingTimes) {
+ private static function calculateNext($options, $openingTimes) {
$openingTimes = json_decode($openingTimes, true);
- $now = time(); $times = [];
+ $now = time();
+ $openTimes = [];
+ $closeTimes = [];
foreach ($openingTimes as $row) {
- // Fetch hour and minutes of opening / closing time.
- $hourmin = explode(':', ($action == 'wol' ? $row['openingtime'] : $row['closingtime']));
- // Calculate time based on offset.
- $min = ($action == 'wol' ? $hourmin[0] * 60 + $hourmin[1] - $options['wol-offset'] : $hourmin[0] * 60 + $hourmin[1] + $options['sd-offset']);
- // Calculate opening / closing time of each day.
+ if (!$options['wol'] && !$options['sd']) continue;
+ if ($options['wol']) {
+ $open = explode(':', $row['openingtime']);
+ $openTime = $open[0] * 60 + $open[1] - $options['wol-offset'];
+ }
+ if ($options['sd']) {
+ $close = explode(':', $row['closingtime']);
+ $closeTime = $close[0] * 60 + $close[1] + $options['sd-offset'];
+ }
foreach ($row['days'] as $day) {
- $next = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $min . ' minutes')));
- if ($next < $now) {
- $times[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $min . ' minutes')));
- } else {
- $times[] = $next;
+ if ($options['wol']) {
+ $nextOpen = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $openTime . ' minutes')));
+ if ($nextOpen < $now) $openTimes[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $openTime . ' minutes')));
+ else $openTimes[] = $nextOpen;
+ }
+ if ($options['sd']) {
+ $nextClose = strtotime(date('Y-m-d H:i', strtotime($day . ' ' . $closeTime . ' minutes')));
+ if ($nextClose < $now) $closeTimes[] = strtotime(date('Y-m-d H:i', strtotime('next '.$day . ' ' . $closeTime . ' minutes')));
+ else $closeTimes[] = $nextClose;
}
}
}
- // Iterate over days, use timestamp with smallest difference to now.
- $res = 0; $smallestDiff = 0;
- foreach ($times as $time) {
- $diff = $time - $now;
- if ($res == 0 || $diff < $smallestDiff) {
- $smallestDiff = $diff;
- $res = $time;
+
+ sort($openTimes);
+ sort($closeTimes);
+ $res = array();
+
+ if ($options['wol'] && !$options['sd']) {
+ $res['action'] = 'wol';
+ $res['time'] = $openTimes[0];
+ return $res;
+ } else if ($options['sd'] && !$options['wol']) {
+ $res['action'] = 'sd';
+ $res['time'] = $closeTimes[0];
+ return $res;
+ }
+
+ for ($i = 0; $i <= sizeof($openTimes); $i++) {
+ if (abs($openTimes[$i] - $closeTimes[$i]) < 300) {
+ // If difference is < 5 min, ignore both events.
+ continue;
+ } else if (abs($openTimes[$i] - $closeTimes[$i]) < 900) {
+ // If difference is < 15 min, reboot at the earlier time.
+ $res['action'] = 'rb';
+ $res['time'] = $openTimes[$i] < $closeTimes[$i] ? $openTimes[$i] : $closeTimes[$i];
+ } else {
+ // Use first event.
+ if ($openTimes[$i] < $closeTimes[$i]) {
+ $res['action'] = 'wol';
+ $res['time'] = $openTimes[$i];
+ } else {
+ $res['action'] = 'sd';
+ $res['time'] =$closeTimes[$i];
+ }
}
+ return $res;
}
- return $res;
+ return false;
}
-
-
private static function upsert($locationid, $action, $nextexec, $options) {
- $schedule = Database::queryFirst("SELECT locationid, action
+ $schedule = Database::queryFirst("SELECT locationid
FROM `reboot_scheduler`
- WHERE locationid = :lid AND action = :act", array(
- 'lid' => $locationid,
- 'act' => $action
+ WHERE locationid = :lid", array(
+ 'lid' => $locationid
));
if ($schedule === false) {
Database::exec("INSERT INTO `reboot_scheduler` (locationid, action, nextexecution, options)
@@ -71,12 +105,12 @@ class Scheduler
));
} else {
Database::exec("UPDATE `reboot_scheduler`
- SET nextexecution = :next, options = :opt
- WHERE locationid = :lid AND action = :act", array(
+ SET action = :act, nextexecution = :next, options = :opt
+ WHERE locationid = :lid", array(
+ 'act' => $action,
'next' => $nextexec,
'opt' => $options,
- 'lid' => $locationid,
- 'act' => $action
+ 'lid' => $locationid
));
}
return true;
diff --git a/modules-available/rebootcontrol/install.inc.php b/modules-available/rebootcontrol/install.inc.php
index 7d4382d0..008d26aa 100644
--- a/modules-available/rebootcontrol/install.inc.php
+++ b/modules-available/rebootcontrol/install.inc.php
@@ -55,4 +55,13 @@ $output[] = tableAddConstraint('reboot_subnet_x_subnet', 'dstid', 'reboot_subnet
$output[] = tableAddConstraint('reboot_scheduler', 'locationid', 'location', 'locationid',
'ON UPDATE CASCADE ON DELETE CASCADE');
+if (tableExists('reboot_scheduler')) {
+ Database::exec("ALTER TABLE `reboot_scheduler` DROP PRIMARY KEY , ADD PRIMARY KEY (`locationid`)");
+}
+if (tableHasColumn('reboot_scheduler', 'action')) {
+ Database::exec("ALTER TABLE `reboot_scheduler` MODIFY COLUMN `action` ENUM('wol', 'sd', 'rb')");
+}
+
+
+
responseFromArray($output); \ No newline at end of file