Gitweb: http://git.fedorahosted.org/git/fence-agents.git?p=fence-agents.git;a=commit... Commit: 40e5f51eec5e12e6bf25beeacdcef82aa567a4b5 Parent: 1215fd3ecec974c32df312dacb254ec29088825e Author: Ryan O'Hara rohara@redhat.com AuthorDate: Mon Dec 7 16:43:40 2009 -0600 Committer: Fabio M. Di Nitto fdinitto@redhat.com CommitterDate: Tue Apr 20 14:42:11 2010 +0200
New fence_scsi with config options.
--- fence/agents/scsi/fence_scsi.pl | 379 ++++++++++++++++++++++----------------- 1 files changed, 215 insertions(+), 164 deletions(-)
diff --git a/fence/agents/scsi/fence_scsi.pl b/fence/agents/scsi/fence_scsi.pl index e58a5b1..59259cf 100644 --- a/fence/agents/scsi/fence_scsi.pl +++ b/fence/agents/scsi/fence_scsi.pl @@ -2,7 +2,7 @@
use File::Basename; use Getopt::Std; -use IPC::Open3; +use POSIX;
#BEGIN_VERSION_GENERATION $RELEASE_VERSION=""; @@ -16,67 +16,82 @@ my $ME = fileparse ($0, ".pl");
sub log_debug ($) { + my $time = strftime "%b %e %T", localtime; my ($msg) = @_;
- print STDOUT "[debug]: $msg\n" unless defined ($opt_q); + print STDOUT "$time $ME: [debug] $msg\n" unless defined ($opt_q); + + return; }
sub log_error ($) { + my $time = strftime "%b %e %T", localtime; my ($msg) = @_;
- print STDERR "[error]: $msg\n" unless defined ($opt_q); + print STDERR "$time $ME: [error] $msg\n" unless defined ($opt_q); + + exit (1); }
sub do_action_on ($@) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($node_key, @devices) = @_;
key_write ($node_key);
foreach $dev (@devices) { + log_error ("device $dev does not exist") if (! -e $dev); + log_error ("device $dev is not a block device") if (! -b $dev); + do_register_ignore ($node_key, $dev);
if (!get_reservation_key ($dev)) { do_reserve ($node_key, $dev); } } + + return; }
sub do_action_off ($@) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($node_key, @devices) = @_;
my $host_key = key_read ();
if ($host_key eq $node_key) { log_error ($self); - exit (1); }
foreach $dev (@devices) { + log_error ("device $dev does not exist") if (! -e $dev); + log_error ("device $dev is not a block device") if (! -b $dev); + my @keys = grep { /$node_key/ } get_registration_keys ($dev);
if (scalar (@keys) != 0) { do_preempt_abort ($host_key, $node_key, $dev); } } + + return; }
sub do_action_status ($@) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($node_key, @devices) = @_;
my $dev_count = 0; my $key_count = 0;
foreach $dev (@devices) { + log_error ("device $dev does not exist") if (! -e $dev); + log_error ("device $dev is not a block device") if (! -b $dev); + my @keys = grep { /$node_key/ } get_registration_keys ($dev);
if (scalar (@keys) != 0) { @@ -94,140 +109,125 @@ sub do_action_status ($@)
sub do_register ($$$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($host_key, $node_key, $dev) = @_;
if (substr ($dev, 5) =~ /^dm/) { my @slaves = get_mpath_slaves ($dev); - foreach (@slaves) { do_register ($node_key, $_); } return; }
- my $cmd = "sg_persist -n -o -G -K $host_key -S $node_key -d $dev"; - $cmd .= " -Z" if (defined $opt_a); + log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)"); + + my $cmd; + my $out;
- my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + $cmd = "sg_persist -n -o -G -K $host_key -S $node_key -d $dev"; + $cmd .= " -Z" if (defined $opt_a); + $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub do_register_ignore ($$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($node_key, $dev) = @_;
if (substr ($dev, 5) =~ /^dm/) { my @slaves = get_mpath_slaves ($dev); - foreach (@slaves) { do_register_ignore ($node_key, $_); } return; }
- my $cmd = "sg_persist -n -o -I -S $node_key -d $dev"; - $cmd .= " -Z" if (defined $opt_a); + log_debug ("$self (node_key=$node_key, dev=$dev)");
- my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + my $cmd; + my $out;
- waitpid ($pid, 0); + $cmd = "sg_persist -n -o -I -S $node_key -d $dev"; + $cmd .= " -Z" if (defined $opt_a); + $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub do_reserve ($$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($host_key, $dev) = @_;
- my $cmd = "sg_persist -n -o -R -T 5 -K $host_key -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + log_debug ("$self (host_key=$host_key, dev=$dev)");
- waitpid ($pid, 0); + my $cmd = "sg_persist -n -o -R -T 5 -K $host_key -d $dev"; + my $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub do_release ($$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($host_key, $dev) = @_;
- my $cmd = "sg_persist -n -o -L -T 5 -K $host_key -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + log_debug ("$self (host_key=$host_key, dev=$dev)");
- waitpid ($pid, 0); + my $cmd = "sg_persist -n -o -L -T 5 -K $host_key -d $dev"; + my $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub do_preempt ($$$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($host_key, $node_key, $dev) = @_;
- my $cmd = "sg_persist -n -o -P -T 5 -K $host_key -S $node_key -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)");
- waitpid ($pid, 0); + my $cmd = "sg_persist -n -o -P -T 5 -K $host_key -S $node_key -d $dev"; + my $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub do_preempt_abort ($$$) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($host_key, $node_key, $dev) = @_;
- my $cmd = "sg_persist -n -o -A -T 5 -K $host_key -S $node_key -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + log_debug ("$self (host_key=$host_key, node_key=$node_key, dev=$dev)");
- waitpid ($pid, 0); + my $cmd = "sg_persist -n -o -A -T 5 -K $host_key -S $node_key -d $dev"; + my $out = qx { $cmd };
- die "[error]: $self ($dev)\n" if ($?>>8); + die "[error]: $self\n" if ($?>>8);
- close (IN); - close (OUT); - close (ERR); + return; }
sub key_read () { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3]; + my $key;
open (*FILE, "</var/lib/cluster/fence_scsi.key") or die "$!\n"; - - chomp (my $key = <FILE>); - + chomp ($key = <FILE>); close (FILE);
return ($key); @@ -235,18 +235,18 @@ sub key_read ()
sub key_write ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3];
open (*FILE, ">/var/lib/cluster/fence_scsi.key") or die "$!\n"; - print FILE "$_[0]\n"; - close (FILE); + + return; }
sub get_key ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3];
my $key = sprintf ("%.4x%.4x", get_cluster_id (), get_node_id ($_[0]));
@@ -255,98 +255,76 @@ sub get_key ($)
sub get_node_id ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3]; + my $node_id;
my $cmd = "cman_tool nodes -n $_[0] -F id"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; - - waitpid ($pid, 0); + my $out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- chomp (my $node_id = <OUT>); + chomp ($out);
- close (IN); - close (OUT); - close (ERR); + $node_id = $out;
return ($node_id); }
sub get_cluster_id () { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3]; + my $cluster_id;
my $cmd = "cman_tool status"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; - - waitpid ($pid, 0); + my @out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- my $cluster_id; - - while (<OUT>) { + foreach (@out) { chomp; - my ($param, $value) = split (/\s*:\s*/, $_); - if ($param =~ /^cluster\s+id/i) { $cluster_id = $value; } }
- close (IN); - close (OUT); - close (ERR); - return ($cluster_id); }
sub get_devices_clvm () { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3]; + my @devices;
my $cmd = "vgs --noheadings " . - " --separator : " . - " --sort pv_uuid " . - " --options vg_attr,pv_name " . - " --config 'global { locking_type = 0 } " . - " devices { preferred_names = [ "^/dev/dm" ] }'"; - - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; + " --separator : " . + " --sort pv_uuid " . + " --options vg_attr,pv_name " . + " --config 'global { locking_type = 0 } " . + " devices { preferred_names = [ "^/dev/dm" ] }'";
- waitpid ($pid, 0); + my @out = qx { $cmd 2> /dev/null };
die "[error]: $self\n" if ($?>>8);
- my @devices; - - while (<OUT>) { + foreach (@out) { chomp; - my ($vg_attr, $pv_name) = split (/:/, $_); - if ($vg_attr =~ /c$/) { push (@devices, $pv_name); } }
- close (IN); - close (OUT); - close (ERR); - return (@devices); }
sub get_devices_scsi () { - (my $self = (caller(0))[3]) =~ s/^main:://; + my $self = (caller(0))[3]; + my @devices;
opendir (*DIR, "/sys/block/") or die "$!\n"; - - my @devices = grep { /^sd/ } readdir (DIR); - + @devices = grep { /^sd/ } readdir (DIR); closedir (DIR);
return (@devices); @@ -354,18 +332,16 @@ sub get_devices_scsi ()
sub get_mpath_name ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($dev) = @_; + my $name;
if ($dev =~ /^/dev//) { $dev = substr ($dev, 5); }
open (*FILE, "/sys/block/$dev/dm/name") or die "$!\n"; - - chomp (my $name = <FILE>); - + chomp ($name = <FILE>); close (FILE);
return ($name); @@ -373,18 +349,16 @@ sub get_mpath_name ($)
sub get_mpath_uuid ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($dev) = @_; + my $uuid;
if ($dev =~ /^/dev//) { $dev = substr ($dev, 5); }
open (*FILE, "/sys/block/$dev/dm/uuid") or die "$!\n"; - - chomp (my $uuid = <FILE>); - + chomp ($uuid = <FILE>); close (FILE);
return ($name); @@ -392,9 +366,9 @@ sub get_mpath_uuid ($)
sub get_mpath_slaves ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($dev) = @_; + my @slaves;
if ($dev =~ /^/dev//) { $dev = substr ($dev, 5); @@ -402,12 +376,10 @@ sub get_mpath_slaves ($)
opendir (*DIR, "/sys/block/$dev/slaves/") or die "$!\n";
- my @slaves = grep { !/^./ } readdir (DIR); - + @slaves = grep { !/^./ } readdir (DIR); if ($slaves[0] =~ /^dm/) { @slaves = get_mpath_slaves ($slaves[0]); - } - else { + } else { @slaves = map { "/dev/$_" } @slaves; }
@@ -418,73 +390,53 @@ sub get_mpath_slaves ($)
sub get_registration_keys ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($dev) = @_; + my @keys;
my $cmd = "sg_persist -n -i -k -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; - - waitpid ($pid, 0); + my @out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- my @keys; - - while (<OUT>) { - chomp; - + foreach (@out) { + chomp; if ($_ =~ s/^\s+0x//i) { push (@keys, $_); } }
- close (IN); - close (OUT); - close (ERR); - return (@keys); }
sub get_reservation_key ($) { - (my $self = (caller(0))[3]) =~ s/^main:://; - + my $self = (caller(0))[3]; my ($dev) = @_; + my $key;
my $cmd = "sg_persist -n -i -r -d $dev"; - my $pid = open3 (*IN, *OUT, *ERR, $cmd) or die "$!\n"; - - waitpid ($pid, 0); + my @out = qx { $cmd };
die "[error]: $self\n" if ($?>>8);
- my $key; - - while (<OUT>) { - chomp; - + foreach (@out) { + chomp; if ($_ =~ s/^\s+key=0x//i) { $key = $_; last; } }
- close (IN); - close (OUT); - close (ERR); - - return ($key); + return ($key) }
sub get_options_stdin () { my $num = 0;
- while (<STDIN>) - { + while (<STDIN>) { chomp; - s/^\s*//; s/\s*$//;
@@ -548,29 +500,102 @@ sub print_version () exit (0); }
+sub print_metadata () +{ + print "<?xml version=\"1.0\" ?>\n"; + print "<resource-agent name="fence_scsi"" . + " shortdesc="fence agent for SCSI-3 persistent reservations">\n"; + print "<longdesc>fence_scsi</longdesc>\n"; + print "<parameters>\n"; + print "\t<parameter name="aptpl" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-a"/>\n"; + print "\t\t<content type="boolean"/>\n"; + print "\t\t<shortdesc lang="en">" . + "Use APTPL flag for registrations" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "\t<parameter name="devices" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-d"/>\n"; + print "\t\t<content type="string"/>\n"; + print "\t\t<shortdesc lang="en">" . + "List of devices to be used for fencing action" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "\t<parameter name="logfile" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-f"/>\n"; + print "\t\t<content type="string"/>\n"; + print "\t\t<shortdesc lang="en">" . + "File to write error/debug messages" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "\t<parameter name="key" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-k"/>\n"; + print "\t\t<content type="string"/>\n"; + print "\t\t<shortdesc lang="en">" . + "Key value to be used for fencing action" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "\t<parameter name="action" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-o"/>\n"; + print "\t\t<content type="string" default="off"/>\n"; + print "\t\t<shortdesc lang="en">" . + "Fencing action" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "\t<parameter name="nodename" unique="1" required="0">\n"; + print "\t\t<getopt mixed="-n"/>\n"; + print "\t\t<content type="string"/>\n"; + print "\t\t<shortdesc lang="en">" . + "Name of node" . + "</shortdesc>\n"; + print "\t</parameter>\n"; + print "</parameters>\n"; + print "<actions>\n"; + print "\t<action name="on"/>\n"; + print "\t<action name="off"/>\n"; + print "\t<action name="status"/>\n"; + print "\t<action name="metadata"/>\n"; + print "</actions>\n"; + print "</resource-agent>\n"; + + exit (0); +} + ################################################################################
if (@ARGV > 0) { - getopts ("ad:f:hk:n:o:qV") or die "$!\n"; + getopts ("ad:f:hk:n:o:qV") or print_usage;
print_usage if (defined $opt_h); print_version if (defined $opt_V); + + ## handle the metadata action here to avoid other parameter checks + ## + if ($opt_o =~ /^metadata$/i) { + print_metadata; + } } else { get_options_stdin (); }
+## if the logfile (-f) parameter was specified, open the logfile +## and redirect STDOUT and STDERR to the logfile. +## if (defined $opt_f) { open (LOG, ">$opt_f") or die "$!\n"; open (STDOUT, ">&LOG"); open (STDERR, ">&LOG"); }
+## verify that either key or nodename have been specified +## if ((!defined $opt_n) && (!defined $opt_k)) { - log_error ("No '-n' or '-k' flag specified."); - exit (1); + print_usage (); }
+## determine key value +## if (defined $opt_k) { $key = $opt_k; } @@ -578,6 +603,20 @@ else { $key = get_key ($opt_n); }
+## verify that key is not zero +## +if ($key == 0) { + log_error ("key cannot be zero"); +} + +## remove any leading zeros from key +## +if ($key =~ /^0/) { + $key =~ s/^0+//; +} + +## get devices +## if (defined $opt_d) { @devices = split (/\s*,\s*/, $opt_d); } @@ -585,10 +624,20 @@ else { @devices = get_devices_clvm (); }
+## verify that device list is not empty +## +if (scalar (@devices) == 0) { + log_error ("no devices found"); +} + +## default action is "off" +## if (!defined $opt_o) { $opt_o = "off"; }
+## determine the action to perform +## if ($opt_o =~ /^on$/i) { do_action_on ($key, @devices); } @@ -603,6 +652,8 @@ else { exit (1); }
+## close the logfile +## if (defined $opt_f) { close (LOG); }