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 v2 20/26] test: add test cases for rules config
Date: Fri, 20 Jun 2025 16:31:32 +0200	[thread overview]
Message-ID: <20250620143148.218469-25-d.kral@proxmox.com> (raw)
In-Reply-To: <20250620143148.218469-1-d.kral@proxmox.com>

Add test cases to verify that the rule checkers correctly identify and
remove ill-defined location and colocation rules from the rules:

- Set defaults when reading location and colocation rules
- Dropping location rules, which specify the same service multiple times
- Dropping colocation rules, which state that two or more services are
  to be kept together and separate at the same time
- Dropping colocation rules, which cannot be fullfilled because of the
  constraints of the location rules of their services
- Dropping colocation rules, which specify less than two services

Signed-off-by: Daniel Kral <d.kral@proxmox.com>
---
changes since v1:
    - dropped connected positive colocation rules check
    - rename illdefined-colocations to ineffective-colocation-rules
    - rename inner-inconsistent-colocations to
      inconsistent-colocation-rules
    - introduced rule set tests for default values
    - introduced rule set tests for duplicate service reference in
      location rules
    - introduced rule set tests for multi-priority location with
      colocation rules


 .gitignore                                    |   1 +
 src/test/Makefile                             |   4 +-
 .../defaults-for-colocation-rules.cfg         |  10 ++
 .../defaults-for-colocation-rules.cfg.expect  |  29 ++++
 .../defaults-for-location-rules.cfg           |  16 +++
 .../defaults-for-location-rules.cfg.expect    |  49 +++++++
 .../duplicate-service-in-location-rules.cfg   |  31 +++++
 ...icate-service-in-location-rules.cfg.expect |  66 +++++++++
 .../inconsistent-colocation-rules.cfg         |  11 ++
 .../inconsistent-colocation-rules.cfg.expect  |  11 ++
 ...inconsistent-location-colocation-rules.cfg |  54 ++++++++
 ...stent-location-colocation-rules.cfg.expect | 130 ++++++++++++++++++
 .../ineffective-colocation-rules.cfg          |   7 +
 .../ineffective-colocation-rules.cfg.expect   |   9 ++
 ...ulti-priority-location-with-colocation.cfg |  19 +++
 ...iority-location-with-colocation.cfg.expect |  47 +++++++
 src/test/test_rules_config.pl                 | 102 ++++++++++++++
 17 files changed, 595 insertions(+), 1 deletion(-)
 create mode 100644 src/test/rules_cfgs/defaults-for-colocation-rules.cfg
 create mode 100644 src/test/rules_cfgs/defaults-for-colocation-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/defaults-for-location-rules.cfg
 create mode 100644 src/test/rules_cfgs/defaults-for-location-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/duplicate-service-in-location-rules.cfg
 create mode 100644 src/test/rules_cfgs/duplicate-service-in-location-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/inconsistent-colocation-rules.cfg
 create mode 100644 src/test/rules_cfgs/inconsistent-colocation-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg
 create mode 100644 src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/ineffective-colocation-rules.cfg
 create mode 100644 src/test/rules_cfgs/ineffective-colocation-rules.cfg.expect
 create mode 100644 src/test/rules_cfgs/multi-priority-location-with-colocation.cfg
 create mode 100644 src/test/rules_cfgs/multi-priority-location-with-colocation.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/defaults-for-colocation-rules.cfg b/src/test/rules_cfgs/defaults-for-colocation-rules.cfg
