all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Daniel Kral <d.kral@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH ha-manager v4 12/19] test: add test cases for rules config
Date: Tue, 29 Jul 2025 20:00:52 +0200	[thread overview]
Message-ID: <20250729180107.428855-13-d.kral@proxmox.com> (raw)
In-Reply-To: <20250729180107.428855-1-d.kral@proxmox.com>

Add test cases to verify that the rule checkers correctly identify and
remove HA rules from the rules to make the rule set feasible. For now,
there only are HA Node Affinity rules, which verify:

- Node Affinity rules retrieve the correct optional default values
- Node Affinity rules, which specify the same HA resource more than
  once, are dropped from the rule set

Signed-off-by: Daniel Kral <d.kral@proxmox.com>
---
 .gitignore                                    |   1 +
 src/test/Makefile                             |   4 +-
 .../defaults-for-node-affinity-rules.cfg      |  22 ++++
 ...efaults-for-node-affinity-rules.cfg.expect |  60 +++++++++++
 ...e-resource-refs-in-node-affinity-rules.cfg |  31 ++++++
 ...rce-refs-in-node-affinity-rules.cfg.expect |  63 +++++++++++
 src/test/test_rules_config.pl                 | 100 ++++++++++++++++++
 7 files changed, 280 insertions(+), 1 deletion(-)
 create mode 100644 src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
 create mode 100644 src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg
 create mode 100644 src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect
 create mode 100755 src/test/test_rules_config.pl

diff --git a/.gitignore b/.gitignore
index c35280ee..35de63f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
 /src/test/test-*/status/*
 /src/test/fence_cfgs/*.cfg.commands
 /src/test/fence_cfgs/*.cfg.write
+/src/test/rules_cfgs/*.cfg.output
diff --git a/src/test/Makefile b/src/test/Makefile
index e54959fb..6da9e100 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -5,6 +5,7 @@ all:
 test:
 	@echo "-- start regression tests --"
 	./test_failover1.pl
+	./test_rules_config.pl
 	./ha-tester.pl
 	./test_fence_config.pl
 	@echo "-- end regression tests (success) --"
@@ -12,4 +13,5 @@ test:
 .PHONY: clean
 clean:
 	rm -rf *~ test-*/log  test-*/*~ test-*/status \
