[pve-devel] [PATCH ha-manager 04/15] add rules section config base plugin

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


Add a rules section config base plugin to allow users to specify
different kinds of rules in a single configuration file.

The interface is designed to allow sub plugins to implement their own
{decode,encode}_value() methods and also offer a canonicalized version
of their rules with canonicalize(), i.e. with any inconsistencies
removed and ambiguities resolved. There is also a are_satisfiable()
method for anticipation of the verification of additions or changes to
the rules config via the API.

Signed-off-by: Daniel Kral <d.kral at proxmox.com>
---
 debian/pve-ha-manager.install |   1 +
 src/PVE/HA/Makefile           |   2 +-
 src/PVE/HA/Rules.pm           | 118 ++++++++++++++++++++++++++++++++++
 src/PVE/HA/Tools.pm           |   5 ++
 4 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 src/PVE/HA/Rules.pm

diff --git a/debian/pve-ha-manager.install b/debian/pve-ha-manager.install
index 0ffbd8d..9bbd375 100644
--- a/debian/pve-ha-manager.install
+++ b/debian/pve-ha-manager.install
@@ -32,6 +32,7 @@
 /usr/share/perl5/PVE/HA/Resources.pm
 /usr/share/perl5/PVE/HA/Resources/PVECT.pm
 /usr/share/perl5/PVE/HA/Resources/PVEVM.pm
+/usr/share/perl5/PVE/HA/Rules.pm
 /usr/share/perl5/PVE/HA/Tools.pm
 /usr/share/perl5/PVE/HA/Usage.pm
 /usr/share/perl5/PVE/HA/Usage/Basic.pm
diff --git a/src/PVE/HA/Makefile b/src/PVE/HA/Makefile
index 8c91b97..489cbc0 100644
--- a/src/PVE/HA/Makefile
+++ b/src/PVE/HA/Makefile
@@ -1,4 +1,4 @@
-SIM_SOURCES=CRM.pm Env.pm Groups.pm Resources.pm LRM.pm Manager.pm \
+SIM_SOURCES=CRM.pm Env.pm Groups.pm Rules.pm Resources.pm LRM.pm Manager.pm \
 	NodeStatus.pm Tools.pm FenceConfig.pm Fence.pm Usage.pm
 
 SOURCES=${SIM_SOURCES} Config.pm
diff --git a/src/PVE/HA/Rules.pm b/src/PVE/HA/Rules.pm
new file mode 100644
index 0000000..bff3375
--- /dev/null
+++ b/src/PVE/HA/Rules.pm
@@ -0,0 +1,118 @@
+package PVE::HA::Rules;
+
+use strict;
+use warnings;
+
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::SectionConfig;
+use PVE::HA::Tools;
+
+use base qw(PVE::SectionConfig);
+
+# TODO Add descriptions, completions, etc.
+my $defaultData = {
+    propertyList => {
+	type => { description => "Rule type." },
+	ruleid => get_standard_option('pve-ha-rule-id'),
+	comment => {
+	    type => 'string',
+	    maxLength => 4096,
+	    description => "Rule description.",
+	},
+    },
+};
+
+sub private {
+    return $defaultData;
+}
+
+sub options {
+    return {
+	type => { optional => 0 },
+	ruleid => { optional => 0 },
+	comment => { optional => 1 },
+    };
+};
+
+sub decode_value {
+    my ($class, $type, $key, $value) = @_;
+
+    if ($key eq 'comment') {
+	return PVE::Tools::decode_text($value);
+    }
+
+    my $plugin = __PACKAGE__->lookup($type);
+    return $plugin->decode_value($type, $key, $value);
+}
+
+sub encode_value {
+    my ($class, $type, $key, $value) = @_;
+
+    if ($key eq 'comment') {
+	return PVE::Tools::encode_text($value);
+    }
+
+    my $plugin = __PACKAGE__->lookup($type);
+    return $plugin->encode_value($type, $key, $value);
+}
+
+sub parse_section_header {
+    my ($class, $line) = @_;
+
+    if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
+	my ($type, $ruleid) = (lc($1), $2);
+	my $errmsg = undef; # set if you want to skip whole section
+	eval { PVE::JSONSchema::pve_verify_configid($ruleid); };
+	$errmsg = $@ if $@;
+	my $config = {}; # to return additional attributes
+	return ($type, $ruleid, $errmsg, $config);
+    }
+    return undef;
+}
+
+sub foreach_service_rule {
+    my ($rules, $func, $opts) = @_;
+
+    my $sid = $opts->{sid};
+    my $type = $opts->{type};
+
+    my @ruleids = sort {
+	$rules->{order}->{$a} <=> $rules->{order}->{$b}
+    } keys %{$rules->{ids}};
+
+    for my $ruleid (@ruleids) {
+	my $rule = $rules->{ids}->{$ruleid};
+
+	next if !$rule; # invalid rules are kept undef in section config, delete them
+	next if $type && $rule->{type} ne $type;
+	next if $sid && !defined($rule->{services}->{$sid});
+
+	$func->($rule, $ruleid);
+    }
+}
+
+sub canonicalize {
+    my ($class, $rules, $groups, $services) = @_;
+
+    die "implement in subclass";
+}
+
+sub are_satisfiable {
+    my ($class, $rules, $groups, $services) = @_;
+
+    die "implement in subclass";
+}
+
+sub checked_config {
+    my ($rules, $groups, $services) = @_;
+
+    my $types = __PACKAGE__->lookup_types();
+
+    for my $type (@$types) {
+	my $plugin = __PACKAGE__->lookup($type);
+
+	$plugin->canonicalize($rules, $groups, $services);
+    }
+}
+
+1;
diff --git a/src/PVE/HA/Tools.pm b/src/PVE/HA/Tools.pm
index fc3282c..35107c9 100644
--- a/src/PVE/HA/Tools.pm
+++ b/src/PVE/HA/Tools.pm
@@ -92,6 +92,11 @@ PVE::JSONSchema::register_standard_option('pve-ha-group-id', {
     type => 'string', format => 'pve-configid',
 });
 
+PVE::JSONSchema::register_standard_option('pve-ha-rule-id', {
+    description => "The HA rule identifier.",
+    type => 'string', format => 'pve-configid',
+});
+
 sub read_json_from_file {
     my ($filename, $default) = @_;
 
-- 
2.39.5





More information about the pve-devel mailing list