[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Linux-cluster] Fencing Problem On APC 7950



Thanks Ramon and Mohd. Attached is our latest, heavily refactored version of this agent. outlet naming and grouping should all work now - on every 7900 series switch. Please try it. Just rename it fence_apc when you drop it into /sbin and make certain the executable bits are set.

-J

Ramon van Alteren wrote:

Hi,

Mohd Irwan Jamaluddin wrote:

I'm running Red Hat Cluster Suite on RHEL 4 U3 with APC 7950
( http://www.apc.com/resource/include/techspec_index.cfm?base_sku=AP7950 )
as the fencing device. The version of my fence package is 1.32.18-0. I try to execute some fence_apc commands but I've got errors. Below are the details:

[root orarac01 ~]# fence_apc -a 10.0.6.150 -l apc -p apc -n 02 \
-o Reboot -T -v
failed: unrecognised Reboot response

Same error occured for On/Off option.

Also, I found a weird problem if I put "2" instead of "02" for the Outlet Number option (-n option). Below are the error message:
[root orarac01 ~]# fence_apc -a 10.0.6.150 -l apc -p apc -n 2 \
-o Reboot -T -v
failed: unrecognised menu response


H Anyone have ever faced similar problem with me? Here I attached the apclog for reference.
we're running fencing through an apc 7920 which I assume is similar.
I've hacked up the fence_apc until it worked, it accepts outlet names
and numbers if I remember correctly.
I've attached ours to the mail, it's originally from cluster-1.02 but
works for me on cluster-1.03 as well.

No guarantees implied ;-) WFM, YMMV

Thanks in advanced for your response.
Hope it helps

Ramon


------------------------------------------------------------------------

#!/usr/bin/perl

###############################################################################
###############################################################################
##
##  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
##  Copyright (C) 2004 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::Telnet ();

# Get the program name from $0 and strip directory names
$_=$0;
s/.*\///;
my $pname = $_;

# Change these if the text returned by your equipment is different.
# Test by running script with options -t -v and checking /tmp/apclog

my $immediate = 'immediate'; # # Or 'delayed' - action string prefix on menu
my $masterswitch = 'masterswitch plus '; # 'Device Manager' option to choose
my $login_prompt = '/: /';
my $cmd_prompt = '/> /';

my $max_open_tries = 3; # How many telnet attempts to make. Because the # APC can fail repeated login attempts, this number
                            # should be more than 1
my $open_wait = 5;           # Seconds to wait between each telnet attempt
my $telnet_timeout = 2;      # Seconds to wait for matching telent response
my $debuglog = '/tmp/apclog';# Location of debugging log when in verbose mode
$opt_o = 'reboot'; # Default fence action.
my $logged_in = 0;

my $t = new Net::Telnet;



# 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="1.02.00";
$REDHAT_COPYRIGHT=("Copyright (C) Red Hat, Inc.  2004  All rights reserved.");
$BUILD_DATE="(built Wed Jun 28 13:17:53 CEST 2006)";
#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 MasterSwitch\n";
	print "  -h               usage\n";
	print "  -l <name>        Login name\n";
	print "  -n <num>         Outlet number to change: [<switch>:]<outlet> \n";
	print "  -o <string>      Action: Reboot (default), Off or On\n";
	print "  -p <string>      Login password\n";
	print "  -q               quiet mode\n";
	print "  -T               Test mode (cancels action)\n";
	print "  -V               version\n";
	print "  -v               Log to file /tmp/apclog\n";
	
	exit 0;
}

sub fail
{
	($msg)= _;
	print $msg."\n" unless defined $opt_q;

	if (defined $t)
	{
		# make sure we don't get stuck in a loop due to errors
$t->errmode('return');
		logout() if $logged_in;
$t->close }
	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 "$pname $FENCE_RELEASE_NAME $BUILD_DATE\n";
	print "$SISTINA_COPYRIGHT\n" if ( $SISTINA_COPYRIGHT );
	exit 0;
}


sub login
{
	for (my $i=0; $i<$max_open_tries; $i++)
	{
		$t->open($opt_a);
		($_) = $t->waitfor($login_prompt);
# Expect 'User Name : ' if (! /name/i) {
			$t->close;
			sleep($open_wait);
next; }

		$t->print($opt_l);
		($_) = $t->waitfor($login_prompt);

# Expect 'Password : ' if (! /password/i ) {
			$t->close;
			sleep($open_wait);
next; } # Send password $t->print($opt_p);
		(my $dummy, $_) = $t->waitfor('/(>|(?i:user name|password)\s*:) /');
		if (/> /)
		{
			$logged_in = 1;

			# send newline to flush prompt
$t->print("");
			return;
		}
		else
		{
			fail "invalid username or password";
		}
	}
