Make positively colocated services migrate to the same target node as the manually migrated service and prevent a service to be manually migrated to a node, which contains negatively colocated services.
The log information here is only redirected to the HA Manager node's syslog, so user-facing endpoints need to implement this logic as well to give users adequate feedback about the errors and side-effects. Signed-off-by: Daniel Kral <d.k...@proxmox.com> --- changes since v1: - NEW! src/PVE/HA/Manager.pm | 44 ++++++++++++++++++++++++++++-- src/PVE/HA/Rules/Colocation.pm | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/PVE/HA/Manager.pm b/src/PVE/HA/Manager.pm index a69898b..66e5710 100644 --- a/src/PVE/HA/Manager.pm +++ b/src/PVE/HA/Manager.pm @@ -12,7 +12,7 @@ use PVE::HA::NodeStatus; use PVE::HA::Rules; use PVE::HA::Rules::Location qw(get_location_preference); use PVE::HA::Rules::Colocation - qw(get_colocation_preference apply_positive_colocation_rules apply_negative_colocation_rules); + qw(get_colocated_services get_colocation_preference apply_positive_colocation_rules apply_negative_colocation_rules); use PVE::HA::Usage::Basic; use PVE::HA::Usage::Static; @@ -412,6 +412,45 @@ sub read_lrm_status { return ($results, $modes); } +sub execute_migration { + my ($self, $cmd, $task, $sid, $target) = @_; + + my ($haenv, $ss) = $self->@{qw(haenv ss)}; + + my ($together, $separate) = get_colocated_services($self->{rules}, $sid); + + for my $csid (sort keys %$separate) { + next if $ss->{$csid}->{node} && $ss->{$csid}->{node} ne $target; + next if $ss->{$csid}->{target} && $ss->{$csid}->{target} ne $target; + + $haenv->log( + 'err', + "crm command '$cmd' error - negatively colocated service '$csid' on '$target'", + ); + + return; # one negative colocation is enough to not execute migration + } + + $haenv->log('info', "got crm command: $cmd"); + $ss->{$sid}->{cmd} = [$task, $target]; + + my $services_to_migrate = []; + for my $csid (sort keys %$together) { + next if $ss->{$csid}->{node} && $ss->{$csid}->{node} eq $target; + next if $ss->{$csid}->{target} && $ss->{$csid}->{target} eq $target; + + push @$services_to_migrate, $csid; + } + + for my $csid (@$services_to_migrate) { + $haenv->log( + 'info', + "crm command '$cmd' - $task positively colocated service '$csid' to '$target'", + ); + $ss->{$csid}->{cmd} = [$task, $target]; + } +} + # read new crm commands and save them into crm master status sub update_crm_commands { my ($self) = @_; @@ -435,8 +474,7 @@ sub update_crm_commands { "ignore crm command - service already on target node: $cmd", ); } else { - $haenv->log('info', "got crm command: $cmd"); - $ss->{$sid}->{cmd} = [$task, $node]; + $self->execute_migration($cmd, $task, $sid, $node); } } } else { diff --git a/src/PVE/HA/Rules/Colocation.pm b/src/PVE/HA/Rules/Colocation.pm index 190478e..45d20d0 100644 --- a/src/PVE/HA/Rules/Colocation.pm +++ b/src/PVE/HA/Rules/Colocation.pm @@ -11,6 +11,7 @@ use base qw(Exporter); use base qw(PVE::HA::Rules); our @EXPORT_OK = qw( + get_colocated_services get_colocation_preference apply_positive_colocation_rules apply_negative_colocation_rules @@ -295,6 +296,55 @@ sub plugin_canonicalize { =cut +=head3 get_colocated_services($rules, $sid) + +Returns a list of two hash sets, where the first hash set contains the +positively colocated services for C<$sid>, while the second hash set contains +the negatively colocated services for C<$sid> according to the colocation rules +in C<$rules>. + +For example, if a service is in a negative colocation with C<'vm:101'> and in a +positive colocation with C<'ct:200'> and C<'ct:201'>, the returned value will be: + + { + together => { + 'vm:101' => 1 + }, + separate => { + 'ct:200' => 1, + 'ct:201' => 1 + } + } + +=cut + +sub get_colocated_services : prototype($$) { + my ($rules, $sid) = @_; + + my $together = {}; + my $separate = {}; + + PVE::HA::Rules::foreach_rule( + $rules, + sub { + my ($rule, $ruleid) = @_; + + my $affinity_set = $rule->{affinity} eq 'together' ? $together : $separate; + + for my $csid (sort keys %{ $rule->{services} }) { + $affinity_set->{$csid} = 1 if $csid ne $sid; + } + }, + { + sid => $sid, + type => 'colocation', + state => 'enabled', + }, + ); + + return ($together, $separate); +} + =head3 get_colocation_preference($rules, $sid, $online_node_usage) Returns a list of two hashes, where the first describes the positive colocation -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel