[pve-devel] [RFC PATCH ha-manager 1/2] rules: node affinity: add affinity property to node affinity rules

Daniel Kral d.kral at proxmox.com
Fri Dec 19 14:35:46 CET 2025


This is in preparation of the next patch, which adds negative node
affinity rules.

Signed-off-by: Daniel Kral <d.kral at 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





More information about the pve-devel mailing list