-	fence_cfgs/*.cfg.commands fence_cfgs/*.write
+	fence_cfgs/*.cfg.commands fence_cfgs/*.write \
+	rules_cfgs/*.cfg.output
diff --git a/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
new file mode 100644
index 00000000..c8b2f2dd
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg
@@ -0,0 +1,22 @@
+# Case 1: Node Affinity rules are enabled 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.
+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.
+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.
+node-affinity: node-affinity-strict
+	resources vm:104
+	nodes node3
+	strict 1
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
new file mode 100644
index 00000000..59a2c364
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-node-affinity-rules.cfg.expect
@@ -0,0 +1,60 @@
+--- Log ---
+--- Config ---
+$VAR1 = {
+          'digest' => 'c96c9de143221a82e44efa8bb4814b8248a8ea11',
+          'ids' => {
+                     'node-affinity-defaults' => {
+                                                   'nodes' => {
+                                                                'node1' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'resources' => {
+                                                                    'vm:101' => 1
+                                                                  },
+                                                   'type' => 'node-affinity'
+                                                 },
+                     'node-affinity-disabled' => {
+                                                   'disable' => 1,
+                                                   'nodes' => {
+                                                                'node2' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'resources' => {
+                                                                    'vm:102' => 1
+                                                                  },
+                                                   'type' => 'node-affinity'
+                                                 },
+                     'node-affinity-disabled-explicit' => {
+                                                            'disable' => 1,
+                                                            'nodes' => {
+                                                                         'node2' => {
+                                                                                      'priority' => 0
+                                                                                    }
+                                                                       },
+                                                            'resources' => {
+                                                                             'vm:103' => 1
+                                                                           },
+                                                            'type' => 'node-affinity'
+                                                          },
+                     'node-affinity-strict' => {
+                                                 'nodes' => {
+                                                              'node3' => {
+                                                                           'priority' => 0
+                                                                         }
+                                                            },
+                                                 'resources' => {
+                                                                  'vm:104' => 1
+                                                                },
+                                                 'strict' => 1,
+                                                 'type' => 'node-affinity'
+                                               }
+                   },
+          'order' => {
+                       'node-affinity-defaults' => 1,
+                       'node-affinity-disabled' => 2,
+                       'node-affinity-disabled-explicit' => 3,
+                       'node-affinity-strict' => 4
+                     }
+        };
diff --git a/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg b/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg
new file mode 100644
index 00000000..1e279e73
--- /dev/null
+++ b/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg
@@ -0,0 +1,31 @@
+# Case 1: Do not remove two Node Affinity rules, which do not share resources.
+node-affinity: no-same-resource1
+	resources vm:101,vm:102,vm:103
+	nodes node1,node2:2
+	strict 0
+
+node-affinity: no-same-resource2
+	resources vm:104,vm:105
+	nodes node1,node2:2
+	strict 0
+
+node-affinity: no-same-resource3
+	resources vm:106
+	nodes node1,node2:2
+	strict 1
+
+# Case 2: Remove Node Affinity rules, which share the same resource between them.
+node-affinity: same-resource1
+	resources vm:201
+	nodes node1,node2:2
+	strict 0
+
+node-affinity: same-resource2
+	resources vm:201,vm:202
+	nodes node3
+	strict 1
+
+node-affinity: same-resource3
+	resources vm:201,vm:203,vm:204
+	nodes node1:2,node3:3
+	strict 0
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
new file mode 100644
index 00000000..3fd0c9ca
--- /dev/null
+++ b/src/test/rules_cfgs/multiple-resource-refs-in-node-affinity-rules.cfg.expect
@@ -0,0 +1,63 @@
+--- Log ---
+Drop rule 'same-resource1', because resource 'vm:201' is already used in another node affinity rule.
+Drop rule 'same-resource2', because resource 'vm:201' is already used in another node affinity rule.
+Drop rule 'same-resource3', because resource 'vm:201' is already used in another node affinity rule.
+--- Config ---
+$VAR1 = {
+          'digest' => '5865d23b1a342e7f8cfa68bd0e1da556ca8d28a6',
+          'ids' => {
+                     'no-same-resource1' => {
+                                              'nodes' => {
+                                                           'node1' => {
+                                                                        'priority' => 0
+                                                                      },
+                                                           'node2' => {
+                                                                        'priority' => 2
+                                                                      }
+                                                         },
+                                              'resources' => {
+                                                               'vm:101' => 1,
+                                                               'vm:102' => 1,
+                                                               'vm:103' => 1
+                                                             },
+                                              'strict' => 0,
+                                              'type' => 'node-affinity'
+                                            },
+                     'no-same-resource2' => {
+                                              'nodes' => {
+                                                           'node1' => {
+                                                                        'priority' => 0
+                                                                      },
+                                                           'node2' => {
+                                                                        'priority' => 2
+                                                                      }
+                                                         },
+                                              'resources' => {
+                                                               'vm:104' => 1,
+                                                               'vm:105' => 1
+                                                             },
+                                              'strict' => 0,
+                                              'type' => 'node-affinity'
+                                            },
+                     'no-same-resource3' => {
+                                              'nodes' => {
+                                                           'node1' => {
+                                                                        'priority' => 0
+                                                                      },
+                                                           'node2' => {
+                                                                        'priority' => 2
+                                                                      }
+                                                         },
+                                              'resources' => {
+                                                               'vm:106' => 1
+                                                             },
+                                              'strict' => 1,
+                                              'type' => 'node-affinity'
+                                            }
+                   },
+          'order' => {
+                       'no-same-resource1' => 1,
+                       'no-same-resource2' => 2,
+                       'no-same-resource3' => 3
+                     }
+        };
diff --git a/src/test/test_rules_config.pl b/src/test/test_rules_config.pl
new file mode 100755
index 00000000..824afed1
--- /dev/null
+++ b/src/test/test_rules_config.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+use lib qw(..);
+
+use Test::More;
+use Test::MockModule;
+
+use Data::Dumper;
+
+use PVE::HA::Rules;
+use PVE::HA::Rules::NodeAffinity;
+
+PVE::HA::Rules::NodeAffinity->register();
+
+PVE::HA::Rules->init(property_isolation => 1);
+
+my $opt_nodiff;
+
+if (!GetOptions("nodiff" => \$opt_nodiff)) {
+    print "usage: $0 [test.cfg] [--nodiff]\n";
+    exit -1;
+}
+
+sub _log {
+    my ($fh, $source, $message) = @_;
+
+    chomp $message;
+    $message = "[$source] $message" if $source;
+
+    print "$message\n";
+
+    $fh->print("$message\n");
+    $fh->flush();
+}
+
+sub check_cfg {
+    my ($cfg_fn, $outfile) = @_;
+
+    my $raw = PVE::Tools::file_get_contents($cfg_fn);
+
+    open(my $LOG, '>', "$outfile");
+    select($LOG);
+    $| = 1;
+
+    print "--- Log ---\n";
+    my $cfg = PVE::HA::Rules->parse_config($cfg_fn, $raw);
+    PVE::HA::Rules->set_rule_defaults($_) for values %{ $cfg->{ids} };
+    my $messages = PVE::HA::Rules->canonicalize($cfg);
+    print $_ for @$messages;
+    print "--- Config ---\n";
+    {
+        local $Data::Dumper::Sortkeys = 1;
+        print Dumper($cfg);
+    }
+
+    select(STDOUT);
+}
+
+sub run_test {
+    my ($cfg_fn) = @_;
+
+    print "* check: $cfg_fn\n";
+
+    my $outfile = "$cfg_fn.output";
+    my $expect = "$cfg_fn.expect";
+
+    eval { check_cfg($cfg_fn, $outfile); };
+    if (my $err = $@) {
+        die "Test '$cfg_fn' failed:\n$err\n";
+    }
+
+    return if $opt_nodiff;
+
+    my $res;
+
+    if (-f $expect) {
+        my $cmd = ['diff', '-u', $expect, $outfile];
+        $res = system(@$cmd);
+        die "test '$cfg_fn' failed\n" if $res != 0;
+    } else {
+        $res = system('cp', $outfile, $expect);
+        die "test '$cfg_fn' failed\n" if $res != 0;
+    }
+
+    print "* end rules test: $cfg_fn (success)\n\n";
+}
+
+# exec tests
+
+if (my $testcfg = shift) {
+    run_test($testcfg);
+} else {
+    for my $cfg (<rules_cfgs/*cfg>) {
+        run_test($cfg);
+    }
+}
-- 
2.47.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-07-29 18:01 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-29 18:00 [pve-devel] [PATCH docs/ha-manager/manager v4 00/25] HA Rules Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 01/19] tree-wide: make arguments for select_service_node explicit Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 02/19] manager: improve signature of select_service_node Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 03/19] introduce rules base plugin Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 04/19] rules: introduce node affinity rule plugin Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 05/19] config, env, hw: add rules read and parse methods Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 06/19] config: delete services from rules if services are deleted from config Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 07/19] manager: read and update rules config Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 08/19] test: ha tester: add test cases for future node affinity rules Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 09/19] resources: introduce failback property in ha resource config Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 10/19] manager: migrate ha groups to node affinity rules in-memory Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 11/19] manager: apply node affinity rules when selecting service nodes Daniel Kral
2025-07-29 18:00 ` Daniel Kral [this message]
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 13/19] api: introduce ha rules api endpoints Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 14/19] cli: expose ha rules api endpoints to ha-manager cli Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 15/19] sim: do not create default groups for test cases Daniel Kral
2025-07-30 10:01   ` Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 16/19] test: ha tester: migrate groups to service and rules config Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 17/19] test: ha tester: replace any reference to groups with node affinity rules Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 18/19] env: add property delete for update_service_config Daniel Kral
2025-07-29 18:00 ` [pve-devel] [PATCH ha-manager v4 19/19] manager: persistently migrate ha groups to ha rules Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH docs v4 1/2] ha: add documentation about ha rules and ha node affinity rules Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH docs v4 2/2] ha: crs: add effects of ha node affinity rule on the crs scheduler Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH manager v4 1/4] api: ha: add ha rules api endpoints Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH manager v4 2/4] ui: ha: remove ha groups from ha resource components Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH manager v4 3/4] ui: ha: show failback flag in resources status view Daniel Kral
2025-07-29 18:01 ` [pve-devel] [PATCH manager v4 4/4] ui: ha: replace ha groups with ha node affinity rules Daniel Kral
2025-07-30 17:29 ` [pve-devel] [PATCH docs/ha-manager/manager v4 00/25] HA Rules Michael Köppl

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=20250729180107.428855-13-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal