+ {{#runmode}}
+
+ {{/runmode}}
--
cgit v1.2.3-55-g7522
From 21029582421912659e090ce6ab958846aa31a709 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Thu, 30 Nov 2017 14:27:01 +0100
Subject: [statistics] Update translations
---
modules-available/statistics/lang/de/messages.json | 4 ++--
modules-available/statistics/lang/de/template-tags.json | 5 ++++-
modules-available/statistics/lang/en/messages.json | 4 ++--
modules-available/statistics/lang/en/template-tags.json | 5 ++++-
4 files changed, 12 insertions(+), 6 deletions(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/statistics/lang/de/messages.json b/modules-available/statistics/lang/de/messages.json
index 8bdf9cfc..e3dff61c 100644
--- a/modules-available/statistics/lang/de/messages.json
+++ b/modules-available/statistics/lang/de/messages.json
@@ -1,6 +1,6 @@
{
- "invalid-filter": "Ung\u00fcltiger Filter",
"invalid-filter-argument": "Das Argument {{1}} ist nicht g\u00fcltig f\u00fcr den Filter {{0}}",
"invalid-filter-key": "{{0}} ist kein g\u00fcltiges Filterkriterium",
- "notes-saved": "Anmerkungen gespeichert"
+ "notes-saved": "Anmerkungen gespeichert",
+ "unknown-machine": "Unbekannte Rechner-ID {{0}}"
}
\ No newline at end of file
diff --git a/modules-available/statistics/lang/de/template-tags.json b/modules-available/statistics/lang/de/template-tags.json
index 02c3e4d6..c755db7a 100644
--- a/modules-available/statistics/lang/de/template-tags.json
+++ b/modules-available/statistics/lang/de/template-tags.json
@@ -37,6 +37,7 @@
"lang_machineOccupied": "Der Rechner ist eingeschaltet und wird benutzt",
"lang_machineOccupiedBy": "In Verwendung durch",
"lang_machineOff": "Der Rechner ist ausgeschaltet, oder hat kein bwLehrpool gebootet",
+ "lang_machineStandby": "Im Standby",
"lang_machineSummary": "Zusammenfassung",
"lang_maximumAbbrev": "Max.",
"lang_memoryStats": "Arbeitsspeicher",
@@ -64,6 +65,8 @@
"lang_ramSlots": "Speicher-Slots",
"lang_realCores": "Kerne",
"lang_reallocatedSectors": "Defekte Sektoren",
+ "lang_runMode": "Betriebsmodus",
+ "lang_runmodeMachines": "Mit besonderem Betriebsmodus",
"lang_screens": "Bildschirme",
"lang_serialNo": "Serien-Nr",
"lang_showList": "Liste",
@@ -82,4 +85,4 @@
"lang_virtualCores": "Virtuelle Kerne",
"lang_when": "Wann",
"lang_withBadSectors": "Clients mit potentiell defekten Festplatten (mehr als 10 defekte Sektoren)"
-}
+}
\ No newline at end of file
diff --git a/modules-available/statistics/lang/en/messages.json b/modules-available/statistics/lang/en/messages.json
index 40eac8c9..ae6c47af 100644
--- a/modules-available/statistics/lang/en/messages.json
+++ b/modules-available/statistics/lang/en/messages.json
@@ -1,6 +1,6 @@
{
- "invalid-filter": "Invalid filter",
"invalid-filter-argument": "{{1}} is not a vald argument for filter {{0}}",
"invalid-filter-key": "{{0}} is not a valid filter",
- "notes-saved": "Notes have been saved"
+ "notes-saved": "Notes have been saved",
+ "unknown-machine": "Unknown machine uuid {{0}}"
}
\ No newline at end of file
diff --git a/modules-available/statistics/lang/en/template-tags.json b/modules-available/statistics/lang/en/template-tags.json
index c097ce37..25847fc5 100644
--- a/modules-available/statistics/lang/en/template-tags.json
+++ b/modules-available/statistics/lang/en/template-tags.json
@@ -37,6 +37,7 @@
"lang_machineOccupied": "Machine is powered on and in use",
"lang_machineOccupiedBy": "In use by",
"lang_machineOff": "Machine is powered down, or is not running bwLehrpool",
+ "lang_machineStandby": "In standby mode",
"lang_machineSummary": "Summary",
"lang_maximumAbbrev": "max.",
"lang_memoryStats": "Memory",
@@ -64,6 +65,8 @@
"lang_ramSlots": "Memory slots",
"lang_realCores": "Cores",
"lang_reallocatedSectors": "Bad sectors",
+ "lang_runMode": "Mode of operation",
+ "lang_runmodeMachines": "With special mode of operation",
"lang_screens": "Screens",
"lang_serialNo": "Serial no",
"lang_showList": "Show list",
@@ -82,4 +85,4 @@
"lang_virtualCores": "Virtual cores",
"lang_when": "When",
"lang_withBadSectors": "Clients with potentially bad HDDs (more than 10 reallocated sectors)"
-}
+}
\ No newline at end of file
--
cgit v1.2.3-55-g7522
From 2f9e87811a21f37f1fa6b5da773ae007ae6e4648 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Thu, 30 Nov 2017 15:02:34 +0100
Subject: [statistics] Reset session name on login to vmchooser
---
modules-available/statistics/api.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index d75f4af8..7b5678de 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -211,7 +211,7 @@ if ($type{0} === '~') {
$params['user'] = Request::post('user', null, 'string');
$res = Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(),'
. $strUpdateBoottime
- . " logintime = UNIX_TIMESTAMP(), currentuser = :user, state = 'OCCUPIED' "
+ . " logintime = UNIX_TIMESTAMP(), currentuser = :user, currentsession = NULL, state = 'OCCUPIED' "
. " WHERE machineuuid = :uuid AND lastseen = :oldlastseen AND state = :oldstate", $params);
} else {
$res = 0;
--
cgit v1.2.3-55-g7522
From b90c97b1f096008b5fa9abf8c50a120a85c47a4e Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Thu, 30 Nov 2017 18:30:01 +0100
Subject: [roomplanner] Refactor to use runmode
---
.idea/inspectionProfiles/Project_Default.xml | 21 +++++++++
modules-available/locations/inc/location.inc.php | 25 +++++++++++
.../roomplanner/inc/pvsgenerator.inc.php | 35 ++++++++++++++-
modules-available/roomplanner/install.inc.php | 43 ++++++++++++------
modules-available/roomplanner/page.inc.php | 36 ++++++++++++---
modules-available/runmode/inc/runmode.inc.php | 23 ++++++++++
modules-available/runmode/page.inc.php | 21 +++++++--
modules-available/statistics/inc/machine.inc.php | 5 +++
.../statistics/inc/statistics.inc.php | 51 ++++++++++++++++++----
9 files changed, 226 insertions(+), 34 deletions(-)
(limited to 'modules-available/statistics')
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index a50453af..b86f71cc 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,9 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php
index 476f4c68..0576e660 100644
--- a/modules-available/locations/inc/location.inc.php
+++ b/modules-available/locations/inc/location.inc.php
@@ -37,6 +37,11 @@ class Location
return Database::queryFirst("SELECT * FROM location WHERE locationid = :locationId", compact('locationId'));
}
+ /**
+ * Get name of location
+ * @param int $locationId id of location to get name for
+ * @return string|false Name of location, false if locationId doesn't exist
+ */
public static function getName($locationId)
{
self::getLocationsAssoc();
@@ -46,6 +51,26 @@ class Location
return self::$assocLocationCache[$locationId]['locationname'];
}
+ /**
+ * Get all the names of the given location and its parents, up
+ * to the root element. Array keys will be locationids, value the names.
+ * @param int $locationId
+ * @return array|false locations, from furthest to nearest or false if locationId doesn't exist
+ */
+ public static function getNameChain($locationId)
+ {
+ self::getLocationsAssoc();
+ settype($locationId, 'int');
+ if (!isset(self::$assocLocationCache[$locationId]))
+ return false;
+ $ret = array();
+ while (isset(self::$assocLocationCache[$locationId])) {
+ $ret[$locationId] = self::$assocLocationCache[$locationId]['locationname'];
+ $locationId = self::$assocLocationCache[$locationId]['parentlocationid'];
+ }
+ return array_reverse($ret, true);
+ }
+
public static function getLocationsAssoc()
{
if (self::$assocLocationCache === false) {
diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php
index d61e826b..43285057 100644
--- a/modules-available/roomplanner/inc/pvsgenerator.inc.php
+++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php
@@ -189,7 +189,7 @@ class PvsGenerator
private static function boundingBox($grid, &$minX, &$minY, &$maxX, &$maxY)
{
- $minX = PHP_INT_MAX; /* PHP_INT_MIN is only avaiable since PHP 7 */
+ $minX = PHP_INT_MAX; /* PHP_INT_MIN is only available since PHP 7 */
$maxX = ~PHP_INT_MAX;
$minY = PHP_INT_MAX;
$maxY = ~PHP_INT_MAX;
@@ -202,4 +202,37 @@ class PvsGenerator
}
}
+ public static function runmodeConfigHook($machineUuid, $locationId, $data)
+ {
+ if (!empty($data)) {
+ $data = json_decode($data, true);
+ }
+ if (!is_array($data)) {
+ $data = array();
+ }
+ ConfigHolder::add("SLX_PVS_CONFIG_URL", 'http://' . $_SERVER['SERVER_ADDR'] . $_SERVER['SCRIPT_NAME'] . '?do=roomplanner');
+
+ if (isset($data['dedicatedmgr']) && $data['dedicatedmgr']) {
+ ConfigHolder::add("SLX_ADDONS", false, 100000);
+ ConfigHolder::add("SLX_PVS_DEDICATED", 'yes');
+ ConfigHolder::add("SLX_EXAM", false, 100000);
+ //ConfigHolder::add("SLX_SYSTEMD_TARGET", 'pvs-dedicated', 100000);
+ } else {
+ ConfigHolder::add("SLX_PVS_HYBRID", 'yes');
+ }
+ }
+
+ /**
+ * Get display name for manager of given locationId.
+ * @param $locationId
+ * @return bool|string
+ */
+ public static function getManagerName($locationId)
+ {
+ $names = Location::getNameChain($locationId);
+ if ($names === false)
+ return false;
+ return implode(' / ', $names);
+ }
+
}
diff --git a/modules-available/roomplanner/install.inc.php b/modules-available/roomplanner/install.inc.php
index a6d98384..13365fe1 100644
--- a/modules-available/roomplanner/install.inc.php
+++ b/modules-available/roomplanner/install.inc.php
@@ -6,7 +6,6 @@ $res = array();
$res[] = tableCreate('location_roomplan', "
`locationid` INT(11) NOT NULL,
`managerip` varchar(45) CHARACTER SET ascii DEFAULT '',
- `dedicatedmgr` tinyint(1) NOT NULL DEFAULT 0,
`tutoruuid` char(36) CHARACTER SET ascii DEFAULT NULL,
`roomplan` BLOB DEFAULT NULL,
PRIMARY KEY (`locationid`),
@@ -29,24 +28,40 @@ if (!tableHasColumn('location_roomplan', 'tutoruuid')) {
}
$res[] = UPDATE_DONE;
}
-if (!tableHasColumn('location_roomplan', 'dedicatedmgr')) {
- $ret = Database::exec("ALTER TABLE `location_roomplan` ADD `dedicatedmgr` tinyint(1) NOT NULL DEFAULT 0 AFTER `managerip`") !== false;
- if ($ret === false) {
- finalResponse(UPDATE_FAILED, 'Adding dedicatedmgr to location_roomplan failed: ' . Database::lastError());
- }
- $res[] = UPDATE_DONE;
-}
if (in_array(UPDATE_DONE, $res)) {
Database::exec("ALTER TABLE `location_roomplan`
- ADD CONSTRAINT `location_roomplan_ibfk_1` FOREIGN KEY (`locationid`) REFERENCES `location` (`locationid`) ON DELETE CASCADE");
+ ADD CONSTRAINT `location_roomplan_ibfk_1` FOREIGN KEY (`locationid`) REFERENCES `location` (`locationid`) ON DELETE CASCADE");
Database::exec("ALTER TABLE `location_roomplan`
- ADD CONSTRAINT `location_roomplan_ibfk_2` FOREIGN KEY (`tutoruuid`) REFERENCES `machine` (`machineuuid`) ON DELETE SET NULL ON UPDATE CASCADE");
+ ADD CONSTRAINT `location_roomplan_ibfk_2` FOREIGN KEY (`tutoruuid`) REFERENCES `machine` (`machineuuid`) ON DELETE SET NULL ON UPDATE CASCADE");
}
-if (in_array(UPDATE_DONE, $res)) {
- finalResponse(UPDATE_DONE, 'Table created successfully');
+// 2017-11-30: Refactor to runmode
+// managerip, dedicatedmgr, --> runmode
+if (tableHasColumn('location_roomplan', 'dedicatedmgr')) {
+ if (!tableExists('runmode') || !tableExists('machine')) {
+ $res[] = UPDATE_RETRY;
+ } else {
+ $ret = Database::simpleQuery('SELECT lr.locationid, lr.managerip, lr.dedicatedmgr, m.machineuuid
+ FROM location_roomplan lr INNER JOIN machine m ON (m.clientip = lr.managerip)');
+ if ($ret === false) {
+ $res[] = UPDATE_FAILED;
+ } else {
+ while ($row = $ret->fetch(PDO::FETCH_ASSOC)) {
+ $dedi = $row['dedicatedmgr'] != 0;
+ $data = json_encode(array('dedicatedmgr' => $dedi));
+ Database::exec("INSERT IGNORE INTO runmode (machineuuid, module, modeid, modedata, isclient)
+ VALUES (:machineuuid, 'roomplanner', :locationid, :modedata, :isclient)", array(
+ 'machineuuid' => $row['machineuuid'],
+ 'locationid' => $row['locationid'],
+ 'modedata' => $data,
+ 'isclient' => ($dedi ? 0 : 1)
+ ));
+ }
+ Database::exec('ALTER TABLE location_roomplan DROP COLUMN dedicatedmgr');
+ $res[] = UPDATE_DONE;
+ }
+ }
}
-finalResponse(UPDATE_NOOP, 'Everything already up to date');
-
+responseFromArray($res);
diff --git a/modules-available/roomplanner/page.inc.php b/modules-available/roomplanner/page.inc.php
index 4e36d3ba..71499caf 100644
--- a/modules-available/roomplanner/page.inc.php
+++ b/modules-available/roomplanner/page.inc.php
@@ -58,7 +58,17 @@ class Page_Roomplanner extends Page
if ($this->action === 'show') {
/* do nothing */
Dashboard::disable();
- $config = Database::queryFirst('SELECT roomplan, managerip, dedicatedmgr, tutoruuid FROM location_roomplan WHERE locationid = :locationid', ['locationid' => $this->locationid]);
+ $config = Database::queryFirst('SELECT roomplan, managerip, tutoruuid FROM location_roomplan WHERE locationid = :locationid', ['locationid' => $this->locationid]);
+ $runmode = RunMode::getForMode(Page::getModule(), $this->locationid, true);
+ if (empty($runmode)) {
+ $config['dedicatedmgr'] = false;
+ } else {
+ $runmode = array_pop($runmode);
+ $config['managerip'] = $runmode['clientip'];
+ $config['manageruuid'] = $runmode['machineuuid'];
+ $data = json_decode($runmode['modedata'], true);
+ $config['dedicatedmgr'] = (isset($data['dedicatedmgr']) && $data['dedicatedmgr']);
+ }
if ($config !== false) {
$managerIp = $config['managerip'];
$dediMgr = $config['dedicatedmgr'] ? 'checked' : '';
@@ -207,16 +217,30 @@ class Page_Roomplanner extends Page
protected function saveRoomConfig($furniture, $tutorUuid)
{
$obj = json_encode(['furniture' => $furniture]);
- Database::exec('INSERT INTO location_roomplan (locationid, roomplan, managerip, tutoruuid, dedicatedmgr)'
- . ' VALUES (:locationid, :roomplan, :managerip, :tutoruuid, :dedicatedmgr)'
+ $managerIp = Request::post('managerip', '', 'string');
+ Database::exec('INSERT INTO location_roomplan (locationid, roomplan, managerip, tutoruuid)'
+ . ' VALUES (:locationid, :roomplan, :managerip, :tutoruuid)'
. ' ON DUPLICATE KEY UPDATE '
- . ' roomplan=VALUES(roomplan), managerip=VALUES(managerip), tutoruuid=VALUES(tutoruuid), dedicatedmgr=VALUES(dedicatedmgr)', [
+ . ' roomplan=VALUES(roomplan), managerip=VALUES(managerip), tutoruuid=VALUES(tutoruuid)', [
'locationid' => $this->locationid,
'roomplan' => $obj,
- 'managerip' => Request::post('managerip', '', 'string'),
- 'dedicatedmgr' => (Request::post('dedimgr') === 'on' ? 1 : 0),
+ 'managerip' => $managerIp,
'tutoruuid' => $tutorUuid
]);
+ // See if the client is known, set run-mode
+ if (empty($managerIp)) {
+ RunMode::deleteMode(Page::getModule(), $this->locationid);
+ } else {
+ RunMode::deleteMode(Page::getModule(), $this->locationid);
+ $pc = Statistics::getMachinesByIp($managerIp, Machine::NO_DATA, 'lastseen DESC');
+ if (!empty($pc)) {
+ $dedicated = (Request::post('dedimgr') === 'on');
+ $pc = array_shift($pc);
+ RunMode::setRunMode($pc->machineuuid, Page::getModule()->getIdentifier(), $this->locationid, json_encode([
+ 'dedicatedmgr' => $dedicated
+ ]), !$dedicated);
+ }
+ }
}
protected function getFurniture($config)
diff --git a/modules-available/runmode/inc/runmode.inc.php b/modules-available/runmode/inc/runmode.inc.php
index 59f8cf01..50ae2d72 100644
--- a/modules-available/runmode/inc/runmode.inc.php
+++ b/modules-available/runmode/inc/runmode.inc.php
@@ -36,6 +36,9 @@ class RunMode
*/
public static function setRunMode($machineuuid, $moduleId, $modeId, $modeData = null, $isClient = null)
{
+ if (is_object($moduleId)) {
+ $moduleId = $moduleId->getIdentifier();
+ }
// - Check if machine exists
$machine = Statistics::getMachine($machineuuid, Machine::NO_DATA);
if ($machine === false)
@@ -196,6 +199,21 @@ class RunMode
return call_user_func($conf->getModeName, $modeId);
}
+ /**
+ * Delete given runmode.
+ *
+ * @param string|\Module $module Module runmode belongs to
+ * @param string $modeId run mode id
+ */
+ public static function deleteMode($module, $modeId)
+ {
+ if (is_object($module)) {
+ $module = $module->getIdentifier();
+ }
+ Database::exec('DELETE FROM runmode WHERE module = :module AND modeid = :modeId',
+ compact('module', 'modeId'));
+ }
+
}
/* *\
@@ -235,6 +253,10 @@ class RunModeModuleConfig
* @var bool If true, config.tgz should not be downloaded by the client
*/
public $noSysconfig = false;
+ /**
+ * @var bool Allow adding and removing machines to this mode via the generic form
+ */
+ public $allowGenericEditor = true;
public function __construct($file)
{
@@ -248,6 +270,7 @@ class RunModeModuleConfig
$this->loadType($data, 'configHook', 'string');
$this->loadType($data, 'isClient', 'boolean');
$this->loadType($data, 'noSysconfig', 'boolean');
+ $this->loadType($data, 'allowGenericEditor', 'boolean');
}
private function loadType($data, $key, $type)
diff --git a/modules-available/runmode/page.inc.php b/modules-available/runmode/page.inc.php
index 24566cec..ef42e7be 100644
--- a/modules-available/runmode/page.inc.php
+++ b/modules-available/runmode/page.inc.php
@@ -26,20 +26,33 @@ class Page_RunMode extends Page
$machines = array_filter(Request::post('machines', [], 'array'), 'is_string');
$module = Request::post('module', false, 'string');
$modeId = Request::post('modeid', false, 'string');
- // TODO Validate
+ $modConfig = RunMode::getModuleConfig($module);
+ if ($modConfig === false) {
+ Message::addError('module-hasnt-runmode', $module);
+ return;
+ }
+ if (!$modConfig->allowGenericEditor) {
+ Message::addError('cannot-edit-module', $module);
+ return;
+ }
+ $test = RunMode::getModeName($module, $modeId);
+ if ($test === false) {
+ Message::addError('invalid-modeid', $module, $modeId);
+ return;
+ }
$active = 0;
foreach ($machines as $machine) {
$ret = RunMode::setRunMode($machine, $module, $modeId, null, null);
if ($ret) {
$active++;
} else {
- Message::addError('invalid-module-or-machine', $module, $machine);
+ Message::addError('runmode.machine-not-found', $machine);
}
}
$deleted = Database::exec('DELETE FROM runmode
WHERE module = :module AND modeid = :modeId AND machineuuid NOT IN (:machines)',
compact('module', 'modeId', 'machines'));
- Message::addError('enabled-removed-save', $active, $deleted);
+ Message::addSuccess('runmode.enabled-removed-save', $active, $deleted);
$redirect = Request::post('redirect', false, 'string');
if ($redirect !== false) {
Util::redirect($redirect);
@@ -141,7 +154,7 @@ class Page_RunMode extends Page
$moduleId = $module->getIdentifier();
$modeName = RunMode::getModeName($moduleId, $modeId);
if ($modeName === false) {
- Message::addError('invalid-modeid', $modeId);
+ Message::addError('invalid-modeid', $moduleId, $modeId);
Util::redirect('?do=runmode');
}
Render::addTemplate('machine-selector', [
diff --git a/modules-available/statistics/inc/machine.inc.php b/modules-available/statistics/inc/machine.inc.php
index 8cb5e884..8605749b 100644
--- a/modules-available/statistics/inc/machine.inc.php
+++ b/modules-available/statistics/inc/machine.inc.php
@@ -50,6 +50,11 @@ class Machine
*/
public $logintime;
+ /**
+ * @var string state of machine (OFFLINE, IDLE, OCCUPIED, STANDBY)
+ */
+ public $state;
+
/**
* @var string json data of position inside room (if any), null/empty otherwise
*/
diff --git a/modules-available/statistics/inc/statistics.inc.php b/modules-available/statistics/inc/statistics.inc.php
index 1c9ebf07..2500f16f 100644
--- a/modules-available/statistics/inc/statistics.inc.php
+++ b/modules-available/statistics/inc/statistics.inc.php
@@ -7,17 +7,12 @@ class Statistics
private static $machineFields = false;
- /**
- * @param string $machineuuid
- * @param int $returnData
- * @return \Machine|false
- */
- public static function getMachine($machineuuid, $returnData)
+ private static function initFields($returnData)
{
if (self::$machineFields === false) {
$r = new ReflectionClass('Machine');
$props = $r->getProperties(ReflectionProperty::IS_PUBLIC);
- self::$machineFields = array_flip(array_map(function($e) { return $e->getName(); }, $props));
+ self::$machineFields = array_flip(array_map(function(/* @var ReflectionProperty $e */ $e) { return $e->getName(); }, $props));
}
if ($returnData === Machine::NO_DATA) {
unset(self::$machineFields['data']);
@@ -26,8 +21,19 @@ class Statistics
} else {
Util::traceError('Invalid $returnData option passed');
}
- $fields = implode(',', array_keys(self::$machineFields));
- $row = Database::queryFirst("SELECT * FROM machine WHERE machineuuid = :machineuuid", compact('machineuuid'));
+ return implode(',', array_keys(self::$machineFields));
+ }
+
+ /**
+ * @param string $machineuuid
+ * @param int $returnData What kind of data to return Machine::NO_DATA, Machine::RAW_DATA, ...
+ * @return \Machine|false
+ */
+ public static function getMachine($machineuuid, $returnData)
+ {
+ $fields = self::initFields($returnData);
+
+ $row = Database::queryFirst("SELECT $fields FROM machine WHERE machineuuid = :machineuuid", compact('machineuuid'));
if ($row === false)
return false;
$m = new Machine();
@@ -37,4 +43,31 @@ class Statistics
return $m;
}
+ /**
+ * @param string $ip
+ * @param int $returnData What kind of data to return Machine::NO_DATA, Machine::RAW_DATA, ...
+ * @param string $sort something like 'lastseen ASC' - not sanitized, don't pass user input!
+ * @return \Machine[] list of matches
+ */
+ public static function getMachinesByIp($ip, $returnData, $sort = false)
+ {
+ $fields = self::initFields($returnData);
+
+ if ($sort === false) {
+ $sort = '';
+ } else {
+ $sort = "ORDER BY $sort";
+ }
+ $res = Database::simpleQuery("SELECT $fields FROM machine WHERE clientip = :ip $sort", compact('ip'));
+ $list = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $m = new Machine();
+ foreach ($row as $key => $val) {
+ $m->{$key} = $val;
+ }
+ $list[] = $m;
+ }
+ return $list;
+ }
+
}
--
cgit v1.2.3-55-g7522
From 5c23e7d7e1c9ade9755c530c9320ad7e5b463413 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Fri, 1 Dec 2017 12:30:23 +0100
Subject: [statistics, roomplanner, locationinfo] Ignore machines with
runmode:isclient==0
---
modules-available/locationinfo/inc/infopanel.inc.php | 10 +++++++++-
modules-available/roomplanner/inc/pvsgenerator.inc.php | 13 +++++++++++--
modules-available/statistics/api.inc.php | 1 -
modules-available/statistics/hooks/cron.inc.php | 11 ++++++++---
4 files changed, 28 insertions(+), 7 deletions(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php
index dacf860f..aa4741ee 100644
--- a/modules-available/locationinfo/inc/infopanel.inc.php
+++ b/modules-available/locationinfo/inc/infopanel.inc.php
@@ -83,6 +83,12 @@ class InfoPanel
$idList = array_keys($array);
}
+ $ignoreList = array();
+ if (Module::isAvailable('runmode')) {
+ // Ignore clients with special runmode not marked as still being a client
+ $ignoreList = RunMode::getAllClients(false, true);
+ }
+
$positionCol = $withPosition ? 'm.position,' : '';
$query = "SELECT m.locationid, m.machineuuid, $positionCol m.logintime, m.lastseen, m.lastboot, m.state FROM machine m
WHERE m.locationid IN (:idlist)";
@@ -90,6 +96,8 @@ class InfoPanel
// Iterate over matching machines
while ($row = $dbquery->fetch(PDO::FETCH_ASSOC)) {
+ if (isset($ignoreList[$row['machineuuid']]))
+ continue;
settype($row['locationid'], 'int');
if (!isset($array[$row['locationid']])) {
$array[$row['locationid']] = array('id' => $row['locationid'], 'machines' => array());
@@ -219,4 +227,4 @@ class InfoPanel
return $result;
}
-}
\ No newline at end of file
+}
diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php
index 6dc9b648..6df7c10e 100644
--- a/modules-available/roomplanner/inc/pvsgenerator.inc.php
+++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php
@@ -54,9 +54,18 @@ class PvsGenerator
/* collect names and build room blocks - filter empty rooms while at it */
$roomNames = array();
$roomBlocks = '';
+ $overrides = [];
foreach ($rooms as $room) {
- if (is_null($room['notnull']) || isset($room['skip']) // Not leaf
- || empty($room['managerip'])) // rooms without managerips don't make sense
+ if (is_null($room['notnull']) || isset($room['skip'])) // Not leaf
+ continue;
+ if (Module::isAvailable('runmode')) {
+ $pc = RunMode::getForMode('roomplanner', $room['locationid']);
+ if (!empty($pc)) {
+ $pc = array_pop($pc);
+ $room['managerip'] = $pc['clientip'];
+ }
+ }
+ if (empty($room['managerip'])) // rooms without managerips don't make sense
continue;
$roomBlock = PvsGenerator::generateRoomBlock($room);
if ($roomBlock === false)
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index 7b5678de..a614658a 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -79,7 +79,6 @@ if ($type{0} === '~') {
'id44mb' => $id44mb,
'badsectors' => $badsectors,
'data' => $data,
- 'hostname' => $hostname,
'state' => 'IDLE',
);
// Create/update machine entry
diff --git a/modules-available/statistics/hooks/cron.inc.php b/modules-available/statistics/hooks/cron.inc.php
index eb88173d..4df7b0d4 100644
--- a/modules-available/statistics/hooks/cron.inc.php
+++ b/modules-available/statistics/hooks/cron.inc.php
@@ -4,9 +4,14 @@ function logstats()
{
$NOW = time();
$cutoff = $NOW - 86400 * 30;
- $known = Database::queryFirst("SELECT Count(*) AS val FROM machine WHERE lastseen > $cutoff");
- $on = Database::queryFirst("SELECT Count(*) AS val FROM machine WHERE state IN ('IDLE', 'OCCUPIED')");
- $used = Database::queryFirst("SELECT Count(*) AS val FROM machine WHERE state = 'OCCUPIED'");
+ $join = $where = '';
+ if (Module::get('runmode') !== false) {
+ $join = 'LEFT JOIN runmode r USING (machineuuid)';
+ $where = 'AND (r.isclient IS NULL OR r.isclient <> 0)';
+ }
+ $known = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.lastseen > $cutoff $where");
+ $on = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.state IN ('IDLE', 'OCCUPIED') $where");
+ $used = Database::queryFirst("SELECT Count(*) AS val FROM machine m $join WHERE m.state = 'OCCUPIED' $where");
Database::exec("INSERT INTO statistic (dateline, typeid, clientip, username, data) VALUES (:now, '~stats', '', '', :vals)", array(
'now' => $NOW,
'vals' => $known['val'] . '#' . $on['val'] . '#' . $used['val'],
--
cgit v1.2.3-55-g7522
From cfd181a3ee8025ac39886a8ba422fefd8545fb2c Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Fri, 1 Dec 2017 23:07:06 +0100
Subject: [syslog, statistics] Pretty print time, shorten CPU model in list
---
modules-available/statistics/page.inc.php | 21 +++++++--------------
.../statistics/templates/clientlist.html | 2 +-
modules-available/syslog/page.inc.php | 10 +---------
3 files changed, 9 insertions(+), 24 deletions(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index d80d4614..fafa7cd2 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -555,7 +555,7 @@ class Page_Statistics extends Page
$row['hostname'] = $row['clientip'];
}
$row['firstseen_int'] = $row['firstseen'];
- $row['firstseen'] = date('d.m. H:i', $row['firstseen']);
+ $row['firstseen'] = Util::prettyTime($row['firstseen']);
$row['gbram'] = round(round($row['mbram'] / 500) / 2, 1); // Trial and error until we got "expected" rounding..
$row['gbtmp'] = round($row['id44mb'] / 1024);
$row['ramclass'] = $this->ramColorClass($row['mbram']);
@@ -601,10 +601,10 @@ class Page_Statistics extends Page
$singleMachine = false;
}
$row['state_' . $row['state']] = true;
- //$row['firstseen'] = date('d.m.Y H:i', $row['firstseen']);
+ //$row['firstseen'] = Util::prettyTime($row['firstseen']);
$row['lastseen_int'] = $row['lastseen'];
- $row['lastseen'] = date('d.m. H:i', $row['lastseen']);
- //$row['lastboot'] = date('d.m. H:i', $row['lastboot']);
+ $row['lastseen'] = Util::prettyTime($row['lastseen']);
+ //$row['lastboot'] = Util::prettyTime($row['lastboot']);
$row['gbram'] = round(round($row['mbram'] / 500) / 2, 1); // Trial and error until we got "expected" rounding..
$row['gbtmp'] = round($row['id44mb'] / 1024);
$octets = explode('.', $row['clientip']);
@@ -623,6 +623,7 @@ class Page_Statistics extends Page
$row['nohdd'] = true;
}
}
+ $row['cpumodel'] = preg_replace('/\(R\)|\(TM\)|\bintel\b|\bamd\b|\bcpu\b|dual-core|\bdual\s+core\b|\bdual\b|\bprocessor\b/i', ' ', $row['cpumodel']);
$rows[] = $row;
}
if ($singleMachine !== false && $singleMachine !== 'none') {
@@ -882,7 +883,7 @@ class Page_Statistics extends Page
$row['data'] -= ($cutoff - $row['dateline']);
$row['dateline'] = $cutoff;
}
- $row['from'] = date('d.m. H:i', $row['dateline']);
+ $row['from'] = Util::prettyTime($row['dateline']);
$row['duration'] = floor($row['data'] / 86400) . 'd ' . gmdate('H:i', $row['data']);
if ($row['typeid'] === '~offline-length') {
$row['glyph'] = 'off';
@@ -933,21 +934,13 @@ class Page_Statistics extends Page
if (Module::get('syslog') !== false) {
$lres = Database::simpleQuery('SELECT logid, dateline, logtypeid, clientip, description, extra FROM clientlog'
. ' WHERE machineuuid = :uuid ORDER BY logid DESC LIMIT 25', array('uuid' => $client['machineuuid']));
- $today = date('d.m.Y');
- $yesterday = date('d.m.Y', time() - 86400);
$count = 0;
$log = array();
while ($row = $lres->fetch(PDO::FETCH_ASSOC)) {
if (substr($row['description'], -5) === 'on :0' && strpos($row['description'], 'root logged') === false) {
continue;
}
- $day = date('d.m.Y', $row['dateline']);
- if ($day === $today) {
- $day = Dictionary::translate('lang_today');
- } elseif ($day === $yesterday) {
- $day = Dictionary::translate('lang_yesterday');
- }
- $row['date'] = $day . date(' H:i', $row['dateline']);
+ $row['date'] = Util::prettyTime($row['dateline']);
$row['icon'] = $this->eventToIconName($row['logtypeid']);
$log[] = $row;
if (++$count === 10) {
diff --git a/modules-available/statistics/templates/clientlist.html b/modules-available/statistics/templates/clientlist.html
index 0b6fb37f..01ca82f1 100644
--- a/modules-available/statistics/templates/clientlist.html
+++ b/modules-available/statistics/templates/clientlist.html
@@ -63,7 +63,7 @@
{{#rmmodule}}
{{/rmmodule}}
{{subnet}} {{lastoctet}} {{macaddr}}
-
{{lastseen}}
+
{{lastseen}}
{{kvmstate}}
{{gbram}} GiB
diff --git a/modules-available/syslog/page.inc.php b/modules-available/syslog/page.inc.php
index 927a3adf..c679877a 100644
--- a/modules-available/syslog/page.inc.php
+++ b/modules-available/syslog/page.inc.php
@@ -57,19 +57,11 @@ class Page_SysLog extends Page
$whereClause .= "machineuuid='" . preg_replace('/[^0-9a-zA-Z\-]/', '', Request::get('machineuuid', '', 'string')) . "'";
}
- $today = date('d.m.Y');
- $yesterday = date('d.m.Y', time() - 86400);
$lines = array();
$paginate = new Paginate("SELECT logid, dateline, logtypeid, clientip, description, extra FROM clientlog $whereClause ORDER BY logid DESC", 50);
$res = $paginate->exec();
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $day = date('d.m.Y', $row['dateline']);
- if ($day === $today) {
- $day = Dictionary::translate('lang_today');
- } elseif ($day === $yesterday) {
- $day = Dictionary::translate('lang_yesterday');
- }
- $row['date'] = $day . date(' H:i', $row['dateline']);
+ $row['date'] = Util::prettyTime($row['dateline']);
$row['icon'] = $this->eventToIconName($row['logtypeid']);
$lines[] = $row;
}
--
cgit v1.2.3-55-g7522
From f609c3619546e782674d5a893e9a3f61e1cc0d02 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Sun, 3 Dec 2017 16:58:16 +0100
Subject: [statistics] Add missing filter values to "state"
---
modules-available/statistics/page.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index fafa7cd2..5716a09c 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -111,7 +111,7 @@ class Page_Statistics extends Page
'op' => Page_Statistics::$op_nominal,
'type' => 'enum',
'column' => true,
- 'values' => ['occupied', 'on']
+ 'values' => ['occupied', 'on', 'off', 'idle', 'standby']
]
];
if (Module::isAvailable('locations')) {
--
cgit v1.2.3-55-g7522
From 327b8c93ab15b17196b4d936359d378014ebb5f9 Mon Sep 17 00:00:00 2001
From: Simon Rettberg
Date: Mon, 4 Dec 2017 12:35:32 +0100
Subject: [statistics] Add delete functionality
---
modules-available/statistics/lang/de/messages.json | 1 +
.../statistics/lang/de/template-tags.json | 1 +
modules-available/statistics/lang/en/messages.json | 1 +
.../statistics/lang/en/template-tags.json | 1 +
modules-available/statistics/page.inc.php | 32 ++++++++++++++-
.../statistics/templates/clientlist.html | 45 ++++++++++++++++++++--
6 files changed, 76 insertions(+), 5 deletions(-)
(limited to 'modules-available/statistics')
diff --git a/modules-available/statistics/lang/de/messages.json b/modules-available/statistics/lang/de/messages.json
index e3dff61c..c9667f7b 100644
--- a/modules-available/statistics/lang/de/messages.json
+++ b/modules-available/statistics/lang/de/messages.json
@@ -1,4 +1,5 @@
{
+ "deleted-n-machines": "{{0}} Clients gel\u00f6scht",
"invalid-filter-argument": "Das Argument {{1}} ist nicht g\u00fcltig f\u00fcr den Filter {{0}}",
"invalid-filter-key": "{{0}} ist kein g\u00fcltiges Filterkriterium",
"notes-saved": "Anmerkungen gespeichert",
diff --git a/modules-available/statistics/lang/de/template-tags.json b/modules-available/statistics/lang/de/template-tags.json
index 56cf55d7..3cdde813 100644
--- a/modules-available/statistics/lang/de/template-tags.json
+++ b/modules-available/statistics/lang/de/template-tags.json
@@ -74,6 +74,7 @@
"lang_showVisualization": "Visualisierung",
"lang_sockets": "Sockel",
"lang_subnet": "Subnetz",
+ "lang_sureDeletePermanent": "M\u00f6chten Sie diese(n) Rechner wirklich unwiderruflich aus der Datenbank entfernen?\r\n\r\nWichtig: L\u00f6schen verhindert nicht, dass ein Rechner nach erneutem Starten von bwLehrpool wieder in die Datenbank aufgenommen wird.",
"lang_tempPart": "Temp. Partition",
"lang_tempPartStats": "Tempor\u00e4re Partition",
"lang_thoseAreProjectors": "Diese Modellnamen werden als Beamer behandelt, auch wenn die EDID-Informationen des Ger\u00e4tes anderes berichten.",
diff --git a/modules-available/statistics/lang/en/messages.json b/modules-available/statistics/lang/en/messages.json
index ae6c47af..3471c472 100644
--- a/modules-available/statistics/lang/en/messages.json
+++ b/modules-available/statistics/lang/en/messages.json
@@ -1,4 +1,5 @@
{
+ "deleted-n-machines": "Deleted {{0}} clients",
"invalid-filter-argument": "{{1}} is not a vald argument for filter {{0}}",
"invalid-filter-key": "{{0}} is not a valid filter",
"notes-saved": "Notes have been saved",
diff --git a/modules-available/statistics/lang/en/template-tags.json b/modules-available/statistics/lang/en/template-tags.json
index ab7a7d0a..35c4e68a 100644
--- a/modules-available/statistics/lang/en/template-tags.json
+++ b/modules-available/statistics/lang/en/template-tags.json
@@ -74,6 +74,7 @@
"lang_showVisualization": "Visualization",
"lang_sockets": "Sockets",
"lang_subnet": "Subnet",
+ "lang_sureDeletePermanent": "Are your sure you want to delete the selected machine(s) from the database? This cannot be undone.\r\n\r\nNote: Deleting machines from the database does not prevent booting up bwLehrpool again, which would recreate their respective database entries.",
"lang_tempPart": "Temp. partition",
"lang_tempPartStats": "Temporary partition",
"lang_thoseAreProjectors": "These model names will always be treated as beamers, even if the device's EDID data says otherwise.",
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index 5716a09c..df12c568 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -195,6 +195,35 @@ class Page_Statistics extends Page
Util::redirect('?do=Statistics&uuid=' . $uuid);
} elseif ($action === 'addprojector' || $action === 'delprojector') {
$this->handleProjector($action);
+ } elseif ($action === 'delmachines') {
+ $this->deleteMachines();
+ Util::redirect('?do=statistics', true);
+ }
+ }
+
+ private function deleteMachines()
+ {
+ $ids = Request::post('uuid', [], 'array');
+ $ids = array_values($ids);
+ if (empty($ids)) {
+ Message::addError('main.parameter-empty', 'uuid');
+ return;
+ }
+ $res = Database::simpleQuery('SELECT machineuuid, locationid FROM machine WHERE machineuuid IN (:ids)', compact('ids'));
+ $ids = array_flip($ids);
+ $delete = [];
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ // TODO: Check locationid permissions
+ unset($ids[$row['machineuuid']]);
+ $delete[] = $row['machineuuid'];
+ }
+ if (!empty($delete)) {
+ Database::exec('DELETE FROM machine WHERE machineuuid IN (:delete)', compact('delete'));
+ Message::addSuccess('deleted-n-machines', count($delete));
+ }
+ if (!empty($ids)) {
+ // TODO: Warn permissions
+ Message::addWarning('unknown-machine', implode(', ', array_keys($ids)));
}
}
@@ -638,7 +667,8 @@ class Page_Statistics extends Page
'sortColumn' => $filterSet->getSortColumn(),
'columns' => json_encode(Page_Statistics::$columns),
'showList' => 1,
- 'show' => 'list'
+ 'show' => 'list',
+ 'redirect' => $_SERVER['QUERY_STRING']
));
}
diff --git a/modules-available/statistics/templates/clientlist.html b/modules-available/statistics/templates/clientlist.html
index 01ca82f1..b20b202e 100644
--- a/modules-available/statistics/templates/clientlist.html
+++ b/modules-available/statistics/templates/clientlist.html
@@ -1,6 +1,8 @@
+