[pve-devel] [PATCH ha-manager v5 11/23] manager: apply node affinity rules when selecting service nodes
Daniel Kral
d.kral at proxmox.com
Thu Jul 31 10:21:24 CEST 2025
On Thu Jul 31, 2025 at 7:26 AM CEST, Thomas Lamprecht wrote:
> Am 30.07.25 um 20:01 schrieb Daniel Kral:
>> @@ -210,4 +215,82 @@ __PACKAGE__->register_check(
>> },
>> );
>>
>> +=head1 NODE AFFINITY RULE HELPERS
>> +
>> +=cut
>> +
>> +my $get_resource_node_affinity_rule = sub {
>> + my ($rules, $sid) = @_;
>> +
>> + # with the current restriction a resource can only be in one node affinity rule
>> + my $node_affinity_rule;
>> + PVE::HA::Rules::foreach_rule(
>> + $rules,
>> + sub {
>> + my ($rule) = @_;
>> +
>> + $node_affinity_rule = dclone($rule) if !$node_affinity_rule;
>> + },
>> + {
>> + sid => $sid,
>> + type => 'node-affinity',
>> + exclude_disabled_rules => 1,
>> + },
>
> meh. this a bit hard to read, passing the opts as hash value not hash
> ref could be nicer?
>
> foreach_rule : prototype($$;%) {
> my ($rules, $func, %opts) = @_;
>
> # here avoid the useless intermediate variables
>
> ....-+
> }
>
>
> PVE::HA::Rules::foreach_rule(
> $rules,
> sub {
> ...
> },
> sid => $sid,
> type => 'node-affinity',
> ....
> }
ACK, that look much cleaner, I'll send it as a follow-up patch (after
the more important follow-ups of course).
>
>> + );
>> +
>> + return $node_affinity_rule;
>> +};
>> +
>> +=head3 get_node_affinity($rules, $sid, $online_node_usage)
>> +
>> +Returns a list of two hashes representing the node affinity of C<$sid>
>> +according to the node affinity rules in C<$rules> and the available nodes in
>> +C<$online_node_usage>.
>> +
>> +The first hash is a hash set of available nodes, i.e. nodes where the
>> +resource C<$sid> is allowed to be assigned to, and the second hash is a hash set
>> +of preferred nodes, i.e. nodes where the resource C<$sid> should be assigned to.
>> +
>> +If there are no available nodes at all, returns C<undef>.
>> +
>> +=cut
>> +
>> +sub get_node_affinity : prototype($$$) {
>> + my ($rules, $sid, $online_node_usage) = @_;
>> +
>> + my $node_affinity_rule = $get_resource_node_affinity_rule->($rules, $sid);
>> +
>> + # default to a node affinity rule with all available nodes
>> + if (!$node_affinity_rule) {
>
> This seems not so nice, uses auto-vifivication to get the hash going again,
> that's almost always a code smell, let's rather explicitly assign and check,
> e.g. something like:
>
> if (!defined($node_affinity_rule) || !scalar($node_affinity_rule->%*)) {
> $node_affinity_rule //= {};
>
ACK, will also send a follow-up patch cleaning that up!
>
>
>> + for my $node ($online_node_usage->list_nodes()) {
>> + $node_affinity_rule->{nodes}->{$node} = { priority => 0 };
>> + }
>> + }
>> +
>> + # add remaining nodes with low priority for non-strict node affinity rules
>> + if (!$node_affinity_rule->{strict}) {
>> + for my $node ($online_node_usage->list_nodes()) {
>> + next if defined($node_affinity_rule->{nodes}->{$node});
>> +
>> + $node_affinity_rule->{nodes}->{$node} = { priority => -1 };
>> + }
>> + }
>> +
>> + my $allowed_nodes = {};
>> + my $prioritized_nodes = {};
>> +
>> + while (my ($node, $props) = each %{ $node_affinity_rule->{nodes} }) {
>> + next if !$online_node_usage->contains_node($node); # node is offline
>> +
>> + $allowed_nodes->{$node} = 1;
>> + $prioritized_nodes->{ $props->{priority} }->{$node} = 1;
>
> style nit: please avoid using hash for hash key access.
ACK, here too.
>
>> + }
>> +
>> + my $preferred_nodes = {};
>> + my $highest_priority = (sort { $b <=> $a } keys %$prioritized_nodes)[0];
>> + $preferred_nodes = $prioritized_nodes->{$highest_priority} if defined($highest_priority);
>> +
>> + return ($allowed_nodes, $preferred_nodes);
>> +}
>> +
>> 1;
More information about the pve-devel
mailing list