fail "failed: telnet failed: ". $t->errmsg."\n" }

# print_escape_char() -- utility subroutine for sending the 'Esc' character
sub print_escape_char
{
	# The APC menu uses "<esc>" to go 'up' menues.  We must set
	# the output_record_separator to "" so that "\n" is not printed
	# after the "<esc>" character

	$ors=$t->output_record_separator;
	$t->output_record_separator("");
	$t->print("\x1b"); # send escape
	$t->output_record_separator("$ors");
}


# Determine if the switch is a working state. Also check to make sure that # the switch has been specified in the case that there are slave switches
# present.  This assumes that we are at the main menu.
sub identify_switch
{

	($_) = $t->waitfor($cmd_prompt);
	print_escape_char();

	# determine what type of switch we are dealling with
	($_) = $t->waitfor($cmd_prompt);
	if ( /Switched Rack PDU: Communication Established/i)
	{
		# No further test needed
	}
	elsif ( /MS plus 1 : Serial Communication Established/i )
	{
		if ( defined $switchnum )
		{
			$masterswitch = $masterswitch . $switchnum;
		}
		elsif ( /MS plus [^1] : Serial Communication Established/i )
		{
			fail "multiple switches detected.  'switch' must be defined.";
		}
		else
		{
			$switchnum = 1;
		}
	}
	else
	{
		fail "APC is in undetermined state"
	}	

	# send a newline to cause APC to reprint the menu
	$t->print("");
}


# Navigate through menus to the appropriate outlet control menu of the apc
# MasterSwitch and 79xx series switches. Uses multi-line (mostly) # case-insensitive matches to recognise menus and works out what option number # to select from each menu.
sub navigate
{
	# Limit the ammount of menu depths to 20.  We should never be this deep
	for(my $i=20; $i ; $i--)
	{
		# Get the new text from the menu
		($_) = $t->waitfor($cmd_prompt);
# Identify next option if ( # "Control Console", "1- Device Manager"
			/--\s*control console.*(\d+)\s*-\s*device manager/is  ||

			# "Device Manager", "2- Outlet Control"
			/--\s*device manager.*(\d+)\s*-\s*outlet control/is ||

# # APC MasterSwitch Menus
			#
			# "Device Manager", "1- MasterSwitch plus 1"
			/--\s*device manager.*(\d+)\s*-\s*$masterswitch/is ||

			# "Device Manager", "1- Cluster Node 0   ON"
			/--\s*(?:device manager|$masterswitch).*(\d+)\s*-\s+Outlet\s+$switchnum:$opt_n\D[^\n]*\s(?-i:ON|OFF)\*?\s/ism ||

			# "MasterSwitch plus 1", "1- Outlet 1:1  Outlet #1  ON"
			/--\s*$masterswitch.*(\d+)\s*-\s*Outlet\s+$switchnum:$opt_n\s[^\n]*\s(?-i:ON|OFF)\*?\s/ism ||
	
			# Administrator outlet control menu
/--\s*Outlet $switchnum:$opt_n\D.*(\d+)\s*-\s*outlet control\s*$switchnum:?$opt_n\D/ism ||

			#
			# APC 79XX Menus
			#
			# "3- Outlet Control/Configuration"
			/--\s*device manager.*(\d+)\s*-\s*Outlet Control/is ||

			# "Device Manager", "1- Cluster Node 0   ON"
			/--\s*Outlet Control.*(\d+)\s*-\s+Outlet\s+$opt_n\D[^\n]*\s(?-i:ON|OFF)\*?\s/ism ||

			# "Device Manager", "1- <name>   ON"
			/--\s*Outlet Control.*(\d+)\s*-\s+$opt_n\D[^\n]*\s(?-i:ON|OFF)\*?\s/ism ||

			# Administrator Outlet Control menu
			/--\s*Outlet $opt_n\D.*(\d+)\s*-\s*control\s*outlet\s+$opt_n\D/ism ||
/--\s*Outlet $opt_n\D.*(\d+)\s*-\s*control\s*outlet/ism
		) {
			$t->print($1);
			next;
		}

		# "Outlet Control X:N", "4- Immediate Reboot"
if ( /(\d+)\s*-\s*immediate $opt_o/is || /--\s*$opt_n.*(\d+)\s*-\s*immediate\s*$opt_o/is || /--\s*Control Outlet\D.*(\d+)\s*-\s*Immediate\s*$opt_o/is ) {
			$t->print($1);
			last;
		}

		fail "failed: unrecognised menu response\n";
	}
}


