blob: 51c56467c241276b943b4511d08134cd5ce2b06f [file] [log] [blame]
#!/usr/bin/perl
use Getopt::Long;
my $ME = $0;
END {
defined fileno STDOUT or return;
close STDOUT and return;
warn "$ME: failed to close standard output: $!\n";
$? ||= 1;
}
# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;
$opt_o = 'reset'; # Default fence action
$opt_t = '300'; # Default fence timeout (seconds)
$extra_args = '-E';
sub usage
{
print "Helper that presents a RHCS-style interface to stonith-ng for CMAN based clusters\n\n";
print "Should never need to use invoked by the user directly\n\n";
print "\n";
print "Usage: $pname [options]\n";
print "\n";
print "Options:\n";
print " -h usage\n";
print " -n <name> nodename\n";
print " -o <string> Action: on | off | reset (default) | stat | hostlist\n";
print " -q quiet mode\n";
print " -V version\n";
exit 0;
}
sub print_metadata
{
print '<?xml version="1.0" ?>
<resource-agent name="fence_pcmk" shortdesc="Helper that presents a RHCS-style interface to stonith-ng for CMAN based clusters" >
<longdesc>
Should never need to use invoked by the user directly and should only
be configured in cluster.conf, not directly in Pacemaker.
</longdesc>
<vendor-url>http://www.clusterlabs.org</vendor-url>
<parameters>
<parameter name="action" unique="1" required="1">
<getopt mixed="-o &lt;action&gt;" />
<content type="string" default="disable" />
<shortdesc lang="en">Fencing Action</shortdesc>
</parameter>
<parameter name="port" unique="1" required="1">
<getopt mixed="-n &lt;id&gt;" />
<content type="string" />
<shortdesc lang="en">Physical plug number or name of virtual machine</shortdesc>
</parameter>
<parameter name="help" unique="1" required="0">
<getopt mixed="-h" />
<content type="string" />
<shortdesc lang="en">Display help and exit</shortdesc>
</parameter>
</parameters>
<actions>
<action name="enable" />
<action name="disable" />
<action name="status" />
<action name="metadata" />
</actions>
</resource-agent>
';
}
sub fail
{
($msg) = @_;
print $msg."\n" unless defined $opt_q;
$t->close if defined $t;
exit 1;
}
sub fail_usage
{
($msg)=@_;
print STDERR $msg."\n" if $msg;
print STDERR "Please use '-h' for usage.\n";
exit 1;
}
sub version
{
print "1.0.0\n";
exit 0;
}
sub get_options_stdin
{
my $opt;
my $line = 0;
while( defined($in = <>) )
{
$_ = $in;
chomp;
# strip leading and trailing whitespace
s/^\s*//;
s/\s*$//;
# skip comments
next if /^#/;
$line+=1;
$opt=$_;
next unless $opt;
($name,$val)=split /\s*=\s*/, $opt, 2;
if ( $name eq "" )
{
print STDERR "parse error: illegal name in option $line\n";
exit 2;
}
# DO NOTHING -- this field is used by fenced
elsif ($name eq "agent" ) {}
elsif ($name eq "timeout" )
{
$opt_t = $val;
}
elsif ($name eq "option" || $name eq "action" )
{
$opt_o = $val;
}
elsif ($name eq "port" )
{
$opt_n = $val;
}
else
{
$ENV{$name} = $val;
}
}
}
######################################################################33
# MAIN
if (@ARGV > 0) {
GetOptions("n=s"=>\$opt_n,
"o=s"=>\$opt_o,
"t=s"=>\$opt_t,
"q" =>\$opt_q,
"V" =>\$opt_V,
"version" =>\$opt_V,
"help" =>\$opt_h,
"h" =>\$opt_h) || fail_usage;
foreach (@ARGV) {
print "$_\n";
}
# getopts("ht:n:o:s:qV") || fail_usage ;
usage if defined $opt_h;
version if defined $opt_V;
fail_usage "Unknown parameter." if (@ARGV > 0);
} else {
get_options_stdin();
}
if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
print_metadata();
exit 0;
}
$opt_o=lc($opt_o);
fail "failed: unrecognised action: $opt_o"
unless $opt_o =~ /^(on|off|reset|reboot|stat|status|monitor|list|hostlist|poweroff|poweron)$/;
sub term_handler {
local $SIG{TERM} = 'IGNORE';
kill(TERM,-getpgrp($$));
}
setpgrp($$,0);
$agent_pid=$$;
if ( $pid=fork() == 0 )
{
$cmd="--help $opt_o";
if ( $opt_o eq "monitor" || $opt_o eq "stat" || $opt_o eq "status" || $opt_o eq "list" ) {
$cmd="--list";
$cmd="--list-registered" unless defined $opt_n;
} else {
fail "failed: no plug number" unless defined $opt_n;
if ( $opt_o eq "reboot" || $opt_o eq "reset" ) {
$cmd="--reboot";
} elsif ( $opt_o eq "on" || $opt_o eq "poweron" ) {
$cmd="--unfence";
} elsif ( $opt_o eq "off" || $opt_o eq "poweroff" ) {
$cmd="--fence";
}
system "logger -p daemon.notice -t \"fence_pcmk[$agent_pid]\" \"Requesting Pacemaker fence $opt_n ($opt_o)\"";
}
exec "stonith_admin $cmd $opt_n --tolerance 5s --tag cman" or die "failed to exec \"stonith_admin $cmd $opt_n\"\n";
}
$SIG{TERM} = \&term_handler;
wait;
$status=$?/256;
print (($status == 0 ? "success":"failed") . ": $opt_n $status\n")
unless defined $opt_q;
if ( $status != 0 ) {
system "logger -p daemon.notice -t \"fence_pcmk[$agent_pid]\" \"Call to fence $opt_n ($opt_o) failed with rc=$status\"";
}
exit ($status == 0 ? 0 : 1 );