Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 636d2bc385af29f3f773eb0cdc8fed8992f367fd
Parent: 5e8ef2ca3e43652e77b277fe72eb3832d2c2b656
Author: Ryan O'Hara <rohara(a)redhat.com>
AuthorDate: Mon Sep 27 10:50:12 2010 -0500
Committer: Ryan O'Hara <rohara(a)redhat.com>
CommitterDate: Mon Sep 27 10:59:33 2010 -0500
fence_scsi_test: rewrite to more accurately test
The old fence_scsi_test tool was far too simple to adequately
test it a devices was capable of being used with fence_scsi.
This rewrite should adequately test all requirements, such as
support for "preempt-and-abort" subcommand. This script will
also verify that each command worked as expected.
Resolves: rhbz#603838
Signed-off-by: Ryan O'Hara <rohara(a)redhat.com>
---
fence/agents/scsi/fence_scsi_test.pl | 748 ++++++++++++++++++++++++++--------
fence/man/fence_scsi_test.8 | 68 +++
2 files changed, 653 insertions(+), 163 deletions(-)
diff --git a/fence/agents/scsi/fence_scsi_test.pl b/fence/agents/scsi/fence_scsi_test.pl
index e24ef61..25db6ba 100755
--- a/fence/agents/scsi/fence_scsi_test.pl
+++ b/fence/agents/scsi/fence_scsi_test.pl
@@ -1,272 +1,694 @@
#!/usr/bin/perl
-use POSIX;
-use IPC::Open3;
-use XML::LibXML;
-use Getopt::Std;
-
-my @devices;
-my %results;
-
#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="";
$REDHAT_COPYRIGHT="";
$BUILD_DATE="";
#END_VERSION_GENERATION
-sub get_scsi_block_devices
+################################################################################
+
+use File::Basename;
+use Term::ANSIColor;
+use Getopt::Long;
+use XML::LibXML;
+
+################################################################################
+
+my @devices = ();
+my %devices_name = ();
+my %devices_path = ();
+my %options = ();
+my %results = ();
+
+################################################################################
+
+sub do_action_on (\@$$)
{
- print "[debug] get_scsi_block_devices\n" if ($opt_d);
+ my @devices = @{(shift)};
+ my ($dev, $node_key) = @_;
+ my $err = 0;
- my $block_dir = "/sys/block";
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev node_key=$node_key)\n";
+ }
- opendir(DIR, $block_dir) or die "$!\n";
+ foreach (@devices) {
+ if (do_reset ($_) != 0) {
+ }
+ if (do_register_ignore ($_, $node_key) != 0) {
+ $err++;
+ }
+ }
- my @block_devices = grep { /^sd*/ } readdir(DIR);
+ if (scalar (get_keys_reserve ($dev)) == 0) {
+ if (do_reserve ($dev, $node_key) != 0) {
+ $err = 0;
+ }
+ }
- closedir(DIR);
+ return ($err);
+}
- for $block_dev (@block_devices)
- {
- print "[debug] \t device = $block_dev\n" if ($opt_d);
+sub do_action_off ($$$)
+{
+ my ($dev, $node_key, $host_key) = @_;
+ my $err = 0;
- push(@devices, "/dev/" . $block_dev);
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev node_key=$node_key host_key=$host_key)\n";
}
+
+ if (do_preempt_abort ($dev, $host_key, $node_key) != 0) {
+ $err++;
+ }
+
+ return ($err);
}
-sub get_cluster_vol_devices
+sub do_verify_on (\@$$)
{
- print "[debug] get_cluster_vol_devices\n" if ($opt_d);
+ my @devices = @{(shift)};
+ my ($dev, $node_key) = @_;
+ my $err = 0;
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev node_key=$node_key)\n";
+ }
+
+ @keys = grep { /^$node_key$/ } get_keys_register ($dev);
- my ($in, $out, $err);
+ if (scalar (@keys) != scalar (@devices)) {
+ $err++;
+ }
- my $cmd = "vgs --config 'global { locking_type = 0 }'" .
- " --noheadings --separator : -o vg_attr,pv_name";
+ @keys = get_keys_reserve ($dev);
- my $pid = open3($in, $out, $err, $cmd) or die "$!\n";
+ if (scalar (@keys) == 0) {
+ $err++;
+ }
- waitpid($pid, 0);
+ return ($err);
+}
- die "[error] unable to execute vgs command.\n" if WEXITSTATUS($?);
+sub do_verify_off ($$$)
+{
+ my ($dev, $node_key, $host_key) = @_;
+ my $err = 0;
- while (<$out>)
- {
- chomp;
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev node_key=$node_key host_key=$host_key)\n";
+ }
- my ($vg_attr, $pv_name) = split(/:/, $_);
+ @keys = grep { /^$node_key$/ } get_keys_register ($dev);
- if ($vg_attr =~ /.*c$/)
- {
- print "[debug] \t device = $pv_name\n" if ($opt_d);
+ if (scalar (@keys) != 0) {
+ $err++;
+ }
- push(@devices, $pv_name);
- }
+ @keys = grep { /^$host_key$/ } get_keys_reserve ($dev);
+
+ if (scalar (@keys) == 0) {
+ $err++;
}
- close($in);
- close($out);
- close($err);
+ return ($err);
}
-sub register_device
+sub do_key_write ($)
{
- my ($dev, $key) = @_;
- my ($in, $out, $err);
+ my $key = shift;
- print "[debug] register_device (device=$dev, key=$key)\n" if ($opt_d);
+ open (\*FILE, ">/tmp/.fence_scsi_test") or die "$!\n";
+ print (FILE "$key\n");
+ close (FILE);
- my $cmd = "sg_persist -n -d $dev -o -G -S $key";
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (key=$key)\n";
+ }
- print "[debug] \t cmd = $cmd\n" if ($opt_d);
+ return;
+}
- my $pid = open3($in, $out, $err, $cmd) or die "$!\n";
+sub do_key_read ($)
+{
+ my $key = shift;
- waitpid($pid, 0);
+ open (\*FILE, "</tmp/.fence_scsi_test") or die "$!\n";
+ chomp ($$key = <FILE>);
+ close (FILE);
- $results{$dev}[0] = WEXITSTATUS($?);
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (key=$$key)\n";
+ }
- close($in);
- close($out);
- close($err);
+ return;
}
-sub unregister_device
+sub do_register ($$)
{
- my ($dev, $key) = @_;
- my ($in, $out, $err);
+ my ($dev, $sark) = @_;
- print "[debug] unregister_device (device=$dev, key=$key)\n" if ($opt_d);
+ my $cmd = "sg_persist -n -o -G -S $sark -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
- my $cmd = "sg_persist -n -d $dev -o -G -K $key -S 0";
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev sark=$sark)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ }
- print "[debug] \t cmd = $cmd\n" if ($opt_d);
+ return ($err);
+}
- my $pid = open3($in, $out, $err, $cmd) or die "$!\n";
+sub do_register_ignore ($$)
+{
+ my ($dev, $sark) = @_;
- waitpid($pid, 0);
+ my $cmd = "sg_persist -n -o -I -S $sark -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
- $results{$dev}[1] = WEXITSTATUS($?);
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev sark=$sark)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ }
- close($in);
- close($out);
- close($err);
+ return ($err);
}
-sub test_devices
+sub do_reserve ($$)
{
- my $key = "0x1";
+ my ($dev, $rk) = @_;
+
+ my $cmd = "sg_persist -n -o -R -T 5 -K $rk -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
- foreach $dev (@devices)
- {
- register_device($dev, $key);
- unregister_device($dev, $key);
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev rk=$rk)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
}
+
+ return ($err);
}
-sub check_config_fence
+sub do_release ($$)
{
- my $xml = XML::LibXML->new();
- my $tree = $xml->parse_file("/etc/cluster/cluster.conf");
- my $root = "//cluster/fencedevices/fencedevice";
+ my ($dev, $rk) = @_;
- my $xpath_fence = "count(${root}[\@agent='fence_scsi'])";
+ my $cmd = "sg_persist -n -o -L -T 5 -K $rk -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev rk=$rk)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ }
- return ( ! $tree->findvalue($xpath_fence));
+ return ($err);
}
-sub check_config_nodes
+sub do_preempt ($$$)
{
- my $xml = XML::LibXML->new();
- my $tree = $xml->parse_file("/etc/cluster/cluster.conf");
- my $root = "//cluster/clusternodes/clusternode";
+ my ($dev, $rk, $sark) = @_;
- my $xpath_name = "count(${root}/\@name)";
- my $xpath_nodeid = "count(${root}/\@nodeid)";
+ my $cmd = "sg_persist -n -o -P -T 5 -K $rk -S $sark -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev rk=$rk sark=$sark)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ }
- return ($tree->findvalue($xpath_name) != $tree->findvalue($xpath_nodeid));
+ return ($err);
}
-sub print_results
+sub do_preempt_abort ($$$)
{
- my $device_count = scalar(@devices);
+ my ($dev, $rk, $sark) = @_;
- my $failure_count = 0;
- my $success_count = 0;
+ my $cmd = "sg_persist -n -o -A -T 5 -K $rk -S $sark -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
- print "\nAttempted to register with devices:\n";
- print "-------------------------------------\n";
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev rk=$rk sark=$sark)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ }
- for $dev (@devices)
- {
- print "\t$dev\t";
- if ($results{$dev}[0] == 0)
- {
- $success_count++;
- print "Success\n";
- }
- else
- {
- $failure_count++;
- print "Failure\n";
- }
+ return ($err);
+}
+
+sub do_clear ($$)
+{
+ my ($dev, $rk) = @_;
+
+ my $cmd = "sg_persist -n -o -C -K $rk -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev rk=$rk)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
}
- print "-------------------------------------\n";
- print "Number of devices tested: $device_count\n";
- print "Number of devices passed: $success_count\n";
- print "Number of devices failed: $failure_count\n\n";
+ return ($err);
+}
+
+sub do_reset ($)
+{
+ my ($dev) = @_;
+
+ my $cmd = "sg_turs $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
- if ($failure_count != 0)
- {
- exit(1);
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
}
+
+ return ($err);
}
-sub print_usage
+sub get_options ()
{
- print "\nUsage: fence_scsi_test [-c|-s] [-d] [-h]\n\n";
+ my @opts = ("d|device=s",
+ "h|help",
+ "k|key=s",
+ "o|action=s",
+ "t|test=s",
+ "v|verbose");
- print "Options:\n\n";
+ Getopt::Long::Configure ("no_auto_abbrev") or exit (1);
+ Getopt::Long::GetOptions (\%options, @opts) or exit (1);
- print " -c Cluster mode. This mode is intended to test\n";
- print " SCSI persistent reservation capabilties for\n";
- print " devices that are part of existing clustered\n";
- print " volumes. Only devices in LVM cluster volumes\n";
- print " will be tested.\n\n";
- print " -s SCSI mode. This mode is intended to test SCSI\n";
- print " persistent reservation capabilities for all SCSI\n";
- print " devices visible on a node.\n\n";
- print " -d Debug flag. This will print debugging information\n";
- print " such as the actual commands being run to register\n";
- print " and unregister a device.\n\n";
- print " -h Help. Prints out this usage information.\n\n";
+ return;
}
-sub test_tools_path
+sub get_devices ()
{
- my $tool_name = "sg_persist";
-
- for my $path ( split /:/, $ENV{PATH} ) {
- if ( -f "$path/$tool_name" && -x _ ) {
- return;
- }
+ my @devices = split (/,/, $options{'d'});
+
+ map { s/^\s+// } @devices;
+ map { s/\s+$// } @devices;
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self\n";
+ }
+
+ return (@devices);
+}
+
+sub get_devices_clvm ()
+{
+ my @devices = ();
+
+ my $cmd = "vgs" .
+ " --noheadings" .
+ " --sort pv_uuid" .
+ " --options pv_name,vg_attr" .
+ " --config 'global { locking_type=0 }'";
+
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ @devices = map { (split)[0] } grep { /c$/ } @out;
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self\n";
+ }
+
+ return (@devices);
+}
+
+sub get_devices_scsi ()
+{
+ my @devices = ();
+
+ open (\*DIR, "/sys/block/") or die "$!\n";
+ @devices = grep { /^sd/ } readdir (DIR);
+ close (DIR);
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self\n";
+ }
+
+ return (@devices);
+}
+
+sub get_devices_name ($)
+{
+ my $dev = shift;
+ my $name = basename ($dev);
+
+ if (-l "/dev/mpath/$name") {
+ $name = basename (readlink "/dev/mpath/$name");
+ }
+
+ $name = "/dev/$name";
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " name=$name\n";
}
-
- die "No $tool_name command available, please install the sg3_utils
package.\n"
+
+ return ($name);
}
-### MAIN #######################################################################
+sub get_devices_path ($)
+{
+ my $dev = shift;
+ my $name = basename ($dev);
+ my @path = ();
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ }
+
+ if (-d "/sys/block/$name/slaves/") {
+ opendir (\*DIR, "/sys/block/$name/slaves/");
+ @path = grep { !/^\./ } readdir (DIR);
+ closedir (DIR);
+ }
+
+ if (scalar (@path) == 0) {
+ push (@path, $name);
+ }
-test_tools_path;
+ if ($path[0] =~ /^dm/) {
+ @path = get_devices_path ("/dev/$path[0]");
+ } else {
+ @path = map { "/dev/$_" } @path;
+ if (defined $options{'v'}) {
+ print " path=[ @path ]\n";
+ }
+ }
-if (getopts("cdhst:v") == 0)
+ return (@path);
+}
+
+sub get_devices_info ($)
{
- print_usage;
- exit(1);
+ my $dev = shift;
+ my $name = basename ($dev);
+ my @info = ();
+
+ if (-e "/sys/block/$name/device/vendor") {
+ open (\*FILE, "</sys/block/$name/device/vendor");
+ chomp ($info[0] = <FILE>);
+ close (FILE);
+ }
+
+ if (-e "/sys/block/$name/device/model") {
+ open (\*FILE, "</sys/block/$name/device/model");
+ chomp ($info[1] = <FILE>);
+ close (FILE);
+ }
+
+ map { s/^\s+// } @info;
+ map { s/\s+$// } @info;
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " info=[ @info ]\n";
+ }
+
+ return (@info);
}
-if ($opt_h)
+sub get_keys_register ($)
{
- print_usage;
- exit(0);
+ my $dev = shift;
+ my @keys = ();
+
+ my $cmd = "sg_persist -n -i -k -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ foreach (@out) {
+ chomp;
+ push (@keys, $_) if ($_ =~ s/^\s+0x//i);
+ }
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ print " keys=[ @keys ]\n";
+ }
+
+ return (@keys);
}
-if ($opt_c && $opt_s) {
- print_usage;
- exit(1);
+sub get_keys_reserve
+{
+ my $dev = shift;
+ my @keys = ();
+
+ my $cmd = "sg_persist -n -i -r -d $dev";
+ my @out = qx { $cmd 2> /dev/null };
+ my $err = ($?>>8);
+
+ foreach (@out) {
+ chomp;
+ push (@keys, $_) if ($_ =~ s/^\s+key=0x//i);
+ }
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " cmd=$cmd\n";
+ print " err=$err\n";
+ print " keys=[ @keys ]\n";
+ }
+
+ return (@keys);
}
-if ($opt_c)
+sub test_config_fence ()
{
- print "\nTesting devices in cluster volumes...\n";
- get_cluster_vol_devices;
- test_devices;
- print_results;
+ my $xml = XML::LibXML->new();
+ my $file = "/etc/cluster/cluster.conf";
+ my $tree = $xml->parse_file ($file);
+ my $root = "//cluster/fencedevices/fencedevice";
+ my $err = 0;
+
+ my $xpath_agent = "count(${root}[\@agent='fence_scsi'])";
+
+ if ($tree->findvalue ($xpath_agent) == 0) {
+ $err = 1;
+ }
+
+ exit ($err);
}
-if ($opt_s)
+sub test_config_nodes ()
{
- print "\nTesting all SCSI block devices...\n";
- get_scsi_block_devices;
- test_devices;
- print_results;
+ my $xml = XML::LibXML->new();
+ my $file = "/etc/cluster/cluster.conf";
+ my $tree = $xml->parse_file ($file);
+ my $root = "//cluster/clusternodes/clusternode";
+ my $err = 0;
+
+ my $xpath_name = "count(${root}/\@name)";
+ my $xpath_nodeid = "count(${root}/\@nodeid)";
+
+ if ($tree->findvalue ($xpath_name) != $tree->findvalue ($xpath_nodeid)) {
+ $err = 1;
+ }
+
+ exit ($err);
}
-if ($opt_t)
+sub print_devices ()
{
- if ($opt_t eq "fence")
- {
- exit check_config_fence;
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self\n";
+ foreach (@devices) {
+ print " $_\n";
+ }
}
- if ($opt_t eq "nodes")
- {
- exit check_config_nodes;
+
+ return;
+}
+
+sub print_options ()
+{
+ return;
+}
+
+sub print_results ($)
+{
+ my $dev = shift;
+ my @results = @{$results{$dev}};
+
+ if (defined $options{'v'}) {
+ $self = (caller(0))[3];
+ print " $self (dev=$dev)\n";
+ print " results=[ action=$results[0] verify=$results[1] ]\n";
+ } else {
+ printf (" %-*s", $width, $_);
+ if (grep { $_ } @results) {
+ $test = colored (" FAIL ", "red");
+ } else {
+ $test = colored (" OK ", "green");
+ }
+ printf ("[%s]\n", $test);
}
+
+ return;
}
-if (!$opt_c && !$opt_s && !$opt_t)
+sub print_usage
{
- print "\nPlease specify either cluster or SCSI mode.\n";
- print_usage;
- exit(1);
+ print "\n";
+ print "Usage: fence_scsi_test -o <on|off> -k <key>
[options]\n";
+ print "\n";
+ print "Actions:\n";
+ print "\n";
+ print " on Register <key> with the devices.\n";
+ print " off Remove <key> form the devices.\n";
+ print "\n";
+ print "Options:\n";
+ print "\n";
+ print " -d, --devices=LIST Devices used for the current action.\n";
+ print " -h, --help Display this help and exit.\n";
+ print " -v, --verbose Verbose mode.\n";
+ print "\n";
+
+ defined $options{'h'} ? exit (0) : exit (1);
+}
+
+################################################################################
+
+get_options ();
+
+if (scalar (keys %options) == 0) {
+ print_usage ();
+}
+
+if (defined $options{'v'}) {
+ print_options ();
+}
+
+if (defined $options{'h'}) {
+ print_usage ();
+}
+
+if (defined $options{'t'}) {
+ for ($options{'t'}) {
+ ($_ =~ /^fence$/i) && do {
+ test_config_fence ();
+ last;
+ };
+ ($_ =~ /^nodes$/i) && do {
+ test_config_nodes ();
+ last;
+ };
+ exit (1);
+ }
+}
+
+if ($options{'k'} =~ /^[[:xdigit:]]+$/) {
+ $node_key = lc ($options{'k'});
+} else {
+ print_usage ();
+}
+
+for ($options{'o'}) {
+ ($_ =~ /^on$/i) && do {
+ do_key_write ($node_key);
+ last;
+ };
+ ($_ =~ /^off$/i) && do {
+ do_key_read (\$host_key);
+ last;
+ };
+ print_usage ();
+}
+
+if (defined $options{'d'}) {
+ @devices = get_devices ();
+} else {
+ @devices = get_devices_clvm ();
+}
+
+if (scalar (@devices) == 0) {
+ die "error: no devices found\n";
+} else {
+ $count = scalar (@devices);
+ $width = (reverse sort { $a <=> $b } map { (length) + 8 } @devices)[0];
+}
+
+if (defined $options{'v'}) {
+ print_devices ();
+}
+
+foreach (@devices) {
+ if (! -e $_) {
+ die "error: $_ does not exist\n";
+ }
+ if (! -b $_) {
+ die "error: $_ is not a block device\n";
+ }
+
+ $devices_name{$_} = get_devices_name ($_);
+ $devices_path{$_} = [ get_devices_path ($devices_name{$_}) ];
+}
+
+for ($options{'o'}) {
+ ($_ =~ /^on$/i) && do {
+ print "\n" if (!defined $options{'v'});
+ foreach (@devices) {
+ $results{$_}[0] = do_action_on (@{$devices_path{$_}}, $_, $node_key);
+ $results{$_}[1] = do_verify_on (@{$devices_path{$_}}, $_, $node_key);
+ print_results ($_);
+ }
+ print "\n" if (!defined $options{'v'});
+ last;
+ };
+ ($_ =~ /^off$/i) && do {
+ print "\n" if (!defined $options{'v'});
+ foreach (@devices) {
+ $results{$_}[0] = do_action_off ($devices_name{$_}, $node_key, $host_key);
+ $results{$_}[1] = do_verify_off ($devices_name{$_}, $node_key, $host_key);
+ print_results ($_);
+ }
+ print "\n" if (!defined $options{'v'});
+ last;
+ };
+ print_usage ();
}
diff --git a/fence/man/fence_scsi_test.8 b/fence/man/fence_scsi_test.8
new file mode 100644
index 0000000..3252dca
--- /dev/null
+++ b/fence/man/fence_scsi_test.8
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+.\"
+.\" This copyrighted material is made available to anyone wishing to use,
+.\" modify, copy, or redistribute it subject to the terms and conditions
+.\" of the GNU General Public License v.2.
+
+.TH fence_scsi_test 8
+
+.SH NAME
+fence_scsi_test - Test for SCSI persistent reservation fencing
+
+.SH SYNOPSIS
+.B
+fence_scsi_test -o <on|off> -k <key>
+[\fIOPTIONS\fR]
+
+.SH DESCRIPTION
+fence_scsi_test is a script used to verify that specific hardware
+configurations are capable of being used with the fence_scsi
+agent. All storage devices that are to be used with the fence_scsi
+agent must be capable of SCSI persistent reservations. This script
+assists in determining that the requirements are met by performing
+appropriate SCSI-PR actions and verifying the results.
+
+This script is capable of creating reservations and registrations, as
+well as removing them. The "on" action is used to create reservations,
+just as you would do when a node comes online. The "off" action is
+used to remove registrations, which is equivalent to fencing. It is
+important to test both the "on" and "off" actions when testing for
+fence_scsi compatibility.
+
+Because this script is capable of creating, modifying, and removing
+existing reservations and registrations, it should not be used on any
+systems that are actively using SCSI persistent reservations.
+
+.SH OPTIONS
+.TP
+\fB-o, --action=[on|off]\fR
+The action to perform. This value can be "on" or "off". For
"on", the
+script will attempt to register a key (see -k option) with the
+device(s) (see -d option) and create a reservation if none exists. The
+"off" action will attempt to remove a key from the device(s). This
+option is required.
+
+.TP
+\fB-k, --key=VALUE\fR
+The key to use for the current action. The key must be a hexadecimal
+value and should be unique to a node. For the "on" action, the key
+specifies the key value use to register the local node with the
+device(s). For the "off" action, the key specifies the key value to be
+removed from the device(s).
+
+.TP
+\fB-d, --devices=LIST\fR
+List of devices to use for current action. This can be a single device
+or a comma-separated list of devices. Each device should be given as
+the full path (eg. /dev/sdc).
+
+.TP
+\fB-h, --help\fR
+Print out a help message describing available options, then exit.
+
+.TP
+\fB-v, --verbose\fR
+Verbose output.
+
+.SH SEE ALSO
+fence_scsi(8), fence(8), fence_node(8), sg_persist(8), lvs(8), lvm.conf(5)