]>
git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/HA/NodeStatus.pm
1 package PVE
::HA
::NodeStatus
;
9 my ($this, $haenv, $status) = @_;
11 my $class = ref($this) || $this;
22 # possible node state:
23 my $valid_node_states = {
24 online
=> "node online and member of quorate partition",
25 unknown
=> "not member of quorate partition, but possibly still running",
26 fence
=> "node needs to be fenced",
27 gone
=> "node vanished from cluster members list, possibly deleted"
31 my ($self, $node) = @_;
33 $self->{status
}->{$node} = 'unknown'
34 if !$self->{status
}->{$node};
36 return $self->{status
}->{$node};
40 my ($self, $node) = @_;
42 return $self->get_node_state($node) eq 'online';
45 sub node_is_offline_delayed
{
46 my ($self, $node, $delay) = @_;
48 my $haenv = $self->{haenv
};
50 return undef if $self->get_node_state($node) eq 'online';
52 my $last_online = $self->{last_online
}->{$node};
54 my $ctime = $haenv->get_time();
56 if (!defined($last_online)) {
57 $self->{last_online
}->{$node} = $ctime;
61 return ($ctime - $last_online) >= $delay;
67 return [sort keys %{$self->{status
}}];
70 sub list_online_nodes
{
75 foreach my $node (sort keys %{$self->{status
}}) {
76 next if $self->{status
}->{$node} ne 'online';
83 my $delete_node = sub {
84 my ($self, $node) = @_;
86 return undef if $self->get_node_state($node) ne 'gone';
88 my $haenv = $self->{haenv
};
90 delete $self->{last_online
}->{$node};
91 delete $self->{status
}->{$node};
93 $haenv->log('notice', "deleting gone node '$node', not a cluster member".
97 my $set_node_state = sub {
98 my ($self, $node, $state) = @_;
100 my $haenv = $self->{haenv
};
102 die "unknown node state '$state'\n"
103 if !defined($valid_node_states->{$state});
105 my $last_state = $self->get_node_state($node);
107 return if $state eq $last_state;
109 $self->{status
}->{$node} = $state;
111 $haenv->log('info', "node '$node': state changed from " .
112 "'$last_state' => '$state'\n");
116 my ($self, $node_info) = @_;
118 my $haenv = $self->{haenv
};
120 foreach my $node (sort keys %$node_info) {
121 my $d = $node_info->{$node};
122 next if !$d->{online
};
124 # record last time the node was online (required to implement fence delay)
125 $self->{last_online
}->{$node} = $haenv->get_time();
127 my $state = $self->get_node_state($node);
129 if ($state eq 'online') {
130 # &$set_node_state($self, $node, 'online');
131 } elsif ($state eq 'unknown' || $state eq 'gone') {
132 &$set_node_state($self, $node, 'online');
133 } elsif ($state eq 'fence') {
134 # do nothing, wait until fenced
136 die "detected unknown node state '$state";
140 foreach my $node (keys %{$self->{status
}}) {
141 my $d = $node_info->{$node};
142 next if $d && $d->{online
};
144 my $state = $self->get_node_state($node);
146 # node is not inside quorate partition, possibly not active
148 if ($state eq 'online') {
149 &$set_node_state($self, $node, 'unknown');
150 } elsif ($state eq 'unknown') {
152 # node isn't in the member list anymore, deleted from the cluster?
153 &$set_node_state($self, $node, 'gone') if(!defined($d));
155 } elsif ($state eq 'fence') {
156 # do nothing, wait until fenced
157 } elsif($state eq 'gone') {
158 if($self->node_is_offline_delayed($node, 3600)) {
159 &$delete_node($self, $node);
162 die "detected unknown node state '$state";
170 my ($self, $node) = @_;
172 my $haenv = $self->{haenv
};
174 my $state = $self->get_node_state($node);
176 if ($state ne 'fence') {
177 &$set_node_state($self, $node, 'fence');
180 my $success = $haenv->get_ha_agent_lock($node);
183 $haenv->log("info", "fencing: acknowleged - got agent lock for node '$node'");
184 &$set_node_state($self, $node, 'unknown');