sub logout { # send a newline to make sure that we refresh the menus # ($t->waitfor() can hang otherwise)
	$t->print("");

	# Limit the ammount of menu depths to 20.  We should never be this deep
	for(my $i=20; $i ; $i--)
	{

		# Get the new text from the menu
		($_) = $t->waitfor($cmd_prompt);

if ( # "Control Console", "4- Logout" /--\s*control console.*(\d+)\s*-\s*Logout/is
		) {
			$t->print($1);
			last;
		}
else {
			print_escape_char();
			next;
		}
	}
}


sub action
{
	# "Enter 'YES' to continue or <ENTER> to cancel : "
	($_) = $t->waitfor('/: /');
	if (! /.*immediate $opt_o.*YES.*to continue/si ) {
		fail "failed: unrecognised $opt_o response\n";
	}

	# Test mode?
	$t->print($opt_T?'NO':'YES');

# "Success", "Press <ENTER> to continue..." ($_) = $t->waitfor('/continue/');
	$t->print('');

	if (defined $opt_T) {
logout(); print "success: test outlet $opt_n $opt_o\n" unless defined $opt_q; $t->close;

		# Allow the APC some time to clean connection
		# before next login.
		sleep 1;

		exit 0;
	} elsif ( /Success/i ) {
		logout();
print "success: outlet $opt_n $opt_o\n" unless defined $opt_q; $t->close;

		# Allow the APC some time to clean connection
		# before next login.
		sleep 1;

		exit 0;
}
	fail "failed: unrecognised action response\n";
}


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 "login" ) {
			$opt_l = $val;
} elsif ($name eq "option" ) {
			$opt_o = $val;
} elsif ($name eq "passwd" ) {
			$opt_p = $val;
} elsif ($name eq "port" ) {
			$opt_n = $val;
} elsif ($name eq "switch" ) {
			$switchnum = $val;
} elsif ($name eq "test" ) {
			$opt_T = $val;
} elsif ($name eq "verbose" ) {
			$opt_v = $val;
} # Excess name/vals will fail else {
			fail "parse error: unknown option \"$opt\"";
		}
	}
}
		

sub telnet_error
{
	fail "failed: telnet returned: ".$t->errmsg."\n";
}


### MAIN #######################################################

if (@ARGV > 0) {
	getopts("a:hl:n:o:p:qTvV") || fail_usage ;
	
	usage if defined $opt_h;
	version if defined $opt_V;

	fail_usage "Unkown 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 '-l' flag specified." unless defined $opt_l;
	fail_usage "No '-p' flag specified." unless defined $opt_p;
	fail_usage "Unrecognised action '$opt_o' for '-o' flag"
	unless $opt_o =~ /^(Off|On|Reboot)$/i;

	if ( $opt_n =~ /(\d+):(\d+)/ ) {
		$switchnum=($1);
		$opt_n = ($2);
	}
} 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 login name" unless defined $opt_l;
	fail "failed: no password" unless defined $opt_p;
	fail "failed: unrecognised action: $opt_o"
	unless $opt_o =~ /^(Off|On|Reboot)$/i;
}
$t->timeout($telnet_timeout);
$t->input_log($debuglog) if $opt_v;
$t->errmode('return');
&login;

&identify_switch;

# Abort on failure beyond here
$t->errmode(\&telnet_error);
&navigate;
&action;

exit 0;



------------------------------------------------------------------------

--
Linux-cluster mailing list
Linux-cluster redhat com
https://www.redhat.com/mailman/listinfo/linux-cluster



#!/usr/bin/python

###############################################################################
###############################################################################
##
##  Copyright (C) 2006 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.
##
###############################################################################
###############################################################################

import getopt, sys
import os
import socket
import time

from telnetlib import Telnet

TELNET_TIMEOUT=5  #How long to wait for a response from a telnet try

# 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="New APC Agent - test release"
REDHAT_COPYRIGHT=""
BUILD_DATE="September 21, 2006"
#END_VERSION_GENERATION

