]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/node/ZFS.js
1 Ext
.define('PVE.node.CreateZFS', {
2 extend
: 'Proxmox.window.Edit',
5 onlineHelp
: 'chapter_zfs',
17 isDraid
: get => get('raidLevel')?.startsWith("draid"),
21 initComponent: function() {
25 throw "no node name specified";
29 url
: `/nodes/${me.nodename}/disks/zfs`,
34 onGetValues: function(values
) {
35 if (values
.draidData
|| values
.draidSpares
) {
36 let opt
= { data
: values
.draidData
, spares
: values
.draidSpares
};
37 values
['draid-config'] = PVE
.Parser
.printPropertyString(opt
);
39 delete values
.draidData
;
40 delete values
.draidSpares
;
45 xtype
: 'proxmoxtextfield',
47 fieldLabel
: gettext('Name'),
49 maxLength
: 128, // ZFS_MAX_DATASET_NAME_LEN is (256 - some edge case)
51 // see zpool_name_valid function in libzfs_zpool.c
52 if (v
.match(/^(mirror|raidz|draid|spare)/) || v
=== 'log') {
53 return gettext('Cannot use reserved pool name');
54 } else if (!v
.match(/^[a-zA-Z][a-zA-Z0-9\-_.]*$/)) {
55 // note: zfs would support also : and whitespace, but we don't
56 return gettext("Invalid characters in pool name");
62 xtype
: 'proxmoxcheckbox',
64 fieldLabel
: gettext('Add Storage'),
70 xtype
: 'proxmoxKVComboBox',
71 fieldLabel
: gettext('RAID Level'),
75 ['single', gettext('Single Disk')],
90 xtype
: 'proxmoxKVComboBox',
91 fieldLabel
: gettext('Compression'),
105 xtype
: 'proxmoxintegerfield',
106 fieldLabel
: gettext('ashift'),
116 title
: gettext('dRAID Config'),
119 hidden
: '{!isDraid}',
128 xtype
: 'proxmoxintegerfield',
130 fieldLabel
: gettext('Data Devs'),
136 disabled
: '{!isDraid}',
137 hidden
: '{!isDraid}',
142 xtype
: 'proxmoxintegerfield',
144 fieldLabel
: gettext('Spares'),
150 disabled
: '{!isDraid}',
151 hidden
: '{!isDraid}',
157 xtype
: 'pmxMultiDiskSelector',
159 nodename
: me
.nodename
,
161 includePartitions
: true,
163 emptyText
: gettext('No Disks unused'),
169 xtype
: 'displayfield',
172 value
: 'Note: ZFS is not compatible with disks backed by a hardware ' +
173 'RAID controller. For details see <a target="_blank" href="' +
174 Proxmox
.Utils
.get_help_link('chapter_zfs') + '">the reference documentation</a>.',
184 Ext
.define('PVE.node.ZFSList', {
185 extend
: 'Ext.grid.Panel',
195 xclass
: 'Ext.app.ViewController',
197 destroyPool: function() {
199 let vm
= me
.getViewModel();
200 let view
= me
.getView();
202 const pool
= vm
.get('pool');
204 if (!view
.nodename
) {
205 throw "no node name specified";
209 throw "no pool specified";
212 Ext
.create('PVE.window.SafeDestroyStorage', {
213 url
: `/nodes/${view.nodename}/disks/zfs/${pool}`,
215 taskName
: 'zfsremove',
216 taskDone
: () => { view
.reload(); },
222 stateId
: 'grid-node-zfs',
225 text
: gettext('Name'),
230 header
: gettext('Size'),
231 renderer
: Proxmox
.Utils
.format_size
,
235 header
: gettext('Free'),
236 renderer
: Proxmox
.Utils
.format_size
,
240 header
: gettext('Allocated'),
241 renderer
: Proxmox
.Utils
.format_size
,
245 header
: gettext('Fragmentation'),
246 renderer: function(value
) {
247 return value
.toString() + '%';
252 header
: gettext('Health'),
253 renderer
: PVE
.Utils
.render_zfs_health
,
257 header
: gettext('Deduplication'),
259 renderer: function(value
) {
260 return value
.toFixed(2).toString() + 'x';
271 text
: gettext('Reload'),
272 iconCls
: 'fa fa-refresh',
273 handler: function() {
274 this.up('panel').reload();
278 text
: gettext('Create') + ': ZFS',
279 handler: function() {
280 let view
= this.up('panel');
281 Ext
.create('PVE.node.CreateZFS', {
282 nodename
: view
.nodename
,
284 destroy
: () => view
.reload(),
291 text
: gettext('Detail'),
294 handler: function() {
295 let view
= this.up('panel');
296 let selection
= view
.getSelection();
297 if (selection
.length
) {
298 view
.show_detail(selection
[0].get('name'));
317 Ext
.String
.format(gettext('No {0} selected'), 'pool'),
322 text
: gettext('More'),
323 iconCls
: 'fa fa-bars',
330 text
: gettext('Destroy'),
332 iconCls
: 'fa fa-fw fa-trash-o',
333 handler
: 'destroyPool',
343 show_detail: function(zpool
) {
346 Ext
.create('Proxmox.window.ZFSDetail', {
348 nodename
: me
.nodename
,
352 set_button_status: function() {
363 activate: function() {
366 selectionchange: function(model
, selected
) {
368 let vm
= me
.getViewModel();
370 me
.down('#detailbtn').setDisabled(selected
.length
=== 0);
371 vm
.set('pool', selected
[0]?.data
.name
|| '');
373 itemdblclick: function(grid
, record
) {
374 this.show_detail(record
.get('name'));
378 initComponent: function() {
381 me
.nodename
= me
.pveSelNode
.data
.node
;
383 throw "no node name specified";
388 fields
: ['name', 'size', 'free', 'alloc', 'dedup', 'frag', 'health'],
391 url
: `/api2/json/nodes/${me.nodename}/disks/zfs`,
399 Proxmox
.Utils
.monStoreErrors(me
, me
.getStore(), true);