diff options
author | Simon Rettberg | 2019-09-09 11:47:27 +0200 |
---|---|---|
committer | Simon Rettberg | 2019-09-09 11:47:27 +0200 |
commit | 72e9ba141f5c82d71800f502f1c40028ffafb5b6 (patch) | |
tree | 7e4129a97da7023799d7de338084e350603d59b3 /modules-available/dnbd3 | |
parent | [slx-fixes.js] Put current tab on pages with tab-panes in history (diff) | |
download | slx-admin-72e9ba141f5c82d71800f502f1c40028ffafb5b6.tar.gz slx-admin-72e9ba141f5c82d71800f502f1c40028ffafb5b6.tar.xz slx-admin-72e9ba141f5c82d71800f502f1c40028ffafb5b6.zip |
[dnbd3] proxy view: Show cache-map when clicking percentage of image
Requires up to date DNBD3-Server
Diffstat (limited to 'modules-available/dnbd3')
-rw-r--r-- | modules-available/dnbd3/inc/dnbd3rpc.inc.php | 44 | ||||
-rw-r--r-- | modules-available/dnbd3/page.inc.php | 79 | ||||
-rw-r--r-- | modules-available/dnbd3/templates/page-proxy-images.html | 86 | ||||
-rw-r--r-- | modules-available/dnbd3/templates/page-proxy-stats.html | 10 |
4 files changed, 199 insertions, 20 deletions
diff --git a/modules-available/dnbd3/inc/dnbd3rpc.inc.php b/modules-available/dnbd3/inc/dnbd3rpc.inc.php index 6ed43254..6e7480c0 100644 --- a/modules-available/dnbd3/inc/dnbd3rpc.inc.php +++ b/modules-available/dnbd3/inc/dnbd3rpc.inc.php @@ -6,20 +6,7 @@ class Dnbd3Rpc { const QUERY_NOT_200 = 2; const QUERY_NOT_JSON = 3; - /** - * Query given DNBD3 server for status information. - * - * @param string $server server address - * @param int $port server port - * @param bool $stats include general stats - * @param bool $clients include client list - * @param bool $images include image list - * @param bool $diskSpace include disk space stats - * @param bool $config get config - * @param bool $altservers list of alt servers with status - * @return int|array the queried data as an array, or false on error - */ - public static function query($server, $stats, $clients, $images, $diskSpace = false, $config = false, $altservers = false) + private static function translateServer($server) { // Special case - local server if ($server === '<self>') { @@ -36,6 +23,24 @@ class Dnbd3Rpc { $server .= ':5003'; } } + return $server; + } + + /** + * Query given DNBD3 server for status information. + * + * @param string $server server address + * @param bool $stats include general stats + * @param bool $clients include client list + * @param bool $images include image list + * @param bool $diskSpace include disk space stats + * @param bool $config get config + * @param bool $altservers list of alt servers with status + * @return int|array the queried data as an array, or false on error + */ + public static function query($server, $stats, $clients, $images, $diskSpace = false, $config = false, $altservers = false) + { + $server = self::translateServer($server); $url = 'http://' . $server . '/query?'; if ($stats) { $url .= 'q=stats&'; @@ -66,4 +71,15 @@ class Dnbd3Rpc { return $ret; } + public static function getCacheMap($server, $imgId) + { + $server = self::translateServer($server); + $str = Download::asString('http://' . $server . '/cachemap?id=' . $imgId, 3, $code); + if ($str === false) + return self::QUERY_UNREACHABLE; + if ($code !== 200) + return self::QUERY_NOT_200; + return $str; + } + } diff --git a/modules-available/dnbd3/page.inc.php b/modules-available/dnbd3/page.inc.php index 4a32b0a3..87169a03 100644 --- a/modules-available/dnbd3/page.inc.php +++ b/modules-available/dnbd3/page.inc.php @@ -264,6 +264,9 @@ class Page_Dnbd3 extends Page foreach (['bytesSent', 'bytesReceived', 'spaceTotal', 'spaceFree'] as $key) { $stats[$key . '_s'] = Util::readableFileSize($stats[$key]); } + if ($stats['bytesReceived'] > 0) { + $stats['ratio'] = round($stats['bytesSent'] / $stats['bytesReceived'], 2); + } if ($stats['spaceTotal'] > 0) { $stats['percentFree'] = ($stats['spaceFree'] / $stats['spaceTotal']) * 100; $stats['percentFree'] = round($stats['percentFree'], $stats['percentFree'] < 10 ? 1 : 0); @@ -294,7 +297,20 @@ class Page_Dnbd3 extends Page } else { $extra = ''; $class2 = 'slx-bold'; - if (in_array($line['key'], ['serverPenalty', 'clientPenalty'])) { + if ($line['key'] === 'autoFreeDiskSpaceDelay') { + $v = (int)$line['val']; + if ($v >= 3600 * 24) { + $extra = floor($v / (3600 * 24)) . 'd '; + $v %= 3600 * 24; + } + if ($v >= 3600) { + $extra .= floor($v / 3600) . 'h '; + $v %= 3600; + } + if ($v >= 60) { + $extra .= floor($v / 60) . 'm '; + } + } elseif (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'; @@ -367,6 +383,15 @@ class Page_Dnbd3 extends Page $sort2[] = $image['name']; } array_multisort($sort1, SORT_NUMERIC | SORT_DESC, $sort2, SORT_ASC, $stats['images']); + $stats['serverId'] = $server['serverId']; + // Colors for bars + $stats['colors'] = []; + for ($i = 0; $i < 16; ++$i) { + $dark = dechex(max(0, $i - 3)); + $normal = dechex($i); + $extra = dechex(max(0, $i - 12)); + $stats['colors'][] = ['i' => $i, 'dark' => "#0{$dark}0", 'bright' => "#$extra$normal$extra"]; + } Render::addTemplate('page-proxy-images', $stats); Render::closeTag('div'); } @@ -416,7 +441,7 @@ class Page_Dnbd3 extends Page WHERE s.serverid = :serverId', compact('serverId')); if ($server === false) { if (AJAX) - die('Invalid server id'); + die('Invalid server id: ' . $serverId); Message::addError('server-non-existent', $serverId); Util::redirect('?do=dnbd3'); } @@ -427,6 +452,7 @@ class Page_Dnbd3 extends Page } else { $server['ip'] = '127.0.0.1'; } + $server['serverId'] = $serverId; return $server; } @@ -455,6 +481,8 @@ class Page_Dnbd3 extends Page $this->ajaxEditServer(); } elseif ($action === 'reboot') { $this->ajaxReboot(); + } elseif ($action === 'cachemap') { + $this->ajaxCacheMap(); } else { die($action . '???'); } @@ -545,4 +573,51 @@ class Page_Dnbd3 extends Page die(json_encode($status)); } + private function ajaxCacheMap() + { + $server = $this->getServerById(); + $imgId = Request::any('id', 0, 'int'); + if ($imgId <= 0) { + Header('HTTP/1.1 400 Bad Request'); + die('Invalid/no image id'); + } + $data = Dnbd3Rpc::getCacheMap($server['ip'], $imgId); + if ($data === Dnbd3Rpc::QUERY_UNREACHABLE) { + Header('HTTP/1.1 504 Gateway Timeout'); + die('Proxy not reachable'); + } + if ($data === Dnbd3Rpc::QUERY_NOT_200) { + Header('HTTP/1.1 503 Service Unavailable'); + die("Proxy didn't reply with 200 OK"); + } + Header('Content-Type: application/octet-stream'); + die($data); + } + + private function genChunk($acc) + { + static $last = -1; + static $count = 0; + if ($acc !== false) { + if ($acc > 15) { + $acc = 15; + } + $acc = round($acc); + if ($last === $acc) { + $count++; + return ''; + } + } + if ($last !== -1) { + if ($count === 1) + return '<b style="background:#0' . dechex($acc) . '0"></b>'; + $line = '<b style="background:#0' . dechex($last) . '0;flex-grow:' . $count . '"></b>'; + } else { + $line = ''; + } + $last = $acc; + $count = 1; + return $line; + } + } diff --git a/modules-available/dnbd3/templates/page-proxy-images.html b/modules-available/dnbd3/templates/page-proxy-images.html index ff420ffd..3ec4908c 100644 --- a/modules-available/dnbd3/templates/page-proxy-images.html +++ b/modules-available/dnbd3/templates/page-proxy-images.html @@ -21,7 +21,7 @@ {{size_s}} </td> <td class="text-right text-nowrap"> - {{complete}} % + <a data-imgid="{{id}}" class="cache-map" href="#">{{complete}} %</a> </td> <td class="text-right text-nowrap"> {{idle_s}} @@ -33,3 +33,87 @@ {{/images}} </table> </div> + +<style type="text/css"> + .cmbar { + display: flex; + width: 250px; + align-items: stretch; + padding: 0; + } + .cmbar b { + display: inline-block; + flex-grow: 1; + height: 1em; + margin: 0; + } + {{#colors}} + .cmbar .a{{i}} {background: linear-gradient({{dark}}, {{bright}}, {{dark}})} + {{/colors}} +</style> + +<script> + document.addEventListener('DOMContentLoaded', function () { + $('.cache-map').click(function (e) { + e.preventDefault(); + var $this = $(this); + // Use xhr directly as jQuery doesn't support arraybuffer + var xhr = new XMLHttpRequest(); + xhr.open('GET', '?do=dnbd3&action=cachemap&server={{serverId}}&id=' + $this.data('imgid') + '&raw=1&async=1', true); + xhr.responseType = 'arraybuffer'; + xhr.onload = function(e) { + if (this.readyState !== 4) + return; + var ua = new Uint8Array(this.response); + console.log(ua); + if (this.status !== 200) { + $this.replaceWith($('<span>').text(typeof TextDecoder !== 'undefined' ? new TextDecoder("utf-8").decode(ua) : 'HTTP ' + this.status)); + return; + } + var llast = -1; + var lcount = 0; + var genChunk = function(acc) { + var line; + if (acc !== false) { + if (acc > 15) acc = 15; else acc = (acc + 0.49) | 0; + if (llast === acc) { + lcount++; + return ''; + } + } + if (llast !== -1 || acc === false) { + if (lcount === 1) { + line = '<b class="a' + llast + '"></b>'; + } else { + line = '<b class="a' + llast + '" style="flex-grow:' + lcount + '"></b>'; + } + } else { + line = ''; + } + llast = acc; + lcount = 1; + return line; + }; + var l = ua.length; + var div; + if (l >= 240) { + div = l / 120; + } else { + div = 1; + } + var acc = 0, target = div, div16 = div * 16, html = ''; + for (var i = 0; i < l; ++i) { + acc += ua[i]; + if (i + 1 >= target) { + html += genChunk(acc / (div16)); + acc = 0; + target += div; + } + } + html += genChunk(false); + $this.replaceWith($('<div class="cmbar">').html(html)); + }; + xhr.send(); + }); + }); +</script> diff --git a/modules-available/dnbd3/templates/page-proxy-stats.html b/modules-available/dnbd3/templates/page-proxy-stats.html index a866903c..9c3a4a84 100644 --- a/modules-available/dnbd3/templates/page-proxy-stats.html +++ b/modules-available/dnbd3/templates/page-proxy-stats.html @@ -1,11 +1,15 @@ <div class="panel panel-default"> <div class="panel-body"> + <div class="pull-right"> + {{lang_uptime}}: <b>{{uptime_s}}</b> + </div> <div> {{lang_sessionTx}}: <b>{{bytesSent_s}}</b> - –– + – {{lang_sessionRx}}: <b>{{bytesReceived_s}}</b> - –– - {{lang_uptime}}: <b>{{uptime_s}}</b> + {{#ratio}} +   ({{lang_ratio}}: {{ratio}}) + {{/ratio}} </div> <div> {{lang_storageSize}}: <b>{{spaceTotal_s}}</b> |