]>
git.proxmox.com Git - pve-ha-manager.git/blob - PVE/HA/SimEnv.pm
1 package PVE
::HA
::SimEnv
;
5 use POSIX
qw(strftime);
11 use base
qw(PVE::HA::Env);
15 my $max_sim_time = 1000;
17 # time => quorate nodes (first node gets manager lock)
18 my $quorum_setup = [];
20 my $compute_node_info = sub {
22 my $last_node_info = {};
24 foreach my $entry (@$quorum_setup) {
25 my ($time, $members) = @$entry;
27 $max_sim_time = $time + 1000;
31 foreach my $node (@$members) {
32 $node_info->{$node}->{online
} = 1;
33 if (!$last_node_info->{$node}) {
34 $node_info->{$node}->{join_time
} = $time;
36 $node_info->{$node}->{join_time
} =
37 $last_node_info->{$node}->{join_time
};
41 push @$entry, $node_info;
43 $last_node_info = $node_info;
47 my $lookup_quorum_info = sub {
50 foreach my $entry (reverse @$quorum_setup) {
51 my ($time, $members) = @$entry;
53 if ($cur_time >= $time) {
61 my $node_is_lock_owner = sub {
64 if (my $members = &$lookup_quorum_info($self)) {
65 return $members->[0] eq $self->{nodename
} ?
1 : 0;
72 my ($this, $testdir) = @_;
74 my $class = ref($this) || $this;
76 my $nodename = 'node1';
77 if (-f
"$testdir/hostname") {
78 $nodename = PVE
::Tools
::file_read_firstline
("$testdir/hostname");
81 if (-f
"$testdir/membership") {
82 my $raw = PVE
::Tools
::file_get_contents
("$testdir/membership");
83 $quorum_setup = decode_json
($raw);
86 my $statusdir = "$testdir/status";
88 my $self = $class->SUPER::new
($statusdir, $nodename);
90 &$compute_node_info();
95 sub read_manager_status
{
98 die "detected read without lock\n"
99 if !&$node_is_lock_owner($self);
101 my $filename = "$self->{statusdir}/manager_status";
103 my $raw = PVE
::Tools
::file_get_contents
($filename);
105 return decode_json
($raw) || {};
108 sub write_manager_status
{
109 my ($self, $status_obj) = @_;
111 die "detected write without lock\n"
112 if !&$node_is_lock_owner($self);
114 my $data = encode_json
($status_obj);
115 my $filename = "$self->{statusdir}/manager_status";
117 PVE
::Tools
::file_set_contents
($filename, $data);
120 sub manager_status_exists
{
123 my $filename = "$self->{statusdir}/manager_status";
125 return -f
$filename ?
1 : 0;
128 my $read_service_status = sub {
131 my $filename = "$self->{statusdir}/service_status";
134 my $raw = PVE
::Tools
::file_get_contents
($filename);
135 return decode_json
($raw);
141 my $write_service_status = sub {
142 my ($self, $status_obj) = @_;
144 my $data = encode_json
($status_obj);
145 my $filename = "$self->{statusdir}/service_status";
147 PVE
::Tools
::file_set_contents
($filename, $data);
150 sub read_service_config
{
171 my $rl = &$read_service_status($self);
173 foreach my $sid (keys %$conf) {
174 die "service '$sid' does not exists\n"
175 if !($rl->{$sid} && $rl->{$sid}->{node
});
178 foreach my $sid (keys %$rl) {
179 next if !$conf->{$sid};
180 $conf->{$sid}->{current_node
} = $rl->{$sid}->{node
};
181 $conf->{$sid}->{node
} = $conf->{$sid}->{current_node
};
188 my ($self, $level, $msg) = @_;
192 my $time = $self->get_time();
194 printf("%-5s %10d $self->{nodename}: $msg\n", $level, $time);
204 my ($self, $delay) = @_;
209 sub get_ha_manager_lock
{
212 my $res = &$node_is_lock_owner($self);
217 # return true when cluster is quorate
221 if (my $members = &$lookup_quorum_info($self)) {
222 foreach my $node (@$members) {
223 return 1 if $node eq $self->{nodename
};
233 foreach my $entry (reverse @$quorum_setup) {
234 my ($time, $members, $node_info) = @$entry;
236 if ($cur_time >= $time) {
241 die "unbale to get node info";
244 sub loop_start_hook
{
247 $self->{loop_start_time
} = $cur_time;
255 my $delay = $cur_time - $self->{loop_start_time
};
257 die "loop take too long ($delay seconds)\n" if $delay > 30;
259 die "simulation end\n" if $cur_time > $max_sim_time;