summaryrefslogtreecommitdiffstats
path: root/modules-available/dnbd3
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/dnbd3')
-rw-r--r--modules-available/dnbd3/config.json9
-rw-r--r--modules-available/dnbd3/hooks/main-warning.inc.php2
-rw-r--r--modules-available/dnbd3/hooks/runmode/config.json5
-rw-r--r--modules-available/dnbd3/inc/dnbd3util.inc.php52
-rw-r--r--modules-available/dnbd3/lang/de/permissions.json8
-rw-r--r--modules-available/dnbd3/lang/de/template-tags.json18
-rw-r--r--modules-available/dnbd3/lang/en/permissions.json8
-rw-r--r--modules-available/dnbd3/lang/en/template-tags.json12
-rw-r--r--modules-available/dnbd3/page.inc.php178
-rw-r--r--modules-available/dnbd3/permissions/permissions.json20
-rw-r--r--modules-available/dnbd3/templates/page-proxy-altservers.html12
-rw-r--r--modules-available/dnbd3/templates/page-proxy-clients.html69
-rw-r--r--modules-available/dnbd3/templates/page-proxy-config.html20
-rw-r--r--modules-available/dnbd3/templates/page-proxy-header.html3
-rw-r--r--modules-available/dnbd3/templates/page-proxy-images.html31
-rw-r--r--modules-available/dnbd3/templates/page-proxy-loclist.html27
-rw-r--r--modules-available/dnbd3/templates/page-proxy-stats.html30
-rw-r--r--modules-available/dnbd3/templates/page-serverlist.html55
18 files changed, 428 insertions, 131 deletions
diff --git a/modules-available/dnbd3/config.json b/modules-available/dnbd3/config.json
index f84a4170..9670ded9 100644
--- a/modules-available/dnbd3/config.json
+++ b/modules-available/dnbd3/config.json
@@ -1,4 +1,7 @@
{
- "category":"main.settings-server",
- "dependencies":["locations","runmode"]
-}
+ "category": "main.settings-server",
+ "dependencies": [
+ "locations",
+ "runmode"
+ ]
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/hooks/main-warning.inc.php b/modules-available/dnbd3/hooks/main-warning.inc.php
index e38048e1..5f8a844f 100644
--- a/modules-available/dnbd3/hooks/main-warning.inc.php
+++ b/modules-available/dnbd3/hooks/main-warning.inc.php
@@ -1,6 +1,6 @@
<?php
-if (Dnbd3::isEnabled()) {
+if (Dnbd3::isEnabled() && User::hasPermission('.dnbd3.access-page')) {
$res = Database::simpleQuery('SELECT s.fixedip, s.lastseen AS dnbd3lastseen, s.errormsg, m.clientip, m.hostname
FROM dnbd3_server s
LEFT JOIN machine m USING (machineuuid)
diff --git a/modules-available/dnbd3/hooks/runmode/config.json b/modules-available/dnbd3/hooks/runmode/config.json
index 5db53f0b..683e0280 100644
--- a/modules-available/dnbd3/hooks/runmode/config.json
+++ b/modules-available/dnbd3/hooks/runmode/config.json
@@ -3,6 +3,7 @@
"configHook": "Dnbd3Util::runmodeConfigHook",
"noSysconfig": true,
"systemdDefaultTarget": "dnbd3-proxy",
- "allowGenericEditor": false,
- "deleteUrlSnippet": "dummyparam="
+ "allowGenericEditor": true,
+ "deleteUrlSnippet": "dummyparam=",
+ "permission": ".dnbd3.configure.proxy"
} \ No newline at end of file
diff --git a/modules-available/dnbd3/inc/dnbd3util.inc.php b/modules-available/dnbd3/inc/dnbd3util.inc.php
index 95b6ffe2..33581b77 100644
--- a/modules-available/dnbd3/inc/dnbd3util.inc.php
+++ b/modules-available/dnbd3/inc/dnbd3util.inc.php
@@ -103,6 +103,7 @@ class Dnbd3Util {
*/
public static function runmodeConfigHook($machineUuid, $mode, $modeData)
{
+ $self = Property::getServerIp();
// Get all directly assigned locations
$res = Database::simpleQuery('SELECT locationid FROM dnbd3_server
INNER JOIN dnbd3_server_x_location USING (serverid)
@@ -124,10 +125,20 @@ class Dnbd3Util {
}
$res = Database::simpleQuery('SELECT startaddr, endaddr FROM subnet WHERE locationid IN (:locs)',
array('locs' => array_values($recursiveLocs)));
+ // Coalesce overlapping ranges
+ $floatIp = ip2long($self); // Float for 32bit php :/
+ if (PHP_INT_SIZE === 4) {
+ $floatIp = (float)sprintf('%u', $floatIp); // Float for 32bit php :/
+ }
+ $ranges = [['startaddr' => $floatIp, 'endaddr' => $floatIp]];
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ settype($row['startaddr'], PHP_INT_SIZE === 4 ? 'float' : 'int');
+ settype($row['endaddr'], PHP_INT_SIZE === 4 ? 'float' : 'int');
+ self::mergeRanges($ranges, $row);
+ }
// Got subnets, build whitelist
- // TODO: Coalesce overlapping ranges
$opt = '';
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($ranges as $row) {
$opt .= ' ' . self::range2Cidr($row['startaddr'], $row['endaddr']);
}
if (!empty($opt)) {
@@ -141,7 +152,6 @@ class Dnbd3Util {
WHERE s.machineuuid <> :uuid OR s.machineuuid IS NULL', array('uuid' => $machineUuid));
$public = array();
$private = array();
- $self = Property::getServerIp();
$public[$self] = $self;
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
$ip = $row['fixedip'] ? $row['fixedip'] : $row['clientip'];
@@ -188,13 +198,47 @@ class Dnbd3Util {
*/
private static function range2Cidr($start, $end)
{
- $bin = decbin((int)$start ^ (int)$end);
+ if (PHP_INT_SIZE > 4) {
+ $bin = decbin((int)$start ^ (int)$end);
+ } else {
+ $bin = decbin((int)(float)$start ^ (int)(float)$end);
+ }
if ($bin === '0')
return long2ip($start);
$mask = 32 - strlen($bin);
return long2ip($start) . '/' . $mask;
}
+ private static function mergeRanges(&$ranges, $row)
+ {
+ if ($row['startaddr'] >= $row['endaddr'])
+ return; // Don't even bother
+ foreach (array_keys($ranges) as $key) {
+ if ($row['startaddr'] <= $ranges[$key]['startaddr'] && $row['endaddr'] >= $ranges[$key]['endaddr']) {
+ // Fully dominated
+ unset($ranges[$key]);
+ continue; // Might partially overlap with additional ranges, keep going
+ }
+ if ($ranges[$key]['startaddr'] <= $row['startaddr'] && $ranges[$key]['endaddr'] >= $row['startaddr']) {
+ // $row['startaddr'] lies within existing range
+ if ($ranges[$key]['startaddr'] <= $row['endaddr'] && $ranges[$key]['endaddr'] >= $row['endaddr'])
+ return; // Fully in existing range, do nothing
+ // $row['endaddr'] seems to extend range we're checking against but $row['startaddr'] lies within this range, update and keep going
+ $row['startaddr'] = $ranges[$key]['startaddr'];
+ unset($ranges[$key]);
+ continue;
+ }
+ // Last possibility: $row['startaddr'] is before range, $row['endaddr'] within range
+ if ($ranges[$key]['startaddr'] <= $row['endaddr'] && $ranges[$key]['endaddr'] >= $row['endaddr']) {
+ // $row['startaddr'] must lie before range start, otherwise we'd have hit the case above
+ $row['endaddr'] = $ranges[$key]['endaddr'];
+ unset($ranges[$key]);
+ continue;
+ }
+ }
+ $ranges[] = $row;
+ }
+
public static function defaultRunmodeConfig()
{
return array(
diff --git a/modules-available/dnbd3/lang/de/permissions.json b/modules-available/dnbd3/lang/de/permissions.json
new file mode 100644
index 00000000..15d17336
--- /dev/null
+++ b/modules-available/dnbd3/lang/de/permissions.json
@@ -0,0 +1,8 @@
+{
+ "access-page": "Seite sehen",
+ "configure.external": "Externen Proxy bearbeiten",
+ "configure.proxy": "Automatischen Proxy bearbeiten",
+ "refresh": "Serverliste aktualisieren",
+ "toggle-usage": "Aktivieren\/Deaktivieren",
+ "view.details": "Proxydetails anzeigen"
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/lang/de/template-tags.json b/modules-available/dnbd3/lang/de/template-tags.json
index 5406f1b5..22c74b7d 100644
--- a/modules-available/dnbd3/lang/de/template-tags.json
+++ b/modules-available/dnbd3/lang/de/template-tags.json
@@ -10,12 +10,14 @@
"lang_client": "Client",
"lang_clientCount": "Clients",
"lang_clientList": "Liste der Clients",
+ "lang_clients": "Clients",
"lang_clientsByLocation": "Clients nach Raum\/Ort",
"lang_comment": "Kommentar",
+ "lang_complete": "Komplett",
"lang_count": "Anzahl",
"lang_disabled": "Deaktiviert",
"lang_diskFree": "Freier Speicher",
- "lang_dnbd3IntroText": "DNBD3 ist ein verteiltes Speichersystem speziell f\u00fcr die Anforderungen von bwLehrpool. Erst in Verbindung mit mindestens einem Proxy (zus\u00e4tzlich zum Satellitenserver) kann das System seine Geschwindigkeitsvorteile gegen\u00fcber NFS\/CIFS ausspielen. F\u00fcr schlecht angebundene Poolr\u00e4ume empfiehlt sich jeweils ein eigener Proxy-Server.\r\nBitte beachten Sie die Hinweise im Wiki.",
+ "lang_dnbd3IntroText": "DNBD3 ist ein verteiltes Speichersystem speziell f\u00fcr die Anforderungen von bwLehrpool. Erst in Verbindung mit mindestens einem Proxy (zus\u00e4tzlich zum Satellitenserver) kann das System seine Geschwindigkeitsvorteile gegen\u00fcber NFS\/CIFS ausspielen. F\u00fcr schlecht angebundene Poolr\u00e4ume empfiehlt sich jeweils ein eigener Proxy-Server. Bitte beachten Sie die Hinweise im Wiki.",
"lang_dnbd3Management": "DNBD3 Verwaltung",
"lang_dnbd3Status": "DNBD3 Status",
"lang_editProxyHeading": "Proxy-Einstellungen bearbeiten",
@@ -24,11 +26,13 @@
"lang_enterIpOfServer": "Bitte geben Sie die IP-Adresse des hinzuzuf\u00fcgenden Servers ein",
"lang_externalServer": "Externer DNBD3-Server",
"lang_externalServerAdd": "Externen Server hinzuf\u00fcgen",
- "lang_externalServerHelp": "Ein externer Server wird nicht \u00fcber den Satellitenserver konfiguriert und verwaltet. Das Installieren, Einrichten und ggf. Aktualisieren der DNBD3-Serversoftware muss manuell durchgef\u00fchrt werden.\r\nDies bietet mehr Flexibilit\u00e4t bei der Konfiguration und Anpassung, z.B. bei der Verwendung von RAID- oder bcache-Setups, oder wenn der DNBD3-Server auf einer Maschine laufen soll, die noch andere Services bereitstellt.\r\nWeitere Informationen dazu finden Sie im Wiki.",
- "lang_firewallInfo": "Wird ein Proxy auf einen oder mehrere R\u00e4ume beschr\u00e4nkt, werden Clients aus anderen R\u00e4umen diesen Proxy nicht verwenden. Technisch ist der Zugriff aus anderen R\u00e4umen jedoch trotzdem noch m\u00f6glich. Mit aktivieren dieser Option wird der Zugriff aus anderen R\u00e4umen per Firewall verhindert.",
- "lang_firewalled": "Zugriff auf zugewiesene R\u00e4ume beschr\u00e4nken",
+ "lang_externalServerHelp": "Ein externer Server wird nicht \u00fcber den Satellitenserver konfiguriert und verwaltet. Das Installieren, Einrichten und ggf. Aktualisieren der DNBD3-Serversoftware muss manuell durchgef\u00fchrt werden. Dies bietet mehr Flexibilit\u00e4t bei der Konfiguration und Anpassung, z.B. bei der Verwendung von RAID- oder bcache-Setups, oder wenn der DNBD3-Server auf einer Maschine laufen soll, die noch andere Services bereitstellt. Weitere Informationen dazu finden Sie im Wiki.",
+ "lang_firewallInfo": "Wird ein Proxy auf einen oder mehrere R\u00e4ume beschr\u00e4nkt, werden Clients aus anderen R\u00e4umen diesen Proxy nicht verwenden. Technisch ist der Zugriff aus anderen R\u00e4umen jedoch trotzdem noch m\u00f6glich. Mit Aktivieren dieser Option wird der Zugriff aus anderen R\u00e4umen per Firewall verhindert.",
+ "lang_firewalled": "Zugriff zus\u00e4tzlich per Firewall auf zugewiesene R\u00e4ume beschr\u00e4nken",
"lang_flags": "Flags",
"lang_global": "Global",
+ "lang_image": "Image",
+ "lang_imageList": "Image-Liste",
"lang_lastSeen": "Letzte Aktivit\u00e4t",
"lang_latency": "Latenz",
"lang_location": "Ort",
@@ -36,7 +40,9 @@
"lang_manageAccessTo": "Zugriff auf Server festlegen:",
"lang_managedServer": "Automatisch konfigurierter DNBD3-Proxy",
"lang_managedServerAdd": "Automatisch konfigurierten Proxy hinzuf\u00fcgen",
- "lang_managedServerHelp": "Automatisch konfigurierte DNBD3-Proxies booten wie gew\u00f6hnliche bwLehrpool-Clients via PXE \u00fcber den Satelliten-Server. Sobald ein bwLehrpool-Client als DNBD3-Proxy konfiguriert wird, erh\u00e4lt er beim Booten eine gesonderte Konfiguration, sodass er fortan exklusiv als DNBD3-Proxy arbeitet, und nicht mehr als Arbeitsstation zur Verf\u00fcgung steht.\r\nDer Vorteil ist, dass die Konfiguration automatisiert erfolgt, und durch w\u00f6chentliche Reboots sichergestellt wird, dass eventuelle Updates des MiniLinux angewendet werden.\r\nIn diesem Fall legen Sie bitte eine Partition mit der ID 45 auf der Festplatte des Proxy-Servers an; diese wird persistent Behandelt und im Gegensatz zur ID44-Partition nicht beim Booten formatiert. Generell sollte diese Partition so gro\u00df wie m\u00f6glich sein, abh\u00e4ngig von der Anzahl der genutzten VMs. Bei Platzmangel l\u00f6scht der Proxy automatisch die VM, die am l\u00e4ngsten nicht verwendet wurde, um neuen VMs Platz zu machen.\r\nWeitere Informationen dazu finden Sie im Wiki.",
+ "lang_managedServerHelp": "Automatisch konfigurierte DNBD3-Proxies booten wie gew\u00f6hnliche bwLehrpool-Clients via PXE \u00fcber den Satellitenserver. Sobald ein bwLehrpool-Client als DNBD3-Proxy konfiguriert wird, erh\u00e4lt er beim Booten eine gesonderte Konfiguration, sodass er fortan exklusiv als DNBD3-Proxy arbeitet, und nicht mehr als Arbeitsstation zur Verf\u00fcgung steht. Der Vorteil ist, dass die Konfiguration automatisiert erfolgt, und durch w\u00f6chentliche Reboots sichergestellt wird, dass eventuelle Updates des MiniLinux angewendet werden. In diesem Fall legen Sie bitte eine Partition mit der ID 45 auf der Festplatte des Proxy-Servers an; diese wird persistent Behandelt und im Gegensatz zur ID44-Partition nicht beim Booten formatiert. Generell sollte diese Partition so gro\u00df wie m\u00f6glich sein, abh\u00e4ngig von der Anzahl der genutzten VMs. Bei Platzmangel l\u00f6scht der Proxy automatisch die VM, die am l\u00e4ngsten nicht verwendet wurde, um neuen VMs Platz zu machen. Weitere Informationen dazu finden Sie im Wiki.",
+ "lang_manualRefresh": "Jetzt abfragen",
+ "lang_manualRefreshInfo": "Normalerweile werden die in dieser Tabelle angezeigten Daten alle 5 Minuten aktualisiert. Mit diesem Button k\u00f6nnen Sie die Daten sofort aktualisieren.",
"lang_numFails": "Fehler",
"lang_overrideIp": "Zu verwendende IP-Adresse",
"lang_overrideIpInfo": "Normalerweise wird die automatisch per DHCP zugewiesene Adresse auf dem Boot-Interface verwendet. Falls der Proxy mit weiteren Netzwerkkarten ausgestattet ist (die ebenfalls per DHCP konfiguriert werden) kann durch Angabe einer solchen Alternativadresse hier die Verwendung der entsprechenden Karte erzwungen werden.",
@@ -52,9 +58,11 @@
"lang_sessionRx": "Seit Neustart empfangen",
"lang_sessionTx": "Seit Neustart gesendet",
"lang_settings": "Einstellungen",
+ "lang_size": "Gr\u00f6\u00dfe",
"lang_storageSize": "Speichergr\u00f6\u00dfe",
"lang_test": "Testen",
"lang_txTotal": "Gesamt gesendet",
+ "lang_uplink": "Uplink",
"lang_uptime": "Aktuelle Laufzeit",
"lang_wantToDelete": "Wollen Sie diesen Server wirklich entfernen? (Rebooten\/Ausschalten muss in diesem Fall manuell vorgenommen werden)"
} \ No newline at end of file
diff --git a/modules-available/dnbd3/lang/en/permissions.json b/modules-available/dnbd3/lang/en/permissions.json
new file mode 100644
index 00000000..112deb94
--- /dev/null
+++ b/modules-available/dnbd3/lang/en/permissions.json
@@ -0,0 +1,8 @@
+{
+ "access-page": "View this page",
+ "configure.external": "Edit external proxy",
+ "configure.proxy": "Edit automatic proxy",
+ "refresh": "Refresh server list",
+ "toggle-usage": "Activate\/Deactivate",
+ "view.details": "Show proxy details"
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/lang/en/template-tags.json b/modules-available/dnbd3/lang/en/template-tags.json
index 81b9d538..932b899a 100644
--- a/modules-available/dnbd3/lang/en/template-tags.json
+++ b/modules-available/dnbd3/lang/en/template-tags.json
@@ -10,8 +10,10 @@
"lang_client": "Client",
"lang_clientCount": "Clients",
"lang_clientList": "List of clients",
+ "lang_clients": "Clients",
"lang_clientsByLocation": "Clients by location",
"lang_comment": "Comment",
+ "lang_complete": "Complete",
"lang_count": "Count",
"lang_disabled": "Disabled",
"lang_diskFree": "Free space",
@@ -25,10 +27,12 @@
"lang_externalServer": "External DNBD3-Server",
"lang_externalServerAdd": "Add external server",
"lang_externalServerHelp": "An external server is not configured and managed by the satellite server. The installation, configuration and update of the DNBD3 software has to be done manually. This is a more flexible approach which is preferable for RAID or bcache setups or if the DNBD3-Server offers additional services. More information in the wiki.",
- "lang_firewallInfo": "If the proxy is restricted to one or more locations, clients from other locations won't use that specific proxy. But technically it's still possible to gain access from other locations. If you activate this setting the access from other locations is blocked with iptables.",
- "lang_firewalled": "Limit access to corresponding locations",
+ "lang_firewallInfo": "If the proxy is restricted to one or more locations, clients from other locations won't use that specific proxy, but technically it's still possible to access this proxy from other locations. If you activate this setting the access from other locations is forcefully blocked using iptables.",
+ "lang_firewalled": "Limit access to corresponding locations via firewall",
"lang_flags": "Flags",
"lang_global": "Global",
+ "lang_image": "Image",
+ "lang_imageList": "Image list",
"lang_lastSeen": "Last seen",
"lang_latency": "Latency",
"lang_location": "Location",
@@ -37,6 +41,8 @@
"lang_managedServer": "Automatically configured DNBD3-Proxy",
"lang_managedServerAdd": "Add automatically configured proxy",
"lang_managedServerHelp": "Automatically configured DNBD3-Proxies will boot like normal bwLehrpool-Clients over PXE and the satellite server. If a client is configured as proxy it will boot with a different configuration and acts exclusively as proxy. The client can therefore not be used as a normal working station.\r\nThe advantage is that you don't need to install or configure anything else. The client will reboot every week to get possible updates ot the minilinux.\r\nIf you want to use this feature, please create a partition with ID 45 on the local hard disk of the proxy server. In contrast to the ID 44 partition which is formated after every reboot, this partition is persistent. As a rule of thumb the partition should be as big as possible. If there is no space left the proxy will delete the VM which hasn't be used for the longest time. More information in the wiki.",
+ "lang_manualRefresh": "Manual refresh",
+ "lang_manualRefreshInfo": "All servers are queried every 5 minutes to update the table below. Hit the refresh button to update the table immediately.",
"lang_numFails": "Errors",
"lang_overrideIp": "IP address to use",
"lang_overrideIpInfo": "Usually the address that the DHCP server assigns to the boot interface of the proxy will be used. If the proxy has multiple interfaces (that also get an address assigned via DHCP) you can specify that address here to enforce their usage instead.",
@@ -52,9 +58,11 @@
"lang_sessionRx": "Received since boot",
"lang_sessionTx": "Sent since boot",
"lang_settings": "Settings",
+ "lang_size": "Size",
"lang_storageSize": "Storage size",
"lang_test": "Test",
"lang_txTotal": "Total sent",
+ "lang_uplink": "Uplink",
"lang_uptime": "Uptime",
"lang_wantToDelete": "Do you really want to delete this server? (Reboot\/Shutdown has to be done manually)"
} \ No newline at end of file
diff --git a/modules-available/dnbd3/page.inc.php b/modules-available/dnbd3/page.inc.php
index 1fa38805..d8dd6cb8 100644
--- a/modules-available/dnbd3/page.inc.php
+++ b/modules-available/dnbd3/page.inc.php
@@ -11,8 +11,10 @@ class Page_Dnbd3 extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
+
$action = Request::post('action', false, 'string');
if ($action === 'refresh') {
+ User::assertPermission('refresh');
Dnbd3Util::updateServerStatus();
} elseif ($action === 'delserver') {
$this->deleteServer();
@@ -37,6 +39,7 @@ class Page_Dnbd3 extends Page
Message::addError('not-automatic-server', $server['ip']);
return;
}
+ $this->assertPermission($server);
$bgr = Request::post('bgr', false, 'bool');
$firewall = Request::post('firewall', false, 'bool');
$overrideIp = false;
@@ -73,6 +76,7 @@ class Page_Dnbd3 extends Page
private function toggleUsage()
{
+ User::assertPermission('toggle-usage');
$enabled = Request::post('enabled', false, 'bool');
$nfs = Request::post('with-nfs', false, 'bool');
$task = Dnbd3::setEnabled($enabled);
@@ -83,6 +87,7 @@ class Page_Dnbd3 extends Page
private function saveServerLocations()
{
$server = $this->getServerById();
+ $this->assertPermission($server);
$locids = Request::post('location', [], 'array');
if (empty($locids)) {
Database::exec('DELETE FROM dnbd3_server_x_location WHERE serverid = :serverid',
@@ -99,6 +104,7 @@ class Page_Dnbd3 extends Page
private function addServer()
{
+ User::assertPermission('configure.external');
$ip = Request::post('newip', false, 'string');
if ($ip === false) {
Message::addError('main.parameter-missing', 'ip');
@@ -126,6 +132,7 @@ class Page_Dnbd3 extends Page
private function deleteServer()
{
$server = $this->getServerById();
+ $this->assertPermission($server);
if ($server['fixedip'] === '<self>')
return;
if (!is_null($server['machineuuid'])) {
@@ -156,9 +163,10 @@ class Page_Dnbd3 extends Page
private function showServerList()
{
+ User::assertPermission('access-page');
$dynClients = RunMode::getForMode(Page::getModule(), 'proxy', true, true);
$res = Database::simpleQuery('SELECT s.serverid, s.machineuuid, s.fixedip, s.lastseen AS dnbd3lastseen,
- s.uptime, s.totalup, s.totaldown, s.clientcount, s.disktotal, s.diskfree, Count(sxl.locationid) AS locations,
+ s.uptime, s.totalup, s.totaldown, s.clientcount, s.disktotal, s.diskfree, GROUP_CONCAT(sxl.locationid) AS locations,
s.errormsg
FROM dnbd3_server s
LEFT JOIN dnbd3_server_x_location sxl USING (serverid)
@@ -166,8 +174,22 @@ class Page_Dnbd3 extends Page
$servers = array();
$sort = array();
$NOW = time();
+ $externalAllowed = User::hasPermission('configure.external');
+ $locsRunmode = User::getAllowedLocations('configure.proxy');
while ($server = $res->fetch(PDO::FETCH_ASSOC)) {
- if (isset($dynClients[$server['machineuuid']])) {
+ if (!is_null($server['machineuuid'])) {
+ // Auto proxy
+ if (!isset($dynClients[$server['machineuuid']])) {
+ // Not in runmode dnbd3!?
+ if ($NOW - $server['dnbd3lastseen'] > 660) {
+ // Also seems to be down - delete
+ Database::exec('DELETE FROM dnbd3_server WHERE serverid = :serverid',
+ array('serverid' => $server['serverid']));
+ continue;
+ }
+ // Not in runmode but (still?) up -- show
+ $server += ['locationid' => null, 'hostname' => '<invalid>'];
+ }
$server += $dynClients[$server['machineuuid']];
unset($dynClients[$server['machineuuid']]);
}
@@ -195,6 +217,23 @@ class Page_Dnbd3 extends Page
$server['slxOk'] = true;
}
}
+ if (is_null($server['locations'])) {
+ $server['locations'] = 0;
+ } else {
+ $locations = explode(',', $server['locations']);
+ $server['locations'] = count($locations);
+ }
+ // Permission to edit
+ if (is_null($server['machineuuid'])) {
+ if (!$externalAllowed) {
+ $server['edit_disabled'] = 'disabled';
+ }
+ } else {
+ if (!array_key_exists('locationid', $server) || !in_array($server['locationid'], $locsRunmode)) {
+ $server['edit_disabled'] = 'disabled';
+ }
+ }
+ // Array for sorting
if ($server['self']) {
$sort[] = '---';
} else {
@@ -203,66 +242,99 @@ class Page_Dnbd3 extends Page
$servers[] = $server;
}
foreach ($dynClients as $server) {
+ $server['edit_disabled'] = 'disabled';
$servers[] = $server;
$sort[] = '-' . $server['machineuuid'];
- Database::exec('INSERT INTO dnbd3_server (machineuuid) VALUES (:uuid)', array('uuid' => $server['machineuuid']));
+ Database::exec('INSERT IGNORE INTO dnbd3_server (machineuuid) VALUES (:uuid)', array('uuid' => $server['machineuuid']));
}
array_multisort($sort, SORT_ASC, $servers);
- Render::addTemplate('page-serverlist', array(
+ $data = array(
'list' => $servers,
'enabled' => Dnbd3::isEnabled(),
'enabled_checked_s' => Dnbd3::isEnabled() ? 'checked' : '',
'nfs_checked_s' => Dnbd3::hasNfsFallback() ? 'checked' : '',
'rebootcontrol' => Module::isAvailable('rebootcontrol', false)
- ));
+ );
+ Permission::addGlobalTags($data['perms'], null, ['view.details', 'refresh', 'toggle-usage', 'configure.proxy', 'configure.external']);
+ Render::addTemplate('page-serverlist', $data);
}
private function showProxyDetails()
{
+ User::assertPermission('view.details');
$server = $this->getServerById();
Render::addTemplate('page-proxy-header', $server);
- $stats = Dnbd3Rpc::query($server['ip'], 5003,true, true, false, true);
+ $stats = Dnbd3Rpc::query($server['ip'], 5003, true, true, true, true, true, true);
if (!is_array($stats) || !isset($stats['runId'])) {
Message::addError('server-unreachable');
return;
}
- $stats['bytesSent_s'] = Util::readableFileSize($stats['bytesSent']);
- $stats['bytesReceived_s'] = Util::readableFileSize($stats['bytesReceived']);
+ foreach (['bytesSent', 'bytesReceived', 'spaceTotal', 'spaceFree'] as $key) {
+ $stats[$key . '_s'] = Util::readableFileSize($stats[$key]);
+ }
+ if ($stats['spaceTotal'] > 0) {
+ $stats['percentFree'] = ($stats['spaceFree'] / $stats['spaceTotal']) * 100;
+ $stats['percentFree'] = round($stats['percentFree'], $stats['percentFree'] < 10 ? 1 : 0);
+ }
$stats['uptime_s'] = floor($stats['uptime'] / 86400) . 'd ' . gmdate('H:i:s', $stats['uptime']);
+ $stats['tab_config'] = is_string($stats['config']);
+ $stats['tab_altservers'] = is_array($stats['altservers']);
Render::addTemplate('page-proxy-stats', $stats);
- // TODO $images = Dnbd3Rpc::query($server['ip'], 5003,false, false, true);
- $confAlts = Dnbd3Rpc::query($server['ip'], 5003,false, false, false, false, true, true);
+ Render::openTag('div', ['class' => 'tab-content']);
$ips = array();
$sort = array();
foreach ($stats['clients'] as &$c) {
$c['bytesSent_s'] = Util::readableFileSize($c['bytesSent']);
$sort[] = $c['bytesSent'];
- $ips[] = preg_replace('/:\d+$/', '', $c['address']);
+ $ips[preg_replace('/:\d+$/', '', $c['address'])] = true;
}
+ $ips = array_keys($ips);
array_multisort($sort, SORT_DESC, $stats['clients']);
- Render::openTag('div', ['class' => 'row']);
// Config
- if (is_string($confAlts['config'])) {
- Render::addTemplate('page-proxy-config', $confAlts);
+ if (is_string($stats['config'])) {
+ preg_match_all('/^((?<sec>\[.*\])|(?<key>[^=]+)=(?<val>.*)|(?<other>[^\[][^=]*))$/m', $stats['config'], $out, PREG_SET_ORDER);
+ $stats['config'] = [];
+ foreach ($out as $line) {
+ if (!empty($line['sec'])) {
+ $stats['config'][] = ['class1' => 'text-primary', 'text1' => $line['sec']];
+ } elseif (!empty($line['other'])) {
+ $stats['config'][] = ['class1' => 'text-muted', 'text1' => $line['other']];
+ } else {
+ $extra = '';
+ $class2 = 'slx-bold';
+ if (in_array($line['key'], ['serverPenalty', 'clientPenalty'])) {
+ $extra = round($line['val'] / 1000, 1) . 'ms';
+ } elseif (in_array($line['key'], ['uplinkTimeout', 'clientTimeout'])) {
+ $extra = round($line['val'] / 1000, 1) . 's';
+ } elseif (in_array($line['key'], ['maxPayload', 'maxReplicationSize'])) {
+ $extra = Util::readableFilesize($line['val']);
+ } elseif ($line['val'] === 'true') {
+ $class2 .= ' text-success';
+ } elseif ($line['val'] === 'false') {
+ $class2 .= ' text-danger';
+ }
+ $stats['config'][] = ['text1' => $line['key'], 'class2' => $class2, 'text2' => $line['val'] . ' ', 'extra' => $extra];
+ }
+ }
+ Render::addTemplate('page-proxy-config', $stats);
}
- if (is_array($confAlts['altservers'])) {
- foreach ($confAlts['altservers'] as &$as) {
+ if (is_array($stats['altservers'])) {
+ foreach ($stats['altservers'] as &$as) {
$as['rtt'] = round(array_sum($as['rtt']) / count($as['rtt']) / 1000, 2);
}
unset($as);
- Render::addTemplate('page-proxy-altservers', $confAlts);
+ Render::addTemplate('page-proxy-altservers', $stats);
}
- Render::closeTag('div');
- Render::openTag('div', ['class' => 'row']);
// Count locations
- $res = Database::simpleQuery('SELECT locationid, Count(*) AS cnt FROM machine WHERE clientip IN (:ips) GROUP BY locationid', compact('ips'));
+ $res = Database::simpleQuery("SELECT locationid, Count(*) AS cnt FROM machine
+ WHERE clientip IN (:ips) AND state IN ('IDLE', 'OCCUPIED') GROUP BY locationid", compact('ips'));
$locCount = Location::getLocationsAssoc();
$locCount[0] = array(
'locationname' => '/',
'depth' => 0,
- 'recCount' => 0,
);
foreach ($locCount as &$loc) {
+ $loc['clientCount'] = 0;
$loc['recCount'] = 0;
}
$showLocs = false;
@@ -281,18 +353,27 @@ class Page_Dnbd3 extends Page
$locCount[$p]['recCount'] += $row['cnt'];
}
}
+ $locCount[0]['recCount'] += $row['cnt'];
}
if ($showLocs) {
- $locCount = array_filter($locCount, function ($v) { return isset($v['keep']); });
- Render::addTemplate('page-proxy-loclist', array('list' => array_values($locCount)));
+ $stats['loclist'] = array_values(array_filter($locCount, function ($v) { return isset($v['keep']); }));
}
Render::addTemplate('page-proxy-clients', $stats);
+ $sort1 = $sort2 = [];
+ foreach ($stats['images'] as &$image) {
+ $image['size_s'] = Util::readableFileSize($image['size']);
+ $sort1[] = $image['users'];
+ $sort2[] = $image['name'];
+ }
+ array_multisort($sort1, SORT_NUMERIC | SORT_DESC, $sort2, SORT_ASC, $stats['images']);
+ Render::addTemplate('page-proxy-images', $stats);
Render::closeTag('div');
}
private function showServerLocationEdit()
{
$server = $this->getServerById();
+ $this->assertPermission($server);
// Get selected ones
$res = Database::simpleQuery('SELECT locationid FROM dnbd3_server_x_location WHERE serverid = :serverid',
array('serverid' => $server['serverid']));
@@ -328,14 +409,14 @@ class Page_Dnbd3 extends Page
Message::addError('main.parameter-missing', 'server');
Util::redirect('?do=dnbd3');
}
- $server = Database::queryFirst('SELECT s.serverid, s.machineuuid, s.fixedip, m.clientip, m.hostname
+ $server = Database::queryFirst('SELECT s.serverid, s.machineuuid, s.fixedip, m.clientip, m.hostname, m.locationid
FROM dnbd3_server s
LEFT JOIN machine m USING (machineuuid)
WHERE s.serverid = :serverId', compact('serverId'));
if ($server === false) {
if (AJAX)
die('Invalid server id');
- Message::addError('server-non-existent', 'server');
+ Message::addError('server-non-existent', $serverId);
Util::redirect('?do=dnbd3');
}
if (!is_null($server['fixedip'])) {
@@ -348,6 +429,15 @@ class Page_Dnbd3 extends Page
return $server;
}
+ private function assertPermission($server)
+ {
+ if (isset($server['machineuuid'])) {
+ User::assertPermission('configure.proxy', $server['locationid'], '?do=dnbd3');
+ } else {
+ User::assertPermission('configure.external', null, '?do=dnbd3');
+ }
+ }
+
/*
* AJAX
*/
@@ -371,6 +461,7 @@ class Page_Dnbd3 extends Page
private function ajaxServerTest()
{
+ User::assertPermission('configure.external');
Header('Content-Type: application/json; charset=utf-8');
$ip = Request::post('ip', false, 'string');
if ($ip === false)
@@ -407,6 +498,7 @@ class Page_Dnbd3 extends Page
echo 'Not automatic server.';
return;
}
+ $this->assertPermission($server);
$rm = RunMode::getForMode(Page::getModule(), 'proxy', false, true);
if (!isset($rm[$server['machineuuid']])) {
echo 'Error: RunMode entry missing.';
@@ -423,23 +515,37 @@ class Page_Dnbd3 extends Page
if (!isset($server['machineuuid'])) {
die('Not automatic server.');
}
- if (!Module::isAvailable('rebootcontrol')) {
- die('No rebootcontrol');
- }
$uuid = $server['machineuuid'];
- $task = RebootControl::reboot([ $uuid ]);
+ $task = Request::any('taskid', false, 'string');
if ($task === false) {
- die('Taskmanager unreachable');
+ $this->assertPermission($server);
+ if (!Module::isAvailable('rebootcontrol')) {
+ die('No rebootcontrol');
+ }
+ $task = RebootControl::reboot([$uuid]);
+ if ($task === false) {
+ die('Taskmanager unreachable');
+ }
}
- $task = Taskmanager::waitComplete($task, 2000);
- if (is_array($task) && isset($task['data']) && isset($task['data']['clientStatus']) && isset($task['data']['clientStatus'][$uuid])) {
- $status = $task['data']['clientStatus'][$uuid];
+ $task = Taskmanager::waitComplete($task, 1000);
+ if (is_array($task) && isset($task['data']['clientStatus'][$uuid])) {
+ $status = [
+ 'rebootStatus' => $task['data']['clientStatus'][$uuid],
+ 'taskStatus' => $task['statusCode'],
+ 'taskId' => $task['id'],
+ ];
if (!empty($task['data']['error'])) {
- $status .= "\n --- \n" . $task['data']['error'];
+ $status['error'] = $task['data']['error'];
}
- die($status);
+ } else {
+ $status = [
+ 'rebootStatus' => 'FAILURE',
+ 'taskStatus' => 'FAILURE',
+ 'taskId' => $task['id'],
+ ];
}
- die('Unknown :-(');
+ Header('Content-Type: application/json; charset=utf-8');
+ die(json_encode($status));
}
}
diff --git a/modules-available/dnbd3/permissions/permissions.json b/modules-available/dnbd3/permissions/permissions.json
new file mode 100644
index 00000000..77a72d62
--- /dev/null
+++ b/modules-available/dnbd3/permissions/permissions.json
@@ -0,0 +1,20 @@
+{
+ "access-page": {
+ "location-aware": false
+ },
+ "toggle-usage": {
+ "location-aware": false
+ },
+ "refresh": {
+ "location-aware": false
+ },
+ "view.details": {
+ "location-aware": false
+ },
+ "configure.proxy": {
+ "location-aware": true
+ },
+ "configure.external": {
+ "location-aware": false
+ }
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-proxy-altservers.html b/modules-available/dnbd3/templates/page-proxy-altservers.html
index 00a884cc..d2e520f9 100644
--- a/modules-available/dnbd3/templates/page-proxy-altservers.html
+++ b/modules-available/dnbd3/templates/page-proxy-altservers.html
@@ -1,11 +1,11 @@
-<div class="col-md-6">
+<div role="tabpanel" class="tab-pane" id="tab-altservers">
<h2>{{lang_altservers}}</h2>
<table class="table table-condensed">
<tr>
- <th>{{lang_proxyServerTHead}}</th>
- <th>{{lang_numFails}}</th>
- <th class="text-right">{{lang_latency}}</th>
- <th>{{lang_flags}}</th>
+ <th class="slx-smallcol">{{lang_proxyServerTHead}}</th>
+ <th class="slx-smallcol">{{lang_numFails}}</th>
+ <th class="text-right slx-smallcol">{{lang_latency}}</th>
+ <th class="slx-smallcol">{{lang_flags}}</th>
<th>{{lang_comment}}</th>
</tr>
{{#altservers}}
@@ -21,7 +21,7 @@
{{rtt}}&thinsp;ms
{{/isClientOnly}}
</td>
- <td>
+ <td class="text-nowrap">
{{#isClientOnly}}
[CO]
{{/isClientOnly}}
diff --git a/modules-available/dnbd3/templates/page-proxy-clients.html b/modules-available/dnbd3/templates/page-proxy-clients.html
index 9e7cec4c..6733a056 100644
--- a/modules-available/dnbd3/templates/page-proxy-clients.html
+++ b/modules-available/dnbd3/templates/page-proxy-clients.html
@@ -1,20 +1,53 @@
-<div class="col-md-6">
- <h2>{{lang_clientList}}</h2>
+<div role="tabpanel" class="tab-pane active" id="tab-clients">
+ <div class="row">
+ <div class="col-md-6">
+ {{#loclist.0}}
+ <h2>{{lang_clientsByLocation}}</h2>
- <table class="table table-condensed">
- <tr>
- <th>{{lang_client}}</th>
- <th class="text-right">{{lang_bytesSent}}</th>
- </tr>
- {{#clients}}
- <tr>
- <td>
- {{address}}
- </td>
- <td data-sort="int" data-sort-value="{{bytesSent}}" class="text-right">
- {{bytesSent_s}}
- </td>
- </tr>
- {{/clients}}
- </table>
+ <table class="table table-condensed">
+ <tr>
+ <th>{{lang_location}}</th>
+ <th class="text-right">{{lang_count}}</th>
+ <th class="text-right">{{lang_recursiveCount}}</th>
+ </tr>
+ {{#loclist}}
+ <tr>
+ <td>
+ {{#depth}}
+ <div style="display:inline-block;width:{{depth}}em"></div>
+ {{/depth}}
+ {{locationname}}
+ </td>
+ <td class="text-right">
+ {{clientCount}}
+ </td>
+ <td class="text-right">
+ {{recCount}}
+ </td>
+ </tr>
+ {{/loclist}}
+ </table>
+ {{/loclist.0}}
+ </div>
+ <div class="col-md-6">
+ <h2>{{lang_clientList}}</h2>
+
+ <table class="table table-condensed">
+ <tr>
+ <th>{{lang_client}}</th>
+ <th class="text-right">{{lang_bytesSent}}</th>
+ </tr>
+ {{#clients}}
+ <tr>
+ <td>
+ {{address}}
+ </td>
+ <td data-sort="int" data-sort-value="{{bytesSent}}" class="text-right">
+ {{bytesSent_s}}
+ </td>
+ </tr>
+ {{/clients}}
+ </table>
+ </div>
+ </div>
</div> \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-proxy-config.html b/modules-available/dnbd3/templates/page-proxy-config.html
index adc73a57..f258e030 100644
--- a/modules-available/dnbd3/templates/page-proxy-config.html
+++ b/modules-available/dnbd3/templates/page-proxy-config.html
@@ -1,4 +1,18 @@
-<div class="col-md-6">
+<style>
+.tt { font-family:monospace }
+.tt .eq { margin:0 1ex }
+.tt .usel { user-select:none }
+.tt .usel::before { content: attr(data-con) }
+</style>
+<div role="tabpanel" class="tab-pane" id="tab-config">
<h2>{{lang_proxyConfig}}</h2>
- <pre>{{config}}</pre>
-</div> \ No newline at end of file
+ <div class="well tt" style="font-family:monospace">
+ {{#config}}
+ <span class="{{class1}}">{{text1}}</span>{{#text2}}<span class="eq">=</span>{{/text2}}<span class="{{class2}}">{{text2}}</span>
+ {{#extra}}
+ <span class="text-muted usel" data-con=" ; {{extra}}"></span>
+ {{/extra}}
+ <br>
+ {{/config}}
+ </div>
+</div>
diff --git a/modules-available/dnbd3/templates/page-proxy-header.html b/modules-available/dnbd3/templates/page-proxy-header.html
index 6f3f1b7f..7f3418cc 100644
--- a/modules-available/dnbd3/templates/page-proxy-header.html
+++ b/modules-available/dnbd3/templates/page-proxy-header.html
@@ -1 +1,2 @@
-<h1>{{ip}}</h1> \ No newline at end of file
+<h1>{{ip}}</h1>
+
diff --git a/modules-available/dnbd3/templates/page-proxy-images.html b/modules-available/dnbd3/templates/page-proxy-images.html
new file mode 100644
index 00000000..7e30de20
--- /dev/null
+++ b/modules-available/dnbd3/templates/page-proxy-images.html
@@ -0,0 +1,31 @@
+<div role="tabpanel" class="tab-pane" id="tab-images">
+ <h2>{{lang_imageList}}</h2>
+ <table class="table table-condensed">
+ <tr>
+ <th>{{lang_image}}</th>
+ <th class="text-right slx-smallcol">{{lang_clients}}</th>
+ <th class="text-right slx-smallcol">{{lang_size}}</th>
+ <th class="text-right slx-smallcol">{{lang_complete}}</th>
+ <th class="slx-smallcol">{{lang_uplink}}</th>
+ </tr>
+ {{#images}}
+ <tr>
+ <td class="text-nowrap">
+ {{name}}:{{rid}}
+ </td>
+ <td class="text-right text-nowrap">
+ {{users}}
+ </td>
+ <td class="text-right text-nowrap">
+ {{size_s}}
+ </td>
+ <td class="text-right text-nowrap">
+ {{complete}}&thinsp;%
+ </td>
+ <td class="text-nowrap">
+ {{uplinkServer}}
+ </td>
+ </tr>
+ {{/images}}
+ </table>
+</div> \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-proxy-loclist.html b/modules-available/dnbd3/templates/page-proxy-loclist.html
deleted file mode 100644
index 67c90683..00000000
--- a/modules-available/dnbd3/templates/page-proxy-loclist.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<div class="col-md-6">
- <h2>{{lang_clientsByLocation}}</h2>
-
- <table class="table table-condensed">
- <tr>
- <th>{{lang_location}}</th>
- <th class="text-right">{{lang_count}}</th>
- <th class="text-right">{{lang_recursiveCount}}</th>
- </tr>
- {{#list}}
- <tr>
- <td>
- {{#depth}}
- <div style="display:inline-block;width:{{depth}}em"></div>
- {{/depth}}
- {{locationname}}
- </td>
- <td class="text-right">
- {{clientCount}}
- </td>
- <td class="text-right">
- {{recCount}}
- </td>
- </tr>
- {{/list}}
- </table>
-</div> \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-proxy-stats.html b/modules-available/dnbd3/templates/page-proxy-stats.html
index e7811028..a866903c 100644
--- a/modules-available/dnbd3/templates/page-proxy-stats.html
+++ b/modules-available/dnbd3/templates/page-proxy-stats.html
@@ -1,9 +1,27 @@
<div class="panel panel-default">
<div class="panel-body">
- {{lang_sessionTx}}: <b>{{bytesSent_s}}</b>
- ––
- {{lang_sessionRx}}: <b>{{bytesReceived_s}}</b>
- ––
- {{lang_uptime}}: <b>{{uptime_s}}</b>
+ <div>
+ {{lang_sessionTx}}: <b>{{bytesSent_s}}</b>
+ ––
+ {{lang_sessionRx}}: <b>{{bytesReceived_s}}</b>
+ ––
+ {{lang_uptime}}: <b>{{uptime_s}}</b>
+ </div>
+ <div>
+ {{lang_storageSize}}: <b>{{spaceTotal_s}}</b>
+ ––
+ {{lang_diskFree}}: <b>{{spaceFree_s}} ({{percentFree}}&thinsp;%)</b>
+ </div>
</div>
-</div> \ No newline at end of file
+</div>
+
+<ul class="nav nav-tabs text-center" role="tablist">
+ {{#tab_config}}
+ <li role="presentation"><a href="#tab-config" role="tab" data-toggle="tab">{{lang_proxyConfig}}</a></li>
+ {{/tab_config}}
+ <li role="presentation" class="active"><a href="#tab-clients" role="tab" data-toggle="tab">{{lang_clientList}}</a></li>
+ <li role="presentation"><a href="#tab-images" role="tab" data-toggle="tab">{{lang_imageList}}</a></li>
+ {{#tab_altservers}}
+ <li role="presentation"><a href="#tab-altservers" role="tab" data-toggle="tab">{{lang_altservers}}</a></li>
+ {{/tab_altservers}}
+</ul> \ No newline at end of file
diff --git a/modules-available/dnbd3/templates/page-serverlist.html b/modules-available/dnbd3/templates/page-serverlist.html
index c5905dcd..65e4d6ea 100644
--- a/modules-available/dnbd3/templates/page-serverlist.html
+++ b/modules-available/dnbd3/templates/page-serverlist.html
@@ -15,14 +15,14 @@
<form method="post" action="?do=dnbd3">
<input type="hidden" name="token" value="{{token}}">
<div class="checkbox">
- <input id="enable-dnbd3" type="checkbox" name="enabled" {{enabled_checked_s}}>
+ <input id="enable-dnbd3" type="checkbox" name="enabled" {{enabled_checked_s}} {{perms.toggle-usage.disabled}}>
<label for="enable-dnbd3">{{lang_enableDnbd3}}</label>
</div>
<div class="checkbox">
- <input id="allow-nfs" type="checkbox" name="with-nfs" {{nfs_checked_s}}>
+ <input id="allow-nfs" type="checkbox" name="with-nfs" {{nfs_checked_s}} {{perms.toggle-usage.disabled}}>
<label for="allow-nfs">{{lang_allowNfsFallback}}</label>
</div>
- <button type="submit" name="action" value="toggle-usage" class="btn btn-success">
+ <button type="submit" name="action" value="toggle-usage" class="btn btn-success" {{perms.toggle-usage.disabled}}>
<span class="glyphicon glyphicon-floppy-disk"></span>
{{lang_save}}
</button>
@@ -36,7 +36,10 @@
<input type="hidden" name="action" value="refresh">
<h2>
{{lang_serverList}}
- <button id="refbtn" type="submit" class="btn btn-default"><span class="glyphicon glyphicon-refresh"></span></button>
+ <button id="refbtn" type="submit" class="btn btn-default" {{perms.refresh.disabled}} title="{{lang_manualRefreshInfo}}">
+ <span class="glyphicon glyphicon-refresh"></span>
+ {{lang_manualRefresh}}
+ </button>
</h2>
</form>
@@ -78,14 +81,18 @@
</td>
<td class="{{#self}}slx-bold{{/self}}">
{{#machineuuid}}
- <a class="pull-right btn btn-default btn-xs" href="?do=Statistics&uuid={{machineuuid}}">
+ <a class="pull-right btn btn-default btn-xs" href="?do=statistics&uuid={{machineuuid}}">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{{/machineuuid}}
+ {{^perms.view.details.disabled}}
<a href="?do=dnbd3&amp;show=proxy&amp;server={{serverid}}">
+ {{/perms.view.details.disabled}}
{{fixedip}}
<span class="small">{{clientip}}</span>
+ {{^perms.view.details.disabled}}
</a>
+ {{/perms.view.details.disabled}}
<div class="small">{{hostname}}</div>
</td>
<td data-sort="int" data-sort-default="desc" data-sort-value="{{disktotal}}">
@@ -123,7 +130,7 @@
{{#locations}}
{{locations}}
{{/locations}}
- <a href="?do=dnbd3&amp;show=locations&amp;server={{serverid}}" class="btn btn-default btn-xs">
+ <a href="?do=dnbd3&amp;show=locations&amp;server={{serverid}}" class="btn btn-default btn-xs {{edit_disabled}}">
<span class="glyphicon glyphicon-map-marker"></span>
</a>
{{/self}}
@@ -132,17 +139,19 @@
{{#machineuuid}}
{{#rebootcontrol}}
<button class="btn btn-warning btn-xs reboot-btn" type="button" data-id="{{serverid}}"
- data-toggle="modal" data-target="#server-reboot-modal" title="{{lang_reboot}}">
+ data-toggle="modal" data-target="#server-reboot-modal" title="{{lang_reboot}}"
+ {{edit_disabled}}>
<span class="glyphicon glyphicon-repeat"></span>
</button>
{{/rebootcontrol}}
<button class="btn btn-default btn-xs edit-btn" type="button" data-id="{{serverid}}"
- data-toggle="modal" data-target="#server-edit-modal" title="{{lang_settings}}">
+ data-toggle="modal" data-target="#server-edit-modal" title="{{lang_settings}}"
+ {{edit_disabled}}>
<span class="glyphicon glyphicon-cog"></span>
</button>
{{/machineuuid}}
{{^self}}
- <button class="btn btn-danger btn-xs" name="server" value="{{serverid}}"
+ <button class="btn btn-danger btn-xs" name="server" value="{{serverid}}" {{edit_disabled}}
onclick="return confirm('{{lang_wantToDelete}}')" title="{{lang_delete}}">
<span class="glyphicon glyphicon-trash"></span>
</button>
@@ -156,7 +165,7 @@
<div class="btn-toolbar pull-right">
<div class="btn-group">
- <button type="button" class="btn btn-success" data-toggle="modal" data-target="#add-modal">
+ <button type="button" class="btn btn-success" data-toggle="modal" data-target="#add-modal" {{perms.configure.external.disabled}}>
<span class="glyphicon glyphicon-plus"></span>
{{lang_externalServerAdd}}
</button>
@@ -165,7 +174,7 @@
</button>
</div>
<div class="btn-group">
- <a class="btn btn-success" href="?do=runmode&amp;module=dnbd3&amp;modeid=proxy&amp;redirect=?do=dnbd3">
+ <a class="btn btn-success {{perms.configure.proxy.disabled}}" href="?do=runmode&amp;module=dnbd3&amp;modeid=proxy&amp;redirect=?do=dnbd3">
<span class="glyphicon glyphicon-plus"></span>
{{lang_managedServerAdd}}
</a>
@@ -380,20 +389,32 @@ document.addEventListener('DOMContentLoaded', function () {
}
$t.html('<span class="glyphicon glyphicon-refresh slx-rotation"></span>');
var sid = rebootServerId;
+ var taskId = false;
+ var lastText;
var query = function() {
+ data = {"token": TOKEN, "action": "reboot", "server": sid};
+ if (taskId !== false) data['taskid'] = taskId;
$.ajax({
- "data": {"token": TOKEN, "action": "reboot", "server": sid},
+ "data": data,
"method": "POST",
- "dataType": "text",
+ "dataType": "json",
"url": "?do=dnbd3"
}).done(function (data) {
- $t.text(data);
- if (data.indexOf('REBOOTING') !== -1 || data.indexOf('CONNECTING') !== -1) {
+ if (!data || !data.taskId) return;
+ if (taskId === false) taskId = data.taskId;
+ if (data.error) data.rebootStatus += ' (' + data.error + ')';
+ if (data.rebootStatus !== lastText) {
+ $t.empty().text(data.rebootStatus);
+ }
+ if (data.taskStatus === 'TASK_PROCESSING' || data.taskStatus === 'TASK_WAITING') {
setTimeout(query, 5000);
- $t.append($('<span class="glyphicon glyphicon-refresh slx-rotation"></span>'));
+ if (data.rebootStatus !== lastText) {
+ $t.append($('<span class="glyphicon glyphicon-refresh slx-rotation"></span>'));
+ }
}
+ lastText = data.rebootStatus;
}).fail(function () {
- $.text('Failed');
+ $t.text('Failed');
});
};
query();