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