new file mode 100644
index 0000000..8e68030
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-colocation-rules.cfg
@@ -0,0 +1,10 @@
+# Case 1: Colocation rules are enabled by default, so set it so if it isn't yet.
+colocation: colocation-defaults
+	services vm:101,vm:102
+	affinity separate
+
+# Case 2: Colocation rule is disabled, it shouldn't be enabled afterwards.
+colocation: colocation-disabled
+	services vm:201,vm:202
+	affinity separate
+	state disabled
diff --git a/src/test/rules_cfgs/defaults-for-colocation-rules.cfg.expect b/src/test/rules_cfgs/defaults-for-colocation-rules.cfg.expect
new file mode 100644
index 0000000..faafec8
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-colocation-rules.cfg.expect
@@ -0,0 +1,29 @@
+--- Log ---
+--- Config ---
+$VAR1 = {
+          'digest' => '692081df1aaf03092f67cd415f5c66222b1d55e2',
+          'ids' => {
+                     'colocation-defaults' => {
+                                                'affinity' => 'separate',
+                                                'services' => {
+                                                                'vm:101' => 1,
+                                                                'vm:102' => 1
+                                                              },
+                                                'state' => 'enabled',
+                                                'type' => 'colocation'
+                                              },
+                     'colocation-disabled' => {
+                                                'affinity' => 'separate',
+                                                'services' => {
+                                                                'vm:201' => 1,
+                                                                'vm:202' => 1
+                                                              },
+                                                'state' => 'disabled',
+                                                'type' => 'colocation'
+                                              }
+                   },
+          'order' => {
+                       'colocation-defaults' => 1,
+                       'colocation-disabled' => 2
+                     }
+        };
diff --git a/src/test/rules_cfgs/defaults-for-location-rules.cfg b/src/test/rules_cfgs/defaults-for-location-rules.cfg
new file mode 100644
index 0000000..728558d
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-location-rules.cfg
@@ -0,0 +1,16 @@
+# Case 1: Location rules are enabled and loose by default, so set it so if it isn't yet.
+location: location-defaults
+	services vm:101
+	nodes node1
+
+# Case 2: Location rule is disabled, it shouldn't be enabled afterwards.
+location: location-disabled
+	services vm:102
+	nodes node2
+	state disabled
+
+# Case 3: Location rule is set to strict, so it shouldn't be loose afterwards.
+location: location-strict
+	services vm:103
+	nodes node3
+	strict 1
diff --git a/src/test/rules_cfgs/defaults-for-location-rules.cfg.expect b/src/test/rules_cfgs/defaults-for-location-rules.cfg.expect
new file mode 100644
index 0000000..d534deb
--- /dev/null
+++ b/src/test/rules_cfgs/defaults-for-location-rules.cfg.expect
@@ -0,0 +1,49 @@
+--- Log ---
+--- Config ---
+$VAR1 = {
+          'digest' => '27c1704d1a5497b314f8f5717b633184c1a1aacf',
+          'ids' => {
+                     'location-defaults' => {
+                                              'nodes' => {
+                                                           'node1' => {
+                                                                        'priority' => 0
+                                                                      }
+                                                         },
+                                              'services' => {
+                                                              'vm:101' => 1
+                                                            },
+                                              'state' => 'enabled',
+                                              'type' => 'location'
+                                            },
+                     'location-disabled' => {
+                                              'nodes' => {
+                                                           'node2' => {
+                                                                        'priority' => 0
+                                                                      }
+                                                         },
+                                              'services' => {
+                                                              'vm:102' => 1
+                                                            },
+                                              'state' => 'disabled',
+                                              'type' => 'location'
+                                            },
+                     'location-strict' => {
+                                            'nodes' => {
+                                                         'node3' => {
+                                                                      'priority' => 0
+                                                                    }
+                                                       },
+                                            'services' => {
+                                                            'vm:103' => 1
+                                                          },
+                                            'state' => 'enabled',
+                                            'strict' => 1,
+                                            'type' => 'location'
+                                          }
+                   },
+          'order' => {
+                       'location-defaults' => 1,
+                       'location-disabled' => 2,
+                       'location-strict' => 3
+                     }
+        };
diff --git a/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg b/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg
new file mode 100644
index 0000000..7409bd7
--- /dev/null
+++ b/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg
@@ -0,0 +1,31 @@
+# Case 1: Do not remove two location rules, which do not share services.
+location: no-same-service1
+	services vm:101,vm:102,vm:103
+	nodes node1,node2:2
+	strict 0
+
+location: no-same-service2
+	services vm:104,vm:105
+	nodes node1,node2:2
+	strict 0
+
+location: no-same-service3
+	services vm:106
+	nodes node1,node2:2
+	strict 1
+
+# Case 2: Remove location rules, which share the same service between them.
+location: same-service1
+	services vm:201
+	nodes node1,node2:2
+	strict 0
+
+location: same-service2
+	services vm:201,vm:202
+	nodes node3
+	strict 1
+
+location: same-service3
+	services vm:201,vm:203,vm:204
+	nodes node1:2,node3:3
+	strict 0
diff --git a/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg.expect b/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg.expect
new file mode 100644
index 0000000..39b95bd
--- /dev/null
+++ b/src/test/rules_cfgs/duplicate-service-in-location-rules.cfg.expect
@@ -0,0 +1,66 @@
+--- Log ---
+Drop rule 'same-service1', because service 'vm:201' is already used in another location rule.
+Drop rule 'same-service2', because service 'vm:201' is already used in another location rule.
+Drop rule 'same-service3', because service 'vm:201' is already used in another location rule.
+--- Config ---
+$VAR1 = {
+          'digest' => '07ee7a87159672339144fb9d1021b54905e09632',
+          'ids' => {
+                     'no-same-service1' => {
+                                             'nodes' => {
+                                                          'node1' => {
+                                                                       'priority' => 0
+                                                                     },
+                                                          'node2' => {
+                                                                       'priority' => 2
+                                                                     }
+                                                        },
+                                             'services' => {
+                                                             'vm:101' => 1,
+                                                             'vm:102' => 1,
+                                                             'vm:103' => 1
+                                                           },
+                                             'state' => 'enabled',
+                                             'strict' => 0,
+                                             'type' => 'location'
+                                           },
+                     'no-same-service2' => {
+                                             'nodes' => {
+                                                          'node1' => {
+                                                                       'priority' => 0
+                                                                     },
+                                                          'node2' => {
+                                                                       'priority' => 2
+                                                                     }
+                                                        },
+                                             'services' => {
+                                                             'vm:104' => 1,
+                                                             'vm:105' => 1
+                                                           },
+                                             'state' => 'enabled',
+                                             'strict' => 0,
+                                             'type' => 'location'
+                                           },
+                     'no-same-service3' => {
+                                             'nodes' => {
+                                                          'node1' => {
+                                                                       'priority' => 0
+                                                                     },
+                                                          'node2' => {
+                                                                       'priority' => 2
+                                                                     }
+                                                        },
+                                             'services' => {
+                                                             'vm:106' => 1
+                                                           },
+                                             'state' => 'enabled',
+                                             'strict' => 1,
+                                             'type' => 'location'
+                                           }
+                   },
+          'order' => {
+                       'no-same-service1' => 1,
+                       'no-same-service2' => 2,
+                       'no-same-service3' => 3
+                     }
+        };
diff --git a/src/test/rules_cfgs/inconsistent-colocation-rules.cfg b/src/test/rules_cfgs/inconsistent-colocation-rules.cfg
new file mode 100644
index 0000000..3199bfb
--- /dev/null
+++ b/src/test/rules_cfgs/inconsistent-colocation-rules.cfg
@@ -0,0 +1,11 @@
+colocation: keep-apart1
+	services vm:102,vm:103
+	affinity separate
+
+colocation: keep-apart2
+	services vm:102,vm:104,vm:106
+	affinity separate
+
+colocation: stick-together1
+	services vm:101,vm:102,vm:103,vm:104,vm:106
+	affinity together
diff --git a/src/test/rules_cfgs/inconsistent-colocation-rules.cfg.expect b/src/test/rules_cfgs/inconsistent-colocation-rules.cfg.expect
new file mode 100644
index 0000000..b1989a8
--- /dev/null
+++ b/src/test/rules_cfgs/inconsistent-colocation-rules.cfg.expect
@@ -0,0 +1,11 @@
+--- Log ---
+Drop rule 'keep-apart1', because rule shares two or more services with 'stick-together1'.
+Drop rule 'keep-apart2', because rule shares two or more services with 'stick-together1'.
+Drop rule 'stick-together1', because rule shares two or more services with 'keep-apart1'.
+Drop rule 'stick-together1', because rule shares two or more services with 'keep-apart2'.
+--- Config ---
+$VAR1 = {
+          'digest' => '469bc45c05ffbb123a277fc0fda48e0132fc9046',
+          'ids' => {},
+          'order' => {}
+        };
diff --git a/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg b/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg
new file mode 100644
index 0000000..ed6b82d
--- /dev/null
+++ b/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg
@@ -0,0 +1,54 @@
+# Case 1: Remove no positive colocation rule, where there is exactly one node to keep them together.
+location: vm101-vm102-must-be-on-node1
+	services vm:101,vm:102
+	nodes node1
+	strict 1
+
+colocation: vm101-vm102-must-be-kept-together
+	services vm:101,vm:102
+	affinity together
+
+# Case 2: Remove no negative colocation rule, where there are exactly enough nodes available to keep them apart.
+location: vm201-must-be-on-node1
+	services vm:201
+	nodes node1
+	strict 1
+
+location: vm202-must-be-on-node2
+	services vm:202
+	nodes node2
+	strict 1
+
+colocation: vm201-vm202-must-be-kept-separate
+	services vm:201,vm:202
+	affinity separate
+
+# Case 1: Remove the positive colocation rules, where two services are restricted to a different node.
+location: vm301-must-be-on-node1
+	services vm:301
+	nodes node1
+	strict 1
+
+location: vm301-must-be-on-node2
+	services vm:302
+	nodes node2
+	strict 1
+
+colocation: vm301-vm302-must-be-kept-together
+	services vm:301,vm:302
+	affinity together
+
+# Case 2: Remove the negative colocation rule, where two services are restricted to less nodes than needed to keep them apart.
+location: vm401-must-be-on-node1
+	services vm:401
+	nodes node1
+	strict 1
+
+location: vm402-must-be-on-node1
+	services vm:402
+	nodes node1
+	strict 1
+
+colocation: vm401-vm402-must-be-kept-separate
+	services vm:401,vm:402
+	affinity separate
diff --git a/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg.expect b/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg.expect
new file mode 100644
index 0000000..bed4668
--- /dev/null
+++ b/src/test/rules_cfgs/inconsistent-location-colocation-rules.cfg.expect
@@ -0,0 +1,130 @@
+--- Log ---
+Drop rule 'vm301-vm302-must-be-kept-together', because two or more services are restricted to different nodes.
+Drop rule 'vm401-vm402-must-be-kept-separate', because two or more services are restricted to less nodes than available to the services.
+--- Config ---
+$VAR1 = {
+          'digest' => '27e76e13c20a1d11c5cbcf14434bcd54655fdd40',
+          'ids' => {
+                     'vm101-vm102-must-be-kept-together' => {
+                                                              'affinity' => 'together',
+                                                              'services' => {
+                                                                              'vm:101' => 1,
+                                                                              'vm:102' => 1
+                                                                            },
+                                                              'state' => 'enabled',
+                                                              'type' => 'colocation'
+                                                            },
+                     'vm101-vm102-must-be-on-node1' => {
+                                                         'nodes' => {
+                                                                      'node1' => {
+                                                                                   'priority' => 0
+                                                                                 }
+                                                                    },
+                                                         'services' => {
+                                                                         'vm:101' => 1,
+                                                                         'vm:102' => 1
+                                                                       },
+                                                         'state' => 'enabled',
+                                                         'strict' => 1,
+                                                         'type' => 'location'
+                                                       },
+                     'vm201-must-be-on-node1' => {
+                                                   'nodes' => {
+                                                                'node1' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:201' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 },
+                     'vm201-vm202-must-be-kept-separate' => {
+                                                              'affinity' => 'separate',
+                                                              'services' => {
+                                                                              'vm:201' => 1,
+                                                                              'vm:202' => 1
+                                                                            },
+                                                              'state' => 'enabled',
+                                                              'type' => 'colocation'
+                                                            },
+                     'vm202-must-be-on-node2' => {
+                                                   'nodes' => {
+                                                                'node2' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:202' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 },
+                     'vm301-must-be-on-node1' => {
+                                                   'nodes' => {
+                                                                'node1' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:301' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 },
+                     'vm301-must-be-on-node2' => {
+                                                   'nodes' => {
+                                                                'node2' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:302' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 },
+                     'vm401-must-be-on-node1' => {
+                                                   'nodes' => {
+                                                                'node1' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:401' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 },
+                     'vm402-must-be-on-node1' => {
+                                                   'nodes' => {
+                                                                'node1' => {
+                                                                             'priority' => 0
+                                                                           }
+                                                              },
+                                                   'services' => {
+                                                                   'vm:402' => 1
+                                                                 },
+                                                   'state' => 'enabled',
+                                                   'strict' => 1,
+                                                   'type' => 'location'
+                                                 }
+                   },
+          'order' => {
+                       'vm101-vm102-must-be-kept-together' => 2,
+                       'vm101-vm102-must-be-on-node1' => 1,
+                       'vm201-must-be-on-node1' => 3,
+                       'vm201-vm202-must-be-kept-separate' => 5,
+                       'vm202-must-be-on-node2' => 4,
+                       'vm301-must-be-on-node1' => 6,
+                       'vm301-must-be-on-node2' => 7,
+                       'vm401-must-be-on-node1' => 9,
+                       'vm402-must-be-on-node1' => 10
+                     }
+        };
diff --git a/src/test/rules_cfgs/ineffective-colocation-rules.cfg b/src/test/rules_cfgs/ineffective-colocation-rules.cfg
new file mode 100644
index 0000000..4f2338e
--- /dev/null
+++ b/src/test/rules_cfgs/ineffective-colocation-rules.cfg
@@ -0,0 +1,7 @@
+colocation: lonely-service1
+	services vm:101
+	affinity together
+
+colocation: lonely-service2
+	services vm:101
+	affinity separate
diff --git a/src/test/rules_cfgs/ineffective-colocation-rules.cfg.expect b/src/test/rules_cfgs/ineffective-colocation-rules.cfg.expect
new file mode 100644
index 0000000..3741ba7
--- /dev/null
+++ b/src/test/rules_cfgs/ineffective-colocation-rules.cfg.expect
@@ -0,0 +1,9 @@
+--- Log ---
+Drop rule 'lonely-service1', because rule is ineffective as there are less than two services.
+Drop rule 'lonely-service2', because rule is ineffective as there are less than two services.
+--- Config ---
+$VAR1 = {
+          'digest' => '47bdd78898e4193aa113ab05b0fd7aaaeb08109d',
+          'ids' => {},
+          'order' => {}
+        };
diff --git a/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg b/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg
new file mode 100644
index 0000000..889fe47
--- /dev/null
+++ b/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg
@@ -0,0 +1,19 @@
+# Case 1: Remove colocation rules, where there is a loose location rule with multiple priority groups set for the nodes.
+location: vm101-vm102-should-be-on-node1-or-node2
+	services vm:101,vm:102
+	nodes node1:1,node2:2
+	strict 0
+
+colocation: vm101-vm102-must-be-kept-separate
+	services vm:101,vm:102
+	affinity separate
+
+# Case 2: Remove colocation rules, where there is a strict location rule with multiple priority groups set for the nodes.
+location: vm201-vm202-must-be-on-node1-or-node2
+	services vm:201,vm:202
+	nodes node1:1,node2:2
+	strict 1
+
+colocation: vm201-vm202-must-be-kept-together
+	services vm:201,vm:202
+	affinity together
diff --git a/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg.expect b/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg.expect
new file mode 100644
index 0000000..47c7af5
--- /dev/null
+++ b/src/test/rules_cfgs/multi-priority-location-with-colocation.cfg.expect
@@ -0,0 +1,47 @@
+--- Log ---
+Drop rule 'vm101-vm102-must-be-kept-separate', because services are in location rules with multiple priorities.
+Drop rule 'vm201-vm202-must-be-kept-together', because services are in location rules with multiple priorities.
+--- Config ---
+$VAR1 = {
+          'digest' => '30292457018bf1ae4fcf9bea92199233c877bf28',
+          'ids' => {
+                     'vm101-vm102-should-be-on-node1-or-node2' => {
+                                                                    'nodes' => {
+                                                                                 'node1' => {
+                                                                                              'priority' => 1
+                                                                                            },
+                                                                                 'node2' => {
+                                                                                              'priority' => 2
+                                                                                            }
+                                                                               },
+                                                                    'services' => {
+                                                                                    'vm:101' => 1,
+                                                                                    'vm:102' => 1
+                                                                                  },
+                                                                    'state' => 'enabled',
+                                                                    'strict' => 0,
+                                                                    'type' => 'location'
+                                                                  },
+                     'vm201-vm202-must-be-on-node1-or-node2' => {
+                                                                  'nodes' => {
+                                                                               'node1' => {
+                                                                                            'priority' => 1
+                                                                                          },
+                                                                               'node2' => {
+                                                                                            'priority' => 2
+                                                                                          }
+                                                                             },
+                                                                  'services' => {
+                                                                                  'vm:201' => 1,
+                                                                                  'vm:202' => 1
+                                                                                },
+                                                                  'state' => 'enabled',
+                                                                  'strict' => 1,
+                                                                  'type' => 'location'
+                                                                }
+                   },
+          'order' => {
+                       'vm101-vm102-should-be-on-node1-or-node2' => 1,
+                       'vm201-vm202-must-be-on-node1-or-node2' => 3
+                     }
+        };
diff --git a/src/test/test_rules_config.pl b/src/test/test_rules_config.pl
new file mode 100755
index 0000000..6e6b7de
--- /dev/null
+++ b/src/test/test_rules_config.pl
@@ -0,0 +1,102 @@
+#!/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::Location;
+use PVE::HA::Rules::Colocation;
+
+PVE::HA::Rules::Location->register();
+PVE::HA::Rules::Colocation->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.39.5



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


  parent reply	other threads:[~2025-06-20 14:36 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-20 14:31 [pve-devel] [RFC common/cluster/ha-manager/docs/manager v2 00/40] HA colocation rules Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH common v2 1/1] introduce HashTools module Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH cluster v2 1/3] cfs: add 'ha/rules.cfg' to observed files Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH cluster v2 2/3] datacenter config: make pve-ha-shutdown-policy optional Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH cluster v2 3/3] datacenter config: introduce feature flag for location rules Daniel Kral
2025-06-23 15:58   ` Thomas Lamprecht
2025-06-24  7:29     ` Daniel Kral
2025-06-24  7:51       ` Thomas Lamprecht
2025-06-24  8:19         ` Daniel Kral
2025-06-24  8:25           ` Thomas Lamprecht
2025-06-24  8:52             ` Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 01/26] tree-wide: make arguments for select_service_node explicit Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 02/26] manager: improve signature of select_service_node Daniel Kral
2025-06-23 16:21   ` Thomas Lamprecht
2025-06-24  8:06     ` Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 03/26] introduce rules base plugin Daniel Kral
2025-07-04 14:18   ` Michael Köppl
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 04/26] rules: introduce location rule plugin Daniel Kral
2025-06-20 16:17   ` Jillian Morgan
2025-06-20 16:30     ` Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 05/26] rules: introduce colocation " Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 06/26] rules: add global checks between location and colocation rules Daniel Kral
2025-07-01 11:02   ` Daniel Kral
2025-07-04 14:43   ` Michael Köppl
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 07/26] config, env, hw: add rules read and parse methods Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 08/26] manager: read and update rules config Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 09/26] test: ha tester: add test cases for future location rules Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 10/26] resources: introduce failback property in service config Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 11/26] manager: migrate ha groups to location rules in-memory Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 12/26] manager: apply location rules when selecting service nodes Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 13/26] usage: add information about a service's assigned nodes Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 14/26] manager: apply colocation rules when selecting service nodes Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 15/26] manager: handle migrations for colocated services Daniel Kral
2025-06-27  9:10   ` Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 16/26] sim: resources: add option to limit start and migrate tries to node Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 17/26] test: ha tester: add test cases for strict negative colocation rules Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 18/26] test: ha tester: add test cases for strict positive " Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 19/26] test: ha tester: add test cases in more complex scenarios Daniel Kral
2025-06-20 14:31 ` Daniel Kral [this message]
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 21/26] manager: handle negative colocations with too many services Daniel Kral
2025-07-01 12:11   ` Michael Köppl
2025-07-01 12:23     ` Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 22/26] config: prune services from rules if services are deleted from config Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 23/26] api: introduce ha rules api endpoints Daniel Kral
2025-07-04 14:16   ` Michael Köppl
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 24/26] cli: expose ha rules api endpoints to ha-manager cli Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 25/26] api: groups, services: assert use-location-rules feature flag Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH ha-manager v2 26/26] api: services: check for colocations for service motions Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH docs v2 1/5] ha: config: add section about ha rules Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH docs v2 2/5] update static files to include ha rules api endpoints Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH docs v2 3/5] update static files to include use-location-rules feature flag Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH docs v2 4/5] update static files to include ha resources failback flag Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH docs v2 5/5] update static files to include ha service motion return value schema Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH manager v2 1/5] api: ha: add ha rules api endpoints Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH manager v2 2/5] ui: add use-location-rules feature flag Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH manager v2 3/5] ui: ha: hide ha groups if use-location-rules is enabled Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH manager v2 4/5] ui: ha: adapt resources components " Daniel Kral
2025-06-20 14:31 ` [pve-devel] [PATCH manager v2 5/5] ui: ha: add ha rules components and menu entry Daniel Kral
2025-06-30 15:09   ` Michael Köppl
2025-07-01 14:38   ` Michael Köppl
2025-06-20 15:43 ` [pve-devel] [RFC common/cluster/ha-manager/docs/manager v2 00/40] HA colocation rules Daniel Kral
2025-06-20 17:11   ` Jillian Morgan
2025-06-20 17:45     ` DERUMIER, Alexandre via pve-devel
     [not found]     ` <476c41123dced9d560dfbf27640ef8705fd90f11.camel@groupe-cyllene.com>
2025-06-23 15:36       ` Thomas Lamprecht
2025-06-24  8:48         ` Daniel Kral
2025-06-27 12:23           ` Friedrich Weber
2025-06-27 12:41             ` Daniel Kral
2025-06-23  8:11 ` DERUMIER, Alexandre via pve-devel
     [not found] ` <bf973ec4e8c52a10535ed35ad64bf0ec8d1ad37d.camel@groupe-cyllene.com>
2025-06-23 15:28   ` Thomas Lamprecht
2025-06-23 23:21     ` DERUMIER, Alexandre via pve-devel

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=20250620143148.218469-25-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