]> git.proxmox.com Git - pve-ha-manager.git/blobdiff - src/PVE/HA/Sim/Env.pm
resource agents: fix relocate
[pve-ha-manager.git] / src / PVE / HA / Sim / Env.pm
index f37d8d285c311a45a6e08bb07a36078e1d009db2..d7b81225d449d71ea7f383dec2fbe8f0b6d6f103 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use POSIX qw(strftime EINTR);
 use Data::Dumper;
-use JSON; 
+use JSON;
 use IO::File;
 use Fcntl qw(:DEFAULT :flock);
 
@@ -16,7 +16,7 @@ sub new {
 
     die "missing nodename" if !$nodename;
     die "missing log_id" if !$log_id;
-    
+
     my $class = ref($this) || $this;
 
     my $self = bless {}, $class;
@@ -47,7 +47,7 @@ sub sim_get_lock {
 
     my $code = sub {
 
-       my $data = PVE::HA::Tools::read_json_from_file($filename, {});  
+       my $data = PVE::HA::Tools::read_json_from_file($filename, {});
 
        my $res;
 
@@ -58,7 +58,7 @@ sub sim_get_lock {
 
            if (my $d = $data->{$lock_name}) {
                my $tdiff = $ctime - $d->{time};
-           
+
                if ($tdiff > $self->{lock_timeout}) {
                    $res = 1;
                } elsif (($tdiff <= $self->{lock_timeout}) && ($d->{node} eq $nodename)) {
@@ -72,9 +72,9 @@ sub sim_get_lock {
        } else {
 
            if (my $d = $data->{$lock_name}) {
-           
+
                my $tdiff = $ctime - $d->{time};
-           
+
                if ($tdiff <= $self->{lock_timeout}) {
                    if ($d->{node} eq $nodename) {
                        $d->{time} = $ctime;
@@ -99,7 +99,7 @@ sub sim_get_lock {
            }
        }
 
-       PVE::HA::Tools::write_json_to_file($filename, $data); 
+       PVE::HA::Tools::write_json_to_file($filename, $data);
 
        return $res;
     };
@@ -109,10 +109,10 @@ sub sim_get_lock {
 
 sub read_manager_status {
     my ($self) = @_;
-    
+
     my $filename = "$self->{statusdir}/manager_status";
 
-    return PVE::HA::Tools::read_json_from_file($filename, {});  
+    return PVE::HA::Tools::read_json_from_file($filename, {});
 }
 
 sub write_manager_status {
@@ -120,15 +120,7 @@ sub write_manager_status {
 
     my $filename = "$self->{statusdir}/manager_status";
 
-    PVE::HA::Tools::write_json_to_file($filename, $status_obj); 
-}
-
-sub manager_status_exists {
-    my ($self) = @_;
-
-    my $filename = "$self->{statusdir}/manager_status";
-    return -f $filename ? 1 : 0;
+    PVE::HA::Tools::write_json_to_file($filename, $status_obj);
 }
 
 sub read_lrm_status {
@@ -147,6 +139,18 @@ sub write_lrm_status {
     return $self->{hardware}->write_lrm_status($node, $status_obj);
 }
 
+sub is_node_shutdown {
+    my ($self) = @_;
+
+    return 0; # default to freezing services if not overwritten by subclass
+}
+
+sub service_config_exists {
+    my ($self) = @_;
+    
+    return 1;
+}
+
 sub read_service_config {
     my ($self) = @_;
 
@@ -160,9 +164,9 @@ sub read_group_config {
 }
 
 sub change_service_location {
-    my ($self, $sid, $node) = @_;
+    my ($self, $sid, $current_node, $new_node) = @_;
 
-    return $self->{hardware}->change_service_location($sid, $node);
+    return $self->{hardware}->change_service_location($sid, $current_node, $new_node);
 }
 
 sub queue_crm_commands {
@@ -220,19 +224,10 @@ sub get_ha_agent_lock_name {
 }
 
 sub get_ha_agent_lock {
-    my ($self) = @_;
-
-    my $lck = $self->get_ha_agent_lock_name();
-    return $self->sim_get_lock($lck);
-}
-
-sub test_ha_agent_lock {
     my ($self, $node) = @_;
 
     my $lck = $self->get_ha_agent_lock_name($node);
-    my $res = $self->sim_get_lock($lck);
-    $self->sim_get_lock($lck, 1) if $res; # unlock
-    return $res;
+    return $self->sim_get_lock($lck);
 }
 
 # return true when cluster is quorate
@@ -283,10 +278,109 @@ sub watchdog_close {
     return $self->{hardware}->watchdog_close($wfh);
 }
 
+sub can_fork {
+    my ($self) = @_;
+
+    return 1;
+}
+
 sub exec_resource_agent {
-    my ($self, $sid, $service_config, $cmd, @params) = @_;
+    my ($self, $sid, $cd, $cmd, @params) = @_;
+
+    my $hardware = $self->{hardware};
+
+    my $nodename = $self->{nodename};
+
+    # fixme: return valid_exit code (instead of using die)
+
+    my $ss = $hardware->read_service_status($nodename);
+
+    if ($cmd eq 'started') {
+
+       # fixme: return valid_exit code
+       die "service '$sid' not on this node" if $cd->{node} ne $nodename;
+
+       if ($ss->{$sid}) {
+           return 0;
+       }
+       $self->log("info", "starting service $sid");
+       
+       $self->sleep(2);
+
+       $ss->{$sid} = 1;
+       $hardware->write_service_status($nodename, $ss);
+
+       $self->log("info", "service status $sid started");
+
+       return 0;
+
+    } elsif ($cmd eq 'request_stop' || $cmd eq 'stopped') {
+
+       # fixme: return valid_exit code
+       die "service '$sid' not on this node" if $cd->{node} ne $nodename;
+
+       if (!$ss->{$sid}) {
+           return 0;
+       }
+       $self->log("info", "stopping service $sid");
+       
+       $self->sleep(2);
+
+       $ss->{$sid} = 0;
+       $hardware->write_service_status($nodename, $ss);
+
+       $self->log("info", "service status $sid stopped");
+
+       return 0;
+
+    } elsif ($cmd eq 'migrate' || $cmd eq 'relocate') {
+
+       if ($cd->{type} eq 'ct' && $cmd eq 'migrate' && $ss->{$sid}) {
+           $self->log('err', "unable to live migrate running container");
+           return 1;
+       }
+
+       my $target = $params[0];
+       die "$cmd '$sid' failed - missing target\n" if !defined($target);
+
+       if ($cd->{node} eq $target) {
+           # already migrate
+           return 0;
+       } elsif ($cd->{node} eq $nodename) {
+
+           $self->log("info", "service $sid - start $cmd to node '$target'");
+
+           if ($cmd eq 'relocate') {
+
+               if ($ss->{$sid}) {
+                   $self->log("info", "stopping service $sid (relocate)");
+                   $self->sleep(1); # time to stop service
+                   $ss->{$sid} = 0;
+                   $hardware->write_service_status($nodename, $ss);
+               }
+
+               $self->log("info", "service status $sid stopped");
+
+           } else {
+               $self->sleep(2); # (live) migration time
+           }
+
+           $self->change_service_location($sid, $nodename, $target);
+           $self->log("info", "service $sid - end $cmd to node '$target'");
+           # ensure that the old node doesn't has the service anymore
+           $ss->{$sid} = 0;
+           $hardware->write_service_status($nodename, $ss);
+
+           return 0;
+
+       } else {
+           die "migrate '$sid'  failed - service is not on this node\n";
+       }
+       
+       
+    }
 
-    die "implement me";
+    die "implement me (cmd '$cmd')";
 }
 
 1;