]> git.proxmox.com Git - pve-ha-manager.git/blobdiff - src/PVE/HA/CRM.pm
CRM: refactor check if state transition to active is ok
[pve-ha-manager.git] / src / PVE / HA / CRM.pm
index 4052c919c366ba92f51e1211528601866539d84f..2d70570d52fef21b83d8902d5f65df8323f61682 100644 (file)
@@ -5,7 +5,6 @@ package PVE::HA::CRM;
 use strict;
 use warnings;
 
-use PVE::SafeSyslog;
 use PVE::Tools;
 use PVE::HA::Tools;
 
@@ -16,7 +15,7 @@ use PVE::HA::Manager;
 my $valid_states = {
     wait_for_quorum => "cluster is not quorate, waiting",
     master => "quorate, and we got the ha_manager lock",
-    lost_manager_lock => "we lost the ha_manager lock (watchgog active)",
+    lost_manager_lock => "we lost the ha_manager lock (watchdog active)",
     slave => "quorate, but we do not own the ha_manager lock",
 };
 
@@ -39,7 +38,7 @@ sub new {
 sub shutdown_request {
     my ($self) = @_;
 
-    syslog('info' , "server received shutdown request")
+    $self->{haenv}->log('info' , "server received shutdown request")
        if !$self->{shutdown_request};
 
     $self->{shutdown_request} = 1;
@@ -112,14 +111,32 @@ sub get_protected_ha_manager_lock {
     return 0;
 }
 
-sub check_pending_fencing {
-    my ($manager_status, $node) = @_;
+# checks quorum, for no active pending fence jobs and if services are configured
+sub can_get_active {
+    my ($self, $allow_no_service) = @_;
 
+    my $haenv = $self->{haenv};
+
+    return 0 if !$haenv->quorate();
+
+    my $manager_status = eval { $haenv->read_manager_status() };
+    if (my $err = $@) {
+       $haenv->log('err', "could not read manager status: $err");
+       return 0;
+    }
     my $ss = $manager_status->{service_status};
+    return 0 if PVE::HA::Tools::count_fenced_services($ss, $haenv->nodename());
 
-    return 1 if PVE::HA::Tools::count_fenced_services($ss, $node);
+    if (!$allow_no_service) {
+       my $conf = eval { $haenv->read_service_config() };
+       if (my $err = $@) {
+           $haenv->log('err', "could not read service config: $err");
+           return undef;
+       }
+       return 0 if !scalar(%{$conf});
+    }
 
-    return 0;
+    return 1;
 }
 
 sub do_one_iteration {
@@ -130,14 +147,11 @@ sub do_one_iteration {
     my $status = $self->get_local_status();
     my $state = $status->{state};
 
-    my $manager_status = $haenv->read_manager_status();
-    my $pending_fencing = check_pending_fencing($manager_status, $haenv->nodename());
-    
     # do state changes first 
 
     if ($state eq 'wait_for_quorum') {
 
-       if (!$pending_fencing && $haenv->quorate()) {
+       if ($self->can_get_active()) {
            if ($self->get_protected_ha_manager_lock()) {
                $self->set_local_status({ state => 'master' });
            } else {
@@ -147,7 +161,7 @@ sub do_one_iteration {
 
     } elsif ($state eq 'slave') {
 
-       if (!$pending_fencing && $haenv->quorate()) {
+       if ($self->can_get_active()) {
            if ($self->get_protected_ha_manager_lock()) {
                $self->set_local_status({ state => 'master' });
            }
@@ -157,7 +171,7 @@ sub do_one_iteration {
 
     } elsif ($state eq 'lost_manager_lock') {
 
-       if (!$pending_fencing && $haenv->quorate()) {
+       if ($self->can_get_active(1)) {
            if ($self->get_protected_ha_manager_lock()) {
                $self->set_local_status({ state => 'master' });
            }
@@ -204,6 +218,14 @@ sub do_one_iteration {
                    delete $self->{ha_manager_wd};
                }
 
+               # release the manager lock, so another CRM slave can get it
+               # and continue to work without waiting for the lock timeout
+               $haenv->log('info', "voluntary release CRM lock");
+               if (!$haenv->release_ha_manager_lock()) {
+                   $haenv->log('notice', "CRM lock release failed, let the" .
+                               " lock timeout");
+               }
+
                $shutdown = 1;
 
            } else {