[pve-devel] [PATCH ha-manager v3 2/6] Env, HW: add HW fencing related functions

Thomas Lamprecht t.lamprecht at proxmox.com
Mon Mar 14 17:31:29 CET 2016


This adds three to hardware fencing related functions:
* read_fence_config
* fencing_mode
* exec_fence_agent

'read_fence_config' allows to create a common code base between the
real world and the test/sim world regarding fencing a bit easier.
In PVE2 it parses the config from /etc/pve/ha/fence.cfg and in
the Sim method it parses the config from testdir/status/fence.cfg.

The fencing_mode method checks respective to the callee's
environment if hardware fencing is enabled and returns the wanted
mode if:

* PVE2: the datacenter cfg key must be set and not be equal to
        'watchdog' and at least one device must be configured.

* Sim: at least one device must be configured.

For the simulator we should make also a option to turn HW fencing
off and on independent if devices are configured when we implement
HW fencing for it, but that is not really needs for now.

'exec_fence_agent' executes, as the name suggests, environment
specific an fence agent.

In the Hardware class (simulator & regression tests) we simulate
the watchdog through this method, for code reuse and as he is in
the wider sense also a fence agent.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
 src/PVE/HA/Env.pm              | 18 ++++++++++++++++++
 src/PVE/HA/Env/PVE2.pm         | 29 +++++++++++++++++++++++++++++
 src/PVE/HA/Sim/Env.pm          | 22 ++++++++++++++++++++++
 src/PVE/HA/Sim/Hardware.pm     | 33 ++++++++++++++++++++++++++++++--
 src/PVE/HA/Sim/RTHardware.pm   |  3 +--
 src/PVE/HA/Sim/TestHardware.pm |  5 +----
 6 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/src/PVE/HA/Env.pm b/src/PVE/HA/Env.pm
index f6be7b2..c7537b1 100644
--- a/src/PVE/HA/Env.pm
+++ b/src/PVE/HA/Env.pm
@@ -87,6 +87,24 @@ sub read_service_config {
     return $self->{plug}->read_service_config();
 }
 
