diff options
author | Simon Rettberg | 2016-05-17 18:14:13 +0200 |
---|---|---|
committer | Simon Rettberg | 2016-05-17 18:14:13 +0200 |
commit | 8e729913a8f6258762f4e8049caebc9dbb42a71e (patch) | |
tree | 48b1d27787847c012994248e32f5a79695221218 | |
parent | Get baseconfig ready for modularization (diff) | |
download | slx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.tar.gz slx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.tar.xz slx-admin-8e729913a8f6258762f4e8049caebc9dbb42a71e.zip |
Modularized baseconfig fetching (api)
17 files changed, 446 insertions, 347 deletions
@@ -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/'; |