use warnings;
use POSIX qw(strftime EINTR);
use Data::Dumper;
-use JSON;
+use JSON;
use IO::File;
use Fcntl qw(:DEFAULT :flock);
die "missing nodename" if !$nodename;
die "missing log_id" if !$log_id;
-
+
my $class = ref($this) || $this;
my $self = bless {}, $class;
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;
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)) {
} 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;
}
}
- PVE::HA::Tools::write_json_to_file($filename, $data);
+ PVE::HA::Tools::write_json_to_file($filename, $data);
return $res;
};
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 {
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 {
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) = @_;
}
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 {
}
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
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;