Since the node affinity rules can be either 'positive' or 'negative' now, allow users to define either affinity type for the node affinity rules in the web interface as well.
Since the priority field does not have any semantic value for negative node affinity rules, do not use the field for the negative affinity type. As the affinity type is switched from positive to negative and vice versa, the node selection is inverted to make the (lossy) conversion easier. The column widths are changed to minimize movement while switching between the affinity types. The inversion is not done if the selection is empty, as preferring all nodes is rather uselessly verbose and avoiding all nodes is disallowed as this rule would not satisfiable. Signed-off-by: Daniel Kral <[email protected]> --- changes since v1: - new www/manager6/ha/NodePrioritySelector.js | 65 ++++++++++++++++++- www/manager6/ha/rules/NodeAffinityRuleEdit.js | 25 +++++++ www/manager6/ha/rules/NodeAffinityRules.js | 5 ++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/www/manager6/ha/NodePrioritySelector.js b/www/manager6/ha/NodePrioritySelector.js index ec6ac02a..b58b0ada 100644 --- a/www/manager6/ha/NodePrioritySelector.js +++ b/www/manager6/ha/NodePrioritySelector.js @@ -10,6 +10,16 @@ Ext.define('PVE.forms.NodePrioritySelector', { selectAll: false, isFormField: true, + config: { + useNodePriority: null, + }, + + publishes: ['useNodePriority'], + + viewModel: { + showNodePriority: null, + }, + store: { autoLoad: true, fields: ['node', 'cpu', 'mem', 'priority'], @@ -28,7 +38,7 @@ Ext.define('PVE.forms.NodePrioritySelector', { columns: [ { header: gettext('Node'), - flex: 1, + width: 150, dataIndex: 'node', }, { @@ -42,7 +52,7 @@ Ext.define('PVE.forms.NodePrioritySelector', { header: gettext('CPU usage'), renderer: Proxmox.Utils.render_cpu, sortable: true, - width: 150, + flex: 1, dataIndex: 'cpu', }, { @@ -56,6 +66,14 @@ Ext.define('PVE.forms.NodePrioritySelector', { minValue: 0, maxValue: 1000, isFormField: false, + bind: { + hidden: '{!showNodePriority}', + disabled: '{!showNodePriority}', + }, + }, + bind: { + hidden: '{!showNodePriority}', + disabled: '{!showNodePriority}', }, }, ], @@ -74,6 +92,39 @@ Ext.define('PVE.forms.NodePrioritySelector', { }, }, + invertCheckboxSelection: function () { + let me = this; + + let sm = me.getSelectionModel(); + + let allNodeModels = new Set(sm.getStore().getData().items ?? []); + let selectedNodeModels = new Set(sm.getSelection() ?? []); + + if (!allNodeModels.size || !selectedNodeModels.size) { + return; + } + + sm.deselectAll(); + sm.select([...allNodeModels.difference(selectedNodeModels)]); + }, + + applyUseNodePriority: function (newValue) { + let me = this; + + let oldValue = me.getViewModel().get('showNodePriority'); + + if (newValue !== oldValue) { + me.getViewModel().set('showNodePriority', newValue); + + // Prevent inverting the selection during component initialization + if (oldValue !== null) { + me.invertCheckboxSelection(); + } + } + + return newValue; + }, + getSubmitData: function () { let me = this; let res = {}; @@ -91,7 +142,15 @@ Ext.define('PVE.forms.NodePrioritySelector', { let sm = me.getSelectionModel(); let selectedNodeModels = sm.getSelection() ?? []; let nodes = selectedNodeModels - .map(({ data }) => data.node + (data.priority ? `:${data.priority}` : '')) + .map(({ data }) => { + let nodeEntry = data.node; + + if (me.useNodePriority && data.priority) { + nodeEntry += `:${data.priority}`; + } + + return nodeEntry; + }) .join(','); return nodes; diff --git a/www/manager6/ha/rules/NodeAffinityRuleEdit.js b/www/manager6/ha/rules/NodeAffinityRuleEdit.js index 77da18b1..aecaa276 100644 --- a/www/manager6/ha/rules/NodeAffinityRuleEdit.js +++ b/www/manager6/ha/rules/NodeAffinityRuleEdit.js @@ -1,6 +1,15 @@ Ext.define('PVE.ha.rules.NodeAffinityInputPanel', { extend: 'PVE.ha.RuleInputPanel', + viewModel: { + data: { + affinity: 'positive', + }, + formulas: { + isPositiveNodeAffinity: (get) => get('affinity') === 'positive', + }, + }, + initComponent: function () { let me = this; @@ -18,6 +27,19 @@ Ext.define('PVE.ha.rules.NodeAffinityInputPanel', { uncheckedValue: 0, defaultValue: 0, }, + { + xtype: 'proxmoxKVComboBox', + name: 'affinity', + fieldLabel: gettext('Affinity'), + allowBlank: false, + comboItems: [ + ['positive', gettext('Prefer Nodes')], + ['negative', gettext('Avoid Nodes')], + ], + bind: { + value: '{affinity}', + }, + }, ]; me.columnB = [ @@ -25,6 +47,9 @@ Ext.define('PVE.ha.rules.NodeAffinityInputPanel', { xtype: 'pveNodePrioritySelector', name: 'nodes', allowBlank: false, + bind: { + useNodePriority: '{isPositiveNodeAffinity}', + }, }, ]; diff --git a/www/manager6/ha/rules/NodeAffinityRules.js b/www/manager6/ha/rules/NodeAffinityRules.js index 6fc42799..089dece8 100644 --- a/www/manager6/ha/rules/NodeAffinityRules.js +++ b/www/manager6/ha/rules/NodeAffinityRules.js @@ -11,6 +11,11 @@ Ext.define('PVE.ha.NodeAffinityRulesView', { stateId: 'grid-ha-node-affinity-rules', columns: [ + { + header: gettext('Affinity'), + width: 75, + dataIndex: 'affinity', + }, { header: gettext('Strict'), width: 75, -- 2.47.3
