[pve-devel] [PATCH manager v4] ui: storage: combine RBD external and hyperconverged add dialog
Thomas Lamprecht
t.lamprecht at proxmox.com
Tue Jul 31 10:28:06 CEST 2018
Combine both dialogues. This reduces storage choices from the
Storage -> Add menu, and thus improves usability.
We make the whole dialog also more intelligent by querying the
monitors, so that we can show them for the hyper converged case
keeping a similar interface for both cases. Further we can use this
to decide if a hyperconverged setup is possible at all.
While this information would also be available through the fact if
the pool selector has entries I wanted to show them anyway and could
make logic a bit easier using it.
---
changes v3 -> v4:
* add pveceph-possible intelligence
* unified interface for both
* not disabling stuff on edit as it's just hard to read
I initially tried to have two patches, one unifying and one for making it more
intelligent, but those two things are quite intertwined... And just having a
second patch for the sake of it, where then the first one is not much tested,
or undesired anyway, seemed not worth the work.
www/manager6/Utils.js | 11 +-
www/manager6/dc/StorageView.js | 4 -
www/manager6/storage/RBDEdit.js | 200 ++++++++++++++++++++++++--------
3 files changed, 157 insertions(+), 58 deletions(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index c062b591..3ff5ef67 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -430,17 +430,12 @@ Ext.define('PVE.Utils', { utilities: {
rbd: {
name: 'RBD',
ipanel: 'RBDInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- rbd_ext: {
- name: 'RBD (external)',
- ipanel: 'RBDInputPanel',
faIcon: 'building'
},
pveceph: {
name: 'RBD (PVE)',
- ipanel: 'PVERBDInputPanel',
+ ipanel: 'RBDInputPanel',
+ hideAdd: true,
faIcon: 'building'
},
zfs: {
@@ -461,7 +456,7 @@ Ext.define('PVE.Utils', { utilities: {
format_storage_type: function(value, md, record) {
if (value === 'rbd' && record) {
- value = (record.get('monhost')?'rbd_ext':'pveceph');
+ value = (record.get('monhost') ? 'rbd' : 'pveceph');
}
var schema = PVE.Utils.storageSchema[value];
diff --git a/www/manager6/dc/StorageView.js b/www/manager6/dc/StorageView.js
index 57214b7f..cc1e3ed6 100644
--- a/www/manager6/dc/StorageView.js
+++ b/www/manager6/dc/StorageView.js
@@ -54,10 +54,6 @@ Ext.define('PVE.dc.StorageView', {
var type = rec.data.type,
sid = rec.data.storage;
- if (type === 'rbd' && !rec.data.monhost) {
- type = 'pveceph';
- }
-
me.createStorageEditWindow(type, sid);
};
diff --git a/www/manager6/storage/RBDEdit.js b/www/manager6/storage/RBDEdit.js
index d26a6ac3..8ae41d1f 100644
--- a/www/manager6/storage/RBDEdit.js
+++ b/www/manager6/storage/RBDEdit.js
@@ -1,6 +1,86 @@
+/*jslint confusion: true*/
Ext.define('PVE.storage.RBDInputPanel', {
extend: 'PVE.panel.StorageBase',
+ viewModel: {
+ parent: null,
+ data: {
+ pveceph: true,
+ pvecephPossible: true
+ }
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+ control: {
+ '#': {
+ afterrender: 'queryMonitors'
+ },
+ 'textfield[name=username]': {
+ disable: 'resetField'
+ },
+ 'displayfield[name=monhost]': {
+ enable: 'queryMonitors'
+ },
+ 'textfield[name=monhost]': {
+ disable: 'resetField',
+ enable: 'resetField'
+ }
+ },
+ resetField: function(field) {
+ field.reset();
+ },
+ queryMonitors: function(field, newVal, oldVal) {
+ // we get called with two signatures, the above one for a field
+ // change event and the afterrender from the view, this check only
+ // can be true for the field change one and omit the API request if
+ // pveceph got unchecked - as it's not needed there.
+ if (field && !newVal && oldVal) {
+ return;
+ }
+ var view = this.getView();
+ var vm = this.getViewModel();
+ if (!(view.isCreate || vm.get('pveceph'))) {
+ return; // only query on create or if editing a pveceph store
+ }
+
+ var monhostField = this.lookupReference('monhost');
+
+ Proxmox.Utils.API2Request({
+ url: '/api2/json/nodes/localhost/ceph/mon',
+ method: 'GET',
+ scope: this,
+ callback: function(options, success, response) {
+ var data = response.result.data;
+ if (response.status === 200) {
+ if (data.length > 0) {
+ var monhost = Ext.Array.pluck(data, 'name').sort().join(',');
+ monhostField.setValue(monhost);
+ monhostField.resetOriginalValue();
+ if (view.isCreate) {
+ vm.set('pvecephPossible', true);
+ }
+ } else {
+ vm.set('pveceph', false);
+ }
+ } else {
+ vm.set('pveceph', false);
+ vm.set('pvecephPossible', false);
+ }
+ }
+ });
+ }
+ },
+
+ setValues: function(values) {
+ if (values.monhost) {
+ this.viewModel.set('pveceph', false);
+ this.lookupReference('pvecephRef').setValue(false);
+ this.lookupReference('pvecephRef').resetOriginalValue();
+ }
+ this.callParent([values]);
+ },
+
initComponent : function() {
var me = this;
@@ -9,48 +89,68 @@ Ext.define('PVE.storage.RBDInputPanel', {
}
me.type = 'rbd';
- me.column1 = [];
+ var getBinds = function (activeIfPVECeph, hide) {
+ var bind = {
+ disabled: activeIfPVECeph ? '{!pveceph}' : '{pveceph}'
+ };
- if (me.pveceph) {
- me.column1.push(
- {
- xtype: me.isCreate ? 'pveCephPoolSelector' : 'displayfield',
- nodename: me.nodename,
- name: 'pool',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- }
- );
- } else {
- me.column1.push(
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'pool',
- value: 'rbd',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'monhost',
- vtype: 'HostList',
- value: '',
- fieldLabel: 'Monitor(s)',
- allowBlank: false
+ // displayfield has no submitValue and bind mixin cannot handle that
+ if (me.isCreate) {
+ bind.submitValue = activeIfPVECeph ? '{pveceph}' : '{!pveceph}';
+ }
+ if (hide) {
+ bind.hidden = activeIfPVECeph ? '{!pveceph}' : '{pveceph}';
+ }
+
+ return bind;
+ };
+
+ me.column1 = [
+ {
+ xtype: me.isCreate ? 'pveCephPoolSelector' : 'displayfield',
+ nodename: me.nodename,
+ name: 'pool',
+ bind: getBinds(true, true),
+ fieldLabel: gettext('Pool'),
+ allowBlank: false
+ },
+ {
+ xtype: me.isCreate ? 'textfield' : 'displayfield',
+ name: 'pool',
+ value: 'rbd',
+ bind: getBinds(false, true),
+ fieldLabel: gettext('Pool'),
+ allowBlank: false
+ },
+ {
+ xtype: 'textfield',
+ name: 'monhost',
+ vtype: 'HostList',
+ bind: getBinds(false, true),
+ value: '',
+ fieldLabel: 'Monitor(s)',
+ allowBlank: false
+ },
+ {
+ xtype: 'displayfield',
+ reference: 'monhost',
+ bind: {
+ disabled: '{!pveceph}',
+ hidden: '{!pveceph}'
},
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- value: me.isCreate ? 'admin': '',
- fieldLabel: gettext('User name'),
- allowBlank: true
- }
- );
- }
+ value: '',
+ fieldLabel: 'Monitor(s)'
+ },
+ {
+ xtype: me.isCreate ? 'textfield' : 'displayfield',
+ name: 'username',
+ bind: me.isCreate ? getBinds(false) : {},
+ value: 'admin',
+ fieldLabel: gettext('User name'),
+ allowBlank: true
+ }
+ ];
- // here value is an array,
- // while before it was a string
- /*jslint confusion: true*/
me.column2 = [
{
xtype: 'pveContentTypeSelector',
@@ -68,14 +168,22 @@ Ext.define('PVE.storage.RBDInputPanel', {
fieldLabel: 'KRBD'
}
];
- /*jslint confusion: false*/
+
+ me.columnB = [{
+ xtype: 'proxmoxcheckbox',
+ name: 'pveceph',
+ reference: 'pvecephRef',
+ bind : {
+ disabled: '{!pvecephPossible}',
+ value: '{pveceph}'
+ },
+ checked: true,
+ uncheckedValue: 0,
+ submitValue: false,
+ hidden: !me.isCreate,
+ boxLabel: gettext('Use Proxmox VE managed hyper-converged ceph pool')
+ }];
me.callParent();
}
});
-
-Ext.define('PVE.storage.PVERBDInputPanel', {
- extend: 'PVE.storage.RBDInputPanel',
-
- pveceph: 1
-});
--
2.18.0
More information about the pve-devel
mailing list