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