[pve-devel] [PATCH ha-manager 15/15] test: add test cases for rules config

Daniel Kral d.kral at proxmox.com
Tue Mar 25 16:12:54 CET 2025


Add test cases to verify the correct transformation of various types of
ill-defined colocation rules:

- Merging multiple, transitive positive colocation rules of the same
  strictness level
- Dropping colocation rules with not enough defined services
- Dropping colocation rules which have inner conflicts

Signed-off-by: Daniel Kral <d.kral at proxmox.com>
---
These aren't exhaustive yet since there's no tests in conjunction with
HA groups yet.

 .gitignore                                    |   1 +
 src/test/Makefile                             |   4 +-
 .../connected-positive-colocations.cfg        |  34 ++++++
 .../connected-positive-colocations.cfg.expect |  54 ++++++++++
 .../rules_cfgs/illdefined-colocations.cfg     |   9 ++
 .../illdefined-colocations.cfg.expect         |  12 +++
 .../inner-inconsistent-colocations.cfg        |  14 +++
 .../inner-inconsistent-colocations.cfg.expect |  13 +++
 src/test/test_rules_config.pl                 | 100 ++++++++++++++++++
 9 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 src/test/rules_cfgs/connected-positive-colocations.cfg
 create mode 100644 src/test/rules_cfgs/connected-positive-colocations.cfg.expect
 create mode 100644 src/test/rules_cfgs/illdefined-colocations.cfg
 create mode 100644 src/test/rules_cfgs/illdefined-colocations.cfg.expect
 create mode 100644 src/test/rules_cfgs/inner-inconsistent-colocations.cfg
 create mode 100644 src/test/rules_cfgs/inner-inconsistent-colocations.cfg.expect
 create mode 100755 src/test/test_rules_config.pl

