]>
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', | |
e66d75ca GG |
79 | handler: async function(button) { |
80 | let el = document.getElementById('pkgversions'); | |
81 | await navigator.clipboard.writeText(el.textContent); | |
82422c11 TL |
82 | }, |
83 | text: gettext('Copy'), | |
84 | }, | |
85 | { | |
86 | text: gettext('Ok'), | |
87 | handler: function() { | |
88 | this.up('window').close(); | |
89 | }, | |
90 | }, | |
91 | ], | |
92 | }); | |
93 | ||
94 | Proxmox.Utils.API2Request({ | |
95 | waitMsgTarget: me, | |
96 | url: `/nodes/localhost/apt/versions`, | |
97 | method: 'GET', | |
98 | failure: function(response, opts) { | |
99 | win.close(); | |
100 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
101 | }, | |
102 | success: function(response, opts) { | |
103 | let text = ''; | |
104 | Ext.Array.each(response.result.data, function(rec) { | |
105 | let version = "not correctly installed"; | |
106 | let pkg = rec.Package; | |
107 | if (rec.OldVersion && rec.OldVersion !== 'unknown') { | |
108 | version = rec.OldVersion; | |
109 | } | |
110 | if (rec.ExtraInfo) { | |
111 | text += `${pkg}: ${version} (${rec.ExtraInfo})\n`; | |
112 | } else { | |
113 | text += `${pkg}: ${version}\n`; | |
114 | } | |
115 | }); | |
116 | ||
117 | win.show(); | |
118 | panel.update(Ext.htmlEncode(text)); | |
119 | }, | |
120 | }); | |
121 | }, | |
122 | ||
ecb53af6 DM |
123 | initComponent: function() { |
124 | var me = this; | |
125 | ||
126 | var node_command = function(cmd) { | |
127 | Proxmox.Utils.API2Request({ | |
128 | params: { command: cmd }, | |
129 | url: '/nodes/localhost/status', | |
130 | method: 'POST', | |
131 | waitMsgTarget: me, | |
132 | failure: function(response, opts) { | |
133 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
8acd4d9a | 134 | }, |
ecb53af6 DM |
135 | }); |
136 | }; | |
137 | ||
138 | var restartBtn = Ext.create('Proxmox.button.Button', { | |
139 | text: gettext('Reboot'), | |
140 | dangerous: true, | |
141 | confirmMsg: gettext("Reboot backup server?"), | |
142 | handler: function() { | |
143 | node_command('reboot'); | |
144 | }, | |
8acd4d9a | 145 | iconCls: 'fa fa-undo', |
ecb53af6 DM |
146 | }); |
147 | ||
148 | var shutdownBtn = Ext.create('Proxmox.button.Button', { | |
149 | text: gettext('Shutdown'), | |
150 | dangerous: true, | |
151 | confirmMsg: gettext("Shutdown backup server?"), | |
152 | handler: function() { | |
153 | node_command('shutdown'); | |
154 | }, | |
8acd4d9a | 155 | iconCls: 'fa fa-power-off', |
ecb53af6 DM |
156 | }); |
157 | ||
653e2031 DC |
158 | var consoleBtn = Ext.create('Proxmox.button.Button', { |
159 | text: gettext('Console'), | |
160 | iconCls: 'fa fa-terminal', | |
161 | handler: function() { | |
162 | Proxmox.Utils.openXtermJsViewer('shell', 0, Proxmox.NodeName); | |
8acd4d9a | 163 | }, |
653e2031 DC |
164 | }); |
165 | ||
82422c11 TL |
166 | let version_btn = new Ext.Button({ |
167 | text: gettext('Package versions'), | |
168 | iconCls: 'fa fa-gift', | |
169 | handler: function() { | |
170 | Proxmox.Utils.checked_command(function() { me.showVersions(); }); | |
171 | }, | |
172 | }); | |
173 | ||
174 | me.tbar = [version_btn, '-', consoleBtn, '-', restartBtn, shutdownBtn, '->', { xtype: 'proxmoxRRDTypeSelector' }]; | |
880fa939 DM |
175 | |
176 | var rrdstore = Ext.create('Proxmox.data.RRDStore', { | |
177 | rrdurl: "/api2/json/nodes/localhost/rrd", | |
8acd4d9a | 178 | model: 'pve-rrd-node', |
880fa939 DM |
179 | }); |
180 | ||
181 | me.items = { | |
182 | xtype: 'container', | |
183 | itemId: 'itemcontainer', | |
184 | layout: 'column', | |
185 | minWidth: 700, | |
01284de0 DC |
186 | listeners: { |
187 | resize: function(panel) { | |
188 | Proxmox.Utils.updateColumns(panel); | |
189 | }, | |
190 | }, | |
880fa939 DM |
191 | defaults: { |
192 | minHeight: 320, | |
193 | padding: 5, | |
8acd4d9a | 194 | columnWidth: 1, |
880fa939 DM |
195 | }, |
196 | items: [ | |
197 | { | |
198 | xtype: 'proxmoxRRDChart', | |
199 | title: gettext('CPU usage'), | |
8acd4d9a | 200 | fields: ['cpu', 'iowait'], |
947f4525 | 201 | fieldTitles: [gettext('CPU usage'), gettext('IO wait')], |
8acd4d9a | 202 | store: rrdstore, |
880fa939 DM |
203 | }, |
204 | { | |
205 | xtype: 'proxmoxRRDChart', | |
206 | title: gettext('Server load'), | |
207 | fields: ['loadavg'], | |
208 | fieldTitles: [gettext('Load average')], | |
8acd4d9a | 209 | store: rrdstore, |
880fa939 DM |
210 | }, |
211 | { | |
212 | xtype: 'proxmoxRRDChart', | |
213 | title: gettext('Memory usage'), | |
8acd4d9a | 214 | fields: ['memtotal', 'memused'], |
880fa939 | 215 | fieldTitles: [gettext('Total'), gettext('RAM usage')], |
16e60558 TL |
216 | unit: 'bytes', |
217 | powerOfTwo: true, | |
8acd4d9a | 218 | store: rrdstore, |
880fa939 DM |
219 | }, |
220 | { | |
221 | xtype: 'proxmoxRRDChart', | |
222 | title: gettext('Swap usage'), | |
8acd4d9a | 223 | fields: ['swaptotal', 'swapused'], |
880fa939 | 224 | fieldTitles: [gettext('Total'), gettext('Swap usage')], |
16e60558 TL |
225 | unit: 'bytes', |
226 | powerOfTwo: true, | |
8acd4d9a | 227 | store: rrdstore, |
880fa939 DM |
228 | }, |
229 | { | |
230 | xtype: 'proxmoxRRDChart', | |
231 | title: gettext('Network traffic'), | |
8acd4d9a TL |
232 | fields: ['netin', 'netout'], |
233 | store: rrdstore, | |
880fa939 DM |
234 | }, |
235 | { | |
236 | xtype: 'proxmoxRRDChart', | |
237 | title: gettext('Root Disk usage'), | |
8acd4d9a | 238 | fields: ['total', 'used'], |
880fa939 | 239 | fieldTitles: [gettext('Total'), gettext('Disk usage')], |
8acd4d9a | 240 | store: rrdstore, |
880fa939 | 241 | }, |
91e5bb49 DM |
242 | { |
243 | xtype: 'proxmoxRRDChart', | |
244 | title: gettext('Root Disk Transfer Rate (bytes/second)'), | |
8acd4d9a | 245 | fields: ['read_bytes', 'write_bytes'], |
91e5bb49 | 246 | fieldTitles: [gettext('Read'), gettext('Write')], |
8acd4d9a | 247 | store: rrdstore, |
91e5bb49 DM |
248 | }, |
249 | { | |
250 | xtype: 'proxmoxRRDChart', | |
251 | title: gettext('Root Disk Input/Output Operations per Second (IOPS)'), | |
8acd4d9a | 252 | fields: ['read_ios', 'write_ios'], |
91e5bb49 | 253 | fieldTitles: [gettext('Read'), gettext('Write')], |
8acd4d9a | 254 | store: rrdstore, |
91e5bb49 DM |
255 | }, |
256 | { | |
257 | xtype: 'proxmoxRRDChart', | |
258 | title: gettext('Root Disk IO Delay (ms)'), | |
c94e1f65 DM |
259 | fields: ['io_delay'], |
260 | fieldTitles: [gettext('IO Delay')], | |
8acd4d9a | 261 | store: rrdstore, |
91e5bb49 | 262 | }, |
8acd4d9a | 263 | ], |
880fa939 DM |
264 | }; |
265 | ||
266 | me.listeners = { | |
267 | activate: function() { | |
268 | rrdstore.startUpdate(); | |
269 | }, | |
270 | destroy: function() { | |
271 | rrdstore.stopUpdate(); | |
272 | }, | |
273 | }; | |
ecb53af6 DM |
274 | |
275 | me.callParent(); | |
01284de0 DC |
276 | |
277 | let sp = Ext.state.Manager.getProvider(); | |
278 | me.mon(sp, 'statechange', function(provider, key, value) { | |
279 | if (key !== 'summarycolumns') { | |
280 | return; | |
281 | } | |
282 | Proxmox.Utils.updateColumns(me.getComponent('itemcontainer')); | |
283 | }); | |
8acd4d9a | 284 | }, |
ecb53af6 DM |
285 | |
286 | }); |