lxc/MPEdit: rework for advanced options
this is a complete rework of the inputpanel (long overdue) it uses a viewModel and viewcontroller to avoid the multiple is zfs/root/bind checks and concentrate them in one place also some features get optimized (e.g. the noreplication checkbox) adds a setNodename to the DiskStorageSelector so that we can bind the nodename there Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
86daeceb9d
commit
b44ca5bac6
@ -76,6 +76,15 @@ Ext.define('PVE.form.DiskStorageSelector', {
|
||||
hdsizesel.setVisible(!select && !me.hideSize);
|
||||
},
|
||||
|
||||
setNodename: function(nodename) {
|
||||
var me = this;
|
||||
var hdstorage = me.getComponent('hdstorage');
|
||||
var hdfilesel = me.getComponent('hdimage');
|
||||
|
||||
hdstorage.setNodename(nodename);
|
||||
hdfilesel.setNodename(nodename);
|
||||
},
|
||||
|
||||
initComponent: function() {
|
||||
var me = this;
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
/*jslint confusion: true*/
|
||||
/* hidden: boolean and string
|
||||
* bind: function and object
|
||||
* disabled: boolean and string
|
||||
*/
|
||||
Ext.define('PVE.lxc.MountPointInputPanel', {
|
||||
extend: 'Proxmox.panel.InputPanel',
|
||||
alias: 'widget.pveLxcMountPointInputPanel',
|
||||
xtype: 'pveLxcMountPointInputPanel',
|
||||
|
||||
insideWizard: false,
|
||||
|
||||
@ -13,284 +18,274 @@ Ext.define('PVE.lxc.MountPointInputPanel', {
|
||||
vmconfig: {}, // used to select unused disks
|
||||
|
||||
setUnprivileged: function(unprivileged) {
|
||||
this.unprivileged = unprivileged;
|
||||
this.quota.setDisabled(unprivileged);
|
||||
var me = this;
|
||||
var vm = me.getViewModel();
|
||||
me.unprivileged = unprivileged;
|
||||
vm.set('unpriv', unprivileged);
|
||||
},
|
||||
|
||||
onGetValues: function(values) {
|
||||
var me = this;
|
||||
|
||||
var confid = me.confid || values.mpsel;
|
||||
values.file = me.down('field[name=file]').getValue();
|
||||
|
||||
if (me.unused) {
|
||||
me.mpdata.file = me.vmconfig[values.unusedId];
|
||||
confid = values.mpsel;
|
||||
} else if (me.isCreate) {
|
||||
me.mpdata.file = values.hdstorage + ':' + values.disksize;
|
||||
values.file = values.hdstorage + ':' + values.disksize;
|
||||
}
|
||||
|
||||
if (confid !== 'rootfs') {
|
||||
me.mpdata.mp = values.mp;
|
||||
}
|
||||
|
||||
if (values.ro) {
|
||||
me.mpdata.ro = 1;
|
||||
} else {
|
||||
delete me.mpdata.ro;
|
||||
}
|
||||
|
||||
if (values.quota) {
|
||||
me.mpdata.quota = 1;
|
||||
} else {
|
||||
delete me.mpdata.quota;
|
||||
}
|
||||
|
||||
if (values.acl === 'Default') {
|
||||
delete me.mpdata.acl;
|
||||
} else {
|
||||
me.mpdata.acl = values.acl;
|
||||
}
|
||||
|
||||
if (values.backup) {
|
||||
me.mpdata.backup = 1;
|
||||
} else {
|
||||
delete me.mpdata.backup;
|
||||
}
|
||||
|
||||
if (values.noreplicate) {
|
||||
me.mpdata.replicate = '0';
|
||||
}
|
||||
delete me.mpdata.noreplicate;
|
||||
// delete unnecessary fields
|
||||
delete values.mpsel;
|
||||
delete values.hdstorage;
|
||||
delete values.disksize;
|
||||
delete values.diskformat;
|
||||
|
||||
var res = {};
|
||||
res[confid] = PVE.Parser.printLxcMountPoint(me.mpdata);
|
||||
res[confid] = PVE.Parser.printLxcMountPoint(values);
|
||||
return res;
|
||||
},
|
||||
|
||||
|
||||
setMountPoint: function(mp) {
|
||||
var me = this;
|
||||
|
||||
// the fields name is 'hdstorage',
|
||||
// but the api expects/has 'storage'
|
||||
mp.hdstorage = mp.storage;
|
||||
delete mp.hdstorage;
|
||||
|
||||
me.mpdata = mp;
|
||||
if (!Ext.isDefined(me.mpdata.acl)) {
|
||||
me.mpdata.acl = 'Default';
|
||||
}
|
||||
|
||||
if (mp.type === 'bind') {
|
||||
me.quota.setDisabled(true);
|
||||
me.acl.setDisabled(true);
|
||||
me.acl.setValue('Default');
|
||||
me.down('#hdstorage').setDisabled(true);
|
||||
if (me.confid !== 'rootfs') {
|
||||
me.backup.setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (mp.replicate) { // check box reverses the config option
|
||||
mp.noreplicate = !PVE.Parser.parseBoolean(mp.replicate, 1);
|
||||
delete mp.replicate;
|
||||
}
|
||||
|
||||
var vm = this.getViewModel();
|
||||
vm.set('mptype', mp.type);
|
||||
me.setValues(mp);
|
||||
},
|
||||
|
||||
setVMConfig: function(vmconfig) {
|
||||
var me = this;
|
||||
|
||||
var vm = me.getViewModel();
|
||||
me.vmconfig = vmconfig;
|
||||
vm.set('unpriv', vmconfig.unprivileged);
|
||||
vm.notify();
|
||||
|
||||
if (me.mpsel) {
|
||||
var i;
|
||||
for (i = 0; i != 8; ++i) {
|
||||
var name = "mp" + i.toString();
|
||||
if (!Ext.isDefined(vmconfig[name])) {
|
||||
me.mpsel.setValue(name);
|
||||
break;
|
||||
}
|
||||
PVE.Utils.forEachMP(function(bus, i) {
|
||||
var name = "mp" + i.toString();
|
||||
if (!Ext.isDefined(vmconfig[name])) {
|
||||
me.down('field[name=mpsel]').setValue(name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (me.unusedDisks) {
|
||||
var disklist = [];
|
||||
Ext.Object.each(vmconfig, function(key, value) {
|
||||
if (key.match(/^unused\d+$/)) {
|
||||
disklist.push([key, value]);
|
||||
}
|
||||
});
|
||||
me.unusedDisks.store.loadData(disklist);
|
||||
me.unusedDisks.setValue(me.confid);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setNodename: function(nodename) {
|
||||
var me = this;
|
||||
me.down('#hdstorage').setNodename(nodename);
|
||||
me.down('#hdimage').setStorage(undefined, nodename);
|
||||
var vm = me.getViewModel();
|
||||
vm.set('node', nodename);
|
||||
vm.notify();
|
||||
me.down('#diskstorage').setNodename(nodename);
|
||||
},
|
||||
|
||||
initComponent : function() {
|
||||
var me = this;
|
||||
controller: {
|
||||
xclass: 'Ext.app.ViewController',
|
||||
|
||||
var isroot = me.confid === 'rootfs';
|
||||
|
||||
me.mpdata = {};
|
||||
|
||||
me.column1 = [];
|
||||
|
||||
if (!me.confid || me.unused) {
|
||||
var names = [];
|
||||
var i;
|
||||
for (i = 0; i != 8; ++i) {
|
||||
var name = 'mp' + i.toString();
|
||||
names.push([name, name]);
|
||||
}
|
||||
me.mpsel = Ext.create('Proxmox.form.KVComboBox', {
|
||||
name: 'mpsel',
|
||||
fieldLabel: gettext('Mount Point'),
|
||||
matchFieldWidth: false,
|
||||
allowBlank: false,
|
||||
comboItems: names,
|
||||
validator: function(value) {
|
||||
if (!me.rendered) {
|
||||
control: {
|
||||
'field[name=mpsel]': {
|
||||
change: function(field, value) {
|
||||
field.validate();
|
||||
}
|
||||
},
|
||||
'#hdstorage': {
|
||||
change: function(field, newValue) {
|
||||
var me = this;
|
||||
if (!newValue) {
|
||||
return;
|
||||
}
|
||||
if (Ext.isDefined(me.vmconfig[value])) {
|
||||
return "Mount point is already in use.";
|
||||
}
|
||||
/*jslint confusion: true*/
|
||||
/* returns a string above */
|
||||
return true;
|
||||
},
|
||||
listeners: {
|
||||
change: function(field, value) {
|
||||
field.validate();
|
||||
}
|
||||
}
|
||||
});
|
||||
me.column1.push(me.mpsel);
|
||||
}
|
||||
|
||||
me.column1.push({
|
||||
var rec = field.store.getById(newValue);
|
||||
if (!rec) {
|
||||
return;
|
||||
}
|
||||
|
||||
var vm = me.getViewModel();
|
||||
vm.set('type', rec.data.type);
|
||||
vm.notify();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
init: function(view) {
|
||||
var me = this;
|
||||
var vm = this.getViewModel();
|
||||
vm.set('confid', view.confid);
|
||||
vm.set('unused', view.unused);
|
||||
vm.set('node', view.nodename);
|
||||
vm.set('unpriv', view.unprivileged);
|
||||
vm.set('hideStorSelector', view.unused || !view.isCreate);
|
||||
vm.notify();
|
||||
}
|
||||
},
|
||||
|
||||
viewModel: {
|
||||
data: {
|
||||
unpriv: false,
|
||||
unused: false,
|
||||
showStorageSelector: false,
|
||||
mptype: '',
|
||||
type: '',
|
||||
confid: '',
|
||||
node: ''
|
||||
},
|
||||
|
||||
formulas: {
|
||||
quota: function(get) {
|
||||
return !(get('type') === 'zfs' ||
|
||||
get('type') === 'zfspool' ||
|
||||
get('unpriv') ||
|
||||
get('isBind'));
|
||||
},
|
||||
hasMP: function(get) {
|
||||
return !!get('confid') && !get('unused');
|
||||
},
|
||||
isRoot: function(get) {
|
||||
return get('confid') === 'rootfs';
|
||||
},
|
||||
isBind: function(get) {
|
||||
return get('mptype') === 'bind';
|
||||
},
|
||||
isBindOrRoot: function(get) {
|
||||
return get('isBind') || get('isRoot');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
column1: [
|
||||
{
|
||||
xtype: 'proxmoxKVComboBox',
|
||||
name: 'mpsel',
|
||||
fieldLabel: gettext('Mount Point'),
|
||||
matchFieldWidth: false,
|
||||
hidden: true,
|
||||
allowBlank: false,
|
||||
bind: {
|
||||
hidden: '{hasMP}',
|
||||
disabled: '{hasMP}'
|
||||
},
|
||||
comboItems: (function(){
|
||||
var mps = [];
|
||||
PVE.Utils.forEachMP(function(bus,i) {
|
||||
var name = 'mp' + i.toString();
|
||||
mps.push([name,name]);
|
||||
});
|
||||
return mps;
|
||||
}()),
|
||||
validator: function(value) {
|
||||
var me = this.up('inputpanel');
|
||||
if (!me.rendered) {
|
||||
return;
|
||||
}
|
||||
if (Ext.isDefined(me.vmconfig[value])) {
|
||||
return "Mount point is already in use.";
|
||||
}
|
||||
/*jslint confusion: true*/
|
||||
/* returns a string above */
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
xtype: 'pveDiskStorageSelector',
|
||||
nodename: me.nodename,
|
||||
itemId: 'diskstorage',
|
||||
storageContent: 'rootdir',
|
||||
hidden: true,
|
||||
autoSelect: true,
|
||||
selectformat: false,
|
||||
defaultSize: 8,
|
||||
hidden: me.unused || !me.isCreate
|
||||
});
|
||||
|
||||
if (me.unused) {
|
||||
me.unusedDisks = Ext.create('Proxmox.form.KVComboBox', {
|
||||
name: 'unusedId',
|
||||
fieldLabel: gettext('Disk image'),
|
||||
matchFieldWidth: false,
|
||||
listConfig: {
|
||||
width: 350
|
||||
},
|
||||
data: [],
|
||||
allowBlank: false,
|
||||
listeners: {
|
||||
change: function(f, value) {
|
||||
// make sure our buttons are enabled/disabled when switching
|
||||
// between images on different storages:
|
||||
var disk = me.vmconfig[value];
|
||||
var storage = disk.split(':')[0];
|
||||
me.down('#hdstorage').setValue(storage);
|
||||
}
|
||||
}
|
||||
});
|
||||
me.column1.push(me.unusedDisks);
|
||||
} else if (!me.isCreate) {
|
||||
me.column1.push({
|
||||
xtype: 'textfield',
|
||||
disabled: true,
|
||||
submitValue: false,
|
||||
fieldLabel: gettext('Disk image'),
|
||||
name: 'file'
|
||||
});
|
||||
bind: {
|
||||
hidden: '{hideStorSelector}',
|
||||
disabled: '{hideStorSelector}',
|
||||
nodename: '{node}'
|
||||
}
|
||||
},
|
||||
{
|
||||
xtype: 'textfield',
|
||||
disabled: true,
|
||||
submitValue: false,
|
||||
fieldLabel: gettext('Disk image'),
|
||||
name: 'file',
|
||||
bind: {
|
||||
hidden: '{!hideStorSelector}'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
me.acl = Ext.createWidget('proxmoxKVComboBox', {
|
||||
name: 'acl',
|
||||
fieldLabel: 'ACLs',
|
||||
comboItems: [['Default', 'Default'], ['1', 'On'], ['0', 'Off']],
|
||||
value: 'Default',
|
||||
allowBlank: true
|
||||
});
|
||||
column2: [
|
||||
{
|
||||
xtype: 'textfield',
|
||||
name: 'mp',
|
||||
value: '',
|
||||
emptyText: gettext('/some/path'),
|
||||
allowBlank: false,
|
||||
fieldLabel: gettext('Path'),
|
||||
bind: {
|
||||
hidden: '{isRoot}',
|
||||
disabled: '{isRoot}'
|
||||
}
|
||||
},
|
||||
{
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'backup',
|
||||
fieldLabel: gettext('Backup'),
|
||||
bind: {
|
||||
hidden: '{isRoot}',
|
||||
disabled: '{isBindOrRoot}'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
me.quota = Ext.createWidget('proxmoxcheckbox', {
|
||||
advancedColumn1: [
|
||||
{
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'quota',
|
||||
defaultValue: 0,
|
||||
disabled: me.unprivileged,
|
||||
bind: {
|
||||
disabled: '{!quota}'
|
||||
},
|
||||
fieldLabel: gettext('Enable quota'),
|
||||
listeners: {
|
||||
disable: function() {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
me.column2 = [
|
||||
me.acl,
|
||||
me.quota
|
||||
];
|
||||
|
||||
if (!isroot) {
|
||||
me.column2.splice(1, 0, {
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'ro',
|
||||
defaultValue: 0,
|
||||
fieldLabel: gettext('Read-only'),
|
||||
hidden: me.insideWizard
|
||||
});
|
||||
|
||||
me.backup = Ext.createWidget('proxmoxcheckbox',{
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'backup',
|
||||
fieldLabel: gettext('Backup')
|
||||
});
|
||||
if (me.mpdata.type !== 'bind') {
|
||||
me.column2.push(me.backup);
|
||||
}
|
||||
me.column2.push({
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'noreplicate',
|
||||
fieldLabel: gettext('Skip replication')
|
||||
});
|
||||
me.column2.push({
|
||||
xtype: 'textfield',
|
||||
name: 'mp',
|
||||
value: '',
|
||||
emptyText: gettext('/some/path'),
|
||||
allowBlank: false,
|
||||
hidden: isroot,
|
||||
fieldLabel: gettext('Path')
|
||||
});
|
||||
},
|
||||
{
|
||||
xtype: 'proxmoxcheckbox',
|
||||
name: 'ro',
|
||||
defaultValue: 0,
|
||||
bind: {
|
||||
hidden: '{isRoot}',
|
||||
disabled: '{isRoot}'
|
||||
},
|
||||
fieldLabel: gettext('Read-only')
|
||||
}
|
||||
],
|
||||
|
||||
me.callParent();
|
||||
|
||||
if (me.unused || me.isCreate) {
|
||||
me.mon(me.down('#hdstorage'), 'change', function(field, newValue) {
|
||||
if (!newValue) {
|
||||
return;
|
||||
}
|
||||
var rec = field.store.getById(newValue);
|
||||
if (!rec) {
|
||||
return;
|
||||
}
|
||||
if (rec.data.type === 'zfs' || rec.data.type === 'zfspool') {
|
||||
me.quota.setDisabled(true);
|
||||
} else {
|
||||
me.quota.setDisabled(me.unprivileged);
|
||||
}
|
||||
});
|
||||
advancedColumn2: [
|
||||
{
|
||||
xtype: 'proxmoxKVComboBox',
|
||||
name: 'acl',
|
||||
fieldLabel: 'ACLs',
|
||||
deleteEmpty: false,
|
||||
comboItems: [
|
||||
['__default__', Proxmox.Utils.defaultText],
|
||||
['1', Proxmox.Utils.enabledText],
|
||||
['0', Proxmox.Utils.disabledText]
|
||||
],
|
||||
value: '__default__',
|
||||
bind: {
|
||||
disabled: '{isBind}'
|
||||
},
|
||||
allowBlank: true
|
||||
},
|
||||
{
|
||||
xtype: 'proxmoxcheckbox',
|
||||
inputValue: '0', // reverses the logic
|
||||
name: 'replicate',
|
||||
fieldLabel: gettext('Skip replication')
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
Ext.define('PVE.lxc.MountPointEdit', {
|
||||
|
Loading…
x
Reference in New Issue
Block a user