POWER_OFF = 0
POWER_ON = 1
POWER_STATUS = 2
POWER_REBOOT = 3

COMPLETE = 0
NOT_COMPLETE = 1

ON = "ON"
OFF = "OFF"

SUCCESS = "success"
FAIL = "fail"

address = ""
login = ""
passwd = ""
port = ""
switchnum = ""
action = POWER_REBOOT   #default action
verbose = False

logfile = None

#set up regex list
CONTROL_CONSOLE = "Control Console -----"
DEVICE_MANAGER = "Device Manager -----"
OUTLET_CONTROL = "- Outlet Control/Configuration -----"
CONTROL_OUTLET = "- Control Outlet -----"
CONTROL_OUTLET_2 = "- Outlet Control "
COMMAND_SUCCESS = "Command successfully issued."
COMMAND_SUCCESS_2 = " Success"
CONFIRM = "Enter 'YES' to continue or <ENTER> to cancel :"
CONTINUE = "Press <ENTER> to continue..."
SCREEN_END = "<ESC>- Main Menu, <ENTER>- Refresh, <CTRL-L>- Event Log"
SCREEN_END_2 = "<ESC>- Back, <ENTER>- Refresh, <CTRL-L>- Event Log"
USERNAME = "User Name :"
PASSWORD = "Password  :"
MASTER = "------- MasterSwitch"

CONTINUE_INDEX = 0

regex_list = list()
regex_list.append(CONTINUE)
regex_list.append(SCREEN_END)
regex_list.append(SCREEN_END_2)
regex_list.append(USERNAME)
regex_list.append(PASSWORD)

def usage():
  print "Usage:\n"
  print "fence_apc [options]"
  print "Options:"
  print "   -a <ipaddress>           ip or hostname of APC switch"
  print "   -h                       print out help"
  print "   -l [login]               login name"
  print "   -n [port]                switch port"
  print "   -p [password]            password"
  print "   -o [action]              Reboot (default), Off, On, or Status"
  print "   -v Verbose               Verbose mode - writes file to /tmp/apclog"
  print "   -V                       Print Version, then exit"

  sys.exit (0)

def version():
  print "fence_apc %s  %s\n" % (FENCE_RELEASE_NAME, BUILD_DATE)
  print "%s\n" % REDHAT_COPYRIGHT
  sys.exit(0)

