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