5
0
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:
Dietmar Maurer 2014-11-29 11:14:59 +01:00
commit 95ca65804c
4 changed files with 231 additions and 0 deletions

60
PVE/HA/Env.pm Normal file
View 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
View 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
View 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
View 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);