]>
Commit | Line | Data |
---|---|---|
fee716d3 DC |
1 | Ext.define('PVE.node.CreateZFS', { |
2 | extend: 'Proxmox.window.Edit', | |
3 | xtype: 'pveCreateZFS', | |
4 | ||
5 | subject: 'ZFS', | |
6 | ||
7 | showProgress: true, | |
8 | ||
9 | onlineHelp: 'chapter_zfs', | |
10 | ||
7d2e6f5b SI |
11 | width: 800, |
12 | ||
fee716d3 DC |
13 | initComponent : function() { |
14 | var me = this; | |
15 | ||
16 | if (!me.nodename) { | |
17 | throw "no node name specified"; | |
18 | } | |
19 | ||
20 | me.isCreate = true; | |
21 | ||
22 | var update_disklist = function() { | |
23 | var grid = me.down('#disklist'); | |
24 | var disks = grid.getSelection(); | |
25 | ||
26 | var val = []; | |
f6710aac | 27 | disks.sort(function(a, b) { |
fee716d3 DC |
28 | var aorder = a.get('order') || 0; |
29 | var border = b.get('order') || 0; | |
30 | return (aorder - border); | |
31 | }); | |
32 | ||
33 | disks.forEach(function(disk) { | |
34 | val.push(disk.get('devpath')); | |
35 | }); | |
36 | ||
37 | me.down('field[name=devices]').setValue(val.join(',')); | |
38 | }; | |
39 | ||
40 | Ext.apply(me, { | |
41 | url: '/nodes/' + me.nodename + '/disks/zfs', | |
42 | method: 'POST', | |
43 | items: [ | |
44 | { | |
45 | xtype: 'inputpanel', | |
46 | onGetValues: function(values) { | |
47 | return values; | |
48 | }, | |
49 | column1: [ | |
50 | { | |
51 | xtype: 'textfield', | |
52 | hidden: true, | |
53 | name: 'devices', | |
f6710aac | 54 | allowBlank: false, |
fee716d3 DC |
55 | }, |
56 | { | |
57 | xtype: 'proxmoxtextfield', | |
58 | name: 'name', | |
59 | fieldLabel: gettext('Name'), | |
f6710aac | 60 | allowBlank: false, |
fee716d3 DC |
61 | }, |
62 | { | |
63 | xtype: 'proxmoxcheckbox', | |
64 | name: 'add_storage', | |
65 | fieldLabel: gettext('Add Storage'), | |
f6710aac TL |
66 | value: '1', |
67 | }, | |
fee716d3 DC |
68 | ], |
69 | column2: [ | |
70 | { | |
71 | xtype: 'proxmoxKVComboBox', | |
72 | fieldLabel: gettext('RAID Level'), | |
73 | name: 'raidlevel', | |
f04e415b | 74 | value: 'single', |
fee716d3 | 75 | comboItems: [ |
f04e415b | 76 | ['single', gettext('Single Disk')], |
fee716d3 DC |
77 | ['mirror', 'Mirror'], |
78 | ['raid10', 'RAID10'], | |
79 | ['raidz', 'RAIDZ'], | |
80 | ['raidz2', 'RAIDZ2'], | |
f6710aac TL |
81 | ['raidz3', 'RAIDZ3'], |
82 | ], | |
fee716d3 DC |
83 | }, |
84 | { | |
85 | xtype: 'proxmoxKVComboBox', | |
86 | fieldLabel: gettext('Compression'), | |
87 | name: 'compression', | |
88 | value: 'on', | |
89 | comboItems: [ | |
90 | ['on', 'on'], | |
91 | ['off', 'off'], | |
92 | ['gzip', 'gzip'], | |
93 | ['lz4', 'lz4'], | |
94 | ['lzjb', 'lzjb'], | |
f6710aac TL |
95 | ['zle', 'zle'], |
96 | ], | |
fee716d3 DC |
97 | }, |
98 | { | |
99 | xtype: 'proxmoxintegerfield', | |
100 | fieldLabel: gettext('ashift'), | |
101 | minValue: 9, | |
102 | maxValue: 16, | |
103 | value: '12', | |
f6710aac TL |
104 | name: 'ashift', |
105 | }, | |
fee716d3 DC |
106 | ], |
107 | columnB: [ | |
108 | { | |
109 | xtype: 'grid', | |
110 | height: 200, | |
111 | emptyText: gettext('No Disks unused'), | |
112 | itemId: 'disklist', | |
113 | selModel: 'checkboxmodel', | |
114 | listeners: { | |
f6710aac | 115 | selectionchange: update_disklist, |
fee716d3 DC |
116 | }, |
117 | store: { | |
118 | proxy: { | |
119 | type: 'proxmox', | |
f6710aac TL |
120 | url: '/api2/json/nodes/' + me.nodename + '/disks/list?type=unused', |
121 | }, | |
fee716d3 DC |
122 | }, |
123 | columns: [ | |
124 | { | |
125 | text: gettext('Device'), | |
126 | dataIndex: 'devpath', | |
7d2e6f5b SI |
127 | flex: 2, |
128 | }, | |
129 | { | |
130 | text: gettext('Model'), | |
131 | dataIndex: 'model', | |
132 | flex: 2, | |
fee716d3 DC |
133 | }, |
134 | { | |
135 | text: gettext('Serial'), | |
7d2e6f5b SI |
136 | dataIndex: 'serial', |
137 | flex: 2, | |
fee716d3 DC |
138 | }, |
139 | { | |
140 | text: gettext('Size'), | |
141 | dataIndex: 'size', | |
7d2e6f5b SI |
142 | renderer: PVE.Utils.render_size, |
143 | flex: 1, | |
fee716d3 DC |
144 | }, |
145 | { | |
146 | header: gettext('Order'), | |
147 | xtype: 'widgetcolumn', | |
148 | dataIndex: 'order', | |
149 | sortable: true, | |
7d2e6f5b | 150 | flex: 1, |
fee716d3 DC |
151 | widget: { |
152 | xtype: 'proxmoxintegerfield', | |
153 | minValue: 1, | |
154 | isFormField: false, | |
155 | listeners: { | |
156 | change: function(numberfield, value, old_value) { | |
157 | var record = numberfield.getWidgetRecord(); | |
158 | record.set('order', value); | |
159 | update_disklist(record); | |
f6710aac TL |
160 | }, |
161 | }, | |
162 | }, | |
163 | }, | |
164 | ], | |
165 | }, | |
166 | ], | |
deca45c1 TL |
167 | }, |
168 | { | |
169 | xtype: 'displayfield', | |
170 | padding: '5 0 0 0', | |
f71b7c28 | 171 | userCls: 'pmx-hint', |
deca45c1 TL |
172 | value: 'Note: ZFS is not compatible with disks backed by a hardware ' + |
173 | 'RAID controller. For details see ' + | |
174 | '<a target="_blank" href="' + Proxmox.Utils.get_help_link('chapter_zfs') + '">the reference documentation</a>.', | |
f6710aac TL |
175 | }, |
176 | ], | |
fee716d3 DC |
177 | }); |
178 | ||
179 | me.callParent(); | |
180 | me.down('#disklist').getStore().load(); | |
f6710aac | 181 | }, |
fee716d3 DC |
182 | }); |
183 | ||
e98bcf01 | 184 | Ext.define('PVE.node.ZFSDevices', { |
fee716d3 | 185 | extend: 'Ext.tree.Panel', |
e98bcf01 | 186 | xtype: 'pveZFSDevices', |
fee716d3 DC |
187 | stateful: true, |
188 | stateId: 'grid-node-zfsstatus', | |
189 | columns: [ | |
190 | { | |
191 | xtype: 'treecolumn', | |
192 | text: gettext('Name'), | |
193 | dataIndex: 'name', | |
f6710aac | 194 | flex: 1, |
fee716d3 DC |
195 | }, |
196 | { | |
197 | text: gettext('Health'), | |
198 | renderer: PVE.Utils.render_zfs_health, | |
f6710aac | 199 | dataIndex: 'state', |
fee716d3 | 200 | }, |
eb43c6f4 | 201 | { |
d52134b7 | 202 | text: 'READ', |
f6710aac | 203 | dataIndex: 'read', |
eb43c6f4 TM |
204 | }, |
205 | { | |
d52134b7 | 206 | text: 'WRITE', |
f6710aac | 207 | dataIndex: 'write', |
eb43c6f4 TM |
208 | }, |
209 | { | |
d52134b7 | 210 | text: 'CKSUM', |
f6710aac | 211 | dataIndex: 'cksum', |
eb43c6f4 | 212 | }, |
fee716d3 DC |
213 | { |
214 | text: gettext('Message'), | |
f6710aac TL |
215 | dataIndex: 'msg', |
216 | }, | |
fee716d3 DC |
217 | ], |
218 | ||
219 | rootVisible: true, | |
220 | ||
fee716d3 DC |
221 | reload: function() { |
222 | var me = this; | |
223 | var sm = me.getSelectionModel(); | |
224 | Proxmox.Utils.API2Request({ | |
225 | url: "/nodes/" + me.nodename + "/disks/zfs/" + me.zpool, | |
226 | waitMsgTarget: me, | |
227 | method: 'GET', | |
228 | failure: function(response, opts) { | |
229 | Proxmox.Utils.setErrorMask(me, response.htmlStatus); | |
230 | }, | |
231 | success: function(response, opts) { | |
232 | sm.deselectAll(); | |
233 | me.setRootNode(response.result.data); | |
234 | me.expandAll(); | |
f6710aac | 235 | }, |
fee716d3 DC |
236 | }); |
237 | }, | |
238 | ||
fee716d3 | 239 | initComponent: function() { |
fee716d3 DC |
240 | var me = this; |
241 | ||
242 | if (!me.nodename) { | |
243 | throw "no node name specified"; | |
244 | } | |
245 | ||
246 | if (!me.zpool) { | |
247 | throw "no zpool specified"; | |
248 | } | |
249 | ||
250 | var sm = Ext.create('Ext.selection.TreeModel', {}); | |
251 | ||
252 | Ext.apply(me, { | |
253 | selModel: sm, | |
254 | fields: ['name', 'status', | |
255 | { | |
256 | type: 'string', | |
257 | name: 'iconCls', | |
258 | calculate: function(data) { | |
259 | var txt = 'fa x-fa-tree fa-'; | |
260 | if (data.leaf) { | |
261 | return txt + 'hdd-o'; | |
262 | } | |
f6710aac TL |
263 | }, |
264 | }, | |
fee716d3 | 265 | ], |
f6710aac | 266 | sorters: 'name', |
fee716d3 DC |
267 | }); |
268 | ||
269 | me.callParent(); | |
270 | ||
271 | me.reload(); | |
f6710aac | 272 | }, |
fee716d3 DC |
273 | }); |
274 | ||
e98bcf01 TM |
275 | Ext.define('PVE.node.ZFSStatus', { |
276 | extend: 'Proxmox.grid.ObjectGrid', | |
277 | xtype: 'pveZFSStatus', | |
278 | layout: 'fit', | |
279 | border: false, | |
280 | ||
281 | initComponent: function() { | |
e98bcf01 TM |
282 | var me = this; |
283 | ||
284 | if (!me.nodename) { | |
285 | throw "no node name specified"; | |
286 | } | |
287 | ||
288 | if (!me.zpool) { | |
289 | throw "no zpool specified"; | |
290 | } | |
291 | ||
292 | me.url = "/api2/extjs/nodes/" + me.nodename + "/disks/zfs/" + me.zpool; | |
293 | ||
294 | me.rows = { | |
295 | scan: { | |
f6710aac | 296 | header: gettext('Scan'), |
e98bcf01 TM |
297 | }, |
298 | status: { | |
f6710aac | 299 | header: gettext('Status'), |
e98bcf01 TM |
300 | }, |
301 | action: { | |
f6710aac | 302 | header: gettext('Action'), |
e98bcf01 TM |
303 | }, |
304 | errors: { | |
f6710aac TL |
305 | header: gettext('Errors'), |
306 | }, | |
e98bcf01 TM |
307 | }; |
308 | ||
309 | me.callParent(); | |
310 | me.reload(); | |
f6710aac | 311 | }, |
e98bcf01 TM |
312 | }); |
313 | ||
fee716d3 DC |
314 | Ext.define('PVE.node.ZFSList', { |
315 | extend: 'Ext.grid.Panel', | |
316 | xtype: 'pveZFSList', | |
317 | ||
318 | stateful: true, | |
319 | stateId: 'grid-node-zfs', | |
320 | columns: [ | |
321 | { | |
322 | text: gettext('Name'), | |
323 | dataIndex: 'name', | |
f6710aac | 324 | flex: 1, |
fee716d3 DC |
325 | }, |
326 | { | |
327 | header: gettext('Size'), | |
328 | renderer: Proxmox.Utils.format_size, | |
f6710aac | 329 | dataIndex: 'size', |
fee716d3 DC |
330 | }, |
331 | { | |
332 | header: gettext('Free'), | |
333 | renderer: Proxmox.Utils.format_size, | |
f6710aac | 334 | dataIndex: 'free', |
fee716d3 DC |
335 | }, |
336 | { | |
337 | header: gettext('Allocated'), | |
338 | renderer: Proxmox.Utils.format_size, | |
f6710aac | 339 | dataIndex: 'alloc', |
fee716d3 DC |
340 | }, |
341 | { | |
342 | header: gettext('Fragmentation'), | |
343 | renderer: function(value) { | |
344 | return value.toString() + '%'; | |
345 | }, | |
f6710aac | 346 | dataIndex: 'frag', |
fee716d3 DC |
347 | }, |
348 | { | |
349 | header: gettext('Health'), | |
350 | renderer: PVE.Utils.render_zfs_health, | |
f6710aac | 351 | dataIndex: 'health', |
fee716d3 DC |
352 | }, |
353 | { | |
354 | header: gettext('Deduplication'), | |
355 | hidden: true, | |
356 | renderer: function(value) { | |
357 | return value.toFixed(2).toString() + 'x'; | |
358 | }, | |
f6710aac TL |
359 | dataIndex: 'dedup', |
360 | }, | |
fee716d3 DC |
361 | ], |
362 | ||
363 | rootVisible: false, | |
364 | useArrows: true, | |
365 | ||
366 | tbar: [ | |
367 | { | |
368 | text: gettext('Reload'), | |
369 | iconCls: 'fa fa-refresh', | |
370 | handler: function() { | |
371 | var me = this.up('panel'); | |
372 | me.reload(); | |
f6710aac | 373 | }, |
fee716d3 DC |
374 | }, |
375 | { | |
376 | text: gettext('Create') + ': ZFS', | |
377 | handler: function() { | |
378 | var me = this.up('panel'); | |
379 | var win = Ext.create('PVE.node.CreateZFS', { | |
f6710aac | 380 | nodename: me.nodename, |
fee716d3 DC |
381 | }).show(); |
382 | win.on('destroy', function() { me.reload(); }); | |
f6710aac | 383 | }, |
fee716d3 DC |
384 | }, |
385 | { | |
386 | text: gettext('Detail'), | |
387 | itemId: 'detailbtn', | |
388 | disabled: true, | |
389 | handler: function() { | |
390 | var me = this.up('panel'); | |
391 | var selection = me.getSelection(); | |
392 | if (selection.length < 1) { | |
393 | return; | |
394 | } | |
395 | me.show_detail(selection[0].get('name')); | |
f6710aac TL |
396 | }, |
397 | }, | |
fee716d3 DC |
398 | ], |
399 | ||
400 | show_detail: function(zpool) { | |
401 | var me = this; | |
8cfe2088 | 402 | |
37e228da TL |
403 | var detailsgrid = Ext.create('PVE.node.ZFSStatus', { |
404 | layout: 'fit', | |
8cfe2088 | 405 | nodename: me.nodename, |
37e228da | 406 | flex: 0, |
f6710aac | 407 | zpool: zpool, |
8cfe2088 TM |
408 | }); |
409 | ||
37e228da TL |
410 | var devicetree = Ext.create('PVE.node.ZFSDevices', { |
411 | title: gettext('Devices'), | |
8cfe2088 | 412 | nodename: me.nodename, |
37e228da | 413 | flex: 1, |
f6710aac | 414 | zpool: zpool, |
8cfe2088 TM |
415 | }); |
416 | ||
37e228da | 417 | |
fee716d3 DC |
418 | var win = Ext.create('Ext.window.Window', { |
419 | modal: true, | |
420 | width: 800, | |
421 | height: 400, | |
422 | resizable: true, | |
423 | layout: 'fit', | |
424 | title: gettext('Status') + ': ' + zpool, | |
8cfe2088 TM |
425 | items:[{ |
426 | xtype: 'panel', | |
427 | region: 'center', | |
50d5490f TL |
428 | layout: { |
429 | type: 'vbox', | |
f6710aac | 430 | align: 'stretch', |
50d5490f | 431 | }, |
8cfe2088 TM |
432 | items: [detailsgrid, devicetree], |
433 | tbar: [{ | |
434 | text: gettext('Reload'), | |
435 | iconCls: 'fa fa-refresh', | |
436 | handler: function() { | |
437 | ||
438 | devicetree.reload(); | |
439 | detailsgrid.reload(); | |
f6710aac TL |
440 | }, |
441 | }], | |
442 | }], | |
fee716d3 DC |
443 | }).show(); |
444 | }, | |
445 | ||
446 | set_button_status: function() { | |
447 | var me = this; | |
448 | var selection = me.getSelection(); | |
449 | me.down('#detailbtn').setDisabled(selection.length === 0); | |
450 | }, | |
451 | ||
452 | reload: function() { | |
453 | var me = this; | |
454 | me.store.load(); | |
455 | me.store.sort(); | |
456 | }, | |
457 | ||
458 | listeners: { | |
459 | activate: function() { | |
460 | var me = this; | |
461 | me.reload(); | |
462 | }, | |
463 | selectionchange: function() { | |
464 | this.set_button_status(); | |
465 | }, | |
466 | itemdblclick: function(grid, record) { | |
467 | var me = this; | |
468 | me.show_detail(record.get('name')); | |
f6710aac | 469 | }, |
fee716d3 DC |
470 | }, |
471 | ||
472 | initComponent: function() { | |
fee716d3 DC |
473 | var me = this; |
474 | ||
475 | me.nodename = me.pveSelNode.data.node; | |
476 | if (!me.nodename) { | |
477 | throw "no node name specified"; | |
478 | } | |
479 | ||
480 | Ext.apply(me, { | |
481 | store: { | |
482 | fields: ['name', 'size', 'free', 'alloc', 'dedup', 'frag', 'health'], | |
483 | proxy: { | |
484 | type: 'proxmox', | |
f6710aac | 485 | url: "/api2/json/nodes/" + me.nodename + '/disks/zfs', |
fee716d3 | 486 | }, |
f6710aac TL |
487 | sorters: 'name', |
488 | }, | |
fee716d3 DC |
489 | }); |
490 | ||
491 | me.callParent(); | |
492 | ||
493 | Proxmox.Utils.monStoreErrors(me, me.getStore(), true); | |
494 | me.reload(); | |
f6710aac | 495 | }, |
fee716d3 DC |
496 | }); |
497 |