diff --git a/.gitignore b/.gitignore
index c35280e..35de63f 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 e54959f..6da9e10 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/connected-positive-colocations.cfg b/src/test/rules_cfgs/connected-positive-colocations.cfg
new file mode 100644
index 0000000..8cd6e0c
--- /dev/null
+++ b/src/test/rules_cfgs/connected-positive-colocations.cfg
@@ -0,0 +1,34 @@
+colocation: positive1
+    services vm:101,vm:106,vm:108
+    affinity together
+    strict 0
+
+colocation: positive2
+    services vm:106,vm:109
+    affinity together
+    strict 0
+
+colocation: positive3
+    services vm:107,vm:105
+    affinity together
+    strict 0
+
+colocation: positive4
+    services vm:101,vm:102,vm:103
+    affinity together
+    strict 0
+
+colocation: positive5
+    services vm:101,vm:104
+    affinity together
+    strict 1
+
+colocation: positive6
+    services vm:105,vm:110
+    affinity together
+    strict 0
+
+colocation: positive7
+    services vm:108,vm:104,vm:109
+    affinity together
+    strict 1
diff --git a/src/test/rules_cfgs/connected-positive-colocations.cfg.expect b/src/test/rules_cfgs/connected-positive-colocations.cfg.expect
new file mode 100644
index 0000000..f20a87e
--- /dev/null
+++ b/src/test/rules_cfgs/connected-positive-colocations.cfg.expect
@@ -0,0 +1,54 @@
+--- Log ---
+Merge services of positive colocation rule 'positive2' into positive colocation rule 'positive1', because they share at least one service.
+Merge services of positive colocation rule 'positive4' into positive colocation rule 'positive1', because they share at least one service.
+Merge services of positive colocation rule 'positive6' into positive colocation rule 'positive3', because they share at least one service.
+Merge services of positive colocation rule 'positive7' into positive colocation rule 'positive5', because they share at least one service.
+--- Config ---
+$VAR1 = {
+          'digest' => '7781c41891832c7f955d835edcdc38fa6b673bea',
+          'ids' => {
+                     'positive1' => {
+                                      'affinity' => 'together',
+                                      'services' => {
+                                                      'vm:101' => 1,
+                                                      'vm:102' => 1,
+                                                      'vm:103' => 1,
+                                                      'vm:106' => 1,
+                                                      'vm:108' => 1,
+                                                      'vm:109' => 1
+                                                    },
+                                      'strict' => 0,
+                                      'type' => 'colocation'
+                                    },
+                     'positive3' => {
+                                      'affinity' => 'together',
+                                      'services' => {
+                                                      'vm:105' => 1,
+                                                      'vm:107' => 1,
+                                                      'vm:110' => 1
+                                                    },
+                                      'strict' => 0,
+                                      'type' => 'colocation'
+                                    },
+                     'positive5' => {
+                                      'affinity' => 'together',
+                                      'services' => {
+                                                      'vm:101' => 1,
+                                                      'vm:104' => 1,
+                                                      'vm:108' => 1,
+                                                      'vm:109' => 1
+                                                    },
+                                      'strict' => 1,
+                                      'type' => 'colocation'
+                                    }
+                   },
+          'order' => {
+                       'positive1' => 1,
+                       'positive2' => 2,
+                       'positive3' => 3,
+                       'positive4' => 4,
+                       'positive5' => 5,
+                       'positive6' => 6,
+                       'positive7' => 7
+                     }
+        };
diff --git a/src/test/rules_cfgs/illdefined-colocations.cfg b/src/test/rules_cfgs/illdefined-colocations.cfg
new file mode 100644
index 0000000..2a4bf9c
--- /dev/null
+++ b/src/test/rules_cfgs/illdefined-colocations.cfg
@@ -0,0 +1,9 @@
+colocation: lonely-service1
+    services vm:101
+    affinity together
+    strict 1
+
+colocation: lonely-service2
+    services vm:101
+    affinity separate
+    strict 1
diff --git a/src/test/rules_cfgs/illdefined-colocations.cfg.expect b/src/test/rules_cfgs/illdefined-colocations.cfg.expect
new file mode 100644
index 0000000..68ce44a
--- /dev/null
+++ b/src/test/rules_cfgs/illdefined-colocations.cfg.expect
@@ -0,0 +1,12 @@
+--- Log ---
+Drop colocation rule 'lonely-service1', because it does not have enough services defined.
+Drop colocation rule 'lonely-service2', because it does not have enough services defined.
+--- Config ---
+$VAR1 = {
+          'digest' => 'd174e745359cbc8c2e0f950ab5a4d202ffaf15e2',
+          'ids' => {},
+          'order' => {
+                       'lonely-service1' => 1,
+                       'lonely-service2' => 2
+                     }
+        };
diff --git a/src/test/rules_cfgs/inner-inconsistent-colocations.cfg b/src/test/rules_cfgs/inner-inconsistent-colocations.cfg
new file mode 100644
index 0000000..70ae352
--- /dev/null
+++ b/src/test/rules_cfgs/inner-inconsistent-colocations.cfg
@@ -0,0 +1,14 @@
+colocation: keep-apart1
+    services vm:102,vm:103
+    affinity separate
+    strict 1
+
+colocation: keep-apart2
+    services vm:102,vm:104,vm:106
+    affinity separate
+    strict 1
+
+colocation: stick-together1
+    services vm:101,vm:102,vm:103,vm:104,vm:106
+    affinity together
+    strict 1
diff --git a/src/test/rules_cfgs/inner-inconsistent-colocations.cfg.expect b/src/test/rules_cfgs/inner-inconsistent-colocations.cfg.expect
new file mode 100644
index 0000000..ea5b96b
--- /dev/null
+++ b/src/test/rules_cfgs/inner-inconsistent-colocations.cfg.expect
@@ -0,0 +1,13 @@
+--- Log ---
+Drop positive colocation rule 'stick-together1' and negative colocation rule 'keep-apart1', because they share two or more services.
+Drop positive colocation rule 'stick-together1' and negative colocation rule 'keep-apart2', because they share two or more services.
+--- Config ---
+$VAR1 = {
+          'digest' => '1e6a049065bec399e5982d24eb348465eec8520b',
+          'ids' => {},
+          'order' => {
+                       'keep-apart1' => 1,
+                       'keep-apart2' => 2,
+                       'stick-together1' => 3
+                     }
+        };
diff --git a/src/test/test_rules_config.pl b/src/test/test_rules_config.pl
new file mode 100755
index 0000000..0eb55c3
--- /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::Colocation;
+
+PVE::HA::Rules::Colocation->register();
+
+PVE::HA::Rules->init();
+
+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::checked_config($cfg, {}, {});
+    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.39.5





More information about the pve-devel mailing list