]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/Status.js
adapt render_ceph_health for luminous
[pve-manager.git] / www / manager6 / ceph / Status.js
1 Ext.define('PVE.node.CephStatus', {
2 extend: 'Ext.panel.Panel',
3 alias: 'widget.pveNodeCephStatus',
4
5 onlineHelp: 'chapter_pveceph',
6
7 scrollable: true,
8
9 bodyPadding: '10 0 0 0',
10
11 defaults: {
12 width: 762,
13 userCls: 'inline-block',
14 padding: '0 0 10 10'
15 },
16
17 items: [
18 {
19 xtype: 'panel',
20 title: gettext('Health'),
21 bodyPadding: '0 10 10 10',
22 minHeight: 210,
23 layout: {
24 type: 'hbox',
25 align: 'top'
26 },
27 items: [
28 {
29 flex: 1,
30 itemId: 'overallhealth',
31 xtype: 'pveHealthWidget',
32 title: gettext('Status')
33 },
34 {
35 flex: 2,
36 itemId: 'warnings',
37 stateful: true,
38 stateId: 'ceph-status-warnings',
39 padding: '15 0 0 0',
40 xtype: 'grid',
41 minHeight: 100,
42 // since we load the store manually,
43 // to show the emptytext, we have to
44 // specify an empty store
45 store: { data:[] },
46 emptyText: gettext('No Warnings/Errors'),
47 columns: [
48 {
49 dataIndex: 'severity',
50 header: gettext('Severity'),
51 align: 'center',
52 width: 70,
53 renderer: function(value) {
54 var health = PVE.Utils.map_ceph_health[value];
55 var classes = PVE.Utils.get_health_icon(health);
56
57 return '<i class="fa fa-fw ' + classes + '"></i>';
58 },
59 sorter: {
60 sorterFn: function(a,b) {
61 var healthArr = ['HEALTH_ERR', 'HEALTH_WARN', 'HEALTH_OK'];
62 return healthArr.indexOf(b.data.severity) - healthArr.indexOf(a.data.severity);
63 }
64 }
65 },
66 {
67 dataIndex: 'summary',
68 header: gettext('Summary'),
69 flex: 1
70 }
71 ]
72 }
73 ]
74 },
75 {
76 xtype: 'pveCephStatusDetail',
77 itemId: 'statusdetail',
78 title: gettext('Status')
79 },
80 {
81 xtype: 'panel',
82 title: gettext('Performance'),
83 bodyPadding: '0 10 10 10',
84 layout: {
85 type: 'hbox',
86 align: 'center'
87 },
88 items: [
89 {
90 flex: 1,
91 xtype: 'pveGauge',
92 itemId: 'space',
93 title: gettext('Usage')
94 },
95 {
96 flex: 2,
97 xtype: 'container',
98 defaults: {
99 padding: '0 0 0 30',
100 height: 100
101 },
102 items: [
103 {
104 itemId: 'reads',
105 xtype: 'pveRunningChart',
106 title: gettext('Reads'),
107 renderer: PVE.Utils.render_bandwidth
108 },
109 {
110 itemId: 'writes',
111 xtype: 'pveRunningChart',
112 title: gettext('Writes'),
113 renderer: PVE.Utils.render_bandwidth
114 },
115 {
116 itemId: 'iops',
117 xtype: 'pveRunningChart',
118 hidden: true,
119 title: 'IOPS', // do not localize
120 renderer: Ext.util.Format.numberRenderer('0,000')
121 },
122 {
123 itemId: 'readiops',
124 xtype: 'pveRunningChart',
125 hidden: true,
126 title: 'IOPS: ' + gettext('Reads'),
127 renderer: Ext.util.Format.numberRenderer('0,000')
128 },
129 {
130 itemId: 'writeiops',
131 xtype: 'pveRunningChart',
132 hidden: true,
133 title: 'IOPS: ' + gettext('Writes'),
134 renderer: Ext.util.Format.numberRenderer('0,000')
135 }
136 ]
137 }
138 ]
139 }
140 ],
141
142 updateAll: function(store, records, success) {
143 if (!success || records.length === 0) {
144 return;
145 }
146
147 var me = this;
148 var rec = records[0];
149
150 // add health panel
151 me.down('#overallhealth').updateHealth(PVE.Utils.render_ceph_health(rec.data.health || {}));
152 // add errors to gridstore
153 me.down('#warnings').getStore().loadRawData(rec.data.health.summary, false);
154
155 // update detailstatus panel
156 me.getComponent('statusdetail').updateAll(rec);
157
158 // add performance data
159 var used = rec.data.pgmap.bytes_used;
160 var total = rec.data.pgmap.bytes_total;
161
162 var text = Ext.String.format(gettext('{0} of {1}'),
163 PVE.Utils.render_size(used),
164 PVE.Utils.render_size(total)
165 );
166
167 // update the usage widget
168 me.down('#space').updateValue(used/total, text);
169
170 // TODO: logic for jewel (iops splitted in read/write)
171
172 var iops = rec.data.pgmap.op_per_sec;
173 var readiops = rec.data.pgmap.read_op_per_sec;
174 var writeiops = rec.data.pgmap.write_op_per_sec;
175 var reads = rec.data.pgmap.read_bytes_sec || 0;
176 var writes = rec.data.pgmap.write_bytes_sec || 0;
177
178 if (iops !== undefined && me.version !== 'hammer') {
179 me.change_version('hammer');
180 } else if((readiops !== undefined || writeiops !== undefined) && me.version !== 'jewel') {
181 me.change_version('jewel');
182 }
183 // update the graphs
184 me.reads.addDataPoint(reads);
185 me.writes.addDataPoint(writes);
186 me.iops.addDataPoint(iops);
187 me.readiops.addDataPoint(readiops);
188 me.writeiops.addDataPoint(writeiops);
189 },
190
191 change_version: function(version) {
192 var me = this;
193 me.version = version;
194 me.sp.set('ceph-version', version);
195 me.iops.setVisible(version === 'hammer');
196 me.readiops.setVisible(version === 'jewel');
197 me.writeiops.setVisible(version === 'jewel');
198 },
199
200 initComponent: function() {
201 var me = this;
202
203 var nodename = me.pveSelNode.data.node;
204 if (!nodename) {
205 throw "no node name specified";
206 }
207
208 me.callParent();
209 me.store = Ext.create('PVE.data.UpdateStore', {
210 storeid: 'ceph-status-' + nodename,
211 interval: 5000,
212 proxy: {
213 type: 'pve',
214 url: '/api2/json/nodes/' + nodename + '/ceph/status'
215 }
216 });
217
218 // save references for the updatefunction
219 me.iops = me.down('#iops');
220 me.readiops = me.down('#readiops');
221 me.writeiops = me.down('#writeiops');
222 me.reads = me.down('#reads');
223 me.writes = me.down('#writes');
224
225 // get ceph version
226 me.sp = Ext.state.Manager.getProvider();
227 me.version = me.sp.get('ceph-version');
228 me.change_version(me.version);
229
230 PVE.Utils.monStoreErrors(me,me.store);
231 me.mon(me.store, 'load', me.updateAll, me);
232 me.on('destroy', me.store.stopUpdate);
233 me.store.startUpdate();
234 }
235
236 });