From: Daniel Kral <d.kral@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH ha-manager v2 01/12] rules: node affinity: add affinity property to node affinity rules
Date: Tue, 2 Jun 2026 12:01:05 +0200 [thread overview]
Message-ID: <20260602100226.180071-2-d.kral@proxmox.com> (raw)
In-Reply-To: <20260602100226.180071-1-d.kral@proxmox.com>
This is in preparation of the next patch, which adds negative node
affinity rules.
Signed-off-by: Daniel Kral <d.kral@proxmox.com>
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
---
changes since v1:
- none
src/PVE/HA/Groups.pm | 1 +
src/PVE/HA/Rules/NodeAffinity.pm | 9 +++++++++
src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg | 8 ++++----
.../defaults-for-node-affinity-rules.cfg.expect | 6 +++++-
.../inconsistent-node-resource-affinity-rules.cfg.expect | 3 +++
...inity-for-positive-resource-affinity-rules.cfg.expect | 4 ++++
...node-affinity-with-resource-affinity-rules.cfg.expect | 2 ++
...tiple-resource-refs-in-node-affinity-rules.cfg.expect | 3 +++
8 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/PVE/HA/Groups.pm b/src/PVE/HA/Groups.pm
index fef7eeb1..ecdfcbcd 100644
--- a/src/PVE/HA/Groups.pm
+++ b/src/PVE/HA/Groups.pm
@@ -147,6 +147,7 @@ sub migrate_groups_to_rules {
type => 'node-affinity',
resources => $resources,
nodes => $nodes,
+ affinity => 'positive',
strict => $groups->{ids}->{$group}->{restricted},
comment => $groups->{ids}->{$group}->{comment},
};
diff --git a/src/PVE/HA/Rules/NodeAffinity.pm b/src/PVE/HA/Rules/NodeAffinity.pm
index 3fa1fdb4..1f15ae2d 100644
--- a/src/PVE/HA/Rules/NodeAffinity.pm
+++ b/src/PVE/HA/Rules/NodeAffinity.pm
@@ -64,6 +64,14 @@ sub properties {
optional => 0,
},
),
+ affinity => {
+ description => "Describes whether the HA resources are supposed to"
+ . " be placed on the given nodes ('positive').",
+ type => 'string',
+ enum => ['positive'],
+ default => 'positive',
+ optional => 1,
+ },
strict => {
description => "Describes whether the node affinity rule is strict or non-strict.",
verbose_description => <<EODESC,
@@ -86,6 +94,7 @@ sub options {
return {
resources => { optional => 0 },
nodes => { optional => 0 },
+ affinity => { optional => 1 },
strict => { optional => 1 },
disable => { optional => 1 },
comment => { optional => 1 },
diff --git a/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
index c8b2f2dd..27658562 100644
--- a/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
+++ b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
@@ -1,21 +1,21 @@
-# Case 1: Node Affinity rules are enabled and loose by default, so set it so if it isn't yet.
+# Case 1: Node Affinity rules are enabled, positive and loose by default, so set it so if it isn't yet.
node-affinity: node-affinity-defaults
resources vm:101
nodes node1
-# Case 2: Node Affinity rule is disabled, it shouldn't be enabled afterwards.
+# Case 2: Positive Node Affinity rule is disabled, it shouldn't be enabled afterwards.
node-affinity: node-affinity-disabled
resources vm:102
nodes node2
disable
-# Case 3: Node Affinity rule is disabled with explicit 1 set, it shouldn't be enabled afterwards.
+# Case 3: Positive Node Affinity rule is disabled with explicit 1 set, it shouldn't be enabled afterwards.
node-affinity: node-affinity-disabled-explicit
resources vm:103
nodes node2
disable 1
-# Case 4: Node Affinity rule is set to strict, so it shouldn't be loose afterwards.
+# Case 4: Positive Node Affinity rule is set to strict, so it shouldn't be loose afterwards.
node-affinity: node-affinity-strict
resources vm:104
nodes node3
diff --git a/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect
index 35d061bd..0d6e5605 100644
--- a/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect
+++ b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect
@@ -1,9 +1,10 @@
--- Log ---
--- Config ---
{
- "digest" : "c96c9de143221a82e44efa8bb4814b8248a8ea11",
+ "digest" : "fcad82def12abc4422061b79cfd0399967053d93",
"ids" : {
"node-affinity-defaults" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -15,6 +16,7 @@
"type" : "node-affinity"
},
"node-affinity-disabled" : {
+ "affinity" : "positive",
"disable" : 1,
"nodes" : {
"node2" : {
@@ -27,6 +29,7 @@
"type" : "node-affinity"
},
"node-affinity-disabled-explicit" : {
+ "affinity" : "positive",
"disable" : 1,
"nodes" : {
"node2" : {
@@ -39,6 +42,7 @@
"type" : "node-affinity"
},
"node-affinity-strict" : {
+ "affinity" : "positive",
"nodes" : {
"node3" : {
"priority" : 0
diff --git a/src/test/rules_cfgs/inconsistent-node-resource-affinity-rules.cfg.expect b/src/test/rules_cfgs/inconsistent-node-resource-affinity-rules.cfg.expect
index 4317292b..42dbc004 100644
--- a/src/test/rules_cfgs/inconsistent-node-resource-affinity-rules.cfg.expect
+++ b/src/test/rules_cfgs/inconsistent-node-resource-affinity-rules.cfg.expect
@@ -22,6 +22,7 @@ Drop rule 'vm503-must-be-on-node2', because at least one resource is in a positi
"type" : "resource-affinity"
},
"vm101-vm102-must-be-on-node1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -35,6 +36,7 @@ Drop rule 'vm503-must-be-on-node2', because at least one resource is in a positi
"type" : "node-affinity"
},
"vm201-must-be-on-node1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -55,6 +57,7 @@ Drop rule 'vm503-must-be-on-node2', because at least one resource is in a positi
"type" : "resource-affinity"
},
"vm202-must-be-on-node2" : {
+ "affinity" : "positive",
"nodes" : {
"node2" : {
"priority" : 0
diff --git a/src/test/rules_cfgs/infer-node-affinity-for-positive-resource-affinity-rules.cfg.expect b/src/test/rules_cfgs/infer-node-affinity-for-positive-resource-affinity-rules.cfg.expect
index ed339777..db505420 100644
--- a/src/test/rules_cfgs/infer-node-affinity-for-positive-resource-affinity-rules.cfg.expect
+++ b/src/test/rules_cfgs/infer-node-affinity-for-positive-resource-affinity-rules.cfg.expect
@@ -4,6 +4,7 @@
"digest" : "32ae135ef2f8bd84cd12c18af6910dce9d6bc9fa",
"ids" : {
"do-not-infer-negative1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -19,6 +20,7 @@
"type" : "node-affinity"
},
"do-not-infer-negative2" : {
+ "affinity" : "positive",
"nodes" : {
"node3" : {
"priority" : 0
@@ -47,6 +49,7 @@
"type" : "resource-affinity"
},
"infer-multi-resources1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -76,6 +79,7 @@
"type" : "resource-affinity"
},
"infer-single-resource1" : {
+ "affinity" : "positive",
"nodes" : {
"node3" : {
"priority" : 0
diff --git a/src/test/rules_cfgs/multi-priority-node-affinity-with-resource-affinity-rules.cfg.expect b/src/test/rules_cfgs/multi-priority-node-affinity-with-resource-affinity-rules.cfg.expect
index 68a2b75f..cc6595ac 100644
--- a/src/test/rules_cfgs/multi-priority-node-affinity-with-resource-affinity-rules.cfg.expect
+++ b/src/test/rules_cfgs/multi-priority-node-affinity-with-resource-affinity-rules.cfg.expect
@@ -8,6 +8,7 @@ Drop rule 'vm201-vm202-must-be-on-node1-or-node2', because resources are in a re
"digest" : "722a98914555f296af0916c980a9d6c780f5f072",
"ids" : {
"vm301-must-be-on-node1-with-prio-1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 1
@@ -28,6 +29,7 @@ Drop rule 'vm201-vm202-must-be-on-node1-or-node2', because resources are in a re
"type" : "resource-affinity"
},
"vm302-must-be-on-node2-with-prio-2" : {
+ "affinity" : "positive",
"nodes" : {
"node2" : {
"priority" : 2
diff --git a/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect b/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect
index 425de2b1..2776b56b 100644
--- a/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect
+++ b/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect
@@ -7,6 +7,7 @@ Drop rule 'same-resource3', because resource 'vm:201' is already used in another
"digest" : "5865d23b1a342e7f8cfa68bd0e1da556ca8d28a6",
"ids" : {
"no-same-resource1" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -24,6 +25,7 @@ Drop rule 'same-resource3', because resource 'vm:201' is already used in another
"type" : "node-affinity"
},
"no-same-resource2" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
@@ -40,6 +42,7 @@ Drop rule 'same-resource3', because resource 'vm:201' is already used in another
"type" : "node-affinity"
},
"no-same-resource3" : {
+ "affinity" : "positive",
"nodes" : {
"node1" : {
"priority" : 0
--
2.47.3
next prev parent reply other threads:[~2026-06-02 10:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-02 10:01 [PATCH-SERIES docs/ha-manager/manager v2 00/12] Negative Node Affinity Rules Daniel Kral
2026-06-02 10:01 ` Daniel Kral [this message]
2026-06-02 10:01 ` [PATCH ha-manager v2 02/12] rules: rename ambiguous argument nodes to cluster nodes Daniel Kral
2026-06-02 10:01 ` [PATCH ha-manager v2 03/12] rules: node affinity: implement negative node affinity rules Daniel Kral
2026-06-02 10:01 ` [PATCH manager v2 04/12] ui: ha: node affinity: handle non-existent nodes Daniel Kral
2026-06-02 10:01 ` [PATCH manager v2 05/12] ui: ha: node affinity: do update node selection all at once Daniel Kral
2026-06-02 10:01 ` [PATCH manager v2 06/12] ui: ha: node affinity: move node priority selector into separate component Daniel Kral
2026-06-02 10:01 ` [PATCH manager v2 07/12] ui: ha: node affinity: allow setting affinity for node affinity rules Daniel Kral
2026-06-02 10:01 ` [PATCH manager v2 08/12] ui: ha: node affinity: do not send default node affinity rule values Daniel Kral
2026-06-02 10:01 ` [PATCH docs v2 09/12] ha-manager: rules: use the correct article for terms starting with HA Daniel Kral
2026-06-02 10:01 ` [PATCH docs v2 10/12] ha-manager: rules: improve resource affinity rule short description Daniel Kral
2026-06-02 10:01 ` [PATCH docs v2 11/12] ha-manager: rules: adapt rule configuration examples Daniel Kral
2026-06-02 10:01 ` [PATCH docs v2 12/12] ha-manager: rules: add negative node affinity rule descriptions Daniel Kral
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260602100226.180071-2-d.kral@proxmox.com \
--to=d.kral@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox