]> git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/HA/NodeStatus.pm
write lrm mode into lrm status file
[pve-ha-manager.git] / src / PVE / HA / NodeStatus.pm
1 package PVE::HA::NodeStatus;
2
3 use strict;
4 use warnings;
5
6 use Data::Dumper;
7
8 sub new {
9 my ($this, $haenv, $status) = @_;
10
11 my $class = ref($this) || $this;
12
13 my $self = bless {
14 haenv => $haenv,
15 status => $status,
16 last_online => {},
17 }, $class;
18
19 return $self;
20 }
21
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 };
28
29 sub get_node_state {
30 my ($self, $node) = @_;
31
32 $self->{status}->{$node} = 'unknown'
33 if !$self->{status}->{$node};
34
35 return $self->{status}->{$node};
36 }
37
38 sub node_is_online {
39 my ($self, $node) = @_;
40
41 return $self->get_node_state($node) eq 'online';
42 }
43
44 sub node_is_offline_delayed {
45 my ($self, $node, $delay) = @_;
46
47 my $haenv = $self->{haenv};
48
49 return undef if $self->get_node_state($node) eq 'online';
50
51 my $last_online = $self->{last_online}->{$node};
52
53 my $ctime = $haenv->get_time();
54
55 if (!defined($last_online)) {
56 $self->{last_online}->{$node} = $ctime;
57 return undef;
58 }
59
60 return ($ctime - $last_online) >= $delay;
61 }
62
63 sub list_nodes {
64 my ($self) = @_;
65
66 return [sort keys %{$self->{status}}];
67 }
68
69 sub list_online_nodes {
70 my ($self) = @_;
71
72 my $res = [];
73
74 foreach my $node (sort keys %{$self->{status}}) {
75 next if $self->{status}->{$node} ne 'online';
76 push @$res, $node;
77 }
78
79 return $res;
80 }
81
82 my $set_node_state = sub {
83 my ($self, $node, $state) = @_;
84
85 my $haenv = $self->{haenv};
86
87 die "unknown node state '$state'\n"
88 if !defined($valid_node_states->{$state});
89
90 my $last_state = $self->get_node_state($node);
91
92 return if $state eq $last_state;
93
94 $self->{status}->{$node} = $state;
95
96 $haenv->log('info', "node '$node': state changed from " .
97 "'$last_state' => '$state'\n");
98 };
99
100 sub update {
101 my ($self, $node_info) = @_;
102
103 my $haenv = $self->{haenv};
104
105 foreach my $node (sort keys %$node_info) {
106 my $d = $node_info->{$node};
107 next if !$d->{online};
108
109 # record last time the node was online (required to implement fence delay)
110 $self->{last_online}->{$node} = $haenv->get_time();
111
112 my $state = $self->get_node_state($node);
113
114 if ($state eq 'online') {
115 # &$set_node_state($self, $node, 'online');
116 } elsif ($state eq 'unknown') {
117 &$set_node_state($self, $node, 'online');
118 } elsif ($state eq 'fence') {
119 # do nothing, wait until fenced
120 } else {
121 die "detected unknown node state '$state";
122 }
123 }
124
125 foreach my $node (keys %{$self->{status}}) {
126 my $d = $node_info->{$node};
127 next if $d && $d->{online};
128
129 my $state = $self->get_node_state($node);
130
131 # node is not inside quorate partition, possibly not active
132
133 if ($state eq 'online') {
134 &$set_node_state($self, $node, 'unknown');
135 } elsif ($state eq 'unknown') {
136 # &$set_node_state($self, $node, 'unknown');
137 } elsif ($state eq 'fence') {
138 # do nothing, wait until fenced
139 } else {
140 die "detected unknown node state '$state";
141 }
142
143 }
144 }
145
146 # start fencing
147 sub fence_node {
148 my ($self, $node) = @_;
149
150 my $haenv = $self->{haenv};
151
152 my $state = $self->get_node_state($node);
153
154 if ($state ne 'fence') {
155 &$set_node_state($self, $node, 'fence');
156 }
157
158 my $success = $haenv->get_ha_agent_lock($node);
159
160 if ($success) {
161 $haenv->log("info", "fencing: acknowleged - got agent lock for node '$node'");
162 &$set_node_state($self, $node, 'unknown');
163 }
164
165 return $success;
166 }
167
168 1;