[pve-devel] [PATCH manager v2 2/2] ha/groups: allow editing node priorities through UI

Thomas Lamprecht t.lamprecht at proxmox.com
Wed Oct 5 11:09:18 CEST 2016


This allows the setting and editing node priorities in HA groups.

Also fixes the bug where the priorities of an existing group (e.g.
set through the CLI) where deleted when editing said group through
the GUI.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---

changes since v1:
* use getWidgetRecord() instead of up.find()
* set sane maximum value for priority numberfield (1000)
* remove insideUpdate "lock" and just suspend the change event when updating
  the hidden nodefield to avoid an endless recursion
* the hidden nodefiled stays as it is without it we have to hack the form
  falidation and dirty tracking ourself, which is not nice

Note: it seems ExtJS has a bug with focusing numberfields in widgetcolumns.
You cannot click directly in the widget field and edit it, you have to use
the spinner buttons first, then the focus works. I saw this as a minor
problem as the user may a) click on the spinner as work around b) only use
the spinners

 www/manager6/ha/GroupEdit.js | 146 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 133 insertions(+), 13 deletions(-)

diff --git a/www/manager6/ha/GroupEdit.js b/www/manager6/ha/GroupEdit.js
index 0d9c3c5..4032ae2 100644
--- a/www/manager6/ha/GroupEdit.js
+++ b/www/manager6/ha/GroupEdit.js
@@ -16,6 +16,136 @@ Ext.define('PVE.ha.GroupInputPanel', {
     initComponent : function() {
 	var me = this;
 
+	var sm = Ext.create('Ext.selection.CheckboxModel', {
+	    mode: 'SIMPLE',
+	    listeners: {
+		selectionchange: function(model, selected) {
+		    update_nodefield(selected);
+		}
+	    }
+	});
+
+	// use already cached data to avoid an API call
+	var data = PVE.data.ResourceStore.getNodes();
+
+	var store = Ext.create('Ext.data.Store', {
+	    fields: [ 'node', 'mem', 'cpu', 'priority' ],
+	    data: data,
+	    proxy: {
+		type: 'memory',
+		reader: {type: 'json'}
+	    },
+	    sorters: [
+		{
+		    property : 'node',
+		    direction: 'ASC'
+		}
+	    ]
+	});
+
+	nodegrid = Ext.createWidget('grid', {
+	    store: store,
+	    border: true,
+	    height: 300,
+	    selModel: sm,
+	    columns: [
+		{
+		    header: gettext('Node'),
+		    flex: 1,
+		    dataIndex: 'node'
+		},
+		{
+		    header: gettext('Memory usage') + " %",
+		    renderer: PVE.Utils.render_mem_usage_percent,
+		    sortable: true,
+		    width: 150,
+		    dataIndex: 'mem'
+		},
+		{
+		    header: gettext('CPU usage'),
+		    renderer: PVE.Utils.render_cpu,
+		    sortable: true,
+		    width: 150,
+		    dataIndex: 'cpu'
+		},
+		{
+		    header: 'Priority',
+		    xtype: 'widgetcolumn',
+		    dataIndex: 'priority',
+		    sortable: true,
+		    stopSelection: true,
+		    widget: {
+			xtype: 'numberfield',
+			minValue: 0,
+			maxValue: 1000,
+			listeners: {
+			    change: function(numberfield, value, old_value) {
+				var record = numberfield.getWidgetRecord();
+				record.set('priority', value);
+				update_nodefield(sm.getSelection());
+			    }
+			}
+		    }
+		}
+	    ]
+	});
+
+	var nodefield = Ext.create('Ext.form.field.Hidden', {
+	    name: 'nodes',
+	    value: '',
+	    listeners: {
+		change: function (nodefield, value) {
+		    update_node_selection(value);
+		}
+	    },
+	    isValid: function () {
+		var value = nodefield.getValue();
+		return (value && 0 !== value.length);
+	    }
+	});
+
+	var update_node_selection = function(string) {
+	    sm.deselectAll(true);
+
+	    string.split(',').forEach(function (e, idx, array) {
+		res = e.split(':');
+
+		store.each(function(record) {
+		    node = record.get('node');
+
+		    if (node == res[0]) {
+			sm.select(record, true);
+			record.set('priority', res[1]);
+			record.commit();
+		    }
+		});
+	    });
+	    nodegrid.reconfigure(store);
+
+	};
+
+	var update_nodefield = function(selected) {
+	    var nodes = '';
+	    var first_iteration = true;
+	    Ext.Array.each(selected, function(record) {
+		if (!first_iteration) {
+		    nodes += ',';
+		}
+		first_iteration = false;
+
+		nodes += record.data.node;
+		if (record.data.priority) {
+		    nodes += ':' + record.data.priority;
+		}
+	    });
+
+	    // nodefield change listener calls us again, which results in a
+	    // endless recursion, suspend the event temporary to avoid this
+	    nodefield.suspendEvent('change');
+	    nodefield.setValue(nodes);
+	    nodefield.resumeEvent('change');
+	}
+
 	me.column1 = [
 	    {
 		xtype: me.create ? 'textfield' : 'displayfield',
@@ -25,14 +155,7 @@ Ext.define('PVE.ha.GroupInputPanel', {
 		vtype: 'StorageId',
 		allowBlank: false
 	    },
-	    {
-		xtype: 'pveNodeSelector',
-		name: 'nodes',
-		fieldLabel: gettext('Nodes'),
-		allowBlank: false,
-		multiSelect: true,
-		autoSelect: false
-	    }
+	    nodefield
 	];
 
 	me.column2 = [
@@ -55,7 +178,8 @@ Ext.define('PVE.ha.GroupInputPanel', {
 		xtype: 'textfield',
 		name: 'comment',
 		fieldLabel: gettext('Comment')
-	    }
+	    },
+	    nodegrid
 	];
 	
 	me.callParent();
@@ -97,10 +221,6 @@ Ext.define('PVE.ha.GroupEdit', {
 		success:  function(response, options) {
 		    var values = response.result.data;
 
-		    if (values.nodes) {
-			values.nodes = values.nodes.split(',');
-		    }
-
 		    ipanel.setValues(values);
 		}
 	    });
-- 
2.1.4





More information about the pve-devel mailing list