]>
Commit | Line | Data |
---|---|---|
880fa939 DM |
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; | |
8acd4d9a | 9 | }, |
880fa939 DM |
10 | }, |
11 | { | |
12 | name: 'iowait', | |
13 | // percentage | |
14 | convert: function(value) { | |
15 | return value*100; | |
8acd4d9a | 16 | }, |
880fa939 DM |
17 | }, |
18 | 'netin', | |
19 | 'netout', | |
20 | 'memtotal', | |
21 | 'memused', | |
22 | 'swaptotal', | |
23 | 'swapused', | |
c94e1f65 DM |
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; } | |
8acd4d9a | 36 | if (ios === 0 || data.io_ticks === undefined) { |
c94e1f65 DM |
37 | return undefined; |
38 | } | |
39 | return (data.io_ticks*1000.0)/ios; | |
8acd4d9a | 40 | }, |
c94e1f65 | 41 | }, |
880fa939 | 42 | 'loadavg', |
8acd4d9a TL |
43 | { type: 'date', dateFormat: 'timestamp', name: 'time' }, |
44 | ], | |
880fa939 | 45 | }); |
ecb53af6 DM |
46 | Ext.define('PBS.ServerStatus', { |
47 | extend: 'Ext.panel.Panel', | |
48 | alias: 'widget.pbsServerStatus', | |
49 | ||
d0e3f5dd | 50 | title: gettext('Server Status'), |
ecb53af6 | 51 | |
880fa939 | 52 | scrollable: true, |
ecb53af6 | 53 | |
82422c11 TL |
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: { | |
82422c11 TL |
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 | ||
ecb53af6 DM |
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); | |
8acd4d9a | 136 | }, |
ecb53af6 DM |
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 | }, | |
8acd4d9a | 147 | iconCls: 'fa fa-undo', |
ecb53af6 DM |
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 | }, | |
8acd4d9a | 157 | iconCls: 'fa fa-power-off', |
ecb53af6 DM |
158 | }); |
159 | ||
653e2031 DC |
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); | |
8acd4d9a | 165 | }, |
653e2031 DC |
166 | }); |
167 | ||
82422c11 TL |
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' }]; | |
880fa939 DM |
177 | |
178 | var rrdstore = Ext.create('Proxmox.data.RRDStore', { | |
179 | rrdurl: "/api2/json/nodes/localhost/rrd", | |
8acd4d9a | 180 | model: 'pve-rrd-node', |
880fa939 DM |
181 | }); |
182 | ||
183 | me.items = { | |
184 | xtype: 'container', | |
185 | itemId: 'itemcontainer', | |
186 | layout: 'column', | |
187 | minWidth: 700, | |
01284de0 DC |
188 | listeners: { |
189 | resize: function(panel) { | |
190 | Proxmox.Utils.updateColumns(panel); | |
191 | }, | |
192 | }, | |
880fa939 DM |
193 | defaults: { |
194 | minHeight: 320, | |
195 | padding: 5, | |
8acd4d9a | 196 | columnWidth: 1, |
880fa939 DM |
197 | }, |
198 | items: [ | |
199 | { | |
200 | xtype: 'proxmoxRRDChart', | |
201 | title: gettext('CPU usage'), | |
8acd4d9a | 202 | fields: ['cpu', 'iowait'], |
947f4525 | 203 | fieldTitles: [gettext('CPU usage'), gettext('IO wait')], |
8acd4d9a | 204 | store: rrdstore, |
880fa939 DM |
205 | }, |
206 | { | |
207 | xtype: 'proxmoxRRDChart', | |
208 | title: gettext('Server load'), | |
209 | fields: ['loadavg'], | |
210 | fieldTitles: [gettext('Load average')], | |
8acd4d9a | 211 | store: rrdstore, |
880fa939 DM |
212 | }, |
213 | { | |
214 | xtype: 'proxmoxRRDChart', | |
215 | title: gettext('Memory usage'), | |
8acd4d9a | 216 | fields: ['memtotal', 'memused'], |
880fa939 | 217 | fieldTitles: [gettext('Total'), gettext('RAM usage')], |
16e60558 TL |
218 | unit: 'bytes', |
219 | powerOfTwo: true, | |
8acd4d9a | 220 | store: rrdstore, |
880fa939 DM |
221 | }, |
222 | { | |
223 | xtype: 'proxmoxRRDChart', | |
224 | title: gettext('Swap usage'), | |
8acd4d9a | 225 | fields: ['swaptotal', 'swapused'], |
880fa939 | 226 | fieldTitles: [gettext('Total'), gettext('Swap usage')], |
16e60558 TL |
227 | unit: 'bytes', |
228 | powerOfTwo: true, | |
8acd4d9a | 229 | store: rrdstore, |
880fa939 DM |
230 | }, |
231 | { | |
232 | xtype: 'proxmoxRRDChart', | |
233 | title: gettext('Network traffic'), | |
8acd4d9a TL |
234 | fields: ['netin', 'netout'], |
235 | store: rrdstore, | |
880fa939 DM |
236 | }, |
237 | { | |
238 | xtype: 'proxmoxRRDChart', | |
239 | title: gettext('Root Disk usage'), | |
8acd4d9a | 240 | fields: ['total', 'used'], |
880fa939 | 241 | fieldTitles: [gettext('Total'), gettext('Disk usage')], |
8acd4d9a | 242 | store: rrdstore, |
880fa939 | 243 | }, |
91e5bb49 DM |
244 | { |
245 | xtype: 'proxmoxRRDChart', | |
246 | title: gettext('Root Disk Transfer Rate (bytes/second)'), | |
8acd4d9a | 247 | fields: ['read_bytes', 'write_bytes'], |
91e5bb49 | 248 | fieldTitles: [gettext('Read'), gettext('Write')], |
8acd4d9a | 249 | store: rrdstore, |
91e5bb49 DM |
250 | }, |
251 | { | |
252 | xtype: 'proxmoxRRDChart', | |
253 | title: gettext('Root Disk Input/Output Operations per Second (IOPS)'), | |
8acd4d9a | 254 | fields: ['read_ios', 'write_ios'], |
91e5bb49 | 255 | fieldTitles: [gettext('Read'), gettext('Write')], |
8acd4d9a | 256 | store: rrdstore, |
91e5bb49 DM |
257 | }, |
258 | { | |
259 | xtype: 'proxmoxRRDChart', | |
260 | title: gettext('Root Disk IO Delay (ms)'), | |
c94e1f65 DM |
261 | fields: ['io_delay'], |
262 | fieldTitles: [gettext('IO Delay')], | |
8acd4d9a | 263 | store: rrdstore, |
91e5bb49 | 264 | }, |
8acd4d9a | 265 | ], |
880fa939 DM |
266 | }; |
267 | ||
268 | me.listeners = { | |
269 | activate: function() { | |
270 | rrdstore.startUpdate(); | |
271 | }, | |
272 | destroy: function() { | |
273 | rrdstore.stopUpdate(); | |
274 | }, | |
275 | }; | |
ecb53af6 DM |
276 | |
277 | me.callParent(); | |
01284de0 DC |
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 | }); | |
8acd4d9a | 286 | }, |
ecb53af6 DM |
287 | |
288 | }); |