]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/ceph/Status.js
gui: cephinstaller: fix create mon url
[pve-manager.git] / www / manager6 / ceph / Status.js
CommitLineData
bd39c945 1Ext.define('PVE.node.CephStatus', {
946730cd
DC
2 extend: 'Ext.panel.Panel',
3 alias: 'widget.pveNodeCephStatus',
4
ba93a9c6 5 onlineHelp: 'chapter_pveceph',
bd39c945 6
946730cd
DC
7 scrollable: true,
8
9f7cbaf3
DC
9 bodyPadding: 5,
10
11 layout: {
12 type: 'column'
13 },
946730cd
DC
14
15 defaults: {
9f7cbaf3 16 padding: 5
946730cd
DC
17 },
18
19 items: [
20 {
21 xtype: 'panel',
22 title: gettext('Health'),
9f7cbaf3
DC
23 bodyPadding: 10,
24 plugins: 'responsive',
25 responsiveConfig: {
26 'width < 1900': {
27b91275 27 minHeight: 230,
9f7cbaf3
DC
28 columnWidth: 1
29 },
30 'width >= 1900': {
27b91275 31 minHeight: 500,
9f7cbaf3
DC
32 columnWidth: 0.5
33 }
34 },
946730cd
DC
35 layout: {
36 type: 'hbox',
9f7cbaf3 37 align: 'stretch'
946730cd
DC
38 },
39 items: [
40 {
41 flex: 1,
42 itemId: 'overallhealth',
43 xtype: 'pveHealthWidget',
44 title: gettext('Status')
45 },
46 {
47 flex: 2,
48 itemId: 'warnings',
49 stateful: true,
50 stateId: 'ceph-status-warnings',
946730cd 51 xtype: 'grid',
946730cd
DC
52 // since we load the store manually,
53 // to show the emptytext, we have to
54 // specify an empty store
55 store: { data:[] },
56 emptyText: gettext('No Warnings/Errors'),
57 columns: [
58 {
59 dataIndex: 'severity',
60 header: gettext('Severity'),
61 align: 'center',
62 width: 70,
63 renderer: function(value) {
64 var health = PVE.Utils.map_ceph_health[value];
65 var classes = PVE.Utils.get_health_icon(health);
66
67 return '<i class="fa fa-fw ' + classes + '"></i>';
68 },
69 sorter: {
70 sorterFn: function(a,b) {
71 var healthArr = ['HEALTH_ERR', 'HEALTH_WARN', 'HEALTH_OK'];
72 return healthArr.indexOf(b.data.severity) - healthArr.indexOf(a.data.severity);
73 }
74 }
75 },
76 {
77 dataIndex: 'summary',
78 header: gettext('Summary'),
79 flex: 1
e932cd5f
DC
80 },
81 {
82 xtype: 'actioncolumn',
83 width: 40,
84 align: 'center',
85 tooltip: gettext('Detail'),
86 items: [
87 {
88 iconCls: 'x-fa fa-info-circle',
89 handler: function(grid, rowindex, colindex, item, e, record) {
90 var win = Ext.create('Ext.window.Window', {
91 title: gettext('Detail'),
92 resizable: true,
bf6e58d2 93 modal: true,
e932cd5f
DC
94 width: 650,
95 height: 400,
96 layout: {
97 type: 'fit'
98 },
99 items: [{
100 scrollable: true,
9f7cbaf3 101 padding: 10,
e932cd5f 102 xtype: 'box',
b01e7f7a
DC
103 html: [
104 '<span>' + Ext.htmlEncode(record.data.summary) + '</span>',
105 '<pre>' + Ext.htmlEncode(record.data.detail) + '</pre>'
106 ]
e932cd5f
DC
107 }]
108 });
109 win.show();
110 }
111 }
112 ]
946730cd
DC
113 }
114 ]
115 }
116 ]
117 },
118 {
119 xtype: 'pveCephStatusDetail',
120 itemId: 'statusdetail',
9f7cbaf3
DC
121 plugins: 'responsive',
122 responsiveConfig: {
123 'width < 1900': {
27b91275
DC
124 columnWidth: 1,
125 minHeight: 250
9f7cbaf3
DC
126 },
127 'width >= 1900': {
27b91275
DC
128 columnWidth: 0.5,
129 minHeight: 300
9f7cbaf3
DC
130 }
131 },
946730cd
DC
132 title: gettext('Status')
133 },
4ad4262d
DC
134 {
135 title: gettext('Services'),
136 xtype: 'pveCephServices',
137 itemId: 'services',
138 plugins: 'responsive',
139 layout: {
140 type: 'hbox',
141 align: 'stretch'
142 },
143 responsiveConfig: {
144 'width < 1900': {
145 columnWidth: 1,
146 minHeight: 200
147 },
148 'width >= 1900': {
149 columnWidth: 0.5,
150 minHeight: 200
151 }
152 }
153 },
946730cd
DC
154 {
155 xtype: 'panel',
156 title: gettext('Performance'),
9f7cbaf3
DC
157 columnWidth: 1,
158 bodyPadding: 5,
946730cd
DC
159 layout: {
160 type: 'hbox',
161 align: 'center'
162 },
163 items: [
164 {
165 flex: 1,
5683fb60 166 xtype: 'proxmoxGauge',
946730cd
DC
167 itemId: 'space',
168 title: gettext('Usage')
169 },
170 {
171 flex: 2,
172 xtype: 'container',
173 defaults: {
9f7cbaf3 174 padding: 0,
946730cd
DC
175 height: 100
176 },
177 items: [
178 {
179 itemId: 'reads',
180 xtype: 'pveRunningChart',
181 title: gettext('Reads'),
182 renderer: PVE.Utils.render_bandwidth
183 },
184 {
185 itemId: 'writes',
186 xtype: 'pveRunningChart',
187 title: gettext('Writes'),
188 renderer: PVE.Utils.render_bandwidth
189 },
190 {
191 itemId: 'iops',
192 xtype: 'pveRunningChart',
193 hidden: true,
2ce6111f 194 title: 'IOPS', // do not localize
946730cd
DC
195 renderer: Ext.util.Format.numberRenderer('0,000')
196 },
197 {
198 itemId: 'readiops',
199 xtype: 'pveRunningChart',
200 hidden: true,
8f8ec25d 201 title: 'IOPS: ' + gettext('Reads'),
946730cd
DC
202 renderer: Ext.util.Format.numberRenderer('0,000')
203 },
204 {
205 itemId: 'writeiops',
206 xtype: 'pveRunningChart',
207 hidden: true,
8f8ec25d 208 title: 'IOPS: ' + gettext('Writes'),
946730cd
DC
209 renderer: Ext.util.Format.numberRenderer('0,000')
210 }
211 ]
212 }
213 ]
bd39c945 214 }
946730cd 215 ],
bd39c945 216
e932cd5f
DC
217 generateCheckData: function(health) {
218 var result = [];
219 var checks = health.checks || {};
220 var keys = Ext.Object.getKeys(checks).sort();
221
222 Ext.Array.forEach(keys, function(key) {
223 var details = checks[key].detail || [];
224 result.push({
225 id: key,
37f01f69
DC
226 summary: checks[key].summary.message,
227 detail: Ext.Array.reduce(
228 checks[key].detail,
229 function(first, second) {
230 return first + '\n' + second.message;
231 },
232 ''
233 ),
e932cd5f
DC
234 severity: checks[key].severity
235 });
236 });
237
238 return result;
239 },
240
946730cd
DC
241 updateAll: function(store, records, success) {
242 if (!success || records.length === 0) {
243 return;
244 }
bd39c945 245
946730cd
DC
246 var me = this;
247 var rec = records[0];
0bf3c581 248 me.status = rec.data;
bd39c945 249
946730cd 250 // add health panel
dfe6d184 251 me.down('#overallhealth').updateHealth(PVE.Utils.render_ceph_health(rec.data.health || {}));
946730cd 252 // add errors to gridstore
e932cd5f 253 me.down('#warnings').getStore().loadRawData(me.generateCheckData(rec.data.health || {}), false);
bd39c945 254
4ad4262d
DC
255 // update services
256 me.getComponent('services').updateAll(me.metadata || {}, rec.data);
257
946730cd 258 // update detailstatus panel
0bf3c581 259 me.getComponent('statusdetail').updateAll(me.metadata || {}, rec.data);
bd39c945 260
946730cd
DC
261 // add performance data
262 var used = rec.data.pgmap.bytes_used;
263 var total = rec.data.pgmap.bytes_total;
bd39c945 264
946730cd
DC
265 var text = Ext.String.format(gettext('{0} of {1}'),
266 PVE.Utils.render_size(used),
267 PVE.Utils.render_size(total)
268 );
bd39c945 269
946730cd
DC
270 // update the usage widget
271 me.down('#space').updateValue(used/total, text);
bd39c945 272
946730cd 273 // TODO: logic for jewel (iops splitted in read/write)
bd39c945 274
946730cd
DC
275 var iops = rec.data.pgmap.op_per_sec;
276 var readiops = rec.data.pgmap.read_op_per_sec;
6783a330 277 var writeiops = rec.data.pgmap.write_op_per_sec;
946730cd
DC
278 var reads = rec.data.pgmap.read_bytes_sec || 0;
279 var writes = rec.data.pgmap.write_bytes_sec || 0;
bd39c945 280
946730cd
DC
281 if (iops !== undefined && me.version !== 'hammer') {
282 me.change_version('hammer');
283 } else if((readiops !== undefined || writeiops !== undefined) && me.version !== 'jewel') {
284 me.change_version('jewel');
285 }
286 // update the graphs
287 me.reads.addDataPoint(reads);
288 me.writes.addDataPoint(writes);
289 me.iops.addDataPoint(iops);
290 me.readiops.addDataPoint(readiops);
291 me.writeiops.addDataPoint(writeiops);
292 },
293
294 change_version: function(version) {
295 var me = this;
296 me.version = version;
297 me.sp.set('ceph-version', version);
298 me.iops.setVisible(version === 'hammer');
299 me.readiops.setVisible(version === 'jewel');
300 me.writeiops.setVisible(version === 'jewel');
301 },
bd39c945 302
946730cd
DC
303 initComponent: function() {
304 var me = this;
bd39c945 305
946730cd 306 var nodename = me.pveSelNode.data.node;
bd39c945 307
946730cd 308 me.callParent();
2365c5c1 309 var baseurl = '/api2/json' + (nodename ? '/nodes/' + nodename : '/cluster') + '/ceph/';
0c7c0d6b 310 me.store = Ext.create('Proxmox.data.UpdateStore', {
2365c5c1 311 storeid: 'ceph-status-' + (nodename || 'cluster'),
946730cd
DC
312 interval: 5000,
313 proxy: {
56a353b9 314 type: 'proxmox',
2365c5c1 315 url: baseurl + '/status'
bd39c945
DM
316 }
317 });
318
7f58689d
DC
319 me.metadatastore = Ext.create('Proxmox.data.UpdateStore', {
320 storeid: 'ceph-metadata-' + (nodename || 'cluster'),
321 interval: 15*1000,
322 proxy: {
323 type: 'proxmox',
44dde2cb 324 url: '/api2/json/cluster/ceph/metadata'
7f58689d
DC
325 }
326 });
327
946730cd
DC
328 // save references for the updatefunction
329 me.iops = me.down('#iops');
330 me.readiops = me.down('#readiops');
331 me.writeiops = me.down('#writeiops');
332 me.reads = me.down('#reads');
333 me.writes = me.down('#writes');
334
335 // get ceph version
336 me.sp = Ext.state.Manager.getProvider();
337 me.version = me.sp.get('ceph-version');
338 me.change_version(me.version);
339
4616a55b
TM
340 var regex = new RegExp("not (installed|initialized)", "i");
341 PVE.Utils.handleStoreErrorOrMask(me, me.store, regex, function(me, error){
342 me.store.stopUpdate();
2365c5c1 343 PVE.Utils.showCephInstallOrMask(me, error.statusText, (nodename || 'localhost'),
4616a55b
TM
344 function(win){
345 me.mon(win, 'cephInstallWindowClosed', function(){
346 me.store.startUpdate();
347 });
348 }
349 );
350 });
351
946730cd 352 me.mon(me.store, 'load', me.updateAll, me);
7f58689d
DC
353 me.mon(me.metadatastore, 'load', function(store, records, success) {
354 if (!success || records.length < 1) {
355 return;
356 }
357 var rec = records[0];
358 me.metadata = rec.data;
359
4ad4262d
DC
360 // update services
361 me.getComponent('services').updateAll(rec.data, me.status || {});
362
7f58689d
DC
363 // update detailstatus panel
364 me.getComponent('statusdetail').updateAll(rec.data, me.status || {});
365
366 }, me);
367
946730cd 368 me.on('destroy', me.store.stopUpdate);
4ad4262d 369 me.on('destroy', me.metadatastore.stopUpdate);
946730cd 370 me.store.startUpdate();
4ad4262d 371 me.metadatastore.startUpdate();
bd39c945 372 }
946730cd 373
bd39c945 374});