my $class = ref($this) || $this;
- my $self = bless { haenv => $haenv }, $class;
+ my $self = bless { haenv => $haenv, crs => {} }, $class;
my $old_ms = $haenv->read_manager_status();
$self->{ms} = { master_node => $haenv->nodename() };
- my $dc_cfg = $haenv->get_datacenter_settings();
- $self->{'scheduler-mode'} = $dc_cfg->{crs}->{ha} ? $dc_cfg->{crs}->{ha} : 'basic';
- $haenv->log('info', "using scheduler mode '$self->{'scheduler-mode'}'")
- if $self->{'scheduler-mode'} ne 'basic';
+ $self->update_crs_scheduler_mode(); # initial set, we update it once every loop
return $self;
}
+sub update_crs_scheduler_mode {
+ my ($self) = @_;
+
+ my $haenv = $self->{haenv};
+ my $dc_cfg = $haenv->get_datacenter_settings();
+
+ my $old_mode = $self->{crs}->{scheduler};
+ my $new_mode = $dc_cfg->{crs}->{ha} || 'basic';
+
+ if (!defined($old_mode)) {
+ $haenv->log('info', "using scheduler mode '$new_mode'") if $new_mode ne 'basic';
+ } elsif ($new_mode eq $old_mode) {
+ return; # nothing to do
+ } else {
+ $haenv->log('info', "switching scheduler mode from '$old_mode' to '$new_mode'");
+ }
+
+ $self->{crs}->{scheduler} = $new_mode;
+
+ return;
+}
+
sub cleanup {
my ($self) = @_;
my $valid_service_states = {
stopped => 1,
request_stop => 1,
+ request_start => 1,
started => 1,
fence => 1,
recovery => 1,
my $online_node_usage;
- if (my $mode = $self->{'scheduler-mode'}) {
+ if (my $mode = $self->{crs}->{scheduler}) {
if ($mode eq 'static') {
$online_node_usage = eval {
my $scheduler = PVE::HA::Usage::Static->new($haenv);
$scheduler->add_node($_) for $online_nodes->@*;
return $scheduler;
};
- $haenv->log('warning', "using 'basic' scheduler mode, init for 'static' failed - $@")
+ $haenv->log('warning', "fallback to 'basic' scheduler mode, init for 'static' failed - $@")
if $@;
} elsif ($mode eq 'basic') {
# handled below in the general fall-back case
$online_node_usage->add_node($_) for $online_nodes->@*;
}
- foreach my $sid (keys %{$self->{ss}}) {
+ foreach my $sid (sort keys %{$self->{ss}}) {
my $sd = $self->{ss}->{$sid};
my $state = $sd->{state};
my $target = $sd->{target}; # optional
if ($online_node_usage->contains_node($sd->{node})) {
if (
- $state eq 'started' || $state eq 'request_stop' || $state eq 'fence' ||
- $state eq 'freeze' || $state eq 'error' || $state eq 'recovery'
+ $state eq 'started' || $state eq 'request_stop' || $state eq 'fence'
+ || $state eq 'freeze' || $state eq 'error' || $state eq 'recovery'
) {
$online_node_usage->add_service_usage_to_node($sd->{node}, $sid, $sd->{node});
} elsif (($state eq 'migrate') || ($state eq 'relocate')) {
# count it for both, source and target as load is put on both
$online_node_usage->add_service_usage_to_node($source, $sid, $source, $target);
$online_node_usage->add_service_usage_to_node($target, $sid, $source, $target);
- } elsif ($state eq 'stopped') {
+ } elsif ($state eq 'stopped' || $state eq 'request_start') {
# do nothing
} else {
die "should not be reached (sid = '$sid', state = '$state')";
return;
}
+ $self->update_crs_scheduler_mode();
+
my $sc = $haenv->read_service_config();
$self->{groups} = $haenv->read_group_config(); # update
$haenv->log('info', "adding new service '$sid' on node '$cd->{node}'");
# assume we are running to avoid relocate running service at add
- my $state = ($cd->{state} eq 'started') ? 'started' : 'request_stop';
- $ss->{$sid} = { state => $state, node => $cd->{node},
- uid => compute_new_uuid('started') };
+ my $state = ($cd->{state} eq 'started') ? 'request_start' : 'request_stop';
+ $ss->{$sid} = {
+ state => $state, node => $cd->{node}, uid => compute_new_uuid('started'),
+ };
}
# remove stale or ignored services from manager state
$self->next_state_started($sid, $cd, $sd, $lrm_res);
+ } elsif ($last_state eq 'request_start') {
+
+ $self->next_state_request_start($sid, $cd, $sd, $lrm_res);
+
} elsif ($last_state eq 'migrate' || $last_state eq 'relocate') {
$self->next_state_migrate_relocate($sid, $cd, $sd, $lrm_res);
} elsif ($last_state eq 'freeze') {
my $lrm_mode = $sd->{node} ? $lrm_modes->{$sd->{node}} : undef;
- # unfreeze
- my $state = ($cd->{state} eq 'started') ? 'started' : 'request_stop';
- &$change_service_state($self, $sid, $state)
- if $lrm_mode && $lrm_mode eq 'active';
+ if ($lrm_mode && $lrm_mode eq 'active') { # unfreeze if active again
+ my $state = ($cd->{state} eq 'started') ? 'started' : 'request_stop';
+ $change_service_state->($self, $sid, $state);
+ }
} elsif ($last_state eq 'error') {
my $lrm_mode = $sd->{node} ? $lrm_modes->{$sd->{node}} : undef;
if ($lrm_mode && $lrm_mode eq 'restart') {
- if (($sd->{state} eq 'started' || $sd->{state} eq 'stopped' ||
- $sd->{state} eq 'request_stop')) {
- &$change_service_state($self, $sid, 'freeze');
+ my $state = $sd->{state};
+ if ($state eq 'started' || $state eq 'stopped'|| $state eq 'request_stop') {
+ $change_service_state->($self, $sid, 'freeze');
}
}
} elsif ($sd->{node} eq $target) {
$haenv->log('info', "ignore service '$sid' $cmd request - service already on node '$target'");
} else {
- &$change_service_state($self, $sid, $cmd, node => $sd->{node},
- target => $target);
+ &$change_service_state($self, $sid, $cmd, node => $sd->{node}, target => $target);
return;
}
} elsif ($cmd eq 'stop') {
}
if ($cd->{state} eq 'started') {
- # simply mark it started, if it's on the wrong node
- # next_state_started will fix that for us
- &$change_service_state($self, $sid, 'started', node => $sd->{node});
+ # simply mark it started, if it's on the wrong node next_state_started will fix that for us
+ $change_service_state->($self, $sid, 'request_start', node => $sd->{node});
return;
}
$haenv->log('err', "service '$sid' - unknown state '$cd->{state}' in service configuration");
}
+sub next_state_request_start {
+ my ($self, $sid, $cd, $sd, $lrm_res) = @_;
+
+ $change_service_state->($self, $sid, 'started', node => $sd->{node});
+}
+
sub record_service_failed_on_node {
my ($self, $sid, $node) = @_;
# store flag to indicate successful start - only valid while state == 'started'
$sd->{running} = 1;
- } elsif ($ec == ERROR) {
+ } elsif ($ec == ERROR || $ec == EWRONG_NODE) {
delete $sd->{running};