def main():

  global address, login, passwd, port, action, verbose, logfile, switchnum

  if len(sys.argv) > 1:
    try:
      opts, args = getopt.getopt(sys.argv[1:], "a:hl:o:n:p:vV", ["help", "output="])
    except getopt.GetoptError:
      #print help info and quit
      usage()
      sys.exit(2)
                                                                                
    for o, a in opts:
      if o == "-v":
        verbose = True
      if o == "-V":
        version()
      if o in ("-h", "--help"):
        usage()
        sys.exit()
      if o == "-l":
        login = a
      if o == "-p":
        passwd = a
      if o == "-n":
        dex = a.find(":")
        if dex == (-1):
          port = a
        else:
          switchnum = a[:dex]
          port = a[(dex+1):]
      if o  == "-o":
        if a == "Off" or a == "OFF" or a == "off":
          action = POWER_OFF
        elif a == "On" or a == "ON" or a == "on":
          action = POWER_ON
        elif a == "Status" or a == "STATUS" or a == "status":
          action = POWER_STATUS
        elif a == "Reboot" or a == "REBOOT" or a == "reboot":
          action = POWER_REBOOT
        else:
          usage()
          sys.exit()
      if o == "-a":
        address = a
    if address == "" or login == "" or passwd == "" or port == "":
      usage()
      sys.exit()

  else: #Take args from stdin...
    params = {}
    #place params in dict
    for line in sys.stdin:
      val = line.split("=")
      params[val[0]] = val[1]

    try:
      address = params["ipaddr"]
    except KeyError, e:
      sys.stderr.write("FENCE: Missing ipaddr param for fence_apc...exiting")
      sys.exit(1)
    try:
      login = params["login"]
    except KeyError, e:
      sys.stderr.write("FENCE: Missing login param for fence_apc...exiting")
      sys.exit(1)
    try:
      passwd = params["passwd"]
    except KeyError, e:
      sys.stderr.write("FENCE: Missing passwd param for fence_apc...exiting")
      sys.exit(1)
    try:
      port = params["port"]
    except KeyError, e:
      sys.stderr.write("FENCE: Missing port param for fence_apc...exiting")
      sys.exit(1)
    try:
      switchnum = params["switch"]
    except KeyError, e:
      pass
    try:
      verbose = params["verbose"]
      verbose = (verbose == 'True' or verbose == 'true' or verbose == 'TRUE')
    except KeyError, e:
      pass
    
    try:
      a = params["option"]
      if a == "Off" or a == "OFF" or a == "off":
        action = POWER_OFF
      elif a == "On" or a == "ON" or a == "on":
        action = POWER_ON
      elif a == "Reboot" or a == "REBOOT" or a == "reboot":
        action = POWER_REBOOT
    except KeyError, e:
      action = POWER_REBOOT

    #### End of stdin section

  ### Order of events
  # 0) If verbose, prepare log file handle
  # 1) Open socket
  # 2) Log in
  # 3) Evaluate task. Task will be one of:
  # 3a - Check status and print to stdout (or log file if verbose)
  # 3b - Turn a port off, then confirm
  # 3c - Turn a port on, then confirm
  # 3d - Reboot by turning a port off, then on, and confirming each step.

  if verbose:
    setup_logging()

  sock = setup_socket()

  # Ok, now lets log in...
  do_login(sock)

  # Now we should be at the outside Control screen
    
  if action == POWER_STATUS:
    # We should be at the Control screen, so we need to write a '1'
    # to kick things off
    sock.write("1\r")
    statusval = do_status_check(sock)
    backout(sock)
    sock.write("4\r")  # Logs out
    
  elif action == POWER_OFF:
    sock.write("1\r")
    do_power_off(sock)
    backout(sock) # Return to control screen
    statusval = do_status_check(sock)
    if statusval == OFF:
      if verbose:
        logit("Power Off successful\n")
      print "Power Off successful"
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(0)
    else:
      if verbose:
        logit("Power Off unsuccessful\n")
        logit("Undetermined error\n")
      sys.stderr.write("Power Off unsuccessful")
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(1)
    
  elif action == POWER_ON:
    sock.write("1\r")
    do_power_on(sock)
    backout(sock) # Return to control screen
    statusval = do_status_check(sock)
    if statusval == ON:
      if verbose:
        logit("Power On successful\n")
      print "Power On successful"
      backout(sock)
      sock.write("4\r")  # logs out
      sock.close()
      sys.exit(0)
    else:
      if verbose:
        logit("Power On unsuccessful\n")
        logit("Undetermined error\n")
      sys.stderr.write("Power On unsuccessful")
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(1)

  elif action == POWER_REBOOT:
    sock.write("1\r")
    do_power_off(sock)
    backout(sock) # Return to control screen
    statusval = do_status_check(sock)
    if statusval == OFF:
      if verbose:
        logit("Power Off successful\n")
      print "Power Off successful"
      backout(sock)
    else:
      if verbose:
        logit("Power Off unsuccessful\n")
        logit("Undetermined error\n")
      sys.stderr.write("Power Off unsuccessful")
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(1)
    do_power_on(sock)
    backout(sock) # Return to control screen
    statusval = do_status_check(sock)
    if statusval == ON:
      if verbose:
        logit("Power Reboot successful\n")
      print "Power Reboot successful"
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(0)
    else:
      if verbose:
        logit("Power Reboot unsuccessful\n")
        logit("Undetermined error\n")
      sys.stderr.write("Power Reboot unsuccessful")
      backout(sock)
      sock.write("4\r")  # Logs out
      sock.close()
      sys.exit(1)
    
  sock.close()

def backout(sock):
  sock.write(chr(27))
  
  while (1):
    i, mo, txt = sock.expect(regex_list, TELNET_TIMEOUT)

    if regex_list[i] == SCREEN_END:
      break
    elif regex_list[i] == SCREEN_END_2:
      sock.write(chr(27))

def setup_socket():
  ## Time to open telnet session and log in. 
  try:
    sock = Telnet(address.strip())
  except socket.error, (errno, msg):
    my_msg = "FENCE: A problem was encountered opening a telnet session with " + address
    if verbose:
      logit(my_msg)
      logit("FENCE: Error number: %d -- Message: %s\n" % (errno, msg))
      logit("Firewall issue? Correct address?\n")

    sys.stderr.write(my_msg)
    sys.stderr.write(("FENCE: Error number: %d -- Message: %s\n" % (errno, msg)))
    sys.stderr.write("Firewall issue? Correct address?\n")
    sys.exit(1)

  if verbose:
    logit("\nsocket open to %s\n" % address)

  return sock

