]> git.proxmox.com Git - pve-ha-manager.git/commitdiff
initial commit
authorDietmar Maurer <dietmar@proxmox.com>
Sat, 29 Nov 2014 10:14:59 +0000 (11:14 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Sat, 29 Nov 2014 11:41:17 +0000 (12:41 +0100)
PVE/HA/Env.pm [new file with mode: 0644]
PVE/HA/SimEnv.pm [new file with mode: 0644]
README [new file with mode: 0644]
pve-ha-manager [new file with mode: 0755]

diff --git a/PVE/HA/Env.pm b/PVE/HA/Env.pm
new file mode 100644 (file)
index 0000000..6dc9a85
--- /dev/null
@@ -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;
diff --git a/PVE/HA/SimEnv.pm b/PVE/HA/SimEnv.pm
new file mode 100644 (file)
index 0000000..a706a30
--- /dev/null
@@ -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;
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..372182d
--- /dev/null
+++ b/README
@@ -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
+
diff --git a/pve-ha-manager b/pve-ha-manager
new file mode 100755 (executable)
index 0000000..fa058d8
--- /dev/null
@@ -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);
+