From 964daeeb59eb1458c792af0ba2088d06367147f4 Mon Sep 17 00:00:00 2001 From: Marek 'marx' Grac <mgrac@redhat.com> Date: Sun, 20 Dec 2009 16:37:54 +0100 Subject: [PATCH] fencing: New fence agent for IBM BladeCenter New implementation of fence_ibmblade based on fencing library. Agent took from STABLE3 branch. Resolves: rhbz#532922 (ibm_bladecenter part) --- fence/agents/ibmblade/Makefile | 2 +- fence/agents/ibmblade/fence_ibmblade.pl | 286 ------------------------------- fence/agents/ibmblade/fence_ibmblade.py | 79 +++++++++ 3 files changed, 80 insertions(+), 287 deletions(-) delete mode 100755 fence/agents/ibmblade/fence_ibmblade.pl create mode 100644 fence/agents/ibmblade/fence_ibmblade.py diff --git a/fence/agents/ibmblade/Makefile b/fence/agents/ibmblade/Makefile index ad29a48..ec8e62b 100644 --- a/fence/agents/ibmblade/Makefile +++ b/fence/agents/ibmblade/Makefile @@ -11,7 +11,7 @@ ############################################################################### ############################################################################### -SOURCE= fence_ibmblade.pl +SOURCE= fence_ibmblade.py TARGET= fence_ibmblade top_srcdir=../.. diff --git a/fence/agents/ibmblade/fence_ibmblade.pl b/fence/agents/ibmblade/fence_ibmblade.pl deleted file mode 100755 index bc1efc8..0000000 --- a/fence/agents/ibmblade/fence_ibmblade.pl +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/perl - -############################################################################### -############################################################################### -## -## Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -## Copyright (C) 2004-2007 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. -## -############################################################################### -############################################################################### - -use Getopt::Std; -use Net::SNMP; - -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 = $_; - -my $sleep_time = 5; -my $snmp_timeout = 10; -$opt_o = "reboot"; -$opt_u = 161; - -my $oid_powerState = ".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4"; # remoteControlBladePowerState -my $oid_powerChange = ".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7"; # powerOnOffBlade -my $oid_resetPower = ".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.8"; # restartBlade - -# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and -# "#END_VERSION_GENERATION" It is generated by the Makefile - -#BEGIN_VERSION_GENERATION -$FENCE_RELEASE_NAME=""; -$REDHAT_COPYRIGHT=""; -$BUILD_DATE=""; -#END_VERSION_GENERATION - -sub usage -{ - print "Usage:\n"; - print "\n"; - print "$pname [options]\n"; - print "\n"; - print "Options:\n"; - print " -a <ip> IP address or hostname of BladeCenter\n"; - print " -h usage\n"; - print " -c <community> SNMP Community\n"; - print " -n <num> Port number to disable\n"; - print " -o <string> Action: Reboot (default), On or Off\n"; - print " -u <udpport> UDP port to use (default: 161)\n"; - print " -q quiet mode\n"; - print " -t test power state\n"; - print " -V version\n"; - - exit 0; -} - -sub fail_usage -{ - ($msg)=@_; - print STDERR $msg."\n" if $msg; - print STDERR "Please use '-h' for usage.\n"; - exit 1; -} - -sub fail -{ - ($msg) = @_; - print $msg."\n" unless defined $opt_q; - $t->close if defined $t; - exit 1; -} - -sub version -{ - print "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n"; - print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT ); - - 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; - - 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 "ipaddr" ) - { - $opt_a = $val; - } - elsif ($name eq "community" ) - { - $opt_c = $val; - } - - elsif ($name eq "option" ) - { - $opt_o = $val; - } - elsif ($name eq "port" ) - { - $opt_n = $val; - } - elsif ($name eq "udpport" ) - { - $opt_u = $val; - } - - # FIXME should we do more error checking? - # Excess name/vals will be eaten for now - else - { - fail "parse error: unknown option \"$opt\""; - } - } -} - -# ---------------------------- MAIN -------------------------------- - -if (@ARGV > 0) { - getopts("a:hc:n:o:qu:tV") || fail_usage ; - - usage if defined $opt_h; - version if defined $opt_V; - - fail_usage "Unknown parameter." if (@ARGV > 0); - - fail_usage "No '-a' flag specified." unless defined $opt_a; - fail_usage "No '-n' flag specified." unless defined $opt_n; - fail_usage "No '-c' flag specified." unless defined $opt_c; - fail_usage "Unrecognised action '$opt_o' for '-o' flag" - unless $opt_o =~ /^(reboot|on|off)$/i; - -} else { - get_options_stdin(); - - fail "failed: no IP address" unless defined $opt_a; - fail "failed: no plug number" unless defined $opt_n; - fail "failed: no SNMP community" unless defined $opt_c; - fail "failed: unrecognised action: $opt_o" - unless $opt_o =~ /^(reboot|on|off)$/i; -} - -my ($snmpsess, $error) = Net::SNMP->session ( - -hostname => $opt_a, - -version => "snmpv1", - -port => $opt_u, - -community => $opt_c, - -timeout => $snmp_timeout); - -if (!defined ($snmpsess)) { - printf("$FENCE_RELEASE_NAME ERROR: %s.\n", $error); - exit 1; -}; - -# first check in what state are we now -my $oid = $oid_powerState . "." . $opt_n; -my $oid_val = ""; -my $result = $snmpsess->get_request ( - -varbindlist => [$oid] -); -if (!defined($result)) { - printf("$FENCE_RELEASE_NAME ERROR: %s.\n", $snmpsess->error); - $snmpsess->close; - exit 1; -} - -if (defined ($opt_t)) { - printf ("$FENCE_RELEASE_NAME STATE: Port %d on %s returned %d\n", $opt_n, $opt_a, $result->{$oid}); - exit 1; -}; - -if ($opt_o =~ /^(reboot|off)$/i) { - if ($result->{$oid} == "0") { - printf ("$FENCE_RELEASE_NAME WARNING: Port %d on %s already down.\n", $opt_n, $opt_a); - $snmpsess->close; - exit 0; - }; -} else { - if ($result->{$oid} == "1") { - printf ("$FENCE_RELEASE_NAME WARNING: Port %d on %s already up.\n", $opt_n, $opt_a); - $snmpsess->close; - exit 0; - }; -}; - -# excellent, now change the state -if ($opt_o =~ /^reboot$/i) { - # reboot - $oid = $oid_resetPower . "." . $opt_n; - $oid_val = "1"; -} elsif ($opt_o =~ /^on$/i) { - # power on - $oid = $oid_powerChange . "." . $opt_n; - $oid_val = "1"; -} else { - # power down - $oid = $oid_powerChange . "." . $opt_n; - $oid_val = "0"; -}; - -$result = $snmpsess->set_request ( - -varbindlist => [$oid, INTEGER, $oid_val] -); - -if (!defined ($result)) { - # ignore this for now, seems like IBM BladeCenter has a broken SNMPd - # it almost always timeouts -}; - -# now, wait a bit and see if we have done it -sleep($sleep_time); - -$oid = $oid_powerState . "." . $opt_n; - -undef $result; -$result = $snmpsess->get_request ( - -varbindlist => [$oid] -); - -if (!defined($result)) { - # this is a real error - printf("$FENCE_RELEASE_NAME ERROR: %s.\n", $snmpsess->error); - $snmpsess->close; - exit 1; -}; - -if ($opt_o =~ /^(off)$/i) { - if ($result->{$oid} == "1") { - printf ("$FENCE_RELEASE_NAME ERROR: Port %d on %s still up.\n", $opt_n, $opt_a); - $snmpsess->close; - exit 1; - }; -} else { - if ($result->{$oid} == "0") { - printf ("$FENCE_RELEASE_NAME ERROR: Port %d on %s still down.\n", $opt_n, $opt_a); - $snmpsess->close; - exit 1; - }; -}; - -# everything's a ok :) -$snmpsess->close; - -printf ("$FENCE_RELEASE_NAME SUCCESS: Port %d on %s changed state to %s\n", $opt_n, $opt_a, $opt_o) unless defined $opt_q; -exit 0; - diff --git a/fence/agents/ibmblade/fence_ibmblade.py b/fence/agents/ibmblade/fence_ibmblade.py new file mode 100644 index 0000000..08022ea --- /dev/null +++ b/fence/agents/ibmblade/fence_ibmblade.py @@ -0,0 +1,79 @@ +#!/usr/bin/python + +import sys, re, pexpect +sys.path.append("/usr/lib/fence") +from fencing import * +from fencing_snmp import * + +#BEGIN_VERSION_GENERATION +FENCE_RELEASE_NAME="IBM Blade SNMP fence agent" +REDHAT_COPYRIGHT="" +BUILD_DATE="" +#END_VERSION_GENERATION + +### CONSTANTS ### +# From fence_ibmblade.pl +STATUSES_OID=".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4" # remoteControlBladePowerState +CONTROL_OID=".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7" # powerOnOffBlade + +# Status constants returned as value from SNMP +STATUS_DOWN=0 +STATUS_UP=1 + +# Status constants to set as value to SNMP +STATUS_SET_OFF=0 +STATUS_SET_ON=1 + +### FUNCTIONS ### + +def get_power_status(conn,options): + (oid,status)=conn.get("%s.%s"%(STATUSES_OID,options["-n"])) + return (status==str(STATUS_UP) and "on" or "off") + +def set_power_status(conn, options): + conn.set("%s.%s"%(CONTROL_OID,options["-n"]),(options["-o"]=="on" and STATUS_SET_ON or STATUS_SET_OFF)) + +def get_outlets_status(conn, options): + result={} + + res_blades=conn.walk(STATUSES_OID,30) + + for x in res_blades: + port_num=x[0].split('.')[-1] + + port_alias="" + port_status=(x[1]==str(STATUS_UP) and "on" or "off") + + result[port_num]=(port_alias,port_status) + + return result + +# Define new options +def ibmblade_define_defaults(): + all_opt["snmp_version"]["default"]="1" + +# Main agent method +def main(): + global port_oid + + device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug", + "action", "ipaddr", "login", "passwd", "passwd_script", + "test", "port", "separator", "no_login", "no_password", + "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", + "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", + "udpport","inet4_only","inet6_only", + "power_timeout", "shell_timeout", "login_timeout", "power_wait" ] + + atexit.register(atexit_handler) + + ibmblade_define_defaults() + + options=check_input(device_opt,process_input(device_opt)) + + show_docs(options) + + # Operate the fencing device + fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) + +if __name__ == "__main__": + main() -- 1.6.0.6