From 4a230b9a4843ade82ff12fda31b771a5a9e58977 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 6 Apr 2017 17:30:12 +0200 Subject: [statistics] Handle client screens, manage projectors --- modules-available/statistics/api.inc.php | 73 ++++++++++++++++++++++ .../statistics/hooks/config-tgz.inc.php | 32 ++++++++++ .../statistics/inc/devicetype.inc.php | 6 ++ modules-available/statistics/install.inc.php | 55 +++++++++++++++- modules-available/statistics/page.inc.php | 70 +++++++++++++++++++++ .../statistics/templates/machine-main.html | 30 +++++++++ .../statistics/templates/projector-list.html | 21 +++++++ 7 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 modules-available/statistics/hooks/config-tgz.inc.php create mode 100644 modules-available/statistics/inc/devicetype.inc.php create mode 100644 modules-available/statistics/templates/projector-list.html (limited to 'modules-available/statistics') diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php index 2ac6e782..126c6e91 100644 --- a/modules-available/statistics/api.inc.php +++ b/modules-available/statistics/api.inc.php @@ -201,6 +201,79 @@ if ($type{0} === '~') { } } Database::exec('UPDATE machine SET logintime = 0, lastseen = UNIX_TIMESTAMP(), lastboot = 0 WHERE machineuuid = :uuid', array('uuid' => $uuid)); + } elseif ($type === '~screens') { + $screens = Request::post('screen', false, 'array'); + if (is_array($screens)) { + // `devicetype`, `devicename`, `subid`, `machineuuid` + // Make sure all screens are in the general hardware table + $hwids = array(); + foreach ($screens as $port => $screen) { + if (!array_key_exists('name', $screen)) + continue; + if (array_key_exists($screen['name'], $hwids)) { + $hwid = $hwids[$screen['name']]; + } else { + $hwid = (int)Database::insertIgnore('statistic_hw', 'hwid', + array('hwtype' => DeviceType::SCREEN, 'hwname' => $screen['name'])); + $hwids[$screen['name']] = $hwid; + } + // Now add new entries + $machinehwid = Database::insertIgnore('machine_x_hw', 'machinehwid', array( + 'hwid' => $hwid, + 'machineuuid' => $uuid, + 'devpath' => $port, + ), array('disconnecttime' => 0)); + $validProps = array(); + if (count($screen) > 1) { + // Screen has additional properties (resolution, size, etc.) + unset($screen['name']); + foreach ($screen as $key => $value) { + if (!preg_match('/^[a-zA-Z0-9][\x21-\x7e]{0,15}$/', $key)) { + echo "No matsch '$key'\n"; + continue; // Ignore evil key names + } + $validProps[] = $key; + Database::exec("INSERT INTO machine_x_hw_prop (machinehwid, prop, value)" + . " VALUES (:id, :key, :value) ON DUPLICATE KEY UPDATE value = VALUES(value)", array( + 'id' => $machinehwid, + 'key' => $key, + 'value' => $value, + )); + } + } + // Purge properties that might have existed in the past + if (empty($validProps)) { + Database::exec("DELETE FROM machine_x_hw_prop WHERE machinehwid = :machinehwid AND prop NOT LIKE '@%'", + array('machinehwid' => $machinehwid)); + } else { + $qs = '?' . str_repeat(',?', count($validProps) - 1); + array_unshift($validProps, $machinehwid); + Database::exec("DELETE FROM machine_x_hw_prop" + . " WHERE machinehwid = ? AND prop NOT LIKE '@%' AND prop NOT IN ($qs)", + $validProps); + } + } + // Remove/disable stale entries + if (empty($hwids)) { + // No screens connected at all, purge all screen entries for this machine + Database::exec("UPDATE machine_x_hw x, statistic_hw h" + . " SET x.disconnecttime = UNIX_TIMESTAMP()" + . " WHERE x.machineuuid = :uuid AND x.hwid = h.hwid AND h.hwtype = :type AND x.disconnecttime = 0", + array('uuid' => $uuid, 'type' => DeviceType::SCREEN)); + } else { + // Some screens connected, make sure old entries get removed + $params = array_values($hwids); + array_unshift($params, $uuid); + array_unshift($params, DeviceType::SCREEN); + $qs = '?' . str_repeat(',?', count($hwids) - 1); + Database::exec("UPDATE machine_x_hw x, statistic_hw h" + . " SET x.disconnecttime = UNIX_TIMESTAMP()" + . " WHERE h.hwid = x.hwid AND x.disconnecttime = 0 AND h.hwtype = ? AND x.machineuuid = ? AND x.hwid NOT IN ($qs)", $params); + + } + } + } else { + die("INVALID ACTION '$type'"); } die("OK. (RESULT=0)\n"); } diff --git a/modules-available/statistics/hooks/config-tgz.inc.php b/modules-available/statistics/hooks/config-tgz.inc.php new file mode 100644 index 00000000..1272a94f --- /dev/null +++ b/modules-available/statistics/hooks/config-tgz.inc.php @@ -0,0 +1,32 @@ + 'projector', + 'screen' => DeviceType::SCREEN, +)); + +$content = ''; +while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $content .= $row['hwname'] . "=beamer\n"; +} + +if (!empty($content)) { + $tmpfile = '/tmp/bwlp-' . md5($content) . '.tar'; + if (!is_file($tmpfile) || !is_readable($tmpfile) || filemtime($tmpfile) + 86400 < time()) { + if (file_exists($tmpfile)) { + unlink($tmpfile); + } + try { + $a = new PharData($tmpfile); + $a->addFromString("/opt/openslx/beamergui/beamer.conf", $content); + $file = $tmpfile; + } catch (Exception $e) { + EventLog::failure('Could not include beamer.conf in config.tgz', (string)$e); + unlink($tmpfile); + } + } elseif (is_file($tmpfile) && is_readable($tmpfile)) { + $file = $tmpfile; + } +} diff --git a/modules-available/statistics/inc/devicetype.inc.php b/modules-available/statistics/inc/devicetype.inc.php new file mode 100644 index 00000000..41ee237d --- /dev/null +++ b/modules-available/statistics/inc/devicetype.inc.php @@ -0,0 +1,6 @@ + $hwid, + 'prop' => 'projector', + 'value' => 'true', + )); + } else { + Database::exec('DELETE FROM statistic_hw_prop WHERE hwid = :hwid AND prop = :prop', array( + 'hwid' => $hwid, + 'prop' => 'projector', + )); + } + if (Module::isAvailable('sysconfig')) { + ConfigTgz::rebuildAllConfigs(); + } + Util::redirect('?do=statistics&show=projectors'); + } + + protected function showProjectors() + { + $res = Database::simpleQuery('SELECT h.hwname, h.hwid FROM statistic_hw h' + . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)" + . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array( + 'projector' => 'projector', + 'screen' => DeviceType::SCREEN, + )); + $data = array( + 'projectors' => $res->fetchAll(PDO::FETCH_ASSOC) + ); + Render::addTemplate('projector-list', $data); + } + + /* + * End TODO + */ + protected function doPreprocess() { $this->initConstants(); @@ -140,6 +187,8 @@ class Page_Statistics extends Page )); Message::addSuccess('notes-saved'); Util::redirect('?do=Statistics&uuid=' . $uuid); + } elseif ($action === 'addprojector' || $action === 'delprojector') { + $this->handleProjector($action); } // Fix online state of machines that crashed -- TODO: Make cronjob for this Database::exec("UPDATE machine SET lastboot = 0 WHERE lastseen < UNIX_TIMESTAMP() - 610"); @@ -174,6 +223,9 @@ class Page_Statistics extends Page Render::closeTag('div'); $this->showMachineList($filterSet); return; + } elseif ($show === 'projectors') { + $this->showProjectors(); + return; } Render::openTag('div', array('class' => 'row')); $this->showFilter('stat', $filterSet); @@ -723,6 +775,24 @@ class Page_Statistics extends Page } $client['locations'] = $output; } + // Screens TODO Move everything else to hw table instead of blob parsing above + // `devicetype`, `devicename`, `subid`, `machineuuid` + $res = Database::simpleQuery("SELECT m.hwid, h.hwname, m.devpath AS connector, m.disconnecttime," + . " p.value AS resolution, q.prop AS projector FROM machine_x_hw m" + . " INNER JOIN statistic_hw h ON (m.hwid = h.hwid AND h.hwtype = :screen)" + . " LEFT JOIN machine_x_hw_prop p ON (m.machinehwid = p.machinehwid AND p.prop = 'resolution')" + . " LEFT JOIN statistic_hw_prop q ON (m.hwid = q.hwid AND q.prop = 'projector')" + . " WHERE m.machineuuid = :uuid", + array('screen' => DeviceType::SCREEN, 'uuid' => $uuid)); + $client['screens'] = array(); + $ports = array(); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + if ($row['disconnecttime'] != 0) + continue; + $ports[] = $row['connector']; + $client['screens'][] = $row; + } + array_multisort($ports, SORT_ASC, $client['screens']); // Throw output at user Render::addTemplate('machine-main', $client); // Sessions diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html index 0b333a27..56454e78 100644 --- a/modules-available/statistics/templates/machine-main.html +++ b/modules-available/statistics/templates/machine-main.html @@ -130,6 +130,36 @@ {{lang_64bitSupport}} {{kvmstate}} + + {{lang_screens}} + +
+ + +
+
+ + +
+ {{#screens}} +
+
+ {{#projector}} + {{lang_projector}} + + {{/projector}} + {{^projector}} + + {{/projector}} +
+ {{connector}}: {{hwname}} {{resolution}} +
+
+ {{/screens}} + +

{{lang_devices}}

{{#lspci1}} diff --git a/modules-available/statistics/templates/projector-list.html b/modules-available/statistics/templates/projector-list.html new file mode 100644 index 00000000..bc9ecdbd --- /dev/null +++ b/modules-available/statistics/templates/projector-list.html @@ -0,0 +1,21 @@ +
+
{{lang_projectors}}
+
+
+ + +

{{lang_thoseAreProjectors}}

+ {{#projectors}} +
+ + {{hwname}} +
+ {{/projectors}} + {{^projectors}} +
{{lang_noProjectorsDefined}}
+ {{/projectors}} +
+
+
\ No newline at end of file -- cgit v1.2.3-55-g7522