+sub read_fence_config {
+    my ($self) = @_;
+
+    return $self->{plug}->read_fence_config();
+}
+
+sub fencing_mode {
+    my ($self) = @_;
+
+    return $self->{plug}->fencing_mode();
+}
+
+sub exec_fence_agent {
+    my ($self, $agent, $node, @param) = @_;
+
+    return $self->{plug}->exec_fence_agent($agent, $node, @param);
+}
+
 # this is normally only allowed by the master to recover a _fenced_ service
 sub steal_service {
     my ($self, $sid, $current_node, $new_node) = @_;
diff --git a/src/PVE/HA/Env/PVE2.pm b/src/PVE/HA/Env/PVE2.pm
index 8638786..37823ee 100644
--- a/src/PVE/HA/Env/PVE2.pm
+++ b/src/PVE/HA/Env/PVE2.pm
@@ -15,6 +15,7 @@ use PVE::RPCEnvironment;
 use PVE::HA::Tools ':exit_codes';
 use PVE::HA::Env;
 use PVE::HA::Config;
+use PVE::HA::FenceConfig;
 use PVE::HA::Resources;
 use PVE::HA::Resources::PVEVM;
 use PVE::HA::Resources::PVECT;
@@ -144,6 +145,34 @@ sub read_service_config {
     return $conf;
 }
 
+sub read_fence_config {
+    my ($self) = @_;
+
+    return PVE::HA::Config::read_fence_config();
+}
+
+sub fencing_mode {
+    my ($self) = @_;
+
+    my $datacenterconfig = cfs_read_file('datacenter.cfg');
+
+    return 'watchdog' if !$datacenterconfig->{fencing};
+
+    return $datacenterconfig->{fencing};
+}
+
+sub exec_fence_agent {
+    my ($self, $agent, $node, @param) = @_;
+
+    # setup execution environment
+    $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
+
+    my $cmd = "$agent " . PVE::HA::FenceConfig::gen_arg_str(@param);
+
+    exec($cmd);
+    exit -1;
+}
+
 # this is only allowed by the master to recover a _fenced_ service
 sub steal_service {
     my ($self, $sid, $current_node, $new_node) = @_;
diff --git a/src/PVE/HA/Sim/Env.pm b/src/PVE/HA/Sim/Env.pm
index 5ce174a..3715eff 100644
--- a/src/PVE/HA/Sim/Env.pm
+++ b/src/PVE/HA/Sim/Env.pm
@@ -167,6 +167,28 @@ sub read_service_config {
     return $self->{hardware}->read_service_config();
 }
 
+sub read_fence_config {
+    my ($self) = @_;
+
+    return $self->{hardware}->read_fence_config();
+}
+
+# the test/sim framework has hardware enabled fencing if
+# it has devices configured
+sub fencing_mode {
+    my ($self) = @_;
+
+    my $cfg = $self->read_fence_config();
+
+    return (defined($cfg) && keys %{$cfg}) ? 'hardware' : 'watchdog';
+}
+
+sub exec_fence_agent {
+    my ($self, $agent, $node, @param) = @_;
+
+    return $self->{hardware}->exec_fence_agent($agent, $node, @param);
+}
+
 sub read_group_config {
     my ($self) = @_;
 
diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
index 652f11d..e7078bb 100644
--- a/src/PVE/HA/Sim/Hardware.pm
+++ b/src/PVE/HA/Sim/Hardware.pm
@@ -15,7 +15,8 @@ use IO::File;
 use Fcntl qw(:DEFAULT :flock);
 use File::Copy;
 use File::Path qw(make_path remove_tree);
-use PVE::HA::Config 'testenv';
+use PVE::HA::Config;
+use PVE::HA::FenceConfig;
 
 my $watchdog_timeout = 60;
 
@@ -114,7 +114,33 @@ sub write_service_config {
 
     my $filename = "$self->{statusdir}/service_config";
     return PVE::HA::Tools::write_json_to_file($filename, $conf);
-} 
+}
+
+sub read_fence_config {
+    my ($self) = @_;
+
+    my $raw = undef;
+
+    my $filename = "$self->{statusdir}/fence.cfg";
+    if (-e $filename) {
+	$raw = PVE::Tools::file_get_contents($filename);
+    }
+
+    return PVE::HA::FenceConfig::parse_config($filename, $raw);
+}
+
+# simulates fence agent, also the watchdog
+sub exec_fence_agent {
+    my ($self, $agent, $node, @param) = @_;
+
+    # let all agent succeed and behave the same for now
+    $self->sim_hardware_cmd("power $node off", $agent);
+    $self->log('info', "server '$node' stopped by poweroff ($agent)");
+    $self->{nodes}->{$node}->{crm} = undef;
+    $self->{nodes}->{$node}->{lrm} = undef;
+
+    return 0; # EXIT_SUCCESS
+}
 
 sub set_service_state {
     my ($self, $sid, $state) = @_;
@@ -306,6 +332,9 @@ sub new {
 	$self->write_hardware_status_nolock($cstatus);
     }
 
+    if (-f "$testdir/fence.cfg") {
+	copy("$testdir/fence.cfg", "$statusdir/fence.cfg");
+    }
 
     my $cstatus = $self->read_hardware_status_nolock();
 
diff --git a/src/PVE/HA/Sim/RTHardware.pm b/src/PVE/HA/Sim/RTHardware.pm
index 866d0bc..289c4db 100644
--- a/src/PVE/HA/Sim/RTHardware.pm
+++ b/src/PVE/HA/Sim/RTHardware.pm
@@ -568,8 +568,7 @@ sub run {
 	my @nodes = sort keys %{$self->{nodes}};
 	foreach my $node (@nodes) {
 	    if (!$self->watchdog_check($node)) {
-		$self->sim_hardware_cmd("power $node off", 'watchdog');
-		$self->log('info', "server '$node' stopped by poweroff (watchdog)");
+		$self->exec_fence_agent('watchdog', $node);
 	    }
 	}
 
diff --git a/src/PVE/HA/Sim/TestHardware.pm b/src/PVE/HA/Sim/TestHardware.pm
index cfd48e7..552ccb5 100644
--- a/src/PVE/HA/Sim/TestHardware.pm
+++ b/src/PVE/HA/Sim/TestHardware.pm
@@ -292,10 +292,7 @@ sub run {
 
 	    foreach my $n (@nodes) {
 		if (!$self->watchdog_check($n)) {
-		    $self->sim_hardware_cmd("power $n off", 'watchdog');
-		    $self->log('info', "server '$n' stopped by poweroff (watchdog)");
-		    $self->{nodes}->{$n}->{crm} = undef;
-		    $self->{nodes}->{$n}->{lrm} = undef;
+		    $self->exec_fence_agent('watchdog', $n);
 		}
 	    }
 	}
-- 
2.1.4





More information about the pve-devel mailing list