def setup_logging( log_location="/tmp/apclog"):
  global logfile
  try:
    logfile = open(log_location, 'a')
    logfile.write("###############################################\n")
    logfile.write("Telnetting to apc switch %s\n" % address)
    now = time.localtime(time.time())
    logfile.write(time.asctime(now))
  except IOError, e:
    sys.stderr.write("Failed to open log file %s" % log_location)
    logfile = None

def logit(instr):
  if logfile != None:
    logfile.write(instr)

def do_login(sock):
  result_code = 1

  ## This loop tries to assemble complete telnet screens and passes
  ## them to helper methods to handle responses accordingly.
  while result_code:
    try:
      i, mo, txt = sock.expect(regex_list, TELNET_TIMEOUT)
    except socket.error, (errno, msg):
      my_msg = "FENCE: A problem was encountered opening a telnet session with " + address + "\n"
      if verbose:
        logit(my_msg)
        logit("FENCE: Error number: %d -- Message: %s\n" % (errno, msg))

      sys.stderr.write(my_msg)
      sys.stderr.write(("FENCE: Error number: %d -- Message: %s\n" % (errno, msg)))
      sys.exit(1)

    if i == CONTINUE_INDEX: # Capture the rest of the screen...
      sock.write("\r")
      ii,moo,txtt = sock.expect(regex_list, TELNET_TIMEOUT)
      txt = txt + txtt

    ndbuf = sock.read_eager() # Scoop up remainder
    if verbose:
      logit(txt + ndbuf)
    result_code,response = log_in(txt + ndbuf)
    if result_code:
      try:
        sock.write(response)
      except socket.error, (errno, msg):
        if verbose:
          logit("Error #%s" % errno)
          logit(msg)
        sys.stderr.write("Error #%s:  %s" % (errno,msg))
        sys.exit(1)

def log_in(buffer):
  lines = buffer.splitlines()

  for i in lines:
    if i.find(USERNAME) != (-1):
      if verbose:
        logit("Sending login: %s\n" % login)
      return (NOT_COMPLETE, login + "\r")
    elif i.find(PASSWORD) != (-1):
      if verbose:
        logit("Sending password: %s\n" % passwd)
      return (NOT_COMPLETE, passwd + "\r")
    elif i.find(CONTROL_CONSOLE) != (-1):
      return (COMPLETE, "1\r") 

def do_status_check(sock):
  result_code = 1
  while result_code:
    i, mo, txt = sock.expect(regex_list, TELNET_TIMEOUT)
    if i == CONTINUE_INDEX: # Capture the rest of the screen...
      sock.write("\r")
      ii,moo,txtt = sock.expect(regex_list, TELNET_TIMEOUT)
      txt = txt + txtt

    ndbuf = sock.read_eager() # Scoop up remainder
    if verbose:
      logit(txt + ndbuf)
    (result_code,response,statusval) = return_status(txt + ndbuf)
    if result_code:
      try:
        sock.write(response)
      except socket.error, (errno, msg):
        if verbose:
          logit("Status check failed.")
          logit("Error #%s" % errno)
          logit(msg)
        sys.stderr.write("Status check failed.")
        sys.stderr.write("Error #%s:  %s" % (errno,msg))
        sys.exit(1)
  # Back from status check - value should be in status var
  if response == SUCCESS:
    if switchnum == "":
      if verbose:
        logit("Status check successful. Port %s is %s" % (port,statusval))
      print "Status check successful. Port %s is %s" % (port,statusval)
    else:
      if verbose:
        logit("Status check successful. Port %s:%s is %s" % (switchnum, port, statusval))
      print "Status check successful. Port %s:%s is %s" % (switchnum, port, statusval)

    return statusval
  else:
    if verbose:
      logit("Status check failed, unknown reason.")
    sys.stderr.write("Status check failed, unknown reason.\n")
    sock.close()
    sys.exit(1) 

