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