disk_detail.html 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. {% extends "layout.html" %}
  2. {% block head %}
  3. {{ super() }}
  4. <style type="text/css">
  5. @media (min-width: 768px) {
  6. .form-horizontal .control-label {
  7. text-align: left;
  8. }
  9. }
  10. label>span {
  11. color: deepskyblue;
  12. }
  13. .btn,
  14. .form-group>div>div,
  15. .form-control {
  16. border-radius: 0;
  17. }
  18. .table {
  19. font-size: 12px;
  20. border-width: 1px;
  21. line-height: 22px;
  22. }
  23. .table > tbody > tr > td {
  24. color: #424547;
  25. }
  26. .table-bordered > tbody > tr {
  27. padding-top: 10px;
  28. padding-bottom: 10px;
  29. }
  30. .table-bordered > thead > tr > th,
  31. .table-bordered > tbody > tr > th,
  32. .table-bordered > tfoot > tr > th,
  33. .table-bordered > thead > tr > td,
  34. .table-bordered > tbody > tr > td,
  35. .table-bordered > tfoot > tr > td {
  36. border-style: solid;
  37. border-width: 1px 0 0 0;
  38. }
  39. .guest-label {
  40. color: #999999;
  41. }
  42. .guest-desc {
  43. color: #333333;
  44. }
  45. </style>
  46. {% endblock head %}
  47. {% block body %}
  48. <script>
  49. var resource_path = window.location.pathname;
  50. var resource_path_array = resource_path.split('/');
  51. var uuid = resource_path_array[resource_path_array.length - 1];
  52. var datetime_format_type = 'time';
  53. function format_time(timestamp, i) {
  54. if (datetime_format_type === 'time') {
  55. return new Date(timestamp).format('HH:MM');
  56. } else {
  57. return new Date(timestamp).format('mm-dd');
  58. }
  59. }
  60. function render_disk_throughput_chart(disk_uuid, granularity, dev_id, dev_name) {
  61. var url = '/api/performance/disk_io/last_hour/' + disk_uuid;
  62. if (granularity === 'hour') {
  63. url = '/api/performance/disk_io/last_hour/' + disk_uuid
  64. } else if (granularity === 'six_hours') {
  65. url = '/api/performance/disk_io/last_six_hours/' + disk_uuid
  66. } else if (granularity === 'day') {
  67. url = '/api/performance/disk_io/last_day/' + disk_uuid
  68. } else {
  69. url = '/api/performance/disk_io/last_seven_days/' + disk_uuid
  70. }
  71. $.ajax({
  72. url : url,
  73. type : 'GET',
  74. contentType: "application/json; charset=utf-8",
  75. dataType: 'json',
  76. error : function() {
  77. alter_danger('获取图表数据失败失败!');
  78. },
  79. success : function(data, textStatus, xhr) {
  80. if (data.data.length > 1) {
  81. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  82. datetime_format_type = 'date';
  83. }
  84. }
  85. var option = {
  86. color: ['#3BC0FF', '#FAB406'],
  87. title: {
  88. text: '磁盘吞吐量 - ' + dev_name
  89. },
  90. legend: {
  91. data:['读(MBps)', '写(MBps)'],
  92. bottom: 5
  93. },
  94. toolbox: {
  95. feature: {
  96. dataZoom: {
  97. yAxisIndex: 'none'
  98. },
  99. magicType: {type: ['line', 'bar']},
  100. saveAsImage: {
  101. show: true,
  102. pixelRatio: 4
  103. }
  104. }
  105. },
  106. tooltip: {
  107. show: true,
  108. trigger: 'axis',
  109. formatter: (function (params, ticket, callback) {
  110. var readSeriesName = params[0].seriesName;
  111. var writeSeriesName = params[1].seriesName;
  112. var read = params[0].data[1];
  113. var write = params[1].data[1];
  114. var readMarker = params[0].marker;
  115. var writeMarker = params[1].marker;
  116. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  117. if (read === null) {
  118. read = '无数据';
  119. }
  120. if (write === null) {
  121. write = '无数据';
  122. }
  123. return datetime + '<br />' + [readMarker, readSeriesName, read].join(' ') +
  124. '<br />' + [writeMarker, writeSeriesName, write].join(' ')
  125. })
  126. },
  127. xAxis: {
  128. type: 'time',
  129. axisTick: {
  130. show: false
  131. },
  132. axisLine: {
  133. lineStyle: {
  134. opacity: 0.1,
  135. color: '#3d4245'
  136. }
  137. },
  138. splitLine: {
  139. show: false
  140. },
  141. axisLabel: {
  142. formatter: format_time
  143. }
  144. },
  145. yAxis: {
  146. min: 0,
  147. max: 'dataMax',
  148. minInterval: 2,
  149. axisTick: {
  150. show: false
  151. },
  152. axisLine: {
  153. lineStyle: {
  154. opacity: 0,
  155. color: '#8c8f91'
  156. }
  157. },
  158. splitLine: {
  159. show: true,
  160. lineStyle: {
  161. width: 1,
  162. opacity: 0.5
  163. }
  164. }
  165. },
  166. series: [{
  167. name: '读(MBps)',
  168. type: 'line',
  169. showSymbol: false,
  170. smooth: true,
  171. lineStyle: {
  172. normal: {
  173. width: 1
  174. }
  175. },
  176. data: (function () {
  177. var d = [];
  178. $.each(data.data, function(i, ele) {
  179. d.push([
  180. ele['timestamp'] * 1000,
  181. ele['rd_bytes'] !== null ? Math.floor(ele['rd_bytes'] / 1024 / 1024 * 1000) / 1000 : null
  182. ])
  183. });
  184. return d;
  185. })()
  186. },{
  187. name: '写(MBps)',
  188. type: 'line',
  189. showSymbol: false,
  190. smooth: true,
  191. lineStyle: {
  192. normal: {
  193. width: 1
  194. }
  195. },
  196. data: (function () {
  197. var d = [];
  198. $.each(data.data, function(i, ele) {
  199. d.push([
  200. ele['timestamp'] * 1000,
  201. ele['wr_bytes'] !== null ? Math.floor(ele['wr_bytes'] / 1024 / 1024 * 1000) / 1000 : null
  202. ])
  203. });
  204. return d;
  205. })()
  206. }]
  207. };
  208. var disk_chart = echarts.init(document.getElementById(dev_id));
  209. disk_chart.setOption(option);
  210. }
  211. });
  212. }
  213. function render_disk_iops_chart(disk_uuid, granularity, dev_id, dev_name) {
  214. var url = '/api/performance/disk_io/last_hour/' + disk_uuid;
  215. if (granularity === 'hour') {
  216. url = '/api/performance/disk_io/last_hour/' + disk_uuid
  217. } else if (granularity === 'six_hours') {
  218. url = '/api/performance/disk_io/last_six_hours/' + disk_uuid
  219. } else if (granularity === 'day') {
  220. url = '/api/performance/disk_io/last_day/' + disk_uuid
  221. } else {
  222. url = '/api/performance/disk_io/last_seven_days/' + disk_uuid
  223. }
  224. $.ajax({
  225. url : url,
  226. type : 'GET',
  227. contentType: "application/json; charset=utf-8",
  228. dataType: 'json',
  229. error : function() {
  230. alter_danger('获取图表数据失败失败!');
  231. },
  232. success : function(data, textStatus, xhr) {
  233. if (data.data.length > 1) {
  234. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  235. datetime_format_type = 'date';
  236. }
  237. }
  238. var option = {
  239. color: ['#3BC0FF', '#FAB406'],
  240. title: {
  241. text: '磁盘IOPS - ' + dev_name
  242. },
  243. legend: {
  244. data:['读(IOPS)', '写(IOPS)'],
  245. bottom: 5
  246. },
  247. toolbox: {
  248. feature: {
  249. dataZoom: {
  250. yAxisIndex: 'none'
  251. },
  252. magicType: {type: ['line', 'bar']},
  253. saveAsImage: {
  254. show: true,
  255. pixelRatio: 4
  256. }
  257. }
  258. },
  259. tooltip: {
  260. show: true,
  261. trigger: 'axis',
  262. formatter: (function (params, ticket, callback) {
  263. var readSeriesName = params[0].seriesName;
  264. var writeSeriesName = params[1].seriesName;
  265. var read = params[0].data[1];
  266. var write = params[1].data[1];
  267. var readMarker = params[0].marker;
  268. var writeMarker = params[1].marker;
  269. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  270. if (read === null) {
  271. read = '无数据';
  272. }
  273. if (write === null) {
  274. write = '无数据';
  275. }
  276. return datetime + '<br />' + [readMarker, readSeriesName, read].join(' ') +
  277. '<br />' + [writeMarker, writeSeriesName, write].join(' ')
  278. })
  279. },
  280. xAxis: {
  281. type: 'time',
  282. axisTick: {
  283. show: false
  284. },
  285. axisLine: {
  286. lineStyle: {
  287. opacity: 0.1,
  288. color: '#3d4245'
  289. }
  290. },
  291. splitLine: {
  292. show: false
  293. },
  294. axisLabel: {
  295. formatter: format_time
  296. }
  297. },
  298. yAxis: {
  299. min: 0,
  300. max: 'dataMax',
  301. minInterval: 2,
  302. axisTick: {
  303. show: false
  304. },
  305. axisLine: {
  306. lineStyle: {
  307. opacity: 0,
  308. color: '#8c8f91'
  309. }
  310. },
  311. splitLine: {
  312. show: true,
  313. lineStyle: {
  314. width: 1,
  315. opacity: 0.5
  316. }
  317. }
  318. },
  319. series: [{
  320. name: '读(IOPS)',
  321. type: 'line',
  322. showSymbol: false,
  323. smooth: true,
  324. lineStyle: {
  325. normal: {
  326. width: 1
  327. }
  328. },
  329. data: (function () {
  330. var d = [];
  331. $.each(data.data, function(i, ele) {
  332. d.push([
  333. ele['timestamp'] * 1000,
  334. ele['rd_req'] !== null ? ele['rd_req'] : null
  335. ])
  336. });
  337. return d;
  338. })()
  339. },{
  340. name: '写(IOPS)',
  341. type: 'line',
  342. showSymbol: false,
  343. smooth: true,
  344. lineStyle: {
  345. normal: {
  346. width: 1
  347. }
  348. },
  349. data: (function () {
  350. var d = [];
  351. $.each(data.data, function(i, ele) {
  352. d.push([
  353. ele['timestamp'] * 1000,
  354. ele['wr_req'] !== null ? ele['wr_req'] : null
  355. ])
  356. });
  357. return d;
  358. })()
  359. }]
  360. };
  361. var disk_chart = echarts.init(document.getElementById(dev_id));
  362. disk_chart.setOption(option);
  363. }
  364. });
  365. }
  366. function render_disks_chart(uuid, granularity) {
  367. var dev_table = [];
  368. for (var i = 1; i <= 26; i++) {
  369. dev_table.push('vd' + String.fromCharCode(0x60+i));
  370. }
  371. var dev_name = dev_table[{{ disk_ret.data.sequence }}];
  372. var dev_id_throughput = 'disk_throughput_chart';
  373. var dev_id_iops = 'disk_iops_chart';
  374. render_disk_throughput_chart(uuid, granularity, dev_id_throughput, dev_name);
  375. render_disk_iops_chart(uuid, granularity, dev_id_iops, dev_name);
  376. }
  377. $(document).ready(function() {
  378. $('body').addClass('add-transition');
  379. $('.add-page-transition').on('click', function(){
  380. var transAttr = $(this).attr('data-transition');
  381. $('.add-transition').attr('class', 'add-transition');
  382. $('.add-transition').addClass(transAttr);
  383. });
  384. render_disks_chart(uuid, 'hour')
  385. });
  386. function refresh_render_with_specify_granularity(granularity) {
  387. render_disks_chart(uuid, granularity)
  388. }
  389. </script>
  390. <div class="container" style="padding-top: 100px; width: 90%; max-width: 100%;">
  391. <div class="panel">
  392. <div class="panel-body">
  393. <a href="javascript:history.go(-1)" class="btn btn-xs btn-default add-page-transition" data-transition="pt-page-moveFromLeft-init" style="margin-bottom: 4px; margin-left: 10px;">
  394. <span class="glyph-icon icon-separator" style="transform: rotateY(-180deg);">
  395. <i class="glyph-icon icon-level-up"></i>
  396. </span>
  397. <span class="button-content">
  398. 返回
  399. </span>
  400. </a>
  401. <div class="row" style="margin-top: 10px;">
  402. <div class="col-xs-4">
  403. <div style="background: #F5f6FA; border: 1px solid #e1e6eb; padding: 10px; font-size: 14px; width: 100%;">
  404. <span>
  405. 磁盘信息
  406. </span>
  407. </div>
  408. <table class="table table-bordered">
  409. <tbody>
  410. <tr>
  411. <td>
  412. <span class="guest-label">UUID:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  413. <span class="guest-desc">
  414. {{ disk_ret.data.uuid }}
  415. </span>
  416. </td>
  417. </tr>
  418. <tr>
  419. <td>
  420. <span class="guest-label">名称:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  421. <span class="guest-desc">
  422. {{ disk_ret.data.remark }}
  423. </span>
  424. </td>
  425. </tr>
  426. <tr>
  427. <td>
  428. <span class="guest-label">状态:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  429. <span class="guest-desc">
  430. {{ format_disk_state(disk_ret.data.state)|safe }}
  431. </span>
  432. </td>
  433. </tr>
  434. <tr>
  435. <td>
  436. <span class="guest-label">磁盘属性:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  437. <span class="guest-desc">
  438. {% if disk_ret.data.sequence == 0 %}
  439. 系统盘
  440. {% else %}
  441. 数据盘
  442. {% endif %}
  443. </span>
  444. </td>
  445. </tr>
  446. <tr>
  447. <td>
  448. <span class="guest-label">磁盘容量:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  449. <span class="guest-desc">
  450. {{ disk_ret.data.size }} GB
  451. </span>
  452. </td>
  453. </tr>
  454. <tr>
  455. <td>
  456. <span class="guest-label">被挂载于:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  457. <span class="guest-desc">
  458. {% if disk_ret.data.sequence != -1 %}
  459. <a href="/guest/detail/{{ disk_ret.data.guest_uuid }}">{{ guest_ret.data.label }}/{{ guest_ret.data.remark }}</a>
  460. {% else %}
  461. {% endif %}
  462. </span>
  463. </td>
  464. </tr>
  465. <tr>
  466. <td>
  467. <span class="guest-label">设备号:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  468. <span class="guest-desc">
  469. {{ format_sequence_to_device_name(disk_ret.data.sequence) }}
  470. </span>
  471. </td>
  472. </tr>
  473. <tr>
  474. <td>
  475. <span class="guest-label">创建时间:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  476. <span class="guest-desc">
  477. {{ format_datetime_by_tus(disk_ret.data.create_time) }}
  478. </span>
  479. </td>
  480. </tr>
  481. </tbody>
  482. </table>
  483. </div>
  484. <div class="col-xs-8">
  485. <div class="row" style="margin-bottom: 20px;">
  486. <div class="col-xs-8"></div>
  487. <div class="col-xs-4">
  488. <div class="btn-group btn-group-justified btn-group-xs">
  489. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('hour');">1小时</a>
  490. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('six_hours');">6小时</a>
  491. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('day');">1天</a>
  492. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('seven_days');">7天</a>
  493. </div>
  494. </div>
  495. </div>
  496. <div>
  497. <div id="disk_throughput_chart" style="width: 800px;height:280px;"></div>
  498. <div id="disk_iops_chart" style="width: 800px;height:280px;"></div>
  499. </div>
  500. <div id="disks_chart"></div>
  501. </div>
  502. </div>
  503. </div>
  504. </div>
  505. </div>
  506. {% endblock body %}