]> git.proxmox.com Git - proxmox-backup.git/blob - www/ServerStatus.js
fix #5117: ui: node info: avoid invalid array access for certain foreign kernels
[proxmox-backup.git] / www / ServerStatus.js
1 Ext.define('pve-rrd-node', {
2 extend: 'Ext.data.Model',
3 fields: [
4 {
5 name: 'cpu',
6 // percentage
7 convert: function(value) {
8 return value*100;
9 },
10 },
11 {
12 name: 'iowait',
13 // percentage
14 convert: function(value) {
15 return value*100;
16 },
17 },
18 'netin',
19 'netout',
20 'memtotal',
21 'memused',
22 'swaptotal',
23 'swapused',
24 'total',
25 'used',
26 'read_ios',
27 'read_bytes',
28 'write_ios',
29 'write_bytes',
30 'io_ticks',
31 {
32 name: 'io_delay', calculate: function(data) {
33 let ios = 0;
34 if (data.read_ios !== undefined) { ios += data.read_ios; }
35 if (data.write_ios !== undefined) { ios += data.write_ios; }
36 if (ios === 0 || data.io_ticks === undefined) {
37 return undefined;
38 }
39 return (data.io_ticks*1000.0)/ios;
40 },
41 },
42 'loadavg',
43 { type: 'date', dateFormat: 'timestamp', name: 'time' },
44 ],
45 });
46 Ext.define('PBS.ServerStatus', {
47 extend: 'Ext.panel.Panel',
48 alias: 'widget.pbsServerStatus',
49
50 title: gettext('Server Status'),
51
52 scrollable: true,
53
54 showVersions: function() {
55 let me = this;
56
57 // Note: use simply text/html here, as ExtJS grid has problems with cut&paste
58 let panel = Ext.createWidget('component', {
59 autoScroll: true,
60 id: 'pkgversions',
61 padding: 5,
62 style: {
63 'white-space': 'pre',
64 'font-family': 'monospace',
65 },
66 });
67
68 let win = Ext.create('Ext.window.Window', {
69 title: gettext('Package versions'),
70 width: 600,
71 height: 600,
72 layout: 'fit',
73 modal: true,
74 items: [panel],
75 buttons: [
76 {
77 xtype: 'button',
78 iconCls: 'fa fa-clipboard',
79 handler: function(button) {
80 window.getSelection().selectAllChildren(
81 document.getElementById('pkgversions'),
82 );
83 document.execCommand("copy");
84 },
85 text: gettext('Copy'),
86 },
87 {
88 text: gettext('Ok'),
89 handler: function() {
90 this.up('window').close();
91 },
92 },
93 ],
94 });
95
96 Proxmox.Utils.API2Request({
97 waitMsgTarget: me,
98 url: `/nodes/localhost/apt/versions`,
99 method: 'GET',
100 failure: function(response, opts) {
101 win.close();
102 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
103 },
104 success: function(response, opts) {
105 let text = '';
106 Ext.Array.each(response.result.data, function(rec) {
107 let version = "not correctly installed";
108 let pkg = rec.Package;
109 if (rec.OldVersion && rec.OldVersion !== 'unknown') {
110 version = rec.OldVersion;
111 }
112 if (rec.ExtraInfo) {
113 text += `${pkg}: ${version} (${rec.ExtraInfo})\n`;
114 } else {
115 text += `${pkg}: ${version}\n`;
116 }
117 });
118
119 win.show();
120 panel.update(Ext.htmlEncode(text));
121 },
122 });
123 },
124
125 initComponent: function() {
126 var me = this;
127
128 var node_command = function(cmd) {
129 Proxmox.Utils.API2Request({
130 params: { command: cmd },
131 url: '/nodes/localhost/status',
132 method: 'POST',
133 waitMsgTarget: me,
134 failure: function(response, opts) {
135 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
136 },
137 });
138 };
139
140 var restartBtn = Ext.create('Proxmox.button.Button', {
141 text: gettext('Reboot'),
142 dangerous: true,
143 confirmMsg: gettext("Reboot backup server?"),
144 handler: function() {
145 node_command('reboot');
146 },
147 iconCls: 'fa fa-undo',
148 });
149
150 var shutdownBtn = Ext.create('Proxmox.button.Button', {
151 text: gettext('Shutdown'),
152 dangerous: true,
153 confirmMsg: gettext("Shutdown backup server?"),
154 handler: function() {
155 node_command('shutdown');
156 },
157 iconCls: 'fa fa-power-off',
158 });
159
160 var consoleBtn = Ext.create('Proxmox.button.Button', {
161 text: gettext('Console'),
162 iconCls: 'fa fa-terminal',
163 handler: function() {
164 Proxmox.Utils.openXtermJsViewer('shell', 0, Proxmox.NodeName);
165 },
166 });
167
168 let version_btn = new Ext.Button({
169 text: gettext('Package versions'),
170 iconCls: 'fa fa-gift',
171 handler: function() {
172 Proxmox.Utils.checked_command(function() { me.showVersions(); });
173 },
174 });
175
176 me.tbar = [version_btn, '-', consoleBtn, '-', restartBtn, shutdownBtn, '->', { xtype: 'proxmoxRRDTypeSelector' }];
177
178 var rrdstore = Ext.create('Proxmox.data.RRDStore', {
179 rrdurl: "/api2/json/nodes/localhost/rrd",
180 model: 'pve-rrd-node',
181 });
182
183 me.items = {
184 xtype: 'container',
185 itemId: 'itemcontainer',
186 layout: 'column',
187 minWidth: 700,
188 listeners: {
189 resize: function(panel) {
190 Proxmox.Utils.updateColumns(panel);
191 },
192 },
193 defaults: {
194 minHeight: 320,
195 padding: 5,
196 columnWidth: 1,
197 },
198 items: [
199 {
200 xtype: 'proxmoxRRDChart',
201 title: gettext('CPU usage'),
202 fields: ['cpu', 'iowait'],
203 fieldTitles: [gettext('CPU usage'), gettext('IO wait')],
204 store: rrdstore,
205 },
206 {
207 xtype: 'proxmoxRRDChart',
208 title: gettext('Server load'),
209 fields: ['loadavg'],
210 fieldTitles: [gettext('Load average')],
211 store: rrdstore,
212 },
213 {
214 xtype: 'proxmoxRRDChart',
215 title: gettext('Memory usage'),
216 fields: ['memtotal', 'memused'],
217 fieldTitles: [gettext('Total'), gettext('RAM usage')],
218 unit: 'bytes',
219 powerOfTwo: true,
220 store: rrdstore,
221 },
222 {
223 xtype: 'proxmoxRRDChart',
224 title: gettext('Swap usage'),
225 fields: ['swaptotal', 'swapused'],
226 fieldTitles: [gettext('Total'), gettext('Swap usage')],
227 unit: 'bytes',
228 powerOfTwo: true,
229 store: rrdstore,
230 },
231 {
232 xtype: 'proxmoxRRDChart',
233 title: gettext('Network traffic'),
234 fields: ['netin', 'netout'],
235 store: rrdstore,
236 },
237 {
238 xtype: 'proxmoxRRDChart',
239 title: gettext('Root Disk usage'),
240 fields: ['total', 'used'],
241 fieldTitles: [gettext('Total'), gettext('Disk usage')],
242 store: rrdstore,
243 },
244 {
245 xtype: 'proxmoxRRDChart',
246 title: gettext('Root Disk Transfer Rate (bytes/second)'),
247 fields: ['read_bytes', 'write_bytes'],
248 fieldTitles: [gettext('Read'), gettext('Write')],
249 store: rrdstore,
250 },
251 {
252 xtype: 'proxmoxRRDChart',
253 title: gettext('Root Disk Input/Output Operations per Second (IOPS)'),
254 fields: ['read_ios', 'write_ios'],
255 fieldTitles: [gettext('Read'), gettext('Write')],
256 store: rrdstore,
257 },
258 {
259 xtype: 'proxmoxRRDChart',
260 title: gettext('Root Disk IO Delay (ms)'),
261 fields: ['io_delay'],
262 fieldTitles: [gettext('IO Delay')],
263 store: rrdstore,
264 },
265 ],
266 };
267
268 me.listeners = {
269 activate: function() {
270 rrdstore.startUpdate();
271 },
272 destroy: function() {
273 rrdstore.stopUpdate();
274 },
275 };
276
277 me.callParent();
278
279 let sp = Ext.state.Manager.getProvider();
280 me.mon(sp, 'statechange', function(provider, key, value) {
281 if (key !== 'summarycolumns') {
282 return;
283 }
284 Proxmox.Utils.updateColumns(me.getComponent('itemcontainer'));
285 });
286 },
287
288 });