From: Daniel Kral <d.kral@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC PATCH ha-manager 1/2] rules: node affinity: add affinity property to node affinity rules
Date: Fri, 19 Dec 2025 14:35:46 +0100 [thread overview]
Message-ID: <20251219133643.295514-2-d.kral@proxmox.com> (raw)
In-Reply-To: <20251219133643.295514-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>
---
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 d2802eee..b23e3414 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
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-12-19 13:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-19 13:35 [pve-devel] [RFC PATCH-SERIES ha-manager 0/2] Negative Node Affinity Rules Daniel Kral
2025-12-19 13:35 ` Daniel Kral [this message]
2025-12-19 13:35 ` [pve-devel] [RFC PATCH ha-manager 2/2] rules: node affinity: implement negative node affinity rules 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=20251219133643.295514-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