summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2016-05-17 18:14:13 +0200
committerSimon Rettberg2016-05-17 18:14:13 +0200
commit8e729913a8f6258762f4e8049caebc9dbb42a71e (patch)
tree48b1d27787847c012994248e32f5a79695221218
parentGet baseconfig ready for modularization (diff)
downloadslx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.tar.gz
slx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.tar.xz
slx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.zip
Modularized baseconfig fetching (api)
-rw-r--r--api.php17
-rw-r--r--apis/clientlog.inc.php232
-rw-r--r--apis/getconfig.inc.php104
-rw-r--r--modules-available/baseconfig-bwlp/lang/de/config-variable-categories.json (renamed from modules-available/baseconfig/lang/de/config-variable-categories.json)0
-rw-r--r--modules-available/baseconfig-bwlp/lang/de/config-variables.json (renamed from modules-available/baseconfig/lang/de/config-variables.json)0
-rw-r--r--modules-available/baseconfig-bwlp/lang/en/config-variable-categories.json (renamed from modules-available/baseconfig/lang/en/config-variable-categories.json)0
-rw-r--r--modules-available/baseconfig-bwlp/lang/en/config-variables.json (renamed from modules-available/baseconfig/lang/en/config-variables.json)0
-rw-r--r--modules-available/baseconfig-bwlp/lang/pt/config-variable-categories.json (renamed from modules-available/baseconfig/lang/pt/config-variable-categories.json)0
-rw-r--r--modules-available/baseconfig-bwlp/lang/pt/config-variables.json (renamed from modules-available/baseconfig/lang/pt/config-variables.json)0
-rw-r--r--modules-available/baseconfig/api.inc.php69
-rw-r--r--modules-available/baseconfig/inc/baseconfigutil.inc.php18
-rw-r--r--modules-available/baseconfig/page.inc.php27
-rw-r--r--modules-available/locations/baseconfig/getconfig.inc.php43
-rw-r--r--modules-available/statistics/api.inc.php217
-rw-r--r--modules-available/syslog/api.inc.php40
-rw-r--r--modules-available/syslog/baseconfig/getconfig.inc.php4
-rw-r--r--modules-available/vmstore/baseconfig/getconfig.inc.php22
17 files changed, 446 insertions, 347 deletions
diff --git a/api.php b/api.php
index e3ef94ce..15b11881 100644
--- a/api.php
+++ b/api.php
@@ -12,15 +12,12 @@ if (CONFIG_SQL_PASS === '%MYSQL_OPENSLX_PASS%')
exit(0); // Ignore API calls if not configured yet
// Autoload classes from ./inc which adhere to naming scheme <lowercasename>.inc.php
-function slxAutoloader($class)
-{
+spl_autoload_register(function ($class) {
$file = 'inc/' . preg_replace('/[^a-z0-9]/', '', mb_strtolower($class)) . '.inc.php';
if (!file_exists($file))
return;
require_once $file;
-}
-
-spl_autoload_register('slxAutoloader');
+});
function isLocalExecution()
{
@@ -36,16 +33,20 @@ if (!empty($_REQUEST['do'])) {
$module = 'main';
}
-$module = 'apis/' . $module . '.inc.php';
+Module::init();
+if (Module::isAvailable($module)) {
+ $module = 'modules/' . $module . '/api.inc.php';
+} else {
+ $module = 'apis/' . $module . '.inc.php';
+}
if (!file_exists($module)) {
- Util::traceError('Invalid module: ' . $module);
+ Util::traceError('Invalid module, or module without API: ' . $module);
}
Header('Content-Type: text/plain; charset=utf-8');
// Load module - it will execute pre-processing, or act upon request parameters
require_once($module);
-unset($module);
diff --git a/apis/clientlog.inc.php b/apis/clientlog.inc.php
index 9c261731..81a7dbf7 100644
--- a/apis/clientlog.inc.php
+++ b/apis/clientlog.inc.php
@@ -1,232 +1,16 @@
<?php
-if (empty($_POST['type'])) die('Missing options.');
-$type = mb_strtolower($_POST['type']);
-
-$ip = $_SERVER['REMOTE_ADDR'];
-if (substr($ip, 0, 7) === '::ffff:') $ip = substr($ip, 7);
-
-/*
- * Power/hw/usage stats
- */
-
-if ($type{0} === '~') {
- // UUID is mandatory
- $uuid = Request::post('uuid', '', 'string');
- if (strlen($uuid) !== 36) die("Invalid UUID.\n");
- $macaddr = Request::post('macaddr', '', 'string');
- if (!empty($macaddr) && substr($uuid, 0, 16) === '000000000000000-') {
- // Override uuid if the mac is known and unique
- $res = Database::simpleQuery('SELECT machineuuid FROM machine WHERE macaddr = :macaddr', array('macaddr' => $macaddr));
- $override = false;
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- if ($override !== false) {
- $override = false;
- break;
- }
- $override = $row['machineuuid'];
- }
- if ($override !== false) {
- $uuid = $override;
- }
- }
- $NOW = time();
- $old = Database::queryFirst('SELECT logintime, lastseen FROM machine WHERE machineuuid = :uuid', array('uuid' => $uuid));
- if ($old !== false) {
- settype($old['logintime'], 'integer');
- settype($old['lastseen'], 'integer');
- }
- // Handle event type
- if ($type === '~poweron') {
- // Poweron & hw stats
- $uptime = Request::post('uptime', '', 'integer');
- if (strlen($macaddr) > 17) die("Invalid MAC.\n");
- if ($uptime < 0 || $uptime > 4000000) die("Implausible uptime.\n");
- $realcores = Request::post('realcores', 0, 'integer');
- if ($realcores < 0 || $realcores > 512) $realcores = 0;
- $mbram = Request::post('mbram', 0, 'integer');
- if ($mbram < 0 || $mbram > 102400) $mbram = 0;
- $kvmstate = Request::post('kvmstate', 'UNKNOWN', 'string');
- $valid = array('UNKNOWN', 'UNSUPPORTED', 'DISABLED', 'ENABLED');
- if (!in_array($kvmstate, $valid)) $kvmstate = 'UNKNOWN';
- $cpumodel = Request::post('cpumodel', '', 'string');
- $systemmodel = Request::post('systemmodel', '', 'string');
- $id44mb = Request::post('id44mb', 0, 'integer');
- if ($id44mb < 0 || $id44mb > 10240000) $id44mb = 0;
- $badsectors = Request::post('badsectors', 0, 'integer');
- if ($badsectors < 0 || $badsectors > 100000) $badsectors = 0;
- $hostname = gethostbyaddr($ip);
- if (!is_string($hostname) || $hostname === $ip) {
- $hostname = '';
- }
- $data = Request::post('data', '', 'string');
- if ($uptime < 120) {
- // See if we have a lingering session, create statistic entry if so
- if ($old !== false && $old['logintime'] !== 0) {
- $sessionLength = $old['lastseen'] - $old['logintime'];
- if ($sessionLength > 0 && $sessionLength < 86400*2) {
- $start = $old['logintime'];
- if ($start === 0) $start = $NOW;
- Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
- . " VALUES (:start, '~session-length', :uuid, :clientip, '', :length)", array(
- 'start' => $start,
- 'uuid' => $uuid,
- 'clientip' => $ip,
- 'length' => $sessionLength
- ));
- }
- }
- // Write poweroff period length to statistic table
- if ($old !== false) {
- $lastSeen = $old['lastseen'] + 500;
- $offtime = ($NOW - $uptime) - $lastSeen;
- if ($offtime > 600 && $offtime < 86400 * 90) {
- Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
- . " VALUES (:shutdown, '~offline-length', :uuid, :clientip, '', :length)", array(
- 'shutdown' => $lastSeen,
- 'uuid' => $uuid,
- 'clientip' => $ip,
- 'length' => $offtime
- ));
- }
- }
- }
- // Create/update machine entry
- Database::exec('INSERT INTO machine '
- . '(machineuuid, macaddr, clientip, firstseen, lastseen, logintime, position, lastboot, realcores, mbram,'
- . ' kvmstate, cpumodel, systemmodel, id44mb, badsectors, data, hostname) VALUES '
- . "(:uuid, :macaddr, :clientip, :firstseen, :lastseen, 0, '', :lastboot, :realcores, :mbram,"
- . ' :kvmstate, :cpumodel, :systemmodel, :id44mb, :badsectors, :data, :hostname)'
- . ' ON DUPLICATE KEY UPDATE'
- . ' macaddr = VALUES(macaddr),'
- . ' clientip = VALUES(clientip),'
- . ' lastseen = VALUES(lastseen),'
- . ($uptime < 180 ? ' logintime = 0,' : '')
- . ' lastboot = VALUES(lastboot),'
- . ' realcores = VALUES(realcores),'
- . ' mbram = VALUES(mbram),'
- . ' kvmstate = VALUES(kvmstate),'
- . ' cpumodel = VALUES(cpumodel),'
- . ' systemmodel = VALUES(systemmodel),'
- . ' id44mb = VALUES(id44mb),'
- . ' badsectors = VALUES(badsectors),'
- . ' data = VALUES(data),'
- . " hostname = If(VALUES(hostname) = '', hostname, VALUES(hostname))", array(
- 'uuid' => $uuid,
- 'macaddr' => $macaddr,
- 'clientip' => $ip,
- 'firstseen' => $NOW,
- 'lastseen' => $NOW,
- 'lastboot' => $NOW - $uptime,
- 'realcores' => $realcores,
- 'mbram' => $mbram,
- 'kvmstate' => $kvmstate,
- 'cpumodel' => $cpumodel,
- 'systemmodel'=> $systemmodel,
- 'id44mb' => $id44mb,
- 'badsectors' => $badsectors,
- 'data' => $data,
- 'hostname' => $hostname,
- ));
- // Write statistics data
-
- } else if ($type === '~runstate') {
- // Usage (occupied/free)
- $sessionLength = 0;
- $used = Request::post('used', 0, 'integer');
- if ($old === false) die("Unknown machine.\n");
- // Figure out what's happening
- if ($used === 0) {
- // Is not in use
- if ($old['logintime'] !== 0) {
- // Was in use, is free now
- // 1) Log last session length
- if ($NOW - $old['lastseen'] > 610) {
- // Old session timed out - might be caused by hard reboot
- $sessionLength = $old['lastseen'] - $old['logintime'];
- } else {
- $sessionLength = $NOW - $old['logintime'];
- }
- }
- Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(), logintime = 0 WHERE machineuuid = :uuid', array('uuid' => $uuid));
- } else {
- // Machine is in use
- if ($old['logintime'] !== 0 && $NOW - $old['lastseen'] > 610) {
- // Old session timed out - might be caused by hard reboot
- $sessionLength = $old['lastseen'] - $old['logintime'];
- }
- if ($sessionLength !== 0 || $old['logintime'] === 0) {
- // This event is a start of a new session, rather than an update
- Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(), logintime = UNIX_TIMESTAMP() WHERE machineuuid = :uuid', array('uuid' => $uuid));
- } else {
- // Nothing changed, simple lastseen update
- Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP() WHERE machineuuid = :uuid', array('uuid' => $uuid));
- }
- }
- // 9) Log last session length if applicable
- if ($sessionLength > 0 && $sessionLength < 86400*2) {
- $start = $old['logintime'];
- if ($start === 0) $start = $NOW;
- Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
- . " VALUES (:start, '~session-length', :uuid, :clientip, '', :length)", array(
- 'start' => $start,
- 'uuid' => $uuid,
- 'clientip' => $ip,
- 'length' => $sessionLength
- ));
- }
- } elseif ($type === '~poweroff') {
- if ($old !== false && (int)$old['logintime'] !== 0) {
- $sessionLength = $old['lastseen'] - $old['logintime'];
- if ($sessionLength > 0 && $sessionLength < 86400*2) {
- $start = $old['logintime'];
- if ($start === 0) $start = $NOW;
- Database::exec('INSERT INTO statistic (dateline, typeid, clientip, username, data)'
- . " VALUES (:start, '~session-length', :clientip, '', :length)", array(
- 'start' => $start,
- 'clientip' => $ip,
- 'length' => $sessionLength
- ));
- }
- }
- Database::exec('UPDATE machine SET logintime = 0, lastseen = UNIX_TIMESTAMP() - 600 WHERE machineuuid = :uuid', array('uuid' => $uuid));
- }
- die("OK. (RESULT=0)\n");
-}
-
/*
- * Normal logging
+ * For compatibility with old slx-admin, where apis were not connected to a module.
+ * This is clientlog, which belonged to module syslog really, plus messy hacked in
+ * hook for machine+user statistics.
*/
-if (!isset($_POST['description'])) die('Missing options..');
-
-$description = $_POST['description'];
-$longdesc = '';
-if (isset($_POST['longdesc'])) $longdesc = $_POST['longdesc'];
-
-// Spam from IP
-$row = Database::queryFirst('SELECT Count(*) AS cnt FROM clientlog WHERE clientip = :client AND dateline + 3600 > UNIX_TIMESTAMP()', array(':client' => $ip));
-if ($row !== false && $row['cnt'] > 150) exit(0);
-
+if (empty($_POST['type'])) die('Missing options.');
+$type = mb_strtolower($_POST['type']);
-if ($type{0} === '.' && preg_match('#^\[([^\]]+)\]\s*(.*)$#', $description, $out)) {
- // Special case '.'-type:
- Database::exec('INSERT INTO statistic (dateline, typeid, clientip, username, data) VALUES (UNIX_TIMESTAMP(), :type, :client, :username, :data)', array(
- 'type' => $type,
- 'client' => $ip,
- 'username' => $out[1],
- 'data' => $out[2],
- ));
-
+if ($type{0} === '~' || $type{0} === '.') {
+ require 'modules/statistics/api.inc.php';
} else {
-
- Database::exec('INSERT INTO clientlog (dateline, logtypeid, clientip, description, extra) VALUES (UNIX_TIMESTAMP(), :type, :client, :description, :longdesc)', array(
- 'type' => $type,
- 'client' => $ip,
- 'description' => $description,
- 'longdesc' => $longdesc,
- ));
+ require 'modules/syslog/api.inc.php';
}
-
-echo "OK.\n";
-
diff --git a/apis/getconfig.inc.php b/apis/getconfig.inc.php
index 2447d622..3fe05ed1 100644
--- a/apis/getconfig.inc.php
+++ b/apis/getconfig.inc.php
@@ -1,104 +1,12 @@
<?php
-$ip = $_SERVER['REMOTE_ADDR'];
-if (substr($ip, 0, 7) === '::ffff:') {
- $ip = substr($ip, 7);
-}
-
-/**
- * Escape given string so it is a valid string in sh that can be surrounded
- * by single quotes ('). This basically turns _'_ into _'"'"'_
- *
- * @param string $string input
- * @return string escaped sh string
+/*
+ * For compatibility with old slx-admin, where apis were not connected to a module.
+ * This is getconfig, which belongs to baseconfig logically.
*/
-function escape($string)
-{
- return str_replace("'", "'\"'\"'", $string);
-}
-// Location handling: figure out location
-$locationId = false; // TODO: machine specific mapping
-if ($locationId === false) {
- // Fallback to subnets
- $locationId = Location::getFromIp($ip);
-}
-$matchingLocations = array();
-if ($locationId !== false) {
- // Get all parents
- settype($locationId, 'integer');
- $locations = Location::getLocationsAssoc();
- $find = $locationId;
- while (isset($locations[$find]) && !in_array($find, $matchingLocations)) {
- $matchingLocations[] = $find;
- $find = (int)$locations[$find]['parentlocationid'];
- }
- echo "SLX_LOCATIONS='" . escape(implode(' ', $matchingLocations)) . "'\n";
+if (!Module::isAvailable('baseconfig')) {
+ Util::traceError('Module baseconfig not available');
}
-$configVars = array();
-// Query location specific settings (from bottom to top)
-if (!empty($matchingLocations)) {
- // First get all settings for all locations we're in
- $list = implode(',', $matchingLocations);
- $res = Database::simpleQuery("SELECT locationid, setting, value FROM setting_location WHERE locationid IN ($list)");
- $tmp = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $tmp[(int)$row['locationid']][$row['setting']] = $row['value'];
- }
- // $matchingLocations contains the location ids sorted from closest to furthest, so we use it to make sure the order
- // in which they override is correct (closest setting wins, e.g. room setting beats department setting)
- foreach ($matchingLocations as $lid) {
- if (!isset($tmp[$lid])) continue;
- foreach ($tmp[$lid] as $setting => $value) {
- if (!isset($configVars[$setting])) {
- $configVars[$setting] = $value;
- }
- }
- }
- unset($tmp);
-}
-
-// Dump config from DB
-$res = Database::simpleQuery('SELECT setting.setting, setting.defaultvalue, tbl.value
- FROM setting
- LEFT JOIN setting_global AS tbl USING (setting)
- ORDER BY setting ASC'); // TODO: Add setting groups and sort order
-while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- if (isset($configVars[$row['setting']])) {
- $row['value'] = $configVars[$row['setting']];
- } elseif (is_null($row['value'])) {
- $row['value'] = $row['defaultvalue'];
- }
- echo $row['setting'] . "='" . escape($row['value']) . "'\n";
-}
-
-// Additional "intelligent" config
-
-// Remote log URL
-echo "SLX_REMOTE_LOG='http://" . escape($_SERVER['SERVER_ADDR']) . escape($_SERVER['SCRIPT_NAME']) . "?do=clientlog'\n";
-// vm list url
-echo "SLX_VMCHOOSER_BASE_URL='http://" . escape($_SERVER['SERVER_ADDR']) . "/vmchooser/'\n";
-
-// VMStore path and type
-$vmstore = Property::getVmStoreConfig();
-if (is_array($vmstore)) {
- switch ($vmstore['storetype']) {
- case 'internal';
- echo "SLX_VM_NFS='" . escape($_SERVER['SERVER_ADDR']) . ":/srv/openslx/nfs'\n";
- break;
- case 'nfs';
- echo "SLX_VM_NFS='" . escape($vmstore['nfsaddr']) . "'\n";
- break;
- case 'cifs';
- echo "SLX_VM_NFS='" . escape($vmstore['cifsaddr']) . "'\n";
- echo "SLX_VM_NFS_USER='" . escape($vmstore['cifsuserro']) . "'\n";
- echo "SLX_VM_NFS_PASSWD='" . escape($vmstore['cifspasswdro']) . "'\n";
- break;
- }
-}
-
-
-// For quick testing or custom extensions: Include external file that should do nothing
-// more than outputting more key-value-pairs. It's expected in the webroot of slxadmin
-if (file_exists('client_config_additional.php')) @include('client_config_additional.php');
+require 'modules/baseconfig/api.inc.php'; \ No newline at end of file
diff --git a/modules-available/baseconfig/lang/de/config-variable-categories.json b/modules-available/baseconfig-bwlp/lang/de/config-variable-categories.json
index d8d7e91f..d8d7e91f 100644
--- a/modules-available/baseconfig/lang/de/config-variable-categories.json
+++ b/modules-available/baseconfig-bwlp/lang/de/config-variable-categories.json
diff --git a/modules-available/baseconfig/lang/de/config-variables.json b/modules-available/baseconfig-bwlp/lang/de/config-variables.json
index af1007be..af1007be 100644
--- a/modules-available/baseconfig/lang/de/config-variables.json
+++ b/modules-available/baseconfig-bwlp/lang/de/config-variables.json
diff --git a/modules-available/baseconfig/lang/en/config-variable-categories.json b/modules-available/baseconfig-bwlp/lang/en/config-variable-categories.json
index f0324e6b..f0324e6b 100644
--- a/modules-available/baseconfig/lang/en/config-variable-categories.json
+++ b/modules-available/baseconfig-bwlp/lang/en/config-variable-categories.json
diff --git a/modules-available/baseconfig/lang/en/config-variables.json b/modules-available/baseconfig-bwlp/lang/en/config-variables.json
index 36ac6e8c..36ac6e8c 100644
--- a/modules-available/baseconfig/lang/en/config-variables.json
+++ b/modules-available/baseconfig-bwlp/lang/en/config-variables.json
diff --git a/modules-available/baseconfig/lang/pt/config-variable-categories.json b/modules-available/baseconfig-bwlp/lang/pt/config-variable-categories.json
index 99819f51..99819f51 100644
--- a/modules-available/baseconfig/lang/pt/config-variable-categories.json
+++ b/modules-available/baseconfig-bwlp/lang/pt/config-variable-categories.json
diff --git a/modules-available/baseconfig/lang/pt/config-variables.json b/modules-available/baseconfig-bwlp/lang/pt/config-variables.json
index 66ec3b1c..66ec3b1c 100644
--- a/modules-available/baseconfig/lang/pt/config-variables.json
+++ b/modules-available/baseconfig-bwlp/lang/pt/config-variables.json
diff --git a/modules-available/baseconfig/api.inc.php b/modules-available/baseconfig/api.inc.php
new file mode 100644
index 00000000..c692a0b2
--- /dev/null
+++ b/modules-available/baseconfig/api.inc.php
@@ -0,0 +1,69 @@
+<?php
+
+$ip = $_SERVER['REMOTE_ADDR'];
+if (substr($ip, 0, 7) === '::ffff:') {
+ $ip = substr($ip, 7);
+}
+
+// TODO: Handle UUID in appropriate modules (optional)
+$uuid = Request::post('uuid', '', 'string');
+if (strlen($uuid) !== 36) {
+ // Probably invalid UUID. What to do? Set empty or ignore?
+}
+
+/**
+ * Escape given string so it is a valid string in sh that can be surrounded
+ * by single quotes ('). This basically turns _'_ into _'"'"'_
+ *
+ * @param string $string input
+ * @return string escaped sh string
+ */
+function escape($string)
+{
+ return str_replace("'", "'\"'\"'", $string);
+}
+
+/*
+ * We gather all config variables here. First, let other modules generate
+ * their desired config vars. Afterwards, add the global config vars from
+ * db. If a variable is already set, it will not be overridden by the
+ * global setting.
+ */
+
+$configVars = array();
+
+// Handle any hooks by other modules first
+// other modules should generally only populate $configVars
+foreach (glob('modules/*/baseconfig/getconfig.inc.php') as $file) {
+ preg_match('#^modules/([^/]+)/#', $file, $out);
+ if (!Module::isAvailable($out[1]))
+ continue;
+ include $file;
+}
+
+// Rest is handled by module
+$defaults = BaseConfigUtil::getVariables();
+
+// Dump global config from DB
+$res = Database::simpleQuery('SELECT setting, value FROM setting_global'); // TODO: Add setting groups and sort order
+while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if (isset($configVars[$row['setting']]) || !isset($defaults[$row['setting']]))
+ continue;
+ $configVars[$row['setting']] = $row['value'];
+}
+
+// Fallback to default values from json files
+foreach ($defaults as $setting => $value) {
+ if (isset($configVars[$setting]))
+ continue;
+ $configVars[$setting] = $value;
+}
+
+// Finally, output what we gathered
+foreach ($configVars as $setting => $value) {
+ echo $setting, "='", escape($value), "'\n";
+}
+
+// For quick testing or custom extensions: Include external file that should do nothing
+// more than outputting more key-value-pairs. It's expected in the webroot of slxadmin
+if (file_exists('client_config_additional.php')) @include('client_config_additional.php');
diff --git a/modules-available/baseconfig/inc/baseconfigutil.inc.php b/modules-available/baseconfig/inc/baseconfigutil.inc.php
index 33875156..ebaefbcf 100644
--- a/modules-available/baseconfig/inc/baseconfigutil.inc.php
+++ b/modules-available/baseconfig/inc/baseconfigutil.inc.php
@@ -20,9 +20,13 @@ class BaseConfigUtil
$settings = array();
foreach (glob('modules/*/baseconfig/settings.json', GLOB_NOSORT) as $file) {
$data = json_decode(file_get_contents($file), true);
- if (is_array($data)) {
- $settings += $data;
+ if (!is_array($data))
+ continue;
+ preg_match('#^modules/([^/]+)/#', $file, $out);
+ foreach ($data as &$entry) {
+ $entry['module'] = $out[1];
}
+ $settings += $data;
}
return $settings;
}
@@ -32,11 +36,15 @@ class BaseConfigUtil
$categories = array();
foreach (glob('modules/*/baseconfig/categories.json', GLOB_NOSORT) as $file) {
$data = json_decode(file_get_contents($file), true);
- if (is_array($data)) {
- $categories += $data;
+ if (!is_array($data))
+ continue;
+ preg_match('#^modules/([^/]+)/#', $file, $out);
+ foreach ($data as &$entry) {
+ $entry = array('module' => $out[1], 'sortpos' => $entry);
}
+ $categories += $data;
}
return $categories;
}
-} \ No newline at end of file
+}
diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php
index 5e209f4e..21b5459b 100644
--- a/modules-available/baseconfig/page.inc.php
+++ b/modules-available/baseconfig/page.inc.php
@@ -90,7 +90,7 @@ class Page_BaseConfig extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
- // Check if valid submodule mode, stire name if any
+ // Check if valid submodule mode, store name if any
if ($this->targetModule !== false) {
$this->qry_extra['subheading'] = $this->getCurrentModuleName();
if ($this->qry_extra['subheading'] === false) {
@@ -111,7 +111,7 @@ class Page_BaseConfig extends Page
$params = array();
}
// Populate structure with existing config from db
- $res = Database::simpleQuery("SELECT setting, displayvalue FROM {$this->qry_extra['table']} "
+ $res = Database::simpleQuery("SELECT setting, value, displayvalue FROM {$this->qry_extra['table']} "
. " {$where} ORDER BY setting ASC", $params);
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if (!isset($vars[$row['setting']]) || !is_array($vars[$row['setting']])) {
@@ -119,9 +119,9 @@ class Page_BaseConfig extends Page
continue;
}
$row += $vars[$row['setting']];
- $row['description'] = Util::markup(Dictionary::translateFile('config-variables', $row['setting']));
- if (is_null($row['displayvalue'])) $row['displayvalue'] = $row['defaultvalue'];
- $row['item'] = $this->makeInput($row['validator'], $row['setting'], $row['displayvalue']);
+ if (is_null($row['displayvalue'])) {
+ $row['displayvalue'] = $row['defaultvalue'];
+ }
if (!isset($row['catid'])) {
$row['catid'] = 'unknown';
}
@@ -132,20 +132,23 @@ class Page_BaseConfig extends Page
if (isset($settings[$var['catid']]['settings'][$key])) {
// Value is set in DB
$settings[$var['catid']]['settings'][$key]['checked'] = 'checked';
- continue;
+ } else {
+ // Value is not set in DB
+ $settings[$var['catid']]['settings'][$key] = $var + array(
+ 'setting' => $key
+ );
}
- // Value is not set in DB
- $settings[$var['catid']]['settings'][$key] = $var + array(
- 'setting' => $key,
- 'item' => $this->makeInput($var['validator'], $key, $var['defaultvalue'])
+ $settings[$var['catid']]['settings'][$key] += array(
+ 'item' => $this->makeInput($var['validator'], $key, $var['defaultvalue']),
+ 'description' => Util::markup(Dictionary::translateFileModule($var['module'], 'config-variables', $key))
);
}
// Sort categories
$sortvals = array();
foreach ($settings as $catid => &$setting) {
- $sortvals[] = isset($cats[$catid]) ? (int)$cats[$catid] : 99999;
+ $sortvals[] = isset($cats[$catid]) ? (int)$cats[$catid]['sortpos'] : 99999;
$setting['category_id'] = $catid;
- $setting['category_name'] = Dictionary::translateFile('config-variable-categories', 'cat_' . $catid);
+ $setting['category_name'] = Dictionary::translateFileModule($cats[$catid]['module'], 'config-variable-categories', $catid);
if ($setting['category_name'] === false) {
$setting['category_name'] = $catid;
}
diff --git a/modules-available/locations/baseconfig/getconfig.inc.php b/modules-available/locations/baseconfig/getconfig.inc.php
new file mode 100644
index 00000000..2643ced6
--- /dev/null
+++ b/modules-available/locations/baseconfig/getconfig.inc.php
@@ -0,0 +1,43 @@
+<?php
+
+// Location handling: figure out location
+$locationId = false; // TODO: machine specific mapping
+if ($locationId === false) {
+ // Fallback to subnets
+ $locationId = Location::getFromIp($ip);
+}
+$matchingLocations = array();
+if ($locationId !== false) {
+ // Get all parents
+ settype($locationId, 'integer');
+ $locations = Location::getLocationsAssoc();
+ $find = $locationId;
+ while (isset($locations[$find]) && !in_array($find, $matchingLocations)) {
+ $matchingLocations[] = $find;
+ $find = (int)$locations[$find]['parentlocationid'];
+ }
+ $configVars["SLX_LOCATIONS"] = implode(' ', $matchingLocations);
+}
+
+// Query location specific settings (from bottom to top)
+if (!empty($matchingLocations)) {
+ // First get all settings for all locations we're in
+ $list = implode(',', $matchingLocations);
+ $res = Database::simpleQuery("SELECT locationid, setting, value FROM setting_location WHERE locationid IN ($list)");
+ $tmp = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $tmp[(int)$row['locationid']][$row['setting']] = $row['value'];
+ }
+ // $matchingLocations contains the location ids sorted from closest to furthest, so we use it to make sure the order
+ // in which they override is correct (closest setting wins, e.g. room setting beats department setting)
+ foreach ($matchingLocations as $lid) {
+ if (!isset($tmp[$lid]))
+ continue;
+ foreach ($tmp[$lid] as $setting => $value) {
+ if (!isset($configVars[$setting])) {
+ $configVars[$setting] = $value;
+ }
+ }
+ }
+ unset($tmp);
+}
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
new file mode 100644
index 00000000..3a2f2440
--- /dev/null
+++ b/modules-available/statistics/api.inc.php
@@ -0,0 +1,217 @@
+<?php
+
+if (empty($_POST['type'])) die('Missing options.');
+$type = mb_strtolower($_POST['type']);
+
+$ip = $_SERVER['REMOTE_ADDR'];
+if (substr($ip, 0, 7) === '::ffff:') $ip = substr($ip, 7);
+
+/*
+ * Section 1/2
+ * Power/hw/usage stats
+ */
+
+if ($type{0} === '~') {
+ // UUID is mandatory
+ $uuid = Request::post('uuid', '', 'string');
+ if (strlen($uuid) !== 36) die("Invalid UUID.\n");
+ $macaddr = Request::post('macaddr', '', 'string');
+ if (!empty($macaddr) && substr($uuid, 0, 16) === '000000000000000-') {
+ // Override uuid if the mac is known and unique
+ $res = Database::simpleQuery('SELECT machineuuid FROM machine WHERE macaddr = :macaddr', array('macaddr' => $macaddr));
+ $override = false;
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($override !== false) {
+ $override = false;
+ break;
+ }
+ $override = $row['machineuuid'];
+ }
+ if ($override !== false) {
+ $uuid = $override;
+ }
+ }
+ $NOW = time();
+ $old = Database::queryFirst('SELECT logintime, lastseen FROM machine WHERE machineuuid = :uuid', array('uuid' => $uuid));
+ if ($old !== false) {
+ settype($old['logintime'], 'integer');
+ settype($old['lastseen'], 'integer');
+ }
+ // Handle event type
+ if ($type === '~poweron') {
+ // Poweron & hw stats
+ $uptime = Request::post('uptime', '', 'integer');
+ if (strlen($macaddr) > 17) die("Invalid MAC.\n");
+ if ($uptime < 0 || $uptime > 4000000) die("Implausible uptime.\n");
+ $realcores = Request::post('realcores', 0, 'integer');
+ if ($realcores < 0 || $realcores > 512) $realcores = 0;
+ $mbram = Request::post('mbram', 0, 'integer');
+ if ($mbram < 0 || $mbram > 102400) $mbram = 0;
+ $kvmstate = Request::post('kvmstate', 'UNKNOWN', 'string');
+ $valid = array('UNKNOWN', 'UNSUPPORTED', 'DISABLED', 'ENABLED');
+ if (!in_array($kvmstate, $valid)) $kvmstate = 'UNKNOWN';
+ $cpumodel = Request::post('cpumodel', '', 'string');
+ $systemmodel = Request::post('systemmodel', '', 'string');
+ $id44mb = Request::post('id44mb', 0, 'integer');
+ if ($id44mb < 0 || $id44mb > 10240000) $id44mb = 0;
+ $badsectors = Request::post('badsectors', 0, 'integer');
+ if ($badsectors < 0 || $badsectors > 100000) $badsectors = 0;
+ $hostname = gethostbyaddr($ip);
+ if (!is_string($hostname) || $hostname === $ip) {
+ $hostname = '';
+ }
+ $data = Request::post('data', '', 'string');
+ if ($uptime < 120) {
+ // See if we have a lingering session, create statistic entry if so
+ if ($old !== false && $old['logintime'] !== 0) {
+ $sessionLength = $old['lastseen'] - $old['logintime'];
+ if ($sessionLength > 30 && $sessionLength < 86400*2) {
+ Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
+ . " VALUES (:start, '~session-length', :uuid, :clientip, '', :length)", array(
+ 'start' => $old['logintime'],
+ 'uuid' => $uuid,
+ 'clientip' => $ip,
+ 'length' => $sessionLength
+ ));
+ }
+ }
+ // Write poweroff period length to statistic table
+ if ($old !== false && $old['lastseen'] !== 0) {
+ $lastSeen = $old['lastseen'];
+ $offtime = ($NOW - $uptime) - $lastSeen;
+ if ($offtime > 300 && $offtime < 86400 * 90) {
+ Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
+ . " VALUES (:shutdown, '~offline-length', :uuid, :clientip, '', :length)", array(
+ 'shutdown' => $lastSeen,
+ 'uuid' => $uuid,
+ 'clientip' => $ip,
+ 'length' => $offtime
+ ));
+ }
+ }
+ }
+ // Create/update machine entry
+ Database::exec('INSERT INTO machine '
+ . '(machineuuid, macaddr, clientip, firstseen, lastseen, logintime, position, lastboot, realcores, mbram,'
+ . ' kvmstate, cpumodel, systemmodel, id44mb, badsectors, data, hostname) VALUES '
+ . "(:uuid, :macaddr, :clientip, :firstseen, :lastseen, 0, '', :lastboot, :realcores, :mbram,"
+ . ' :kvmstate, :cpumodel, :systemmodel, :id44mb, :badsectors, :data, :hostname)'
+ . ' ON DUPLICATE KEY UPDATE'
+ . ' macaddr = VALUES(macaddr),'
+ . ' clientip = VALUES(clientip),'
+ . ' lastseen = VALUES(lastseen),'
+ . ($uptime < 180 ? ' logintime = 0,' : '')
+ . ' lastboot = VALUES(lastboot),'
+ . ' realcores = VALUES(realcores),'
+ . ' mbram = VALUES(mbram),'
+ . ' kvmstate = VALUES(kvmstate),'
+ . ' cpumodel = VALUES(cpumodel),'
+ . ' systemmodel = VALUES(systemmodel),'
+ . ' id44mb = VALUES(id44mb),'
+ . ' badsectors = VALUES(badsectors),'
+ . ' data = VALUES(data),'
+ . " hostname = If(VALUES(hostname) = '', hostname, VALUES(hostname))", array(
+ 'uuid' => $uuid,
+ 'macaddr' => $macaddr,
+ 'clientip' => $ip,
+ 'firstseen' => $NOW,
+ 'lastseen' => $NOW,
+ 'lastboot' => $NOW - $uptime,
+ 'realcores' => $realcores,
+ 'mbram' => $mbram,
+ 'kvmstate' => $kvmstate,
+ 'cpumodel' => $cpumodel,
+ 'systemmodel'=> $systemmodel,
+ 'id44mb' => $id44mb,
+ 'badsectors' => $badsectors,
+ 'data' => $data,
+ 'hostname' => $hostname,
+ ));
+ // Write statistics data
+
+ } else if ($type === '~runstate') {
+ // Usage (occupied/free)
+ $sessionLength = 0;
+ $used = Request::post('used', 0, 'integer');
+ if ($old === false) die("Unknown machine.\n");
+ // Figure out what's happening
+ if ($used === 0) {
+ // Is not in use
+ if ($old['logintime'] !== 0) {
+ // Was in use, is free now
+ // 1) Log last session length
+ if ($NOW - $old['lastseen'] > 610) {
+ // Old session timed out - might be caused by hard reboot
+ $sessionLength = $old['lastseen'] - $old['logintime'];
+ } else {
+ $sessionLength = $NOW - $old['logintime'];
+ }
+ }
+ Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(), logintime = 0 WHERE machineuuid = :uuid', array('uuid' => $uuid));
+ } else {
+ // Machine is in use
+ if ($old['logintime'] !== 0 && $NOW - $old['lastseen'] > 610) {
+ // Old session timed out - might be caused by hard reboot
+ $sessionLength = $old['lastseen'] - $old['logintime'];
+ }
+ if ($sessionLength !== 0 || $old['logintime'] === 0) {
+ // This event is a start of a new session, rather than an update
+ Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP(), logintime = UNIX_TIMESTAMP() WHERE machineuuid = :uuid', array('uuid' => $uuid));
+ } else {
+ // Nothing changed, simple lastseen update
+ Database::exec('UPDATE machine SET lastseen = UNIX_TIMESTAMP() WHERE machineuuid = :uuid', array('uuid' => $uuid));
+ }
+ }
+ // 9) Log last session length if applicable
+ if ($sessionLength > 0 && $sessionLength < 86400*2 && $old['logintime'] !== 0) {
+ Database::exec('INSERT INTO statistic (dateline, typeid, machineuuid, clientip, username, data)'
+ . " VALUES (:start, '~session-length', :uuid, :clientip, '', :length)", array(
+ 'start' => $old['logintime'],
+ 'uuid' => $uuid,
+ 'clientip' => $ip,
+ 'length' => $sessionLength
+ ));
+ }
+ } elseif ($type === '~poweroff') {
+ if ($old !== false && $old['logintime'] !== 0) {
+ $sessionLength = $old['lastseen'] - $old['logintime'];
+ if ($sessionLength > 0 && $sessionLength < 86400*2) {
+ Database::exec('INSERT INTO statistic (dateline, typeid, clientip, username, data)'
+ . " VALUES (:start, '~session-length', :clientip, '', :length)", array(
+ 'start' => $old['logintime'],
+ 'clientip' => $ip,
+ 'length' => $sessionLength
+ ));
+ }
+ }
+ Database::exec('UPDATE machine SET logintime = 0, lastseen = UNIX_TIMESTAMP(), lastboot = 0 WHERE machineuuid = :uuid', array('uuid' => $uuid));
+ }
+ die("OK. (RESULT=0)\n");
+}
+
+/*
+ * Section 2/2
+ * Session information
+ */
+
+if (!isset($_POST['description'])) die('Missing options..');
+$description = $_POST['description'];
+
+
+// For backwards compat, we require the . prefix and username embedded in message
+if ($type{0} === '.' && preg_match('#^\[([^\]]+)\]\s*(.*)$#', $description, $out)) {
+
+ // Spam from IP
+ $row = Database::queryFirst('SELECT Count(*) AS cnt FROM statistic WHERE clientip = :client AND dateline + 300 > UNIX_TIMESTAMP()', array(':client' => $ip));
+ if ($row !== false && $row['cnt'] > 4) exit(0);
+
+ Database::exec('INSERT INTO statistic (dateline, typeid, clientip, username, data) VALUES (UNIX_TIMESTAMP(), :type, :client, :username, :data)', array(
+ 'type' => $type,
+ 'client' => $ip,
+ 'username' => $out[1],
+ 'data' => $out[2],
+ ));
+
+}
+
+echo "OK.\n";
diff --git a/modules-available/syslog/api.inc.php b/modules-available/syslog/api.inc.php
new file mode 100644
index 00000000..cebe5ef1
--- /dev/null
+++ b/modules-available/syslog/api.inc.php
@@ -0,0 +1,40 @@
+<?php
+
+if (empty($_POST['type'])) die('Missing options.');
+$type = mb_strtolower($_POST['type']);
+
+$ip = $_SERVER['REMOTE_ADDR'];
+if (substr($ip, 0, 7) === '::ffff:') $ip = substr($ip, 7);
+
+// TODO: Handle UUID in appropriate modules (optional)
+$uuid = Request::post('uuid', '', 'string');
+if (strlen($uuid) !== 36) {
+ // Probably invalid UUID. What to do? Set empty or ignore?
+}
+
+/*
+ * Normal logging
+ */
+
+if (!isset($_POST['description'])) die('Missing options..');
+
+$description = $_POST['description'];
+$longdesc = '';
+if (isset($_POST['longdesc'])) $longdesc = $_POST['longdesc'];
+
+if ($type{0} !== '.' && $type{0} !== '~') {
+
+ // Spam from IP
+ $row = Database::queryFirst('SELECT Count(*) AS cnt FROM clientlog WHERE clientip = :client AND dateline + 3600 > UNIX_TIMESTAMP()', array(':client' => $ip));
+ if ($row !== false && $row['cnt'] > 150) exit(0);
+
+ Database::exec('INSERT INTO clientlog (dateline, logtypeid, clientip, description, extra) VALUES (UNIX_TIMESTAMP(), :type, :client, :description, :longdesc)', array(
+ 'type' => $type,
+ 'client' => $ip,
+ 'description' => $description,
+ 'longdesc' => $longdesc,
+ ));
+
+}
+
+echo "OK.\n";
diff --git a/modules-available/syslog/baseconfig/getconfig.inc.php b/modules-available/syslog/baseconfig/getconfig.inc.php
new file mode 100644
index 00000000..9706eea1
--- /dev/null
+++ b/modules-available/syslog/baseconfig/getconfig.inc.php
@@ -0,0 +1,4 @@
+<?php
+
+// Remote log URL
+$configVars["SLX_REMOTE_LOG"] = 'http://' . $_SERVER['SERVER_ADDR'] . $_SERVER['SCRIPT_NAME'] . '?do=clientlog';
diff --git a/modules-available/vmstore/baseconfig/getconfig.inc.php b/modules-available/vmstore/baseconfig/getconfig.inc.php
new file mode 100644
index 00000000..e34c502a
--- /dev/null
+++ b/modules-available/vmstore/baseconfig/getconfig.inc.php
@@ -0,0 +1,22 @@
+<?php
+
+// VMStore path and type
+$vmstore = Property::getVmStoreConfig();
+if (is_array($vmstore) && isset($vmstore['storetype'])) {
+ switch ($vmstore['storetype']) {
+ case 'internal';
+ $configVars["SLX_VM_NFS"] = $_SERVER['SERVER_ADDR'] . ":/srv/openslx/nfs";
+ break;
+ case 'nfs';
+ $configVars["SLX_VM_NFS"] = $vmstore['nfsaddr'];
+ break;
+ case 'cifs';
+ $configVars["SLX_VM_NFS"] = $vmstore['cifsaddr'];
+ $configVars["SLX_VM_NFS_USER"] = $vmstore['cifsuserro'];
+ $configVars["SLX_VM_NFS_PASSWD"] = $vmstore['cifspasswdro'];
+ break;
+ }
+}
+
+// vm list url. doesn't really fit anywhere, seems to be a tie between here and dozmod
+$configVars["SLX_VMCHOOSER_BASE_URL"] = 'http://' . $_SERVER['SERVER_ADDR'] . '/vmchooser/';