def return_status(buffer):
  global switchnum, port

  lines = buffer.splitlines()

  for i in lines:
    if i.find(CONTROL_CONSOLE) != (-1):
      return (NOT_COMPLETE, "1\r", "Status Unknown")
    elif i.find(DEVICE_MANAGER) != (-1):
      if switchnum != "":
        res = switchnum + "\r"
      else:
        res = "3\r"
      return (NOT_COMPLETE, res, "Status Unknown")
    elif i.find(OUTLET_CONTROL) != (-1):
      ls = buffer.splitlines()
      portval = port.strip()
      portval = " " + portval + " "
      portval2 = " " + port.strip() + "- "
      found_portval = False
      for l in ls:
        if l.find(portval) != (-1) or l.find(portval2) != (-1):
          found_portval = True
          linesplit = l.split()
          linelen = len(linesplit)
          return (COMPLETE,SUCCESS,linesplit[linelen - 1])
    elif i.find(MASTER) != (-1):
      try:
        e = int(port.strip())
        portval = port.strip()
        switchval = switchnum.strip()
        portval = switchval + ":" + portval
      except ValueError, e:
        portval = port.strip()
      ls = buffer.splitlines()
      found_portval = False
      for l in ls:
        words = l.split()
        if len(words) > 3:
          if words[2] == portval or words[3] == portval:
            found_portval = True
            linesplit = l.split()
            linelen = len(linesplit)
            return (COMPLETE, SUCCESS, linesplit[linelen - 3])
      return (COMPLETE, FAIL, "Incorrect port number")
  return (NOT_COMPLETE, chr(27), "Status Unknown")

def do_power_switch(sock, status):
  result_code = 1

  while result_code:
    i, mo, txt = sock.expect(regex_list, TELNET_TIMEOUT)
    if i == CONTINUE_INDEX: # Capture the rest of the screen...
      sock.write("\r")
      ii,moo,txtt = sock.expect(regex_list, TELNET_TIMEOUT)
      txt = txt + txtt

    ndbuf = sock.read_eager() # Scoop up remainder
    if verbose:
      logit(txt + ndbuf)

    if status == "off":
      result_code, response = power_off(txt + ndbuf)
    elif status == "on":
      result_code, response = power_on(txt + ndbuf)
    else:
      if verbose:
        logit("Invalid status in do_power_switch() function")
      sys.stderr.write("Invalid status in do_power_switch() function") 
      sys.exit(1)

    if result_code:
      try:
        sock.write(response)
      except socket.error, (errno, msg):
        if verbose:
          logit("Error #%s" % errno)
          logit(msg)
        sys.stderr.write("Error #%s:  %s" % (errno,msg))
        sys.exit(1)
      # FIXME: always returns COMPLETE (0)
    else:
      try:
        sock.write(response)
      except socket.error, (errno, msg):
        if verbose:
          logit("Error #%s" % errno)
          logit(msg)
        sys.stderr.write("Error #%s:  %s" % (errno,msg))
        sys.exit(1)
      return COMPLETE


