[pve-devel] [PATCH manager v3 08/10] ceph: gui: rework pool input panel
Alwin Antreich
a.antreich at proxmox.com
Tue Jan 12 11:21:51 CET 2021
* add the ability to edit an existing pool
* allow adjustment of autoscale settings
* warn if user specifies min_size 1
* disallow min_size 1 on pool create
* calculate min_size replica by size
Signed-off-by: Alwin Antreich <a.antreich at proxmox.com>
---
www/manager6/ceph/Pool.js | 249 +++++++++++++++++++++++++++++---------
1 file changed, 191 insertions(+), 58 deletions(-)
diff --git a/www/manager6/ceph/Pool.js b/www/manager6/ceph/Pool.js
index 75c95fce..bd395956 100644
--- a/www/manager6/ceph/Pool.js
+++ b/www/manager6/ceph/Pool.js
@@ -1,17 +1,21 @@
-Ext.define('PVE.CephCreatePool', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreatePool',
+Ext.define('PVE.CephPoolInputPanel', {
+ extend: 'Proxmox.panel.InputPanel',
+ xtype: 'pveCephPoolInputPanel',
+ mixins: ['Proxmox.Mixin.CBind'],
showProgress: true,
onlineHelp: 'pve_ceph_pools',
subject: 'Ceph Pool',
- isCreate: true,
- method: 'POST',
- items: [
+ column1: [
{
- xtype: 'textfield',
+ xtype: 'pmxDisplayEditField',
fieldLabel: gettext('Name'),
+ cbind: {
+ editable: '{isCreate}',
+ value: '{pool_name}',
+ disabled: '{!isCreate}'
+ },
name: 'name',
allowBlank: false
},
@@ -20,75 +24,180 @@ Ext.define('PVE.CephCreatePool', {
fieldLabel: gettext('Size'),
name: 'size',
value: 3,
- minValue: 1,
+ minValue: 2,
maxValue: 7,
- allowBlank: false
+ allowBlank: false,
+ listeners: {
+ change: function(field, val) {
+ let size = Math.round(val / 2);
+ if (size > 1) {
+ field.up('inputpanel').down('field[name=min_size]').setValue(size);
+ }
+ },
+ },
},
+ ],
+ column2: [
+ {
+ xtype: 'proxmoxKVComboBox',
+ fieldLabel: 'PG Autoscale Mode',
+ name: 'pg_autoscale_mode',
+ comboItems: [
+ ['warn', 'warn'],
+ ['on', 'on'],
+ ['off', 'off'],
+ ],
+ value: 'warn',
+ allowBlank: false,
+ autoSelect: false,
+ labelWidth: 140,
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ fieldLabel: gettext('Add as Storage'),
+ cbind: {
+ value: '{isCreate}',
+ hidden: '{!isCreate}',
+ },
+ name: 'add_storages',
+ labelWidth: 140,
+ autoEl: {
+ tag: 'div',
+ 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
+ },
+ },
+ ],
+ advancedColumn1: [
{
xtype: 'proxmoxintegerfield',
fieldLabel: gettext('Min. Size'),
name: 'min_size',
value: 2,
- minValue: 1,
+ cbind: {
+ minValue: (get) => get('isCreate') ? 2 : 1,
+ },
maxValue: 7,
- allowBlank: false
+ allowBlank: false,
+ listeners: {
+ change: function(field, val) {
+ let warn = true;
+ let warn_text = gettext('Min. Size');
+
+ if (val < 2) {
+ warn = false;
+ warn_text = gettext('Min. Size') + ' <i class="fa fa-exclamation-triangle warning"></i>';
+ }
+
+ field.up().down('field[name=min_size-warning]').setHidden(warn);
+ field.setFieldLabel(warn_text);
+ }
+ },
+ },
+ {
+ xtype: 'displayfield',
+ name: 'min_size-warning',
+ userCls: 'pmx-hint',
+ value: 'A pool with min_size=1 could lead to data loss, incomplete PGs or unfound objects.',
+ hidden: true,
},
{
xtype: 'pveCephRuleSelector',
fieldLabel: 'Crush Rule', // do not localize
+ cbind: { nodename: '{nodename}' },
name: 'crush_rule',
allowBlank: false
},
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: 'PG Autoscale Mode', // do not localize
- name: 'pg_autoscale_mode',
- comboItems: [
- ['warn', 'warn'],
- ['on', 'on'],
- ['off', 'off'],
- ],
- value: 'warn',
- allowBlank: false,
- autoSelect: false,
- },
{
xtype: 'proxmoxintegerfield',
- fieldLabel: 'pg_num',
+ fieldLabel: '# of PGs',
name: 'pg_num',
value: 128,
- minValue: 8,
+ minValue: 1,
maxValue: 32768,
+ allowBlank: false,
+ emptyText: 128,
+ },
+ ],
+ advancedColumn2: [
+ {
+ xtype: 'numberfield',
+ fieldLabel: gettext('Target Size Ratio'),
+ name: 'target_size_ratio',
+ labelWidth: 140,
+ minValue: 0,
+ decimalPrecision: 3,
allowBlank: true,
- emptyText: gettext('Autoscale'),
+ emptyText: '0.0',
},
{
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Add as Storage'),
- value: true,
- name: 'add_storages',
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
- },
- }
+ xtype: 'numberfield',
+ fieldLabel: gettext('Target Size') + ' (GiB)',
+ name: 'target_size',
+ labelWidth: 140,
+ minValue: 0,
+ allowBlank: true,
+ emptyText: '0',
+ },
+ {
+ xtype: 'displayfield',
+ name: 'min_size-warning',
+ userCls: 'pmx-hint',
+ value: 'Target Size Ratio takes precedence.',
+ },
],
- initComponent : function() {
- var me = this;
- if (!me.nodename) {
- throw "no node name specified";
+ onGetValues: function(values) {
+ Object.keys(values || {}).forEach(function(name) {
+ if (values[name] === '') {
+ delete values[name];
+ }
+ });
+
+ if (values['target_size'] && values['target_size'] !== 0) {
+ values['target_size'] = values['target_size']*1024*1024*1024;
}
+ return values;
+ },
- Ext.apply(me, {
- url: "/nodes/" + me.nodename + "/ceph/pools",
- defaults: {
- nodename: me.nodename
- }
- });
+ setValues: function(values) {
+ if (values['target_size'] && values['target_size'] !== 0) {
+ values['target_size'] = values['target_size']/1024/1024/1024;
+ }
- me.callParent();
- }
+ this.callParent([values]);
+ },
+
+});
+
+Ext.define('PVE.CephPoolEdit', {
+ extend: 'Proxmox.window.Edit',
+ alias: 'widget.pveCephPoolEdit',
+ xtype: 'pveCephPoolEdit',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ cbindData: {
+ pool_name: '',
+ isCreate: (cfg) => !cfg.pool_name,
+ },
+
+ cbind: {
+ autoLoad: get => !get('isCreate'),
+ url: get => get('isCreate') ?
+ `/nodes/${get('nodename')}/ceph/pools` :
+ `/nodes/${get('nodename')}/ceph/pools/${get('pool_name')}`,
+ method: get => get('isCreate') ? 'POST' : 'PUT',
+ },
+
+ subject: gettext('Ceph Pool'),
+
+ items: [{
+ xtype: 'pveCephPoolInputPanel',
+ cbind: {
+ nodename: '{nodename}',
+ pool_name: '{pool_name}',
+ isCreate: '{isCreate}',
+ },
+ }],
});
Ext.define('PVE.node.CephPoolList', {
@@ -221,6 +330,9 @@ Ext.define('PVE.node.CephPoolList', {
});
var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore });
+ var reload = function() {
+ rstore.load();
+ };
var regex = new RegExp("not (installed|initialized)", "i");
PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
@@ -237,14 +349,36 @@ Ext.define('PVE.node.CephPoolList', {
var create_btn = new Ext.Button({
text: gettext('Create'),
handler: function() {
- var win = Ext.create('PVE.CephCreatePool', {
- nodename: nodename
+ var win = Ext.create('PVE.CephPoolEdit', {
+ title: gettext('Create') + ': Ceph Pool',
+ isCreate: true,
+ nodename: nodename,
});
win.show();
- win.on('destroy', function() {
- rstore.load();
- });
+ win.on('destroy', reload);
+ }
+ });
+
+ var run_editor = function() {
+ var rec = sm.getSelection()[0];
+ if (!rec) {
+ return;
}
+
+ var win = Ext.create('PVE.CephPoolEdit', {
+ title: gettext('Edit') + ': Ceph Pool',
+ nodename: nodename,
+ pool_name: rec.data.pool_name,
+ });
+ win.on('destroy', reload);
+ win.show();
+ };
+
+ var edit_btn = new Proxmox.button.Button({
+ text: gettext('Edit'),
+ disabled: true,
+ selModel: sm,
+ handler: run_editor,
});
var destroy_btn = Ext.create('Proxmox.button.Button', {
@@ -268,19 +402,18 @@ Ext.define('PVE.node.CephPoolList', {
},
item: { type: 'CephPool', id: rec.data.pool_name }
}).show();
- win.on('destroy', function() {
- rstore.load();
- });
+ win.on('destroy', reload);
}
});
Ext.apply(me, {
store: store,
selModel: sm,
- tbar: [ create_btn, destroy_btn ],
+ tbar: [ create_btn, edit_btn, destroy_btn ],
listeners: {
activate: () => rstore.startUpdate(),
destroy: () => rstore.stopUpdate(),
+ itemdblclick: run_editor,
}
});
@@ -302,7 +435,7 @@ Ext.define('PVE.node.CephPoolList', {
{ name: 'pg_autoscale_mode', type: 'string'},
{ name: 'pg_num_final', type: 'integer'},
{ name: 'target_size_ratio', type: 'number'},
- { name: 'target_size_bytes', type: 'integer'},
+ { name: 'target_size', type: 'integer'},
],
idProperty: 'pool_name'
});
--
2.29.2
More information about the pve-devel
mailing list