]> git.proxmox.com Git - pve-ha-manager.git/blame - src/PVE/HA/Env/PVE2.pm
add new class to handle configuration
[pve-ha-manager.git] / src / PVE / HA / Env / PVE2.pm
CommitLineData
714a4016
DM
1package PVE::HA::Env::PVE2;
2
3use strict;
4use warnings;
76737af5
DM
5use POSIX qw(:errno_h :fcntl_h);
6use IO::File;
115805fd 7use IO::Socket::UNIX;
714a4016
DM
8
9use PVE::SafeSyslog;
10use PVE::Tools;
abc920b4 11use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_lock_file);
714a4016
DM
12
13use PVE::HA::Tools;
14use PVE::HA::Env;
abc920b4 15use PVE::HA::Groups;
714a4016 16
007fcc8b
DM
17my $lockdir = "/etc/pve/priv/lock";
18
714a4016 19my $manager_status_filename = "/etc/pve/manager_status";
abc920b4
DM
20my $ha_groups_config = "ha/groups.cfg";
21
6cbcb5f7
DM
22#cfs_register_file($ha_groups_config,
23# sub { PVE::HA::Groups->parse_config(@_); },
24# sub { PVE::HA::Groups->write_config(@_); });
714a4016
DM
25
26sub new {
27 my ($this, $nodename) = @_;
28
29 die "missing nodename" if !$nodename;
30
31 my $class = ref($this) || $this;
32
33 my $self = bless {}, $class;
34
35 $self->{nodename} = $nodename;
36
37 return $self;
38}
39
40sub nodename {
41 my ($self) = @_;
42
43 return $self->{nodename};
44}
45
46sub read_manager_status {
47 my ($self) = @_;
48
49 my $filename = $manager_status_filename;
50
51 return PVE::HA::Tools::read_json_from_file($filename, {});
52}
53
54sub write_manager_status {
55 my ($self, $status_obj) = @_;
56
57 my $filename = $manager_status_filename;
58
59 PVE::HA::Tools::write_json_to_file($filename, $status_obj);
60}
61
c4a221bc
DM
62sub read_lrm_status {
63 my ($self, $node) = @_;
64
65 $node = $self->{nodename} if !defined($node);
66
67 my $filename = "/etc/pve/nodes/$node/lrm_status";
68
69 return PVE::HA::Tools::read_json_from_file($filename, {});
70}
71
72sub write_lrm_status {
73 my ($self, $status_obj) = @_;
74
6cbcb5f7 75 my $node = $self->{nodename};
c4a221bc
DM
76
77 my $filename = "/etc/pve/nodes/$node/lrm_status";
78
79 PVE::HA::Tools::write_json_to_file($filename, $status_obj);
80}
81
714a4016
DM
82sub manager_status_exists {
83 my ($self) = @_;
84
85 return -f $manager_status_filename ? 1 : 0;
86}
87
88sub read_service_config {
89 my ($self) = @_;
90
91 die "implement me";
92}
93
8456bde2
DM
94sub change_service_location {
95 my ($self, $sid, $node) = @_;
96
97 die "implement me";
98}
99
abc920b4
DM
100sub read_group_config {
101 my ($self) = @_;
102
103 return cfs_read_file($ha_groups_config);
104}
105
3b996922
DM
106sub queue_crm_commands {
107 my ($self, $cmd) = @_;
108
109 die "implement me";
110}
111
112sub read_crm_commands {
113 my ($self) = @_;
114
115 die "implement me";
116}
117
714a4016
DM
118# this should return a hash containing info
119# what nodes are members and online.
120sub get_node_info {
121 my ($self) = @_;
122
d706ef8b
DM
123 my ($node_info, $quorate) = ({}, 0);
124
125 my $nodename = $self->{nodename};
126
127 $quorate = PVE::Cluster::check_cfs_quorum(1) || 0;
128
129 my $members = PVE::Cluster::get_members();
130
131 foreach my $node (keys %$members) {
132 my $d = $members->{$node};
133 $node_info->{$node}->{online} = $d->{online};
134 }
135
136 $node_info->{$nodename}->{online} = 1; # local node is always up
137
138 return ($node_info, $quorate);
714a4016
DM
139}
140
141sub log {
142 my ($self, $level, $msg) = @_;
143
144 chomp $msg;
145
146 syslog($level, $msg);
147}
148
007fcc8b
DM
149my $last_lock_status = {};
150
151sub get_pve_lock {
152 my ($self, $lockid) = @_;
714a4016 153
007fcc8b 154 my $got_lock = 0;
4d24e7db 155
4d24e7db
DM
156 my $filename = "$lockdir/$lockid";
157
007fcc8b
DM
158 my $last = $last_lock_status->{$lockid} || 0;
159
160 my $ctime = time();
4d24e7db
DM
161
162 eval {
163
164 mkdir $lockdir;
165
007fcc8b
DM
166 # pve cluster filesystem not online
167 die "can't create '$lockdir' (pmxcfs not mounted?)\n" if ! -d $lockdir;
168
169 if ($last && (($ctime - $last) < 100)) { # fixme: what timeout
170 utime(0, $ctime, $filename) || # cfs lock update request
171 die "cfs lock update failed - $!\n";
172 } else {
173
174 # fixme: wait some time?
175 if (!(mkdir $filename)) {
176 utime 0, 0, $filename; # cfs unlock request
177 die "can't get cfs lock\n";
178 }
179 }
4d24e7db 180
007fcc8b 181 $got_lock = 1;
4d24e7db
DM
182 };
183
007fcc8b
DM
184 my $err = $@;
185
186 $last_lock_status->{$lockid} = $got_lock ? $ctime : 0;
187
188 if ($got_lock != $last) {
189 if ($got_lock) {
190 $self->log('info', "successfully aquired lock '$lockid'");
191 } else {
192 my $msg = "lost lock '$lockid";
193 $msg .= " - $err" if $err;
194 $self->log('err', $msg);
195 }
196 }
197
198 return $got_lock;
199}
200
201sub get_ha_manager_lock {
202 my ($self) = @_;
203
204 my $lockid = "ha_manager_lock";
205
206 my $filename = "$lockdir/$lockid";
207
208 return $self->get_pve_lock("ha_manager_lock");
714a4016
DM
209}
210
211sub get_ha_agent_lock {
212 my ($self) = @_;
007fcc8b
DM
213
214 my $node = $self->nodename();
714a4016 215
007fcc8b 216 return $self->get_pve_lock("ha_agent_${node}_lock");
714a4016
DM
217}
218
219sub test_ha_agent_lock {
220 my ($self, $node) = @_;
007fcc8b
DM
221
222 my $lockid = "ha_agent_${node}_lock";
223 my $filename = "$lockdir/$lockid";
224 my $res = $self->get_pve_lock($lockid);
225 rmdir $filename if $res; # cfs unlock
714a4016 226
007fcc8b 227 return $res;
714a4016
DM
228}
229
230sub quorate {
231 my ($self) = @_;
232
4d24e7db
DM
233 my $quorate = 0;
234 eval {
235 $quorate = PVE::Cluster::check_cfs_quorum();
236 };
237
238 return $quorate;
714a4016
DM
239}
240
241sub get_time {
242 my ($self) = @_;
243
244 return time();
245}
246
247sub sleep {
248 my ($self, $delay) = @_;
249
250 CORE::sleep($delay);
251}
252
253sub sleep_until {
254 my ($self, $end_time) = @_;
255
256 for (;;) {
257 my $cur_time = time();
258
259 last if $cur_time >= $end_time;
260
261 $self->sleep(1);
262 }
263}
264
265sub loop_start_hook {
266 my ($self) = @_;
267
4d24e7db
DM
268 PVE::Cluster::cfs_update();
269
714a4016
DM
270 $self->{loop_start} = $self->get_time();
271}
272
273sub loop_end_hook {
274 my ($self) = @_;
275
276 my $delay = $self->get_time() - $self->{loop_start};
277
278 warn "loop take too long ($delay seconds)\n" if $delay > 30;
279}
280
76737af5
DM
281my $watchdog_fh;
282
714a4016
DM
283sub watchdog_open {
284 my ($self) = @_;
285
76737af5
DM
286 die "watchdog already open\n" if defined($watchdog_fh);
287
115805fd
DM
288 $watchdog_fh = IO::Socket::UNIX->new(
289 Type => SOCK_STREAM(),
290 Peer => "/run/watchdog-mux.sock") ||
291 die "unable to open watchdog socket - $!\n";
292
76737af5 293 $self->log('info', "watchdog active");
714a4016
DM
294}
295
296sub watchdog_update {
297 my ($self, $wfh) = @_;
298
76737af5
DM
299 my $res = $watchdog_fh->syswrite("\0", 1);
300 if (!defined($res)) {
301 $self->log('err', "watchdog update failed - $!\n");
302 return 0;
303 }
304 if ($res != 1) {
305 $self->log('err', "watchdog update failed - write $res bytes\n");
306 return 0;
307 }
308
309 return 1;
714a4016
DM
310}
311
312sub watchdog_close {
313 my ($self, $wfh) = @_;
314
76737af5
DM
315 $watchdog_fh->syswrite("V", 1); # magic watchdog close
316 if (!$watchdog_fh->close()) {
317 $self->log('err', "watchdog close failed - $!");
318 } else {
319 $watchdog_fh = undef;
320 $self->log('info', "watchdog closed (disabled)");
321 }
714a4016
DM
322}
323
c4a221bc
DM
324sub exec_resource_agent {
325 my ($self, $sid, $cmd, @params) = @_;
326
327 die "implement me";
328}
329
714a4016 3301;