mirror of
git://git.proxmox.com/git/pve-ha-manager.git
synced 2024-12-22 17:34:22 +03:00
initial commit
This commit is contained in:
commit
95ca65804c
60
PVE/HA/Env.pm
Normal file
60
PVE/HA/Env.pm
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package PVE::HA::Env;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use PVE::SafeSyslog;
|
||||||
|
|
||||||
|
# abstract out the cluster environment
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my ($this) = @_;
|
||||||
|
|
||||||
|
my $class = ref($this) || $this;
|
||||||
|
|
||||||
|
my $self = bless {}, $class;
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub log {
|
||||||
|
my ($self, $level, $msg) = @_;
|
||||||
|
|
||||||
|
syslog($level, $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
# aquire a cluster wide lock
|
||||||
|
sub get_ha_manager_lock {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
die "implement me";
|
||||||
|
}
|
||||||
|
|
||||||
|
# return current time
|
||||||
|
# overwrite that if you want to simulate
|
||||||
|
sub get_time {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return time();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub sleep {
|
||||||
|
my ($self, $delay) = @_;
|
||||||
|
|
||||||
|
sleep($delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loop_start_hook {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loop_end_hook {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
65
PVE/HA/SimEnv.pm
Normal file
65
PVE/HA/SimEnv.pm
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package PVE::HA::SimEnv;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use POSIX qw(strftime);
|
||||||
|
|
||||||
|
use PVE::HA::Env;
|
||||||
|
|
||||||
|
use base qw(PVE::HA::Env);
|
||||||
|
|
||||||
|
my $max_sim_time = 1000;
|
||||||
|
|
||||||
|
sub log {
|
||||||
|
my ($self, $level, $msg) = @_;
|
||||||
|
|
||||||
|
my $time = $self->get_time();
|
||||||
|
|
||||||
|
my $timestr = strftime("%H:%M:%S", gmtime($time));
|
||||||
|
|
||||||
|
print "$level $timestr: $msg\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cur_time = 0;
|
||||||
|
|
||||||
|
sub get_time {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $cur_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub sleep {
|
||||||
|
my ($self, $delay) = @_;
|
||||||
|
|
||||||
|
$cur_time += $delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_ha_manager_lock {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
++$cur_time;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loop_start_hook {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
$self->{loop_start_time} = $cur_time;
|
||||||
|
|
||||||
|
# do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loop_end_hook {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $delay = $cur_time - $self->{loop_start_time};
|
||||||
|
|
||||||
|
die "loop take too long ($delay seconds)\n" if $delay > 20;
|
||||||
|
|
||||||
|
$cur_time++;
|
||||||
|
|
||||||
|
die "simulation end\n" if $cur_time > $max_sim_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
6
README
Normal file
6
README
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
= Experimental implementation of a simple HA Manager =
|
||||||
|
|
||||||
|
- should run with any distributed key/value store (consul, ...)
|
||||||
|
|
||||||
|
- only works with simply resources like VMs
|
||||||
|
|
100
pve-ha-manager
Executable file
100
pve-ha-manager
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use lib '.';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use PVE::Tools;
|
||||||
|
use PVE::HA::SimEnv;
|
||||||
|
|
||||||
|
my $statusdir = "/var/tmp/pve-ha-manager";
|
||||||
|
|
||||||
|
mkdir $statusdir;
|
||||||
|
|
||||||
|
my $haenv = PVE::HA::SimEnv->new();
|
||||||
|
|
||||||
|
my $status;
|
||||||
|
|
||||||
|
sub get_manager_status {
|
||||||
|
|
||||||
|
my $status = PVE::Tools::file_read_firstline("$statusdir/status");
|
||||||
|
|
||||||
|
$status = 'startup' if !$status;
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_manager_status {
|
||||||
|
my ($new_status) = @_;
|
||||||
|
|
||||||
|
return if $status eq $new_status;
|
||||||
|
|
||||||
|
$haenv->log('info', "manager status change $status => $new_status");
|
||||||
|
|
||||||
|
$status = $new_status;
|
||||||
|
|
||||||
|
PVE::Tools::file_set_contents("$statusdir/status", $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_manager_lock {
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
for (;;) {
|
||||||
|
return 1 if $haenv->get_ha_manager_lock();
|
||||||
|
last if ++$count > 5;
|
||||||
|
$haenv->sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$status = get_manager_status();
|
||||||
|
|
||||||
|
# can happen after crash?
|
||||||
|
if ($status eq 'quorate') {
|
||||||
|
set_manager_status('recover');
|
||||||
|
} else {
|
||||||
|
set_manager_status('startup');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$haenv->log('info', "starting simulation environment (status = $status)");
|
||||||
|
|
||||||
|
eval {
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
$haenv->loop_start_hook();
|
||||||
|
|
||||||
|
if ($status eq 'recover') {
|
||||||
|
$haenv->log('info', "waiting for 5 seconds");
|
||||||
|
$haenv->sleep(5);
|
||||||
|
set_manager_status('startup');
|
||||||
|
} elsif ($status eq 'startup') {
|
||||||
|
if (get_manager_lock()) {
|
||||||
|
set_manager_status('quorate');
|
||||||
|
}
|
||||||
|
} elsif ($status eq 'quorate') {
|
||||||
|
|
||||||
|
} elsif ($status eq 'lost_quorum') {
|
||||||
|
|
||||||
|
} elsif ($status eq 'halt') {
|
||||||
|
die "halt\n";
|
||||||
|
} else {
|
||||||
|
die "got unexpected status '$status'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$haenv->loop_end_hook();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (my $err = $@) {
|
||||||
|
$haenv->log('err', "exit now (status = $status) - $err ");
|
||||||
|
} else {
|
||||||
|
$haenv->log('info', "exit simulation environment (status = $status)");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user