def power_switch(buffer, escape, control_outlet, control_outlet2):
  # If port is not aliased, then outlet control screen will have the word
  # 'Outlet' in the header. If the name is aliased, it will only have the 
  # alias in the header.

  outlet_search_str1 = "Outlet " + port.strip() + " ------------"
  outlet_search_str2 = port.strip() + " ------------"
  outlet_search_str3 = "Outlet " + switchnum.strip() + ":" + port.strip() + " ------"
  outlet_search_str4 = "        Outlet       : " + port.strip()
  outlet_search_str5 = "        Outlet Name : " + port.strip()
  master_search_str1 = "-------- Master"
  lines = buffer.splitlines()

  for i in lines:
    if i.find(CONTROL_CONSOLE) != (-1):
      return (NOT_COMPLETE,"1\r")

    elif i.find(DEVICE_MANAGER) != (-1):
      if switchnum != "":
        res = switchnum + "\r"
      else:
        res = "3\r"
      return (NOT_COMPLETE, res)
      
    elif (i.find(master_search_str1) != (-1)):
      return (NOT_COMPLETE, port.strip() + "\r")
      
    elif i.find(outlet_search_str1) != (-1) and (switchnum == ""):
      return (NOT_COMPLETE,"1\r")

    elif i.find(outlet_search_str2) != (-1) and (switchnum == ""):
      return (NOT_COMPLETE,"1\r")
    
    elif i.find(outlet_search_str3) != (-1):
      return (NOT_COMPLETE, "1\r")
    
    elif i == outlet_search_str4:
      return (NOT_COMPLETE, "1\r")
    
    elif i == outlet_search_str5:
      return (NOT_COMPLETE, "1\r")
    
    elif i.find(OUTLET_CONTROL) != (-1):
      ls = buffer.splitlines()
      portval = port.strip()
      portval = " " + portval + " "
      found_portval = False
      i = 0
      # look for aliased name 
      for l in ls:
        i = i + 1
        if l.find(portval) != (-1):
          found_portval = True
          linesplit = l.split()
          outlet_str = linesplit[0]
          dex = outlet_str.find("-")
          if dex <= (0):
            if verbose:
              logit("Problem identifying outlet\n")
              logit("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.stderr.write("Problem identifying outlet\n")
            sys.stderr.write("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.exit(1)
          normalized_outlet_str = outlet_str[:dex]
          return (NOT_COMPLETE, normalized_outlet_str + "\r")
      # look for portnum
      portval = " " + port.strip() + "-"
      i = 0
      for l in ls:
        i = i + 1
        if l.find(portval) != (-1):
          found_portval = True
          linesplit = l.split()
          outlet_str = linesplit[0]
          dex = outlet_str.find("-")
          if dex <= (0):
            if verbose:
              logit("Problem identifying outlet\n")
              logit("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.stderr.write("Problem identifying outlet\n")
            sys.stderr.write("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.exit(1)
          normalized_outlet_str = outlet_str[:dex]
          return (NOT_COMPLETE, normalized_outlet_str + "\r")
      if found_portval == False:
        if verbose:
          logit("Problem identifying outlet\n")
          logit("Looking for '%s' in string '%s'\n" % (portval, ls))
        sys.stderr.write("Problem identifying outlet\n")
        sys.stderr.write("Looking for '%s' in string '%s'\n" % (portval, ls))
        sys.exit(1)

    elif i.find(MASTER) != (-1):
      ls = buffer.splitlines()
      found_portval = False
      # look for aliased name
      portval = port.strip()
      for l in ls:
        words = l.strip().split()
        if len(words) > 3:
          if words[3].strip() == portval:
            outlet_str = words[0]
            dex = outlet_str.find("-")
            if dex <= (0):
              if verbose:
                logit("Problem identifying outlet\n")
                logit("Looking for %s in string %s\n" % (portval, outlet_str))
              sys.stderr.write("Problem identifying outlet\n")
              sys.stderr.write("Looking for %s in string %s\n" % (portval, outlet_str))
              sys.exit(1)
            normalized_outlet_str = outlet_str[:dex]
            return (NOT_COMPLETE, (normalized_outlet_str + "\r"))
      # look for portnum
      portval = port.strip()
      portval = switchnum.strip() + ":" + portval + " "
      i = 0
      for l in ls:
        i = i + 1
        if l.find(portval) != (-1):
          found_portval = True
          linesplit = l.split()
          outlet_str = linesplit[0]
          dex = outlet_str.find("-")
          if dex <= (0):
            if verbose:
              logit("Problem identifying outlet\n")
              logit("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.stderr.write("Problem identifying outlet\n")
            sys.stderr.write("Looking for %s in string %s\n" % (portval,outlet_str))
            sys.exit(1)
          normalized_outlet_str = outlet_str[:dex]
          return (NOT_COMPLETE, (normalized_outlet_str + "\r"))
      if found_portval == False:
        if verbose:
          logit("Problem identifying outlet\n")
          logit("Looking for '%s' in string '%s'\n" % (portval, ls))
        sys.stderr.write("Problem identifying outlet\n")
        sys.stderr.write("Looking for '%s' in string '%s'\n" % (portval, ls))
        sys.exit(1)

    elif i.find(CONFIRM) != (-1):
      return (NOT_COMPLETE,"YES\r")

    elif i.find(COMMAND_SUCCESS) != (-1):
      return (COMPLETE,"\r")

    elif i.find(COMMAND_SUCCESS_2) != (-1):
      return (COMPLETE,"\r")

    elif i.find(CONTROL_OUTLET) != (-1):
      return (NOT_COMPLETE, control_outlet + "\r")

    elif i.find(CONTROL_OUTLET_2) != (-1):
      return (NOT_COMPLETE, control_outlet2 + "\r")
  
  if (escape == True):
    return (NOT_COMPLETE, chr(27))
  else:
    raise "unknown screen encountered in \n" + str(lines) + "\n"

def do_power_off(sock):
  x = do_power_switch(sock, "off")
  return x

def power_off(buffer):
  x = power_switch(buffer, False, "2", "3");
  return x

def do_power_on(sock):
  x = do_power_switch(sock, "on")
  return x

def power_on(buffer):
  x = power_switch(buffer, True, "1", "1");
  return x

if __name__ == "__main__":
  main()

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]