summaryrefslogtreecommitdiffstats
path: root/modules-available
diff options
context:
space:
mode:
authorUdo Walter2017-12-22 18:06:04 +0100
committerUdo Walter2017-12-22 18:06:04 +0100
commit7072cd446f7c74059c9da1284962b21a45ed4f5f (patch)
tree383be0c209f8f38666b801aa2c160ae2e08493a8 /modules-available
parent[minilinux] Actualized translation. (diff)
parent[sysconfig] Restore long lost ajax functionality (diff)
downloadslx-admin-7072cd446f7c74059c9da1284962b21a45ed4f5f.tar.gz
slx-admin-7072cd446f7c74059c9da1284962b21a45ed4f5f.tar.xz
slx-admin-7072cd446f7c74059c9da1284962b21a45ed4f5f.zip
Merge branch 'master' into permission-manager
Diffstat (limited to 'modules-available')
-rw-r--r--modules-available/baseconfig_bwlp/baseconfig/settings.json6
-rw-r--r--modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json1
-rw-r--r--modules-available/baseconfig_bwlp/lang/de/config-variables.json1
-rw-r--r--modules-available/baseconfig_bwlp/lang/en/config-variables.json3
-rw-r--r--modules-available/dnbd3/templates/page-server-locations.html9
-rw-r--r--modules-available/dozmod/inc/pagemailtemplates.inc.php10
-rw-r--r--modules-available/locationinfo/api.inc.php26
-rw-r--r--modules-available/locationinfo/inc/infopanel.inc.php3
-rw-r--r--modules-available/locationinfo/lang/de/template-tags.json5
-rw-r--r--modules-available/locationinfo/lang/en/template-tags.json3
-rw-r--r--modules-available/locationinfo/page.inc.php79
-rw-r--r--modules-available/locationinfo/templates/frontend-summary.html32
-rw-r--r--modules-available/locationinfo/templates/page-locations.html6
-rw-r--r--modules-available/serversetup-bwlp/inc/ipxe.inc.php102
-rw-r--r--modules-available/statistics/api.inc.php36
-rw-r--r--modules-available/statistics/page.inc.php113
-rw-r--r--modules-available/statistics/pages/projectors.inc.php58
-rw-r--r--modules-available/statistics/templates/machine-main.html4
-rw-r--r--modules-available/statistics/templates/page-replace.html104
-rw-r--r--modules-available/statistics/templates/projector-list.html2
-rw-r--r--modules-available/sysconfig/addmodule_adauth.inc.php92
-rw-r--r--modules-available/sysconfig/addmodule_ldapauth.inc.php23
-rw-r--r--modules-available/sysconfig/clientscript.js2
-rw-r--r--modules-available/sysconfig/inc/configmodule.inc.php10
-rw-r--r--modules-available/sysconfig/inc/configmodulebaseldap.inc.php11
-rw-r--r--modules-available/sysconfig/inc/configtgz.inc.php1
-rw-r--r--modules-available/sysconfig/inc/ldap.inc.php6
-rw-r--r--modules-available/sysconfig/page.inc.php36
-rw-r--r--modules-available/sysconfig/templates/ad-selfsearch.html2
-rw-r--r--modules-available/systemstatus/lang/de/template-tags.json2
-rw-r--r--modules-available/systemstatus/lang/en/template-tags.json2
-rw-r--r--modules-available/systemstatus/page.inc.php7
-rw-r--r--modules-available/systemstatus/templates/_page.html8
-rw-r--r--modules-available/vmstore/lang/de/template-tags.json14
-rw-r--r--modules-available/vmstore/lang/en/template-tags.json8
-rw-r--r--modules-available/vmstore/templates/page-vmstore.html38
36 files changed, 626 insertions, 239 deletions
diff --git a/modules-available/baseconfig_bwlp/baseconfig/settings.json b/modules-available/baseconfig_bwlp/baseconfig/settings.json
index 18e87ab6..0d4db4d4 100644
--- a/modules-available/baseconfig_bwlp/baseconfig/settings.json
+++ b/modules-available/baseconfig_bwlp/baseconfig/settings.json
@@ -79,6 +79,12 @@
"permissions": "2",
"validator": "list:no|yes"
},
+ "SLX_JUMBO_FRAMES": {
+ "catid": "networking",
+ "defaultvalue": "no",
+ "permissions": "2",
+ "validator": "list:no|yes"
+ },
"SLX_REMOTE_LOG_SESSIONS": {
"catid": "other",
"defaultvalue": "anonymous",
diff --git a/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json b/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
index d8d7e91f..a08a8c12 100644
--- a/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
+++ b/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
@@ -1,5 +1,4 @@
{
- "cat_5": "Gemeinsames Netzlaufwerk",
"networking": "Netzwerk-\/Internetzugriff",
"other": "Unkategorisiert",
"power": "Inaktivit\u00e4t und Abschaltung",
diff --git a/modules-available/baseconfig_bwlp/lang/de/config-variables.json b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
index a1ef4bab..ad2abc8d 100644
--- a/modules-available/baseconfig_bwlp/lang/de/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
@@ -5,6 +5,7 @@
"SLX_BIOS_CLOCK": "Legt fest, ob und wie die interne Uhr des Rechners im Bezug auf die Systemzeit des \/MiniLinux\/ gesetzt werden soll.\r\n*off* = Die interne Uhr des Rechners wird nicht ver\u00e4ndert.\r\n*local* = Die interne Uhr wird auf die Lokalzeit gesetzt. Bevorzugt wenn z.B. noch eine native Windows-Installation auf dem PC vorhanden ist.\r\n*utc* = Die interne Uhr wird auf die \/Koordinierte Weltzeit\/ gesetzt. Dies ist die g\u00e4ngige Einstellung in einem reinen Linux-Umfeld.",
"SLX_BRIDGE_OTHER_NICS": "Sofern ein Client mehrere Netzwerkkarten besitzt, k\u00f6nnen Sie mittels dieser Option alle weiteren gefundenen Karten in die VM durchreichen.",
"SLX_DEMO_PASS": "Passwort f\u00fcr den eingebauten *demo*-Account. Leer lassen, um das Einloggen zu verbieten.\r\nDas Passwort wird wie das root-Passwort nur gehasht an den Client \u00fcbertragen.",
+ "SLX_JUMBO_FRAMES": "Setzt die MTU auf den Clients auf 9000, statt wie \u00fcblich 1500. Da dies mit alten\/schlechten Routern oder Switches zu Problemen f\u00fchren k\u00f6nnte, ist diese Option standardm\u00e4\u00dfig deaktiviert.",
"SLX_LOGOUT_TIMEOUT": "Zeit in Sekunden, die eine Benutzersitzung ohne Aktion sein darf, bevor sie beendet wird.Feld leer lassen, um die Funktion zu deaktivieren.",
"SLX_NET_DOMAIN": "DNS-Dom\u00e4ne, in die sich die Clients eingliedern, sofern der DHCP Server keine solche vorgibt.",
"SLX_NET_SEARCH": "Per Leerzeichen getrennte Liste von Suchdom\u00e4nen, die der Client verwenden soll, sofern der DHCP-Server keine Vorgabe macht.",
diff --git a/modules-available/baseconfig_bwlp/lang/en/config-variables.json b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
index 3e33cbef..c56f171d 100644
--- a/modules-available/baseconfig_bwlp/lang/en/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
@@ -5,6 +5,7 @@
"SLX_BIOS_CLOCK": "Specifies whether and how the internal clock of the computer should be set in relation to the system time of the \/MiniLinux\/.\r\n*off* = The internal clock of the computer is not changed.\r\n*local* = The internal clock is set to local time. Preferably if, for example, there is still a native Windows installation available on the PC.\r\n*utc* = The internal clock is set to the \/Coordinated Universal Time\/. This is the most common setup in a pure Linux environment.",
"SLX_BRIDGE_OTHER_NICS": "If enabled, additional network cards installed in the Client will be bridged to the VM. ",
"SLX_DEMO_PASS": "Password for the *demo* account. Leave empty to disallow logging in as the demo user.\r\nLike the root password, the demo user's password will be sent to the client in its hashed form.",
+ "SLX_JUMBO_FRAMES": "Increases the MTU on the clients from 1500 to 9000. As this can lead to issues with old\/bad routers and switches, this option is disabled by default.",
"SLX_LOGOUT_TIMEOUT": "Time in seconds, in which a user session may remain without action before it is terminated.Leave field blank to disable the function.",
"SLX_NET_DOMAIN": "DNS domain in which the client integrate, provided the DHCP server does not specifies such.",
"SLX_NET_SEARCH": "Space separated list of DNS search domains to use in case the DHCP server doesn't supply any.",
@@ -29,4 +30,4 @@
"SLX_VMCHOOSER_TEMPLATES": "Defines how lectures that link to template VMs are treated wrt sorting.\r\n*IGNORE*: Sort among regular lectures\r\n*BUMP*: Move to top of list",
"SLX_VMCHOOSER_TIMEOUT": "Timeout in seconds after which the session will be closed if the user doesn't make any selection in vmChooser. Mouse or keyboard activity resets this timeout.",
"SLX_WAKEUP_SCHEDULE": "Fixed time to turn on the computer. At the moment this feature takes effect on every day - also at the weekend. Several times can be specified, separated by spaces.\r\n\r\nNote that some hardware might not properly support wakeup. It's recommended to only enable this feature for rooms where it's known that the hardware supports it."
-}
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-server-locations.html b/modules-available/dnbd3/templates/page-server-locations.html
index 7d7ddaf1..9ab0e973 100644
--- a/modules-available/dnbd3/templates/page-server-locations.html
+++ b/modules-available/dnbd3/templates/page-server-locations.html
@@ -6,13 +6,6 @@
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="server" value="{{serverid}}">
- <div class="buttonbar text-right">
- <button type="submit" class="btn btn-primary" name="action" value="savelocations">
- <span class="glyphicon glyphicon-floppy-disk"></span>
- {{lang_save}}
- </button>
- </div>
-
<div class="row">
<div class="col-md-6">
<h3>{{lang_allowedSubnets}}</h3>
@@ -93,4 +86,4 @@ document.addEventListener('DOMContentLoaded', function() {
$('.loc-check').change(updateLocations);
updateLocations();
});
-//--></script> \ No newline at end of file
+//--></script>
diff --git a/modules-available/dozmod/inc/pagemailtemplates.inc.php b/modules-available/dozmod/inc/pagemailtemplates.inc.php
index b7b5a8d4..ff47977f 100644
--- a/modules-available/dozmod/inc/pagemailtemplates.inc.php
+++ b/modules-available/dozmod/inc/pagemailtemplates.inc.php
@@ -59,14 +59,16 @@ class Page_mail_templates extends Page
$t['modified'] = !$t['original'];
$t['conflict'] = !$t['original'] && $t['edit_version'] < $t['version'];
}
-
}
+
protected function doRender()
{
$this->enrichHtml();
- $this->templates['allowedReset'] = User::hasPermission("templates.reset");
- $this->templates['allowedSave'] = User::hasPermission("templates.save");
- Render::addTemplate('templates', ['templates' => $this->templates]);
+ Render::addTemplate('templates', [
+ 'templates' => $this->templates,
+ 'allowedReset' => User::hasPermission("templates.reset"),
+ 'allowedSave' => User::hasPermission("templates.save"),
+ ]);
}
private function forcmp($string)
diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php
index ceaf04c0..ad71de8b 100644
--- a/modules-available/locationinfo/api.inc.php
+++ b/modules-available/locationinfo/api.inc.php
@@ -49,15 +49,11 @@ function HandleParameters()
/**
* Get last config modification timestamp for given panel.
- * This was planned to be smart and check the involved locations,
- * even going up the location tree if the opening time schedule
- * is inherited, but this would still be incomplete by design, as
- * it wouldn't react to the linked room plan being considered
- * for changes, or added/removed PCs etc. So rather than giving
- * an incomplete "clever" design for detecting changes, we only
- * consider direct editing of the panel now. So the advice would
- * simply be "if you want the panel to reload automatically, hit
- * the edit button and click save". Might even add a shortcut
+ * This is incomplete however, as it wouldn't react to the
+ * linked room plan being edited, or added/removed PCs
+ * etc. So the advice would simply be "if you want the
+ * panel to reload automatically, hit the edit button
+ * and click save". Might even add a shortcut
* reload-button to the list of panels at some point.
*
* @param string $paneluuid panels uuid
@@ -65,13 +61,21 @@ function HandleParameters()
*/
function getLastChangeTs($paneluuid)
{
- $panel = Database::queryFirst('SELECT lastchange FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ $panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
if ($panel === false) {
http_response_code(404);
die('Panel not found');
}
- return (int)$panel['lastchange'];
+ $lastChange = array((int)$panel['lastchange']);
+ if (!empty($panel['locationids'])) {
+ $res = Database::simpleQuery('SELECT lastchange FROM locationinfo_locationconfig
+ WHERE locationid IN (:locs)', array('locs' => explode(',', $panel['locationids'])));
+ while (($lc = $res->fetchColumn()) !== false) {
+ $lastChange[] = (int)$lc;
+ }
+ }
+ return max($lastChange);
}
/**
diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php
index 12b6aec7..edeb9ccf 100644
--- a/modules-available/locationinfo/inc/infopanel.inc.php
+++ b/modules-available/locationinfo/inc/infopanel.inc.php
@@ -12,7 +12,7 @@ class InfoPanel
*/
public static function getConfig($paneluuid, &$config)
{
- $panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids, lastchange FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ $panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
if ($panel === false) {
@@ -68,7 +68,6 @@ class InfoPanel
}
self::appendOpeningTimes($config['locations'], $lids);
- $config['ts'] = (int)$panel['lastchange'];
$config['locations'] = array_values($config['locations']);
$config['time'] = date('Y-n-j-G-') . (int)date('i') . '-' . (int)(date('s'));
diff --git a/modules-available/locationinfo/lang/de/template-tags.json b/modules-available/locationinfo/lang/de/template-tags.json
index be2814d6..b305f800 100644
--- a/modules-available/locationinfo/lang/de/template-tags.json
+++ b/modules-available/locationinfo/lang/de/template-tags.json
@@ -10,8 +10,6 @@
"lang_checkConnection": "Verbindung pr\u00fcfen",
"lang_closed": "Geschlossen",
"lang_closingTime": "Schlie\u00dfungszeit",
- "lang_config": "Einstellungen",
- "lang_configupdateTooltip": "Zeit nach der die Einstellungen aktualisiert werden (in Minuten)",
"lang_createPanel": "Panel anlegen",
"lang_credentials": "Anmeldung",
"lang_day": "Tag",
@@ -25,8 +23,8 @@
"lang_ecoMode": "E-Ink Modus",
"lang_ecoTooltip": "Anstelle der Farb-basierten PC-Status Bilder, werden Symbol-basierte PC Bilder verwendet",
"lang_editDefaultPanelHints": "Hier k\u00f6nnen Sie ein Panel (z.B. digitales T\u00fcrschild) in Aussehen und Funktionsweise definieren. Um im Kalender \u00d6ffnungszeiten anzeigen zu k\u00f6nnen, m\u00fcssen Sie im Tab \"Raum-\/Ortsbezogene Einstellungen\" f\u00fcr den ausgew\u00e4hlten Raum entsprechend \u00d6ffnungszeiten eintragen. Damit im Kalender Veranstaltungen und andere Termine angezeigt werden k\u00f6nnen, muss ein funktionierendes Backend konfiguriert und den ausgew\u00e4hlten R\u00e4umen zugewiesen worden sein.",
- "lang_editSummaryPanelHints": "Hier k\u00f6nnen Sie ein Summary-Panel definieren. Das Panel zeigt eine Übersicht der in den R\u00e4umen enthalten PCs.",
"lang_editPanel": "Panel bearbeiten",
+ "lang_editSummaryPanelHints": "Hier k\u00f6nnen Sie ein Summary-Panel definieren. Das Panel zeigt eine \u00dcbersicht der in den R\u00e4umen enthalten PCs.",
"lang_editUrlPanelHints": "Hier k\u00f6nnen Sie konfigurieren, welche URL das Panel aufrufen soll. Dies erm\u00f6glicht Ihnen z.B. in Eingangsbereichen aktuelle Meldungen der Hochschule oder sonstige Webseiten anzuzeigen.",
"lang_entryName": "Name",
"lang_error": "Fehler",
@@ -38,6 +36,7 @@
"lang_insecureSsl": "Unsicheres SSL",
"lang_language": "Sprache",
"lang_languageTooltip": "Legt die Sprache der angezeigten Oberfl\u00e4che fest",
+ "lang_lastCalendarUpdate": "Kalender Update",
"lang_locationName": "Name",
"lang_locationSettings": "Raum-\/Ortsbezogene Einstellungen",
"lang_locations": "Orte",
diff --git a/modules-available/locationinfo/lang/en/template-tags.json b/modules-available/locationinfo/lang/en/template-tags.json
index be927ee4..5679e8b8 100644
--- a/modules-available/locationinfo/lang/en/template-tags.json
+++ b/modules-available/locationinfo/lang/en/template-tags.json
@@ -10,8 +10,6 @@
"lang_checkConnection": "Check connection",
"lang_closed": "Closed",
"lang_closingTime": "Closing time",
- "lang_config": "Config",
- "lang_configupdateTooltip": "Time interval the config gets updated (in minutes)",
"lang_createPanel": "Create panel",
"lang_credentials": "Login",
"lang_day": "Day",
@@ -38,6 +36,7 @@
"lang_insecureSsl": "Insecure SSL",
"lang_language": "Language",
"lang_languageTooltip": "The language the frontend uses",
+ "lang_lastCalendarUpdate": "Calendar update",
"lang_locationName": "Name",
"lang_locationSettings": "Location specific settings",
"lang_locations": "Locations",
diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php
index d4a2b35e..22a21951 100644
--- a/modules-available/locationinfo/page.inc.php
+++ b/modules-available/locationinfo/page.inc.php
@@ -129,8 +129,8 @@ class Page_LocationInfo extends Page
}
$serverlocationid = Request::post('serverlocationid', '', 'string');
- $recursive = (Request::post('recursive', '', 'string') !== '');
- if (empty($serverlocationid) && !$recursive) {
+ $changeServerRecursive = (Request::post('recursive', '', 'string') !== '');
+ if (empty($serverlocationid) && !$changeServerRecursive) {
$insertServerId = null;
$ignoreServer = 1;
} else {
@@ -170,12 +170,16 @@ class Page_LocationInfo extends Page
$mangled[] = $entry;
}
if (empty($mangled)) {
- $openingtimes = '';
+ $openingtimes = null;
} else {
$openingtimes = json_encode($mangled);
}
}
}
+ $NOW = time();
+ // Check if openingtimes changed
+ $res = Database::queryFirst('SELECT openingtime FROM locationinfo_locationconfig WHERE locationid = :locationid', compact('locationid'));
+ $otChanged = $res === false || $res['openingtime'] !== $openingtimes;
Database::exec("INSERT INTO `locationinfo_locationconfig` (locationid, serverid, serverlocationid, openingtime, lastcalendarupdate, lastchange)
VALUES (:id, :insertserverid, :serverlocationid, :openingtimes, 0, :now)
@@ -187,27 +191,66 @@ class Page_LocationInfo extends Page
'openingtimes' => $openingtimes,
'serverlocationid' => $serverlocationid,
'ignore_server' => $ignoreServer,
- 'now' => time(),
+ 'now' => $NOW,
));
- if (!$recursive)
- return true;
-
- // Recursive overwriting of serverid
- $children = Location::getRecursiveFlat($locationid);
- $array = array();
- foreach ($children as $loc) {
- $array[] = $loc['locationid'];
+ if ($otChanged) {
+ $tree = Location::getLocationsAssoc();
+ $todo = array();
+ $done = array();
+ foreach ($tree as $l) {
+ if ($l['parentlocationid'] == $locationid) {
+ $todo[] = $l['locationid'];
+ }
+ }
+ while (!empty($todo)) {
+ $loc = array_pop($todo);
+ if (in_array($loc, $done))
+ continue;
+ $done[] = $loc;
+ // See if this one inherits
+ $res = Database::queryFirst('SELECT openingtime FROM locationinfo_locationconfig WHERE locationid = :loc', compact('loc'));
+ if ($res === false) {
+ $res = Database::exec('INSERT INTO locationinfo_locationconfig (locationid, lastchange)
+ VALUES (:locationid, :now) ON DUPLICATE KEY UPDATE lastchange = :now',
+ array('locationid' => $loc, 'now' => $NOW));
+ } elseif (strlen($res['openingtime']) < 5) {
+ $res = Database::exec('UPDATE locationinfo_locationconfig SET lastchange = :now, openingtime = NULL
+ WHERE locationid = :locationid',
+ array('locationid' => $loc, 'now' => $NOW));
+ } else {
+ $res = 0;
+ }
+ if ($res > 0) {
+ // Row was updated, which means the openingtime column was empty, which means the openingtime is inherited, descend further
+ $todo = array_merge($todo, $tree[$loc]['children']);
+ foreach ($tree as $l) {
+ if ($l['parentlocationid'] == $loc) {
+ $todo[] = $l['locationid'];
+ }
+ }
+ }
+ }
}
- if (!empty($array)) {
- Database::exec("UPDATE locationinfo_locationconfig
+
+ if ($changeServerRecursive) {
+ // Recursive overwriting of serverid
+ $children = Location::getRecursiveFlat($locationid);
+ $array = array();
+ foreach ($children as $loc) {
+ $array[] = $loc['locationid'];
+ }
+ if (!empty($array)) {
+ Database::exec("UPDATE locationinfo_locationconfig
SET serverid = :serverid, lastcalendarupdate = IF(serverid <> :serverid, 0, lastcalendarupdate), lastchange = :now
WHERE locationid IN (:locations)", array(
'serverid' => $serverid,
'locations' => $array,
- 'now' => time(),
- ));
+ 'now' => $NOW,
+ ));
+ }
}
+
return true;
}
@@ -465,7 +508,7 @@ class Page_LocationInfo extends Page
$locations[$locid] += array(
'openingGlyph' => $glyph,
'backend' => $backend,
- 'lastCalendarUpdate' => $row['lastcalendarupdate'], // TODO
+ 'lastCalendarUpdate' => Util::prettyTime($row['lastcalendarupdate']), // TODO
'backendMissing' => !CourseBackend::exists($row['servertype']),
);
}
@@ -478,8 +521,8 @@ class Page_LocationInfo extends Page
$depth--;
}
while ($location['depth'] > $depth) {
+ array_push($stack, empty($location['openingGlyph']) && ($depth === -1 || empty($stack[$depth])) ? '' : 'arrow-up');
$depth++;
- array_push($stack, empty($location['openingGlyph']) ? '' : 'arrow-up');
}
if ($depth > 0 && empty($location['openingGlyph'])) {
$location['openingGlyph'] = $stack[$depth - 1];
diff --git a/modules-available/locationinfo/templates/frontend-summary.html b/modules-available/locationinfo/templates/frontend-summary.html
index ec5d8aab..4105dd16 100644
--- a/modules-available/locationinfo/templates/frontend-summary.html
+++ b/modules-available/locationinfo/templates/frontend-summary.html
@@ -226,8 +226,8 @@
queryRooms();
nextUpdate = 1000;
}
- for (property in rooms) {
- upDateRoomState(rooms[property]);
+ if (nextUpdate !== 1000) {
+ queryPanelChange();
}
clearTimeout(timeout);
setTimeout(update, nextUpdate);
@@ -267,7 +267,9 @@
}
ComputeCurrentState(rooms[json[i].id]);
}
- update();
+ for (property in rooms) {
+ upDateRoomState(rooms[property]);
+ }
}
/**
@@ -765,6 +767,30 @@
});
}
+ /**
+ * Checks whether the panel has been edited and reloads
+ * the entire page if so.
+ */
+ function queryPanelChange() {
+ $.ajax({
+ url: "{{dirprefix}}api.php?do=locationinfo&get=timestamp&uuid={{uuid}}",
+ dataType: 'json',
+ cache: false,
+ timeout: 5000,
+ success: function (result) {
+ if (!result || !result.ts) {
+ console.log('Warning: get=timestamp didnt return json with ts field');
+ return;
+ }
+ if (config.ts && config.ts !== result.ts) {
+ // Change
+ window.location.reload(true);
+ }
+ config.ts = result.ts;
+ }
+ })
+ }
+
</script>
</head>
<body>
diff --git a/modules-available/locationinfo/templates/page-locations.html b/modules-available/locationinfo/templates/page-locations.html
index de8dab7e..b30ef2ed 100644
--- a/modules-available/locationinfo/templates/page-locations.html
+++ b/modules-available/locationinfo/templates/page-locations.html
@@ -7,6 +7,7 @@
<tr>
<th>{{lang_locationName}}</th>
<th>{{lang_backend}}</th>
+ <th>{{lang_lastCalendarUpdate}}</th>
<th>{{lang_openingtimes}}</th>
</tr>
</thead>
@@ -25,6 +26,11 @@
{{backend}}
</td>
<td>
+ {{#backend}}
+ {{lastCalendarUpdate}}
+ {{/backend}}
+ </td>
+ <td>
<span class="glyphicon glyphicon-{{openingGlyph}}"></span>
</td>
</tr>
diff --git a/modules-available/serversetup-bwlp/inc/ipxe.inc.php b/modules-available/serversetup-bwlp/inc/ipxe.inc.php
new file mode 100644
index 00000000..abeea748
--- /dev/null
+++ b/modules-available/serversetup-bwlp/inc/ipxe.inc.php
@@ -0,0 +1,102 @@
+<?php
+
+
+class Ipxe
+{
+
+ public static function parsePxeLinux($input)
+ {
+ /*
+ LABEL openslx-debug
+ MENU LABEL ^bwLehrpool-Umgebung starten (nosplash, debug)
+ KERNEL http://IPADDR/boot/default/kernel
+ INITRD http://IPADDR/boot/default/initramfs-stage31
+ APPEND slxbase=boot/default
+ IPAPPEND 3
+ */
+ $propMap = [
+ 'menu label' => ['string', 'title'],
+ 'menu default' => ['true', 'isDefault'],
+ 'menu hide' => ['true', 'isHidden'],
+ 'kernel' => ['string', 'kernel'],
+ 'initrd' => ['string', 'initrd'],
+ 'append' => ['string', 'append'],
+ 'ipappend' => ['int', 'ipAppend'],
+ 'localboot' => ['int', 'localBoot'],
+ ];
+ $sections = array();
+ $lines = preg_split('/[\r\n]+/', $input);
+ $section = null;
+ foreach ($lines as $line) {
+ if (!preg_match('/^\s*([^m\s]+|menu\s+\S+)\s+(.*?)\s*$/i', $line, $out))
+ continue;
+ $key = strtolower($out[1]);
+ $key = preg_replace('/\s+/', ' ', $key);
+ if ($key === 'label') {
+ if ($section !== null) {
+ $sections[] = $section;
+ }
+ $section = new PxeSection($out[2]);
+ } elseif ($section === null) {
+ continue;
+ } elseif (isset($propMap[$key])) {
+ $opt = $propMap[$key];
+ if ($opt[0] === 'true') {
+ $val = true;
+ } else {
+ $val = $out[2];
+ settype($val, $opt[0]);
+ }
+ $section->{$opt[1]} = $val;
+ }
+ }
+ if ($section !== null) {
+ $sections[] = $section;
+ }
+ return $sections;
+ }
+
+}
+
+class PxeMenu
+{
+ public $title;
+ public $timeoutMs;
+ public $totalTimeoutMs;
+ public $timeoutLabel;
+}
+
+class PxeSection
+{
+ /**
+ * @var string label used internally in PXEMENU definition to address this entry
+ */
+ public $label;
+ /**
+ * @var string MENU LABEL of PXEMENU - title of entry displayed to the user
+ */
+ public $title;
+ public $kernel;
+ public $initrd;
+ public $append;
+ /**
+ * @var int IPAPPEND from PXEMENU. Bitmask of valid options 1 and 2.
+ */
+ public $ipAppend;
+ public $passwd;
+ /**
+ * @var bool whether this section is marked as default (booted after timeout)
+ */
+ public $isDefault = false;
+ /**
+ * @var bool Menu entry is not visible (can only be triggered by timeout)
+ */
+ public $isHidden = false;
+ /**
+ * @var int Value of the LOCALBOOT field
+ */
+ public $localBoot;
+
+ public function __construct($label) { $this->label = $label; }
+}
+
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index a614658a..a7a636b3 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -263,6 +263,7 @@ if ($type{0} === '~') {
// `devicetype`, `devicename`, `subid`, `machineuuid`
// Make sure all screens are in the general hardware table
$hwids = array();
+ $keepPair = array();
foreach ($screens as $port => $screen) {
if (!array_key_exists('name', $screen))
continue;
@@ -274,6 +275,7 @@ if ($type{0} === '~') {
$hwids[$screen['name']] = $hwid;
}
// Now add new entries
+ $keepPair[] = array($hwid, $port);
$machinehwid = Database::insertIgnore('machine_x_hw', 'machinehwid', array(
'hwid' => $hwid,
'machineuuid' => $uuid,
@@ -302,30 +304,30 @@ if ($type{0} === '~') {
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);
+ Database::exec("DELETE FROM machine_x_hw_prop
+ WHERE machinehwid = :mhwid AND prop NOT LIKE '@%' AND prop NOT IN (:props)", array(
+ 'mhwid' => $machinehwid,
+ 'props' => array_values($validProps),
+ ));
}
}
// Remove/disable stale entries
- if (empty($hwids)) {
+ if (empty($keepPair)) {
// 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",
+ 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);
-
+ Database::exec("UPDATE machine_x_hw x, statistic_hw h
+ SET x.disconnecttime = UNIX_TIMESTAMP()
+ WHERE (x.hwid, x.devpath) NOT IN (:pairs) AND x.disconnecttime = 0 AND h.hwtype = :type
+ AND x.machineuuid = :uuid", array(
+ 'pairs' => $keepPair,
+ 'uuid' => $uuid,
+ 'type' => DeviceType::SCREEN,
+ ));
}
}
} else if ($type === '~suspend') {
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index bd67123e..ea5b6f03 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -21,6 +21,11 @@ class Page_Statistics extends Page
private $query;
+ /**
+ * @var bool whether we have a SubPage from the pages/ subdir
+ */
+ private $haveSubpage;
+
/* PHP sucks, no static, const array definitions... Or am I missing something? */
public function initConstants()
{
@@ -125,53 +130,6 @@ class Page_Statistics extends Page
/* TODO ... */
}
- /*
- * TODO: Move to separate unit... hardware configurator?
- */
-
- protected function handleProjector($action)
- {
- $hwid = Request::post('hwid', false, 'int');
- if ($hwid === false) {
- Util::traceError('Param hwid missing');
- }
- if ($action === 'addprojector') {
- Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
- . ' VALUES (:hwid, :prop, :value)', array(
- 'hwid' => $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();
@@ -180,24 +138,42 @@ class Page_Statistics extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
- $action = Request::post('action');
- if ($action === 'setnotes') {
- $uuid = Request::post('uuid', '', 'string');
- $text = Request::post('content', '', 'string');
- if (empty($text)) {
- $text = null;
+
+ $show = Request::any('show', 'stat', 'string');
+ $show = preg_replace('/[^a-z0-9_\-]/', '', $show);
+
+ if (file_exists('modules/statistics/pages/' . $show . '.inc.php')) {
+
+ require_once 'modules/statistics/pages/' . $show . '.inc.php';
+ $this->haveSubpage = true;
+ SubPage::doPreprocess();
+
+ } else {
+
+ $action = Request::post('action');
+ if ($action === 'setnotes') {
+ $uuid = Request::post('uuid', '', 'string');
+ $text = Request::post('content', '', 'string');
+ if (empty($text)) {
+ $text = null;
+ }
+ Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
+ 'uuid' => $uuid,
+ 'text' => $text,
+ ));
+ Message::addSuccess('notes-saved');
+ Util::redirect('?do=Statistics&uuid=' . $uuid);
+ } elseif ($action === 'delmachines') {
+ $this->deleteMachines();
+ Util::redirect('?do=statistics', true);
}
- Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
- 'uuid' => $uuid,
- 'text' => $text,
- ));
- Message::addSuccess('notes-saved');
- Util::redirect('?do=Statistics&uuid=' . $uuid);
- } elseif ($action === 'addprojector' || $action === 'delprojector') {
- $this->handleProjector($action);
- } elseif ($action === 'delmachines') {
- $this->deleteMachines();
- Util::redirect('?do=statistics', true);
+
+ }
+
+ if (Request::isPost()) {
+ // Make sure we don't render any content for POST requests - should be handled above and then
+ // redirected properly
+ Util::redirect('?do=statistics');
}
}
@@ -229,6 +205,11 @@ class Page_Statistics extends Page
protected function doRender()
{
+ if ($this->haveSubpage) {
+ SubPage::doRender();
+ return;
+ }
+
$uuid = Request::get('uuid', false, 'string');
if ($uuid !== false) {
$this->showMachine($uuid);
@@ -236,10 +217,6 @@ class Page_Statistics extends Page
}
$show = Request::get('show', 'stat', 'string');
- if ($show === 'projectors') {
- $this->showProjectors();
- return;
- }
/* read filter */
$this->query = Request::any('filters', false);
diff --git a/modules-available/statistics/pages/projectors.inc.php b/modules-available/statistics/pages/projectors.inc.php
new file mode 100644
index 00000000..cde542c6
--- /dev/null
+++ b/modules-available/statistics/pages/projectors.inc.php
@@ -0,0 +1,58 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', false, 'string');
+ if ($action !== false) {
+ self::handleProjector($action);
+ }
+ }
+
+ private static function handleProjector($action)
+ {
+ $hwid = Request::post('hwid', false, 'int');
+ if ($hwid === false) {
+ Util::traceError('Param hwid missing');
+ }
+ if ($action === 'addprojector') {
+ Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
+ . ' VALUES (:hwid, :prop, :value)', array(
+ 'hwid' => $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');
+ }
+
+ public static function doRender()
+ {
+ self::showProjectors();
+ }
+
+ private static 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);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html
index 19deb8b3..d8f2c521 100644
--- a/modules-available/statistics/templates/machine-main.html
+++ b/modules-available/statistics/templates/machine-main.html
@@ -144,11 +144,11 @@
<tr>
<td class="text-nowrap">{{lang_screens}}</td>
<td>
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
</form>
- <form method="post" action="?do=statistics" id="addprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="addprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="addprojector">
</form>
diff --git a/modules-available/statistics/templates/page-replace.html b/modules-available/statistics/templates/page-replace.html
new file mode 100644
index 00000000..f87610a2
--- /dev/null
+++ b/modules-available/statistics/templates/page-replace.html
@@ -0,0 +1,104 @@
+<h1>{{lang_replaceMachinesHeading}}</h1>
+
+<style>
+ .reptable {
+ border-collapse: separate;
+ border-spacing: 2px;
+ }
+ .reptable td.a {
+ padding: 2px;
+ border:1px solid #ccc;
+ border-radius: 3px;
+ background: #eee;
+ vertical-align: top;
+ }
+ .reptable td.b {
+ font-size: 300%;
+ }
+</style>
+
+<form method="post" action="?do=statistics&amp;show=replace">
+ <input type="hidden" name="token" value="{{token}}">
+ <table class="reptable">
+ <thead>
+ <tr>
+ <th>{{lang_replaceOld}}</th>
+ <th></th>
+ <th>{{lang_replaceNew}}</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#pairs}}
+ <tr>
+ <td class="a">
+ <div><b>{{oldhost}}</b> {{oldip}}</div>
+ <div class="slx-bold">{{oldmodel}}</div>
+ <div class="small">{{oldmac}} – {{olduuid}}</div>
+ <div>{{lang_lastSeen}}: {{oldlastseen_s}}</div>
+ </td>
+ <td class="b">&rightarrow;</td>
+ <td class="a">
+ <div><b>{{newhost}}</b> {{newip}}</div>
+ <div class="slx-bold">{{newmodel}}</div>
+ <div class="small">{{newmac}} – {{newuuid}}</div>
+ <div>{{lang_firstSeen}}: {{newfirstseen_s}}</div>
+ </td>
+ <td>
+ <div class="checkbox checkbox-inline">
+ <input type="checkbox" name="replace[]" value="{{olduuid}}x{{newuuid}}">
+ <label></label>
+ </div>
+ </td>
+ </tr>
+ {{/pairs}}
+ </tbody>
+ </table>
+
+ <div class="text-right">
+ <button type="button" class="btn btn-danger" name="action" value="replace" data-toggle="modal" data-target="#confirm-dialog">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ (<span id="rep-count">0</span>)
+ </button>
+ </div>
+
+ <div class="modal fade" id="confirm-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="myModalLabel">{{lang_replace}}</h4>
+ </div>
+ <div class="modal-body">
+ {{lang_sureReplaceNoUndo}}
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="submit" name="action" value="replace" class="btn btn-danger">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</form>
+
+<script type="application/javascript"><!--
+ document.addEventListener('DOMContentLoaded', function () {
+ $('td.a').click(function () {
+ var $cb = $(this).parent().find('input:checkbox');
+ $cb.prop('checked', !$cb.is(':checked'));
+ cbChanged();
+ });
+ $('input:checkbox').change(function () {
+ cbChanged();
+ });
+ function cbChanged() {
+ var cnt = $('input:checkbox:checked').length;
+ $('#rep-count').text(cnt).parent().prop('disabled', cnt === 0);
+ }
+ cbChanged();
+ });
+//--></script> \ No newline at end of file
diff --git a/modules-available/statistics/templates/projector-list.html b/modules-available/statistics/templates/projector-list.html
index bc9ecdbd..c33aae09 100644
--- a/modules-available/statistics/templates/projector-list.html
+++ b/modules-available/statistics/templates/projector-list.html
@@ -1,7 +1,7 @@
<div class="panel panel-default">
<div class="panel-heading">{{lang_projectors}}</div>
<div class="panel-body">
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
<p>{{lang_thoseAreProjectors}}</p>
diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php
index 07806061..df7f385d 100644
--- a/modules-available/sysconfig/addmodule_adauth.inc.php
+++ b/modules-available/sysconfig/addmodule_adauth.inc.php
@@ -31,7 +31,7 @@ class AdAuth_Start extends AddModule_Base
if (isset($data['server']) && preg_match('/^(.*)\:(636|3269|389|3268)$/', $data['server'], $out)) {
$data['server'] = $out[1];
}
- if (isset($data['homeattr']) && !isset($data['mapping']['homemount'])) {
+ if (isset($data['homeattr']) && !isset($data['mapping']['homemount']) && strtolower($data['homeattr']) !== 'homedirectory') {
$data['mapping']['homemount'] = $data['homeattr'];
}
$data['step'] = 'AdAuth_CheckConnection';
@@ -59,13 +59,18 @@ class AdAuth_CheckConnection extends AddModule_Base
$this->server = Request::post('server');
$binddn = Request::post('binddn');
$ssl = Request::post('ssl', 'off') === 'on';
- if (empty($this->server) || empty($binddn)) {
- Message::addError('main.empty-field');
+ if (empty($this->server)) {
+ Message::addError('main.parameter-empty', 'server');
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
+ if (empty($binddn)) {
+ Message::addError('main.parameter-empty', 'binddn');
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
if ((preg_match(AD_AT_REGEX, $this->bindDn) > 0) && (strlen($this->searchBase) < 2)) {
- Message::addError('main.empty-field', 'searchBase');
+ Message::addError('main.parameter-empty', 'searchBase');
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
@@ -91,6 +96,7 @@ class AdAuth_CheckConnection extends AddModule_Base
protected function renderInternal()
{
+ $mapping = Request::post('mapping', false, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -99,17 +105,16 @@ class AdAuth_CheckConnection extends AddModule_Base
'binddn' => $this->bindDn,
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl'),
'fixnumeric' => Request::post('fixnumeric'),
'certificate' => Request::post('certificate', ''),
'taskid' => $this->scanTask['id'],
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
);
$data['prev'] = 'AdAuth_Start';
if ((preg_match(AD_BOTH_REGEX, $this->bindDn) > 0) || (strlen($this->searchBase) < 2)) {
$data['next'] = 'AdAuth_SelfSearch';
- } elseif (empty($data['homeattr'])) {
+ } elseif (empty($mapping['homemount'])) {
$data['next'] = 'AdAuth_HomeAttrCheck';
} else {
$data['next'] = 'AdAuth_CheckCredentials';
@@ -127,10 +132,8 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -138,10 +141,13 @@ class AdAuth_SelfSearch extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
$this->originalBindDn = '';
// Fix bindDN if short name given
@@ -190,6 +196,7 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function renderInternal()
{
+ $mapping = Request::post('mapping', false, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -199,16 +206,15 @@ class AdAuth_SelfSearch extends AddModule_Base
'binddn' => Request::post('binddn'),
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl') === 'on',
'fixnumeric' => Request::post('fixnumeric'),
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
'originalbinddn' => $this->originalBindDn,
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
'prev' => 'AdAuth_Start'
);
- if (empty($data['homeattr'])) {
+ if (empty($mapping['homemount'])) {
$data['next'] = 'AdAuth_HomeAttrCheck';
} else {
$data['next'] = 'AdAuth_CheckCredentials';
@@ -226,10 +232,8 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -237,10 +241,13 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
if ($ssl) {
$uri = "ldaps://$server:$port/";
@@ -276,7 +283,6 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
'binddn' => Request::post('binddn'),
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl') === 'on',
'fixnumeric' => Request::post('fixnumeric'),
'fingerprint' => Request::post('fingerprint'),
@@ -299,10 +305,8 @@ class AdAuth_CheckCredentials extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -310,10 +314,13 @@ class AdAuth_CheckCredentials extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
// Test query 4 users
if ($ssl) {
@@ -502,8 +509,7 @@ class AdAuth_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $parent = $this->stopOldInstance();
- $tgz = $module->generate($this->edit === false, $parent);
+ $tgz = $module->generate($this->edit === false);
}
if ($tgz === false) {
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
@@ -514,24 +520,6 @@ class AdAuth_Finish extends AddModule_Base
);
}
- private function stopOldInstance()
- {
- if ($this->edit === false)
- return NULL;
- $list = ConfigTgz::getAllForModule($this->edit->id());
- if (!is_array($list))
- return NULL;
- $parent = NULL;
- foreach ($list as $tgz) {
- if (!$tgz->isActive())
- continue;
- $task = Trigger::ldadp($tgz->id(), $parent);
- if (isset($task['id']))
- $parent = $task['id'];
- }
- return $parent;
- }
-
protected function renderInternal()
{
Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-finish', $this->taskIds);
diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php
index a193f779..1db6cb51 100644
--- a/modules-available/sysconfig/addmodule_ldapauth.inc.php
+++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php
@@ -23,7 +23,7 @@ class LdapAuth_Start extends AddModule_Base
if (isset($data['server']) && preg_match('/^(.*)\:(636|389)$/', $data['server'], $out)) {
$data['server'] = $out[1];
}
- if (isset($data['homeattr']) && !isset($data['mapping']['homemount'])) {
+ if (isset($data['homeattr']) && !isset($data['mapping']['homemount']) && strtolower($data['homeattr']) !== 'homedirectory') {
$data['mapping']['homemount'] = $data['homeattr'];
}
$data['step'] = 'LdapAuth_CheckConnection';
@@ -281,8 +281,7 @@ class LdapAuth_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $parent = $this->stopOldInstance();
- $tgz = $module->generate($this->edit === false, $parent);
+ $tgz = $module->generate($this->edit === false);
}
if ($tgz === false) {
AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render()
@@ -293,24 +292,6 @@ class LdapAuth_Finish extends AddModule_Base
);
}
- private function stopOldInstance()
- {
- if ($this->edit === false)
- return NULL;
- $list = ConfigTgz::getAllForModule($this->edit->id());
- if (!is_array($list))
- return NULL;
- $parent = NULL;
- foreach ($list as $tgz) {
- if (!$tgz->isActive())
- continue;
- $task = Trigger::ldadp($tgz->id(), $parent);
- if (isset($task['id']))
- $parent = $task['id'];
- }
- return $parent;
- }
-
protected function renderInternal()
{
Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ldap-finish', $this->taskIds);
diff --git a/modules-available/sysconfig/clientscript.js b/modules-available/sysconfig/clientscript.js
index f3a47824..1553d678 100644
--- a/modules-available/sysconfig/clientscript.js
+++ b/modules-available/sysconfig/clientscript.js
@@ -98,7 +98,7 @@ function checkBuildStatus() {
confs.push($(this).val());
});
if (mods.length === 0 && confs.length === 0) return;
- if (++statusChecks < 10) setTimeout(checkBuildStatus, 200 + 50 * statusChecks);
+ if (++statusChecks < 10) setTimeout(checkBuildStatus, 150 + 100 * statusChecks);
$.post('?do=SysConfig', { mods: mods.join(), confs: confs.join(), token: TOKEN, action: 'status' }, function (data) {
if (typeof data === 'undefined') return;
if (typeof data.mods === 'object') updateButtonColor($(".refmod.btn-primary"), data.mods);
diff --git a/modules-available/sysconfig/inc/configmodule.inc.php b/modules-available/sysconfig/inc/configmodule.inc.php
index cfe79802..2cee37a9 100644
--- a/modules-available/sysconfig/inc/configmodule.inc.php
+++ b/modules-available/sysconfig/inc/configmodule.inc.php
@@ -412,6 +412,9 @@ abstract class ConfigModule
$this->markFailed();
return false;
}
+ } elseif (!file_exists($tmpTgz)) {
+ EventLog::warning('ConfigModule::markUpdated for tmpTgz="' . $this->moduleTitle . '" called which doesn\'t exist. Doing nothing.');
+ return true;
} else {
$task = Taskmanager::submit('MoveFile', array(
'source' => $tmpTgz,
@@ -419,10 +422,11 @@ abstract class ConfigModule
));
$task = Taskmanager::waitComplete($task, 5000);
if (Taskmanager::isFailed($task) || !Taskmanager::isFinished($task)) {
- if (!API && !AJAX)
+ if (!API && !AJAX) {
Taskmanager::addErrorMessage($task);
- else
- EventLog::failure('Could not move ' . $tmpTgz . ' to ' . $this->moduleArchive . ' while generating "' . $this->moduleTitle . '"');
+ } else {
+ EventLog::failure('Could not move ' . $tmpTgz . ' to ' . $this->moduleArchive . ' while generating "' . $this->moduleTitle . '"', print_r($task, true));
+ }
$this->markFailed();
return false;
}
diff --git a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
index d8a41a8b..d6fc3ed9 100644
--- a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
+++ b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
@@ -33,7 +33,10 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
protected function generateInternal($tgz, $parent)
{
- Trigger::ldadp($this->id(), $parent);
+ $np = Trigger::ldadp($this->id(), $parent);
+ if ($np !== false) {
+ $parent = $np;
+ }
$config = $this->moduleData;
if (isset($config['certificate']) && !is_string($config['certificate'])) {
unset($config['certificate']);
@@ -64,7 +67,11 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
$config['fixnumeric'] = 's';
}
$this->preTaskmanagerHook($config);
- return Taskmanager::submit('CreateLdapConfig', $config);
+ $task = Taskmanager::submit('CreateLdapConfig', $config);
+ if (is_array($task) && isset($task['id'])) {
+ Trigger::ldadp(null, $task['id']);
+ }
+ return $task;
}
/**
diff --git a/modules-available/sysconfig/inc/configtgz.inc.php b/modules-available/sysconfig/inc/configtgz.inc.php
index 09ea999c..17c9f35d 100644
--- a/modules-available/sysconfig/inc/configtgz.inc.php
+++ b/modules-available/sysconfig/inc/configtgz.inc.php
@@ -157,7 +157,6 @@ class ConfigTgz
{
if ($this->configId === 0)
Util::traceError('ConfigTgz::markUpdated called with invalid config id!');
- Event::activeConfigChanged();
if ($this->areAllModulesUpToDate())
return $this->mark('OK');
return $this->mark('OUTDATED');
diff --git a/modules-available/sysconfig/inc/ldap.inc.php b/modules-available/sysconfig/inc/ldap.inc.php
index 23b24885..349a662e 100644
--- a/modules-available/sysconfig/inc/ldap.inc.php
+++ b/modules-available/sysconfig/inc/ldap.inc.php
@@ -12,11 +12,7 @@ class Ldap
{
// To find ourselves we try to figure out the proper search base, since the given one
// might be just for users, not for functional or utility accounts
- if (preg_match('/,(OU=.*DC=.*)$/i', Ldap::normalizeDn($binddn), $out)) {
- // Get OU from binddn; works if not given short form of DOMAIN\user or user@domain.fqdn.com
- $searchbase = $out[1];
- } elseif (preg_match('/,(DC=.*)$/i', Ldap::normalizeDn($searchbase), $out)) {
- // Otherwise, shorten search base enough to only consider the DC=..,DC=.. part at the end
+ if (preg_match('/^\w+=[^=]+,(.*)$/i', Ldap::normalizeDn($binddn), $out)) {
$searchbase = $out[1];
}
return $searchbase;
diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php
index 043645df..30271514 100644
--- a/modules-available/sysconfig/page.inc.php
+++ b/modules-available/sysconfig/page.inc.php
@@ -343,6 +343,9 @@ class Page_SysConfig extends Page
Message::addError('main.empty-field');
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
+ // Validate that either the configid is valid (in case we override for a specific location)
+ // or that if the locationid is 0 (=global) that the configid exists, because it's not allowed
+ // to unset the global config
if ($this->currentLoc === 0 || $configid !== 0) {
$row = Database::queryFirst("SELECT title, filepath FROM configtgz WHERE configid = :configid LIMIT 1", array('configid' => $configid));
if ($row === false) {
@@ -358,6 +361,7 @@ class Page_SysConfig extends Page
Database::exec("INSERT INTO configtgz_location (locationid, configid) VALUES (:locationid, :configid)"
. " ON DUPLICATE KEY UPDATE configid = :configid", compact('locationid', 'configid'));
}
+ Event::activeConfigChanged();
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
@@ -475,4 +479,36 @@ class Page_SysConfig extends Page
AddConfig_Base::setStep($step);
}
+ /**
+ * If modules need updates (blue refresh buttons), we query their state
+ * via ajax, in case they are about to generate. This happens for example
+ * if you edit a module and a bunch of configs depend on it and will be
+ * rebuilt.
+ */
+ protected function doAjax()
+ {
+ if (Request::post('action') === 'status') {
+ $mods = Request::post('mods');
+ $confs = Request::post('confs');
+ $outMods = array();
+ $outConfs = array();
+ $mods = explode(',', $mods);
+ $confs = explode(',', $confs);
+ // Mods
+ $res = Database::simpleQuery("SELECT moduleid FROM configtgz_module
+ WHERE moduleid in (:mods) AND status = 'OK'", compact('mods'));
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $outMods[] = $row['moduleid'];
+ }
+ // Confs
+ $res = Database::simpleQuery("SELECT configid FROM configtgz
+ WHERE configid in (:confs) AND status = 'OK'", compact('confs'));
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $outConfs[] = $row['configid'];
+ }
+ Header('Content-Type: application/json');
+ die(json_encode(array('mods' => $outMods, 'confs' => $outConfs)));
+ }
+ }
+
}
diff --git a/modules-available/sysconfig/templates/ad-selfsearch.html b/modules-available/sysconfig/templates/ad-selfsearch.html
index 6b85b9ed..64e181b2 100644
--- a/modules-available/sysconfig/templates/ad-selfsearch.html
+++ b/modules-available/sysconfig/templates/ad-selfsearch.html
@@ -54,7 +54,7 @@
<input name="server" value="{{server}}" type="hidden">
<input name="port" value="{{port}}" type="hidden">
<input id="searchbase" name="searchbase" value="{{searchbase}}" type="hidden">
- <input id="fulldn" name="binddn" value="" type="hidden">
+ <input id="fulldn" name="binddn" value="{{binddn}}" type="hidden">
<input id="givendn" name="originalbinddn" value="{{originalbinddn}}" type="hidden">
<input name="bindpw" value="{{bindpw}}" type="hidden">
<input id="home" name="home" value="{{home}}" type="hidden">
diff --git a/modules-available/systemstatus/lang/de/template-tags.json b/modules-available/systemstatus/lang/de/template-tags.json
index fcf836ec..89066257 100644
--- a/modules-available/systemstatus/lang/de/template-tags.json
+++ b/modules-available/systemstatus/lang/de/template-tags.json
@@ -1,7 +1,7 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Adresskonfiguration",
- "lang_areYouSureNoUndo": "Sind Sie sicher? Diese Aktion kann nicht r\u00fcckg\u00e4ngig gemacht werden.",
+ "lang_areYouSureReboot": "Server jetzt neustarten?",
"lang_attention": "Achtung!",
"lang_average": "Durchschnitt",
"lang_capacity": "Kapazit\u00e4t",
diff --git a/modules-available/systemstatus/lang/en/template-tags.json b/modules-available/systemstatus/lang/en/template-tags.json
index 159ae59d..5f6ad898 100644
--- a/modules-available/systemstatus/lang/en/template-tags.json
+++ b/modules-available/systemstatus/lang/en/template-tags.json
@@ -1,7 +1,7 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Address Configuration",
- "lang_areYouSureNoUndo": "Are you sure? This cannot be undone!",
+ "lang_areYouSureReboot": "Reboot server now?",
"lang_attention": "Attention!",
"lang_average": "Average",
"lang_capacity": "Capacity",
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php
index c1c52af0..8a0e5f87 100644
--- a/modules-available/systemstatus/page.inc.php
+++ b/modules-available/systemstatus/page.inc.php
@@ -231,7 +231,12 @@ class Page_SystemStatus extends Page
$data = array('services' => array());
$tasks = array();
- foreach (['dmsd', 'dnbd3-server', 'atftpd'] as $svc) {
+ $todo = ['dmsd', 'atftpd'];
+ if (Module::isAvailable('dnbd3') && Dnbd3::isEnabled()) {
+ $todo[] = 'dnbd3-server';
+ }
+
+ foreach ($todo as $svc) {
$tasks[] = array(
'name' => $svc,
'task' => Taskmanager::submit('Systemctl', ['service' => $svc, 'operation' => 'is-active'])
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
index ca3e6fd2..0de94cad 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -92,12 +92,16 @@
<div class ="modal fade" id="rebootServerModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" style="width: 400px" role="document">
<div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">&times;</button>
+ <b>{{lang_serverReboot}}</b>
+ </div>
<div class="modal-body">
- {{lang_areYouSureNoUndo}}
+ {{lang_areYouSureReboot}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
- <button type="submit" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_serverReboot}}</button>
+ <button type="submit" class="btn btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_serverReboot}}</button>
</div>
</div>
</div>
diff --git a/modules-available/vmstore/lang/de/template-tags.json b/modules-available/vmstore/lang/de/template-tags.json
index a7840aa7..16414809 100644
--- a/modules-available/vmstore/lang/de/template-tags.json
+++ b/modules-available/vmstore/lang/de/template-tags.json
@@ -1,8 +1,13 @@
{
+ "lang_cifsHelp1": "Ben\u00f6tigt wird ein CIFS-Share, z.B. von einem Windows Server, der f\u00fcr\r\nden Satellitenserver schreibbar, und f\u00fcr die Arbeitsstationen lesbar\r\nist.",
+ "lang_cifsHelp2": "Geben Sie f\u00fcr den Satellitenserver einen User mit Lese- und\r\nSchreibberechtigungen an. F\u00fcr die Clients sollte ein User angegeben\r\nwerden, der nur Leseberechtigungen auf dem Share besitzt. Am einfachsten\r\nerreichen Sie dies, indem Sie passwortlosen Gastzugriff mit Leserechten\r\nauf die Freigabe erlauben.",
+ "lang_cifsHelp3": "Wenn exklusiv DNBD3 verwendet wird, k\u00f6nnen Sie den passwortlosen\r\nGastzugriff deaktivieren und die Zeile \"Nur-Lese-Zugangsdaten\" leer\r\nlassen. Dies erh\u00f6ht die Sicherheit.",
"lang_configure": "Konfigurieren",
"lang_intern": "Intern",
"lang_nfsHelp1": "Ben\u00f6tigt wird ein NFSv4\/3-Share, der f\u00fcr den Satelliten-Server schreibbar, und f\u00fcr die Arbeitsstationen lesbar ist. Beispielkonfiguration auf dem NFS-Server, wenn der Satelliten-Server die Adresse 1.2.3.4 hat:",
- "lang_nfsHelp2": "Alternative Konfiguration mittels all_sqash. In diesem Fall muss das Verzeichnis auf dem Server dem Benutzer mit der uid 1234 geh\u00f6ren:",
+ "lang_nfsHelp2": "Alternative Konfiguration mittels all_squash. In diesem Fall muss das Verzeichnis auf dem Server dem Benutzer mit der uid 1234 geh\u00f6ren:",
+ "lang_nfsHelp3": "Die erste Zeile erlaubt den Lese- und Schreibzugriff des\r\nSatellitenservers. Die zweite Zeile erteilt allen anderen Rechnern\r\nausschlie\u00dflich Lesezugriff. Sie k\u00f6nnen dies nat\u00fcrlich auch auf\r\nspezielle Subnetze oder IP-Bereiche beschr\u00e4nken.",
+ "lang_nfsHelp4": "Wenn exklusiv DNBD3 verwendet wird, kann die zweite Zeile ausgelassen\r\nwerden. Dies erh\u00f6ht die Sicherheit.",
"lang_noAdditionalInformation": "Keine weitere Konfiguration notwendig",
"lang_password": "Passwort",
"lang_readOnly": "Nur-Lese-Zugangsdaten",
@@ -11,7 +16,8 @@
"lang_vmLocation": "VM Speicherort",
"lang_vmLocationChoose": "Bitte w\u00e4hlen Sie, wo die Images der Virtuellen Maschinen gespeichert werden sollen.",
"lang_vmLocationConfiguration": "VM Speicherort wird konfiguriert",
- "lang_vmLocationHelp1": "F\u00fcr Testzwecke k\u00f6nnen die VMs direkt auf dem Satellitenserver gespeichert werden. Sofern Sie jedoch die ausgelieferte Satelliten-vmdk betreiben bedenken Sie bitte, dass Sie dann nur ca. 100GB Speicher zur Verf\u00fcgung haben.",
- "lang_vmLocationHelp2": "Im Produktivbetrieb bietet es sich an, hierf\u00fcr einen performanten Netzwerkspeicher zu benutzen. Dieser Netzwerkspeicher kann per NFS oder CIFS\/SMB eingebunden werden. In jedem Fall muss sichergestellt werden, dass der Satellitenserver zum Hinzuf\u00fcgen neuer Virtueller Maschinen Schreibzugriff auf diesen Netzwerkspeicher hat. Bei der Nutzung von NFSv3 kann dies IP-Basiert eingerichtet werden, f\u00fcr die Nutzung von CIFS\/SMB k\u00f6nnen Sie Zugangsdaten angaben, die zum Schreiben berechtigen.",
- "lang_vmLocationHelp3": "Die bwLehrpool-Clients brauchen lediglich Lesezugriff auf den Netzwerkspeicher (und sollten aus Sicherheitsgr\u00fcnden auch wirklich nur lesen k\u00f6nnen). Bei CIFS\/SMB erreichen Sie dies am einfachsten, indem Sie passwortlosen Gastzugriff mit Leserechten auf die Freigabe erlauben."
+ "lang_vmLocationHelp1": "F\u00fcr Testzwecke k\u00f6nnen VMs direkt auf dem Satellitenserver gespeichert\r\nwerden. Sofern Sie den Satellitenserver ohne Anpassung der Virtuellen\r\nFestplatte betreiben, bedenken Sie bitte, dass nur ca. 40GB Speicher zur\r\nVerf\u00fcgung stehen.",
+ "lang_vmLocationHelp2": "Im Produktivbetrieb bietet es sich an, hierf\u00fcr einen performanten\r\nNetzwerkspeicher zu benutzen. Dieser Netzwerkspeicher kann per NFS oder\r\nCIFS\/SMB eingebunden werden. In jedem Fall muss sichergestellt werden,\r\ndass der Satellitenserver zum Hinzuf\u00fcgen neuer Virtueller Maschinen\r\nSchreibzugriff auf diesen Netzwerkspeicher hat. Bei der Nutzung von\r\nNFSv3 kann dies IP-Basiert eingerichtet werden, f\u00fcr die Nutzung von\r\nCIFS\/SMB k\u00f6nnen Sie Zugangsdaten angeben, die zum Schreiben\r\nberechtigen.",
+ "lang_vmLocationHelp3": "Im Fall von NFS und CIFS ben\u00f6tigen die bwLehrpool-Clients\r\nausschlie\u00dflich Lesezugriff auf den Netzwerkspeicher (und sollten aus\r\nSicherheitsgr\u00fcnden auch wirklich nur lesen k\u00f6nnen). Wenn Sie exklusiv\r\nDNBD3 verwenden, sind f\u00fcr die Clients keine Freigaben oder\r\nBerechtigungen notwendig, da der Zugriff \u00fcber den Sallitenserver\r\nstattfindet.",
+ "lang_vmLocationHelp4": "Sie k\u00f6nnen DNBD3 entweder exklusiv oder mit Fallback auf NFS\/CIFS verwenden. Im exklusiven Modus wird der Zugriff der Clients auf den kompletten VM-Speicher verhindert bzw. erschwert. Die Clients ben\u00f6tigen keinerlei Berechtigungen auf dem konfigurierten Share. Wenn Sie den Fallback Modus nutzen, werden f\u00fcr die Clients weiterhin Leseberechtigungen ben\u00f6tigt."
} \ No newline at end of file
diff --git a/modules-available/vmstore/lang/en/template-tags.json b/modules-available/vmstore/lang/en/template-tags.json
index b56cdd23..1072f10e 100644
--- a/modules-available/vmstore/lang/en/template-tags.json
+++ b/modules-available/vmstore/lang/en/template-tags.json
@@ -1,8 +1,13 @@
{
+ "lang_cifsHelp1": "Requires a CIFS\/SMB share that's writable for the satellite server and read-only for the clients (if not using DNBD3).",
+ "lang_cifsHelp2": "Please provide user credentials with read\/write permissions which will be used by the server. For the clients, user credentials that allow read-only access is required. You could also enable passwordless guest login for read-only access.",
+ "lang_cifsHelp3": "If you want to use DNBD3 in exclusive mode, you can leave the read only credentials empty, to prevent people from browsing the share.",
"lang_configure": "Configure",
"lang_intern": "Intern",
"lang_nfsHelp1": "An NFSv4\/3-Share is required. It should be readable by all the workstations, and writable for the satellite server. An example, assuming the satellite server has IP address 1.2.3.4:",
"lang_nfsHelp2": "Alternate configuration using all_squash. The exported directory should be owned (and be writable) by the user with uid 1234.",
+ "lang_nfsHelp3": "The first line allows read\/write access for the satellite server. The second line grants read-only access for every other IP address. You could limit the second line to specific IP ranges only if desired.",
+ "lang_nfsHelp4": "If using DNBD3 in exclusive mode, you can remove the second line completely, so only the satellite server has access to the NFS store.",
"lang_noAdditionalInformation": "No additional cofiguration required",
"lang_password": "Password",
"lang_readOnly": "Read-only Access",
@@ -13,5 +18,6 @@
"lang_vmLocationConfiguration": "VM location is configured",
"lang_vmLocationHelp1": "For test purposes, the VMs can be stored directly on the Satellite server. However, if you operate the delivered satellite vmdk please remember that you have only about 100GB of memory.",
"lang_vmLocationHelp2": "In productive operation, it makes sense for this to use a high-performance network storage. This network storage can be integrated via NFS or CIFS \/ SMB. In any case, it must be ensured that the satellite server has write access to this network storage to add a new Virtual Machine . When using NFSv3 this can be set up IP-based, for the use of CIFS \/ SMB, you can access data disclosures that would entitle them to write.",
- "lang_vmLocationHelp3": "The bwLehrpool clients only need read access to the network storage (and for security reasons, really can only read). In CIFS \/ SMB You can do this most easily by allowing passwordless guest access with read access to the share."
+ "lang_vmLocationHelp3": "The bwLehrpool clients only need read access to the network storage (and for security reasons, really can only read). In CIFS \/ SMB You can do this most easily by allowing passwordless guest access with read access to the share.",
+ "lang_vmLocationHelp4": "You can use DNBD3 exclusively or with NFS\/CIFS as fallback. In exclusive mode, you can deny direct access to the NFS\/CIFS store for clients, to prevent anyone from browsing the VM store directly. In fallback mode, the clients first try to use DNBD3 to run a VM and if that fails, they use NFS\/CIFS directly."
} \ No newline at end of file
diff --git a/modules-available/vmstore/templates/page-vmstore.html b/modules-available/vmstore/templates/page-vmstore.html
index 4a508e74..6156597b 100644
--- a/modules-available/vmstore/templates/page-vmstore.html
+++ b/modules-available/vmstore/templates/page-vmstore.html
@@ -39,10 +39,11 @@
<div class="panel panel-default">
<div class="panel-heading">
- <div class="radio">
+ <div class="radio radio-inline">
<input type="radio" name="storetype" value="cifs" {{pre-cifs}} id="id-cifs">
<label for="id-cifs">CIFS</label>
</div>
+ <a class="btn btn-default btn-sm" data-toggle="modal" data-target="#help-cifs"><span class="glyphicon glyphicon-question-sign"></span></a>
</div>
<div class="panel-body">
<label for="cifsaddr">UNC-Pfad</label>
@@ -73,7 +74,9 @@
</div>
</div>
</div>
- <button class="btn btn-primary pull-right" type="submit"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ <div class="text-right">
+ <button class="btn btn-primary" type="submit"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ </div>
</form>
@@ -94,6 +97,9 @@
<p>
{{lang_vmLocationHelp3}}
</p>
+ <p>
+ {{lang_vmLocationHelp4}}
+ </p>
</div>
</div>
</div>
@@ -121,6 +127,34 @@
/mnt/images 1.2.3.4(rw,all_squash,anonuid=1234,async)
/mnt/images *(ro,async)
</pre>
+ <p>
+ {{lang_nfsHelp3}}
+ </p>
+ <p>
+ {{lang_nfsHelp4}}
+ </p>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="modal fade" id="help-cifs" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ CIFS/SMB
+ </div>
+ <div class="modal-body">
+ <p>
+ {{lang_cifsHelp1}}
+ </p>
+ <p>
+ {{lang_cifsHelp2}}
+ </p>
+ <p>
+ {{lang_cifsHelp3}}
+ </p>
</div>
</div>
</div>