host_detail.html 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  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 cpu_chart = null;
  53. var traffic_chart = null;
  54. var memory_chart = null;
  55. var datetime_format_type = 'time';
  56. function format_time(timestamp, i) {
  57. if (datetime_format_type === 'time') {
  58. return new Date(timestamp).format('HH:MM');
  59. } else {
  60. return new Date(timestamp).format('mm-dd');
  61. }
  62. }
  63. function render_cpu_chart(node_id, granularity) {
  64. var url = '/api/host_performance/cpu_memory/last_hour/' + node_id;
  65. if (granularity === 'hour') {
  66. url = '/api/host_performance/cpu_memory/last_hour/' + node_id
  67. } else if (granularity === 'six_hours') {
  68. url = '/api/host_performance/cpu_memory/last_six_hours/' + node_id
  69. } else if (granularity === 'day') {
  70. url = '/api/host_performance/cpu_memory/last_day/' + node_id
  71. } else {
  72. url = '/api/host_performance/cpu_memory/last_seven_days/' + node_id
  73. }
  74. $.ajax({
  75. url : url,
  76. type : 'GET',
  77. contentType: "application/json; charset=utf-8",
  78. dataType: 'json',
  79. error : function() {
  80. alter_danger('获取图表数据失败失败!');
  81. },
  82. success : function(data, textStatus, xhr) {
  83. if (data.data.length > 1) {
  84. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  85. datetime_format_type = 'date';
  86. }
  87. }
  88. var option = {
  89. color: ['#3BC0FF'],
  90. title: {
  91. text: 'CPU'
  92. },
  93. legend: {
  94. data:['CPU使用率(%)'],
  95. bottom: 5
  96. },
  97. toolbox: {
  98. feature: {
  99. dataZoom: {
  100. yAxisIndex: 'none'
  101. },
  102. magicType: {type: ['line', 'bar']},
  103. saveAsImage: {
  104. show: true,
  105. pixelRatio: 4
  106. }
  107. }
  108. },
  109. tooltip: {
  110. show: true,
  111. trigger: 'axis',
  112. formatter: (function (params, ticket, callback) {
  113. var cpu_load = params[0].data[1];
  114. var seriesName = params[0].seriesName;
  115. var marker = params[0].marker;
  116. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  117. if (cpu_load === null) {
  118. cpu_load = '无数据';
  119. }
  120. return datetime + '<br />' + [marker, seriesName, cpu_load].join(' ')
  121. })
  122. },
  123. xAxis: {
  124. type: 'time',
  125. axisTick: {
  126. show: false
  127. },
  128. axisLine: {
  129. lineStyle: {
  130. opacity: 0.1,
  131. color: '#3d4245'
  132. }
  133. },
  134. splitLine: {
  135. show: false
  136. },
  137. axisLabel: {
  138. formatter: format_time
  139. }
  140. },
  141. yAxis: {
  142. min: 0,
  143. max: 'dataMax',
  144. minInterval: 2,
  145. axisTick: {
  146. show: false
  147. },
  148. axisLine: {
  149. lineStyle: {
  150. opacity: 0,
  151. color: '#8c8f91'
  152. }
  153. },
  154. splitLine: {
  155. show: true,
  156. lineStyle: {
  157. width: 1,
  158. opacity: 0.5
  159. }
  160. }
  161. },
  162. series: [{
  163. name: 'CPU使用率(%)',
  164. type: 'line',
  165. showSymbol: false,
  166. smooth: true,
  167. lineStyle: {
  168. normal: {
  169. width: 1
  170. }
  171. },
  172. data: (function () {
  173. var d = [];
  174. $.each(data.data, function(i, ele) {
  175. d.push([
  176. ele['timestamp'] * 1000,
  177. ele['cpu_load']
  178. ])
  179. });
  180. return d;
  181. })()
  182. }]
  183. };
  184. cpu_chart.setOption(option);
  185. }
  186. });
  187. }
  188. function render_traffic_chart(node_id, granularity) {
  189. var url = '/api/host_performance/traffic/last_hour/' + node_id;
  190. if (granularity === 'hour') {
  191. url = '/api/host_performance/traffic/last_hour/' + node_id
  192. } else if (granularity === 'six_hours') {
  193. url = '/api/host_performance/traffic/last_six_hours/' + node_id
  194. } else if (granularity === 'day') {
  195. url = '/api/host_performance/traffic/last_day/' + node_id
  196. } else {
  197. url = '/api/host_performance/traffic/last_seven_days/' + node_id
  198. }
  199. $.ajax({
  200. url : url,
  201. type : 'GET',
  202. contentType: "application/json; charset=utf-8",
  203. dataType: 'json',
  204. error : function() {
  205. alter_danger('获取图表数据失败失败!');
  206. },
  207. success : function(data, textStatus, xhr) {
  208. if (data.data.length > 1) {
  209. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  210. datetime_format_type = 'date';
  211. }
  212. }
  213. var option = {
  214. color: ['#3BC0FF', '#FAB406'],
  215. title: {
  216. text: '网络'
  217. },
  218. legend: {
  219. data:['流入(kbps)', '流出(kbps)'],
  220. bottom: 5
  221. },
  222. toolbox: {
  223. feature: {
  224. dataZoom: {
  225. yAxisIndex: 'none'
  226. },
  227. magicType: {type: ['line', 'bar']},
  228. saveAsImage: {
  229. show: true,
  230. pixelRatio: 4
  231. }
  232. }
  233. },
  234. tooltip: {
  235. show: true,
  236. trigger: 'axis',
  237. formatter: (function (params, ticket, callback) {
  238. var inflowSeriesName = params[0].seriesName;
  239. var outflowSeriesName = params[1].seriesName;
  240. var inflow = params[0].data[1];
  241. var outflow = params[1].data[1];
  242. var inflowMarker = params[0].marker;
  243. var outflowMarker = params[1].marker;
  244. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  245. if (inflow === null) {
  246. inflow = '无数据';
  247. }
  248. if (outflow === null) {
  249. outflow = '无数据';
  250. }
  251. return datetime + '<br />' + [inflowMarker, inflowSeriesName, inflow].join(' ') +
  252. '<br />' + [outflowMarker, outflowSeriesName, outflow].join(' ')
  253. })
  254. },
  255. xAxis: {
  256. type: 'time',
  257. axisTick: {
  258. show: false
  259. },
  260. axisLine: {
  261. lineStyle: {
  262. opacity: 0.1,
  263. color: '#3d4245'
  264. }
  265. },
  266. splitLine: {
  267. show: false
  268. },
  269. axisLabel: {
  270. formatter: format_time
  271. }
  272. },
  273. yAxis: {
  274. min: 0,
  275. max: 'dataMax',
  276. minInterval: 2,
  277. axisTick: {
  278. show: false
  279. },
  280. axisLine: {
  281. lineStyle: {
  282. opacity: 0,
  283. color: '#8c8f91'
  284. }
  285. },
  286. splitLine: {
  287. show: true,
  288. lineStyle: {
  289. width: 1,
  290. opacity: 0.5
  291. }
  292. }
  293. },
  294. series: [{
  295. name: '流入(kbps)',
  296. type: 'line',
  297. showSymbol: false,
  298. smooth: true,
  299. lineStyle: {
  300. normal: {
  301. width: 1
  302. }
  303. },
  304. data: (function () {
  305. var d = [];
  306. $.each(data.data, function(i, ele) {
  307. d.push([
  308. ele['timestamp'] * 1000,
  309. ele['rx_bytes'] !== null ? Math.floor(ele['rx_bytes'] / 1000) : null
  310. ])
  311. });
  312. return d;
  313. })()
  314. },{
  315. name: '流出(kbps)',
  316. type: 'line',
  317. showSymbol: false,
  318. smooth: true,
  319. lineStyle: {
  320. normal: {
  321. width: 1
  322. }
  323. },
  324. data: (function () {
  325. var d = [];
  326. $.each(data.data, function(i, ele) {
  327. d.push([
  328. ele['timestamp'] * 1000,
  329. ele['tx_bytes'] !== null ? Math.floor(ele['tx_bytes'] / 1000) : null
  330. ])
  331. });
  332. return d;
  333. })()
  334. }]
  335. };
  336. traffic_chart.setOption(option);
  337. }
  338. });
  339. }
  340. function render_memory_chart(node_id, granularity) {
  341. var url = '/api/host_performance/cpu_memory/last_hour/' + node_id;
  342. if (granularity === 'hour') {
  343. url = '/api/host_performance/cpu_memory/last_hour/' + node_id
  344. } else if (granularity === 'six_hours') {
  345. url = '/api/host_performance/cpu_memory/last_six_hours/' + node_id
  346. } else if (granularity === 'day') {
  347. url = '/api/host_performance/cpu_memory/last_day/' + node_id
  348. } else {
  349. url = '/api/host_performance/cpu_memory/last_seven_days/' + node_id
  350. }
  351. $.ajax({
  352. url: url,
  353. type: 'GET',
  354. contentType: "application/json; charset=utf-8",
  355. dataType: 'json',
  356. error: function () {
  357. alter_danger('获取图表数据失败失败!');
  358. },
  359. success: function (data, textStatus, xhr) {
  360. if (data.data.length > 1) {
  361. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  362. datetime_format_type = 'date';
  363. }
  364. }
  365. var option = {
  366. color: ['#35CD03'],
  367. title: {
  368. text: '内存'
  369. },
  370. legend: {
  371. data: ['可用量'],
  372. bottom: 5
  373. },
  374. toolbox: {
  375. feature: {
  376. dataZoom: {
  377. yAxisIndex: 'none'
  378. },
  379. magicType: {type: ['line', 'bar']},
  380. saveAsImage: {
  381. show: true,
  382. pixelRatio: 4
  383. }
  384. }
  385. },
  386. tooltip: {
  387. show: true,
  388. trigger: 'axis',
  389. formatter: (function (params, ticket, callback) {
  390. var seriesName = params[0].seriesName;
  391. var free = params[0].data[1];
  392. var marker = params[0].marker;
  393. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  394. if (free === null) {
  395. free = '无数据';
  396. }
  397. return datetime + '<br />' + [marker, seriesName, free].join(' ')
  398. })
  399. },
  400. xAxis: {
  401. type: 'time',
  402. axisTick: {
  403. show: false
  404. },
  405. axisLine: {
  406. lineStyle: {
  407. opacity: 0.1,
  408. color: '#3d4245'
  409. }
  410. },
  411. splitLine: {
  412. show: false
  413. },
  414. axisLabel: {
  415. formatter: format_time
  416. }
  417. },
  418. yAxis: {
  419. min: 0,
  420. max: 'dataMax',
  421. minInterval: 2,
  422. axisTick: {
  423. show: false
  424. },
  425. axisLine: {
  426. lineStyle: {
  427. opacity: 0,
  428. color: '#8c8f91'
  429. }
  430. },
  431. splitLine: {
  432. show: true,
  433. lineStyle: {
  434. width: 1,
  435. opacity: 0.5
  436. }
  437. }
  438. },
  439. series: [{
  440. name: '可用量(GB)',
  441. type: 'line',
  442. showSymbol: false,
  443. smooth: true,
  444. lineStyle: {
  445. normal: {
  446. width: 1
  447. }
  448. },
  449. areaStyle: {normal: {}},
  450. data: (function () {
  451. var d = [];
  452. $.each(data.data, function (i, ele) {
  453. d.push([
  454. ele['timestamp'] * 1000,
  455. ele['memory_unused'] !== null ? Math.floor(ele['memory_unused'] / 1024) / 1000 : null
  456. ])
  457. });
  458. return d;
  459. })()
  460. }]
  461. };
  462. memory_chart.setOption(option);
  463. }
  464. });
  465. }
  466. function render_disk_throughput_chart(disk_uuid, granularity, dev_id, dev_name) {
  467. var url = '/api/performance/disk_io/last_hour/' + disk_uuid;
  468. if (granularity === 'hour') {
  469. url = '/api/performance/disk_io/last_hour/' + disk_uuid
  470. } else if (granularity === 'six_hours') {
  471. url = '/api/performance/disk_io/last_six_hours/' + disk_uuid
  472. } else if (granularity === 'day') {
  473. url = '/api/performance/disk_io/last_day/' + disk_uuid
  474. } else {
  475. url = '/api/performance/disk_io/last_seven_days/' + disk_uuid
  476. }
  477. $.ajax({
  478. url : url,
  479. type : 'GET',
  480. contentType: "application/json; charset=utf-8",
  481. dataType: 'json',
  482. error : function() {
  483. alter_danger('获取图表数据失败失败!');
  484. },
  485. success : function(data, textStatus, xhr) {
  486. if (data.data.length > 1) {
  487. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  488. datetime_format_type = 'date';
  489. }
  490. }
  491. var option = {
  492. color: ['#3BC0FF', '#FAB406'],
  493. title: {
  494. text: '磁盘吞吐量 - ' + dev_name
  495. },
  496. legend: {
  497. data:['读(MBps)', '写(MBps)'],
  498. bottom: 5
  499. },
  500. toolbox: {
  501. feature: {
  502. dataZoom: {
  503. yAxisIndex: 'none'
  504. },
  505. magicType: {type: ['line', 'bar']},
  506. saveAsImage: {
  507. show: true,
  508. pixelRatio: 4
  509. }
  510. }
  511. },
  512. tooltip: {
  513. show: true,
  514. trigger: 'axis',
  515. formatter: (function (params, ticket, callback) {
  516. var readSeriesName = params[0].seriesName;
  517. var writeSeriesName = params[1].seriesName;
  518. var read = params[0].data[1];
  519. var write = params[1].data[1];
  520. var readMarker = params[0].marker;
  521. var writeMarker = params[1].marker;
  522. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  523. if (read === null) {
  524. read = '无数据';
  525. }
  526. if (write === null) {
  527. write = '无数据';
  528. }
  529. return datetime + '<br />' + [readMarker, readSeriesName, read].join(' ') +
  530. '<br />' + [writeMarker, writeSeriesName, write].join(' ')
  531. })
  532. },
  533. xAxis: {
  534. type: 'time',
  535. axisTick: {
  536. show: false
  537. },
  538. axisLine: {
  539. lineStyle: {
  540. opacity: 0.1,
  541. color: '#3d4245'
  542. }
  543. },
  544. splitLine: {
  545. show: false
  546. },
  547. axisLabel: {
  548. formatter: format_time
  549. }
  550. },
  551. yAxis: {
  552. min: 0,
  553. max: 'dataMax',
  554. minInterval: 2,
  555. axisTick: {
  556. show: false
  557. },
  558. axisLine: {
  559. lineStyle: {
  560. opacity: 0,
  561. color: '#8c8f91'
  562. }
  563. },
  564. splitLine: {
  565. show: true,
  566. lineStyle: {
  567. width: 1,
  568. opacity: 0.5
  569. }
  570. }
  571. },
  572. series: [{
  573. name: '读(MBps)',
  574. type: 'line',
  575. showSymbol: false,
  576. smooth: true,
  577. lineStyle: {
  578. normal: {
  579. width: 1
  580. }
  581. },
  582. data: (function () {
  583. var d = [];
  584. $.each(data.data, function(i, ele) {
  585. d.push([
  586. ele['timestamp'] * 1000,
  587. ele['rd_bytes'] !== null ? Math.floor(ele['rd_bytes'] / 1024 / 1024 * 1000) / 1000 : null
  588. ])
  589. });
  590. return d;
  591. })()
  592. },{
  593. name: '写(MBps)',
  594. type: 'line',
  595. showSymbol: false,
  596. smooth: true,
  597. lineStyle: {
  598. normal: {
  599. width: 1
  600. }
  601. },
  602. data: (function () {
  603. var d = [];
  604. $.each(data.data, function(i, ele) {
  605. d.push([
  606. ele['timestamp'] * 1000,
  607. ele['wr_bytes'] !== null ? Math.floor(ele['wr_bytes'] / 1024 / 1024 * 1000) / 1000 : null
  608. ])
  609. });
  610. return d;
  611. })()
  612. }]
  613. };
  614. var disk_chart = echarts.init(document.getElementById(dev_id));
  615. disk_chart.setOption(option);
  616. }
  617. });
  618. }
  619. function render_disk_iops_chart(disk_uuid, granularity, dev_id, dev_name) {
  620. var url = '/api/performance/disk_io/last_hour/' + disk_uuid;
  621. if (granularity === 'hour') {
  622. url = '/api/performance/disk_io/last_hour/' + disk_uuid
  623. } else if (granularity === 'six_hours') {
  624. url = '/api/performance/disk_io/last_six_hours/' + disk_uuid
  625. } else if (granularity === 'day') {
  626. url = '/api/performance/disk_io/last_day/' + disk_uuid
  627. } else {
  628. url = '/api/performance/disk_io/last_seven_days/' + disk_uuid
  629. }
  630. $.ajax({
  631. url : url,
  632. type : 'GET',
  633. contentType: "application/json; charset=utf-8",
  634. dataType: 'json',
  635. error : function() {
  636. alter_danger('获取图表数据失败失败!');
  637. },
  638. success : function(data, textStatus, xhr) {
  639. if (data.data.length > 1) {
  640. if ((data.data[data.data.length - 1]['timestamp'] - data.data[0]['timestamp']) >= 86400) {
  641. datetime_format_type = 'date';
  642. }
  643. }
  644. var option = {
  645. color: ['#3BC0FF', '#FAB406'],
  646. title: {
  647. text: '磁盘IOPS - ' + dev_name
  648. },
  649. legend: {
  650. data:['读(IOPS)', '写(IOPS)'],
  651. bottom: 5
  652. },
  653. toolbox: {
  654. feature: {
  655. dataZoom: {
  656. yAxisIndex: 'none'
  657. },
  658. magicType: {type: ['line', 'bar']},
  659. saveAsImage: {
  660. show: true,
  661. pixelRatio: 4
  662. }
  663. }
  664. },
  665. tooltip: {
  666. show: true,
  667. trigger: 'axis',
  668. formatter: (function (params, ticket, callback) {
  669. var readSeriesName = params[0].seriesName;
  670. var writeSeriesName = params[1].seriesName;
  671. var read = params[0].data[1];
  672. var write = params[1].data[1];
  673. var readMarker = params[0].marker;
  674. var writeMarker = params[1].marker;
  675. var datetime = new Date(params[0].data[0]).format('yyyy-mm-dd HH:MM:ss');
  676. if (read === null) {
  677. read = '无数据';
  678. }
  679. if (write === null) {
  680. write = '无数据';
  681. }
  682. return datetime + '<br />' + [readMarker, readSeriesName, read].join(' ') +
  683. '<br />' + [writeMarker, writeSeriesName, write].join(' ')
  684. })
  685. },
  686. xAxis: {
  687. type: 'time',
  688. axisTick: {
  689. show: false
  690. },
  691. axisLine: {
  692. lineStyle: {
  693. opacity: 0.1,
  694. color: '#3d4245'
  695. }
  696. },
  697. splitLine: {
  698. show: false
  699. },
  700. axisLabel: {
  701. formatter: format_time
  702. }
  703. },
  704. yAxis: {
  705. min: 0,
  706. max: 'dataMax',
  707. minInterval: 2,
  708. axisTick: {
  709. show: false
  710. },
  711. axisLine: {
  712. lineStyle: {
  713. opacity: 0,
  714. color: '#8c8f91'
  715. }
  716. },
  717. splitLine: {
  718. show: true,
  719. lineStyle: {
  720. width: 1,
  721. opacity: 0.5
  722. }
  723. }
  724. },
  725. series: [{
  726. name: '读(IOPS)',
  727. type: 'line',
  728. showSymbol: false,
  729. smooth: true,
  730. lineStyle: {
  731. normal: {
  732. width: 1
  733. }
  734. },
  735. data: (function () {
  736. var d = [];
  737. $.each(data.data, function(i, ele) {
  738. d.push([
  739. ele['timestamp'] * 1000,
  740. ele['rd_req'] !== null ? ele['rd_req'] : null
  741. ])
  742. });
  743. return d;
  744. })()
  745. },{
  746. name: '写(IOPS)',
  747. type: 'line',
  748. showSymbol: false,
  749. smooth: true,
  750. lineStyle: {
  751. normal: {
  752. width: 1
  753. }
  754. },
  755. data: (function () {
  756. var d = [];
  757. $.each(data.data, function(i, ele) {
  758. d.push([
  759. ele['timestamp'] * 1000,
  760. ele['wr_req'] !== null ? ele['wr_req'] : null
  761. ])
  762. });
  763. return d;
  764. })()
  765. }]
  766. };
  767. var disk_chart = echarts.init(document.getElementById(dev_id));
  768. disk_chart.setOption(option);
  769. }
  770. });
  771. }
  772. function render_disks_chart(uuid, granularity) {
  773. var dev_table = [];
  774. for (var i = 1; i <= 26; i++) {
  775. dev_table.push('vd' + String.fromCharCode(0x60+i));
  776. }
  777. var disks = [];
  778. var url = '/api/disks?filter=guest_uuid:in:' + uuid;
  779. $.ajax({
  780. url: url,
  781. type: 'GET',
  782. contentType: "application/json; charset=utf-8",
  783. dataType: 'json',
  784. error: function () {
  785. alter_danger('获取图表数据失败失败!');
  786. },
  787. success: function (data, textStatus, xhr) {
  788. $('#disks_chart').empty();
  789. $.each(data.data, function(i, ele) {
  790. var dev_name = dev_table[ele['sequence']];
  791. var dev_id_throughput = 'throughput_' + dev_table[ele['sequence']];
  792. var dev_id_iops = 'iops_' + dev_table[ele['sequence']];
  793. var disk_uuid = ele['uuid'];
  794. $('#disks_chart').append($('<div id=' + dev_id_throughput +' style="width: 800px;height:280px;"></div>'));
  795. render_disk_throughput_chart(disk_uuid, granularity, dev_id_throughput, dev_name);
  796. $('#disks_chart').append($('<div id=' + dev_id_iops +' style="width: 800px;height:280px;"></div>'));
  797. render_disk_iops_chart(disk_uuid, granularity, dev_id_iops, dev_name);
  798. });
  799. }
  800. });
  801. }
  802. $(document).ready(function() {
  803. $('body').addClass('add-transition');
  804. $('.add-page-transition').on('click', function(){
  805. var transAttr = $(this).attr('data-transition');
  806. $('.add-transition').attr('class', 'add-transition');
  807. $('.add-transition').addClass(transAttr);
  808. });
  809. cpu_chart = echarts.init(document.getElementById('cpu_chart'));
  810. traffic_chart = echarts.init(document.getElementById('traffic_chart'));
  811. // memory_chart = echarts.init(document.getElementById('memory_chart'));
  812. // render_cpu_chart(uuid, 'hour');
  813. // render_traffic_chart(uuid, 'hour');
  814. // render_disks_chart(uuid, 'hour')
  815. // render_memory_chart(uuid, 'hour');
  816. });
  817. function refresh_render_with_specify_granularity(granularity) {
  818. render_cpu_chart(uuid, granularity);
  819. render_traffic_chart(uuid, granularity);
  820. render_disks_chart(uuid, granularity)
  821. }
  822. </script>
  823. <div class="container" style="padding-top: 100px; width: 90%; max-width: 100%;">
  824. <div class="panel">
  825. <div class="panel-body">
  826. <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;">
  827. <span class="glyph-icon icon-separator" style="transform: rotateY(-180deg);">
  828. <i class="glyph-icon icon-level-up"></i>
  829. </span>
  830. <span class="button-content">
  831. 返回
  832. </span>
  833. </a>
  834. <div class="row" style="margin-top: 10px;">
  835. <div class="col-xs-4">
  836. <div style="background: #F5f6FA; border: 1px solid #e1e6eb; padding: 10px; font-size: 14px; width: 100%;">
  837. <span>
  838. {{ host_ret.data.hostname }}
  839. </span>
  840. </div>
  841. <table class="table table-bordered">
  842. <tbody>
  843. <tr>
  844. <td>
  845. <span class="guest-label">NODE ID:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  846. <span class="guest-desc">
  847. {{ host_ret.data.node_id }}
  848. </span>
  849. </td>
  850. </tr>
  851. <tr>
  852. <td>
  853. <span class="guest-label">状态:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  854. <span class="guest-desc">
  855. <i style="float: right;" class="glyph-icon icon-circle font-size-23 {% if host_ret.data.alive == true %}font-green{% else %}font-red{% endif %}"></i>
  856. </span>
  857. </td>
  858. </tr>
  859. <tr>
  860. <td>
  861. <span class="guest-label">CPU:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  862. <span class="guest-desc">
  863. {{ host_ret.data.cpu }} 核
  864. </span>
  865. </td>
  866. </tr>
  867. <tr>
  868. <td>
  869. <span class="guest-label">内存:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  870. <span class="guest-desc">
  871. {{ (host_ret_data.memory / 1024 / 1024 / 1024)|int }} GB
  872. </span>
  873. </td>
  874. </tr>
  875. {% for nic_name, nic in host_ret.data.interfaces.iteritems() %}
  876. <tr>
  877. <td>
  878. <span class="guest-label">网卡:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  879. <span class="guest-desc">
  880. {{ nic_name }} | IP: {{ nic.ip }} | MAC: {{ nic.mac }}
  881. </span>
  882. </td>
  883. </tr>
  884. {% endfor %}
  885. {% for mountpoint, disk in host_ret.data.disks.iteritems() %}
  886. <tr>
  887. <td>
  888. <span class="guest-label">挂载点:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  889. <span class="guest-desc">
  890. {{ mountpoint }} | {{ (disk.total / 1024 / 1024 / 1024) | int }} GB | 使用率: {{ disk.percent }}%
  891. </span>
  892. </td>
  893. </tr>
  894. {% endfor %}
  895. <tr>
  896. <td>
  897. <span class="guest-label">数据更新时间:&nbsp;&nbsp;&nbsp;&nbsp;</span>
  898. <span class="guest-desc">
  899. {{ format_datetime_by_tus(host_ret.data.timestamp) }}
  900. </span>
  901. </td>
  902. </tr>
  903. </tbody>
  904. </table>
  905. </div>
  906. <div class="col-xs-8">
  907. <div class="row" style="margin-bottom: 20px;">
  908. <div class="col-xs-8"></div>
  909. <div class="col-xs-4">
  910. <div class="btn-group btn-group-justified btn-group-xs">
  911. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('hour');">1小时</a>
  912. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('six_hours');">6小时</a>
  913. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('day');">1天</a>
  914. <a class="btn btn-default" role="button" onclick="refresh_render_with_specify_granularity('seven_days');">7天</a>
  915. </div>
  916. </div>
  917. </div>
  918. <div>
  919. <div id="cpu_chart" style="width: 800px;height:280px;"></div>
  920. <div id="traffic_chart" style="width: 800px;height:280px;"></div>
  921. </div>
  922. <!--<div id="memory_chart" style="width: 800px;height:280px;"></div>-->
  923. <div id="disks_chart"></div>
  924. </div>
  925. </div>
  926. </div>
  927. </div>
  928. </div>
  929. {% endblock body %}