]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/node/Disks.js
drop jslint lines
[pve-manager.git] / www / manager6 / node / Disks.js
CommitLineData
a36deac4
DC
1Ext.define('PVE.node.DiskList', {
2 extend: 'Ext.grid.GridPanel',
3 alias: 'widget.pveNodeDiskList',
0fc9ceb0 4
a36deac4 5 emptyText: gettext('No Disks found'),
0fc9ceb0 6
e19b93ec
DC
7 stateful: true,
8 stateId: 'grid-node-disks',
0fc9ceb0 9
a36deac4
DC
10 columns: [
11 {
12 header: gettext('Device'),
0fc9ceb0 13 width: 150,
a36deac4
DC
14 sortable: true,
15 dataIndex: 'devpath'
16 },
17 {
18 header: gettext('Type'),
19 width: 80,
20 sortable: true,
21 dataIndex: 'type',
22 renderer: function(v) {
23 if (v === 'ssd') {
24 return 'SSD';
25 } else if (v === 'hdd') {
26 return 'Hard Disk';
27 } else if (v === 'usb'){
28 return 'USB';
29 } else {
30 return gettext('Unknown');
31 }
32 }
33 },
34 {
35 header: gettext('Usage'),
0fc9ceb0 36 width: 150,
a36deac4
DC
37 sortable: false,
38 renderer: function(v, metaData, rec) {
6dd90c40
DC
39 if (rec) {
40 if (rec.data.osdid >= 0) {
41 var bluestore = '';
42 if (rec.data.bluestore === 1) {
43 bluestore = ' (Bluestore)';
44 }
45 return "Ceph osd." + rec.data.osdid.toString() + bluestore;
46 }
47
48 var types = [];
49 if (rec.data.journals > 0) {
50 types.push('Journal');
51 }
52
53 if (rec.data.db > 0) {
54 types.push('DB');
55 }
56
57 if (rec.data.wal > 0) {
58 types.push('WAL');
59 }
60
61 if (types.length > 0) {
62 return 'Ceph (' + types.join(', ') + ')';
63 }
a36deac4 64 }
6dd90c40 65
e7ade592 66 return v || Proxmox.Utils.noText;
a36deac4
DC
67 },
68 dataIndex: 'used'
69 },
70 {
71 header: gettext('Size'),
72 width: 100,
73 align: 'right',
74 sortable: true,
e7ade592 75 renderer: Proxmox.Utils.format_size,
a36deac4
DC
76 dataIndex: 'size'
77 },
78 {
b9628aa5 79 header: 'GPT',
a36deac4
DC
80 width: 60,
81 align: 'right',
3f4dc604 82 renderer: Proxmox.Utils.format_boolean,
a36deac4
DC
83 dataIndex: 'gpt'
84 },
85 {
86 header: gettext('Vendor'),
87 width: 100,
88 sortable: true,
0fc9ceb0 89 hidden: true,
23280184 90 renderer: Ext.String.htmlEncode,
a36deac4
DC
91 dataIndex: 'vendor'
92 },
93 {
94 header: gettext('Model'),
95 width: 200,
96 sortable: true,
23280184 97 renderer: Ext.String.htmlEncode,
a36deac4
DC
98 dataIndex: 'model'
99 },
100 {
101 header: gettext('Serial'),
102 width: 200,
103 sortable: true,
23280184 104 renderer: Ext.String.htmlEncode,
a36deac4
DC
105 dataIndex: 'serial'
106 },
107 {
108 header: 'S.M.A.R.T.',
109 width: 100,
110 sortable: true,
23280184 111 renderer: Ext.String.htmlEncode,
a36deac4
DC
112 dataIndex: 'health'
113 },
114 {
115 header: 'Wearout',
0fc9ceb0 116 width: 90,
a36deac4 117 sortable: true,
0fc9ceb0 118 align: 'right',
a36deac4
DC
119 dataIndex: 'wearout',
120 renderer: function(value) {
121 if (Ext.isNumeric(value)) {
122 return (100 - value).toString() + '%';
123 }
124 return 'N/A';
125 }
126 }
127 ],
128
129 initComponent: function() {
a36deac4
DC
130 var me = this;
131
132 var nodename = me.pveSelNode.data.node;
133 if (!nodename) {
134 throw "no node name specified";
135 }
136
137 var sm = Ext.create('Ext.selection.RowModel', {});
138
139 var store = Ext.create('Ext.data.Store', {
140 storeid: 'node-disk-list' + nodename,
141 model: 'node-disk-list',
142 proxy: {
56a353b9 143 type: 'proxmox',
a36deac4
DC
144 url: "/api2/json/nodes/" + nodename + "/disks/list"
145 },
146 sorters: [
147 {
148 property : 'dev',
149 direction: 'ASC'
150 }
151 ]
152 });
153
5720fafa 154 var reloadButton = Ext.create('Proxmox.button.Button', {
a36deac4
DC
155 text: gettext('Reload'),
156 handler: function() {
157 me.store.load();
158 }
159 });
160
5720fafa 161 var smartButton = Ext.create('Proxmox.button.Button', {
a36deac4
DC
162 text: gettext('Show S.M.A.R.T. values'),
163 selModel: sm,
164 enableFn: function() {
165 return !!sm.getSelection().length;
166 },
167 disabled: true,
168 handler: function() {
169 var rec = sm.getSelection()[0];
170
171 var win = Ext.create('PVE.DiskSmartWindow', {
172 nodename: nodename,
173 dev: rec.data.devpath
174 });
175 win.show();
176 }
177 });
178
5720fafa 179 var initButton = Ext.create('Proxmox.button.Button', {
a36deac4
DC
180 text: gettext('Initialize Disk with GPT'),
181 selModel: sm,
182 enableFn: function() {
183 var selection = sm.getSelection();
184
185 if (!selection.length || selection[0].data.used) {
186 return false;
187 } else {
188 return true;
189 }
190 },
191 disabled: true,
192
193 handler: function() {
194 var rec = sm.getSelection()[0];
e7ade592 195 Proxmox.Utils.API2Request({
a36deac4
DC
196 url: '/api2/extjs/nodes/' + nodename + '/disks/initgpt',
197 waitMsgTarget: me,
198 method: 'POST',
199 params: { disk: rec.data.devpath},
200 failure: function(response, options) {
201 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
202 },
203 success: function(response, options) {
204 var upid = response.result.data;
8cbc11a7 205 var win = Ext.create('Proxmox.window.TaskProgress', {
a36deac4
DC
206 upid: upid
207 });
208 win.show();
209 }
210 });
211 }
212 });
213
2149db2a 214 me.loadCount = 1; // avoid duplicate loadmask
e7ade592 215 Proxmox.Utils.monStoreErrors(me, store);
2149db2a 216
a36deac4 217 Ext.apply(me, {
a36deac4
DC
218 store: store,
219 selModel: sm,
a36deac4
DC
220 tbar: [ reloadButton, smartButton, initButton ],
221 listeners: {
222 itemdblclick: function() {
223 var rec = sm.getSelection()[0];
224
225 var win = Ext.create('PVE.DiskSmartWindow', {
226 nodename: nodename,
227 dev: rec.data.devpath
228 });
229 win.show();
230 }
231 }
232 });
233
234
235 me.callParent();
236 me.store.load();
237 }
238}, function() {
239
240 Ext.define('node-disk-list', {
241 extend: 'Ext.data.Model',
242 fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
243 {name: 'osdid', type: 'number'},
244 'vendor', 'model', 'serial', 'rpm', 'type', 'health', 'wearout' ],
245 idProperty: 'devpath'
246 });
247});
248
249Ext.define('PVE.DiskSmartWindow', {
250 extend: 'Ext.window.Window',
251 alias: 'widget.pveSmartWindow',
252
253 modal: true,
254
255 items: [
256 {
257 xtype: 'gridpanel',
258 layout: {
259 type: 'fit'
260 },
261 emptyText: gettext('No S.M.A.R.T. Values'),
262 scrollable: true,
263 flex: 1,
264 itemId: 'smarts',
265 reserveScrollbar: true,
266 columns: [
267 { text: 'ID', dataIndex: 'id', width: 50 },
23280184
DC
268 { text: gettext('Attribute'), flex: 1, dataIndex: 'name', renderer: Ext.String.htmlEncode },
269 { text: gettext('Value'), dataIndex: 'raw', renderer: Ext.String.htmlEncode },
a36deac4
DC
270 { text: gettext('Normalized'), dataIndex: 'value', width: 60},
271 { text: gettext('Threshold'), dataIndex: 'threshold', width: 60},
272 { text: gettext('Worst'), dataIndex: 'worst', width: 60},
273 { text: gettext('Flags'), dataIndex: 'flags'},
23280184 274 { text: gettext('Failing'), dataIndex: 'fail', renderer: Ext.String.htmlEncode }
a36deac4 275 ]
d96ac973
DC
276 },
277 {
278 xtype: 'component',
279 itemId: 'text',
280 layout: {
281 type: 'fit'
282 },
283 hidden: true,
284 style: {
285 'background-color': 'white',
286 'white-space': 'pre',
287 'font-family': 'monospace'
288 }
a36deac4
DC
289 }
290 ],
291
292 buttons: [
293 {
294 text: gettext('Reload'),
295 name: 'reload',
296 handler: function() {
297 var me = this;
298 me.up('window').store.reload();
299 }
300 },
301 {
302 text: gettext('Close'),
303 name: 'close',
304 handler: function() {
305 var me = this;
306 me.up('window').close();
307 }
308 }
309 ],
310
311 layout: {
312 type: 'vbox',
313 align: 'stretch'
314 },
315 width: 800,
316 height: 500,
317 minWidth: 600,
318 minHeight: 400,
319 bodyPadding: 5,
320 title: gettext('S.M.A.R.T. Values'),
321
322 initComponent: function() {
323 var me = this;
324
325 var nodename = me.nodename;
326 if (!nodename) {
327 throw "no node name specified";
328 }
329
330 var dev = me.dev;
331 if (!dev) {
332 throw "no device specified";
333 }
334
335 me.store = Ext.create('Ext.data.Store', {
2149db2a 336 model: 'disk-smart',
a36deac4 337 proxy: {
56a353b9 338 type: 'proxmox',
a36deac4
DC
339 url: "/api2/json/nodes/" + nodename + "/disks/smart?disk=" + dev
340 }
341 });
342
343 me.callParent();
2149db2a 344 var grid = me.down('#smarts');
d96ac973 345 var text = me.down('#text');
2149db2a 346
e7ade592 347 Proxmox.Utils.monStoreErrors(grid, me.store);
2149db2a
DC
348 me.mon(me.store, 'load', function(s, records, success) {
349 if (success && records.length > 0) {
350 var rec = records[0];
d96ac973
DC
351 switch (rec.data.type) {
352 case 'text':
353 grid.setVisible(false);
354 text.setVisible(true);
355 text.setHtml(Ext.String.htmlEncode(rec.data.text));
356 break;
357 default:
358 // includes 'ata'
359 // cannot use empty case because
d96ac973
DC
360 grid.setVisible(true);
361 text.setVisible(false);
362 grid.setStore(rec.attributes());
363 break;
364 }
2149db2a
DC
365 }
366 });
367
a36deac4
DC
368 me.store.load();
369 }
370}, function() {
371
372 Ext.define('disk-smart', {
373 extend: 'Ext.data.Model',
374 fields: [
d96ac973
DC
375 { name:'health'},
376 { name:'type'},
377 { name:'text'}
a36deac4
DC
378 ],
379 hasMany: {model: 'smart-attribute', name: 'attributes'}
380 });
381 Ext.define('smart-attribute', {
382 extend: 'Ext.data.Model',
383 fields: [
384 { name:'id', type:'number' }, 'name', 'value', 'worst', 'threshold', 'flags', 'fail', 'raw'
e62526ea 385 ]
a36deac4
DC
386 });
387});