]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/node/ZFS.js
ui: eslint: fix trailing comma and comma related whitespaces errors
[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 width: 800,
12
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 = [];
27 disks.sort(function(a, b) {
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',
54 allowBlank: false,
55 },
56 {
57 xtype: 'proxmoxtextfield',
58 name: 'name',
59 fieldLabel: gettext('Name'),
60 allowBlank: false,
61 },
62 {
63 xtype: 'proxmoxcheckbox',
64 name: 'add_storage',
65 fieldLabel: gettext('Add Storage'),
66 value: '1',
67 },
68 ],
69 column2: [
70 {
71 xtype: 'proxmoxKVComboBox',
72 fieldLabel: gettext('RAID Level'),
73 name: 'raidlevel',
74 value: 'single',
75 comboItems: [
76 ['single', gettext('Single Disk')],
77 ['mirror', 'Mirror'],
78 ['raid10', 'RAID10'],
79 ['raidz', 'RAIDZ'],
80 ['raidz2', 'RAIDZ2'],
81 ['raidz3', 'RAIDZ3'],
82 ],
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'],
95 ['zle', 'zle'],
96 ],
97 },
98 {
99 xtype: 'proxmoxintegerfield',
100 fieldLabel: gettext('ashift'),
101 minValue: 9,
102 maxValue: 16,
103 value: '12',
104 name: 'ashift',
105 },
106 ],
107 columnB: [
108 {
109 xtype: 'grid',
110 height: 200,
111 emptyText: gettext('No Disks unused'),
112 itemId: 'disklist',
113 selModel: 'checkboxmodel',
114 listeners: {
115 selectionchange: update_disklist,
116 },
117 store: {
118 proxy: {
119 type: 'proxmox',
120 url: '/api2/json/nodes/' + me.nodename + '/disks/list?type=unused',
121 },
122 },
123 columns: [
124 {
125 text: gettext('Device'),
126 dataIndex: 'devpath',
127 flex: 2,
128 },
129 {
130 text: gettext('Model'),
131 dataIndex: 'model',
132 flex: 2,
133 },
134 {
135 text: gettext('Serial'),
136 dataIndex: 'serial',
137 flex: 2,
138 },
139 {
140 text: gettext('Size'),
141 dataIndex: 'size',
142 renderer: PVE.Utils.render_size,
143 flex: 1,
144 },
145 {
146 header: gettext('Order'),
147 xtype: 'widgetcolumn',
148 dataIndex: 'order',
149 sortable: true,
150 flex: 1,
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);
160 },
161 },
162 },
163 },
164 ],
165 },
166 ],
167 },
168 {
169 xtype: 'displayfield',
170 padding: '5 0 0 0',
171 userCls: 'pmx-hint',
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>.',
175 },
176 ],
177 });
178
179 me.callParent();
180 me.down('#disklist').getStore().load();
181 },
182 });
183
184 Ext.define('PVE.node.ZFSDevices', {
185 extend: 'Ext.tree.Panel',
186 xtype: 'pveZFSDevices',
187 stateful: true,
188 stateId: 'grid-node-zfsstatus',
189 columns: [
190 {
191 xtype: 'treecolumn',
192 text: gettext('Name'),
193 dataIndex: 'name',
194 flex: 1,
195 },
196 {
197 text: gettext('Health'),
198 renderer: PVE.Utils.render_zfs_health,
199 dataIndex: 'state',
200 },
201 {
202 text: 'READ',
203 dataIndex: 'read',
204 },
205 {
206 text: 'WRITE',
207 dataIndex: 'write',
208 },
209 {
210 text: 'CKSUM',
211 dataIndex: 'cksum',
212 },
213 {
214 text: gettext('Message'),
215 dataIndex: 'msg',
216 },
217 ],
218
219 rootVisible: true,
220
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();
235 },
236 });
237 },
238
239 initComponent: function() {
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 }
263 },
264 },
265 ],
266 sorters: 'name',
267 });
268
269 me.callParent();
270
271 me.reload();
272 },
273 });
274
275 Ext.define('PVE.node.ZFSStatus', {
276 extend: 'Proxmox.grid.ObjectGrid',
277 xtype: 'pveZFSStatus',
278 layout: 'fit',
279 border: false,
280
281 initComponent: function() {
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: {
296 header: gettext('Scan'),
297 },
298 status: {
299 header: gettext('Status'),
300 },
301 action: {
302 header: gettext('Action'),
303 },
304 errors: {
305 header: gettext('Errors'),
306 },
307 };
308
309 me.callParent();
310 me.reload();
311 },
312 });
313
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',
324 flex: 1,
325 },
326 {
327 header: gettext('Size'),
328 renderer: Proxmox.Utils.format_size,
329 dataIndex: 'size',
330 },
331 {
332 header: gettext('Free'),
333 renderer: Proxmox.Utils.format_size,
334 dataIndex: 'free',
335 },
336 {
337 header: gettext('Allocated'),
338 renderer: Proxmox.Utils.format_size,
339 dataIndex: 'alloc',
340 },
341 {
342 header: gettext('Fragmentation'),
343 renderer: function(value) {
344 return value.toString() + '%';
345 },
346 dataIndex: 'frag',
347 },
348 {
349 header: gettext('Health'),
350 renderer: PVE.Utils.render_zfs_health,
351 dataIndex: 'health',
352 },
353 {
354 header: gettext('Deduplication'),
355 hidden: true,
356 renderer: function(value) {
357 return value.toFixed(2).toString() + 'x';
358 },
359 dataIndex: 'dedup',
360 },
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();
373 },
374 },
375 {
376 text: gettext('Create') + ': ZFS',
377 handler: function() {
378 var me = this.up('panel');
379 var win = Ext.create('PVE.node.CreateZFS', {
380 nodename: me.nodename,
381 }).show();
382 win.on('destroy', function() { me.reload(); });
383 },
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'));
396 },
397 },
398 ],
399
400 show_detail: function(zpool) {
401 var me = this;
402
403 var detailsgrid = Ext.create('PVE.node.ZFSStatus', {
404 layout: 'fit',
405 nodename: me.nodename,
406 flex: 0,
407 zpool: zpool,
408 });
409
410 var devicetree = Ext.create('PVE.node.ZFSDevices', {
411 title: gettext('Devices'),
412 nodename: me.nodename,
413 flex: 1,
414 zpool: zpool,
415 });
416
417
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,
425 items:[{
426 xtype: 'panel',
427 region: 'center',
428 layout: {
429 type: 'vbox',
430 align: 'stretch',
431 },
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();
440 },
441 }],
442 }],
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'));
469 },
470 },
471
472 initComponent: function() {
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',
485 url: "/api2/json/nodes/" + me.nodename + '/disks/zfs',
486 },
487 sorters: 'name',
488 },
489 });
490
491 me.callParent();
492
493 Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
494 me.reload();
495 },
496 });
497