#!/usr/bin/perl -w
#
# $Id: xserve-raid-info.in,v 1.7 2005/12/05 22:47:08 rader Exp $
#

use strict;
use XML::Parser;

my $prefix = "/usr/local";
my $lib_dir = "$prefix/lib/xserve-raid-tools";
my $etc_dir = "$prefix/etc";
my $conf_file = "xserve-raid-tools.conf";
my $attr_template = "xserve-attrs.template";
my $system_template = "xserve-system-status.template";
my $power_template = "xserve-power-state.template";
my $status_template = "xserve-status-page.template";
my $temp_template = "xserve-temperature.template";
my $dev_template = "xserve-device.template";
my $pwr_supply_template = "xserve-power-supply.template";
my $port = "80";
my $debug = 0;
my $raid_status = 'optimal';
my $component_status = 'optimal';
my $fibre_status = 'optimal';
my $network_status = 'optimal';
my $warnings = '';

my $addr;
my $passwd;
my $xml;
my %attrs;
my %cf;

#------------------------------------------------------------------

&read_conf_file;
$addr = $cf{'addr'};
$passwd = $cf{'passwd'};

#------------------------------------------------------------------

while ( $ARGV[0] && $ARGV[0] =~ /^-/ ) {
  if ( $ARGV[0] eq '-d' || $ARGV[0] eq '--debug' ) { 
    $debug++;
    shift @ARGV;
    next;
  }
  if ( $ARGV[0] eq '-a' || $ARGV[0] eq '--address' ) { 
    shift @ARGV;
    if ( ! $ARGV[0] ) { &usage; exit 1; }
    $addr = $ARGV[0];
    shift @ARGV;
    next;
  }
  if ( $ARGV[0] eq '-p' || $ARGV[0] eq '--passwd' ) {
    shift @ARGV;
    if ( ! $ARGV[0] ) { &usage; exit 1; }
    $passwd = $ARGV[0];
    shift @ARGV;
    next;
  }
  &usage;
  exit 1;
}
if ( $ARGV[0] ) { 
  &usage;
  exit 1;
}

#------------------------------------------------------------------

my $p = new XML::Parser(Style=>'Tree');

#------------------------------------------------------------------

&get_power_state('top');
#&get_date();
$attrs{'date'} = 'unknown';
for my $c qw(top bottom) {
  &get_attrs($c);
  &get_system($c);
  &get_page0($c);
  &get_page1($c);
  &get_pwr_supply($c);
  &get_devs($c);
  &get_temp($c);
}
if ( $debug ) { print "-" x 78, "\n"; }

#------------------------------------------------------------------

for my $c qw(top bottom) {
  if ( $attrs{"$c.syLo"} eq '-10' ) { $attrs{"$c.syLo"} = '--'; }
  if ( $attrs{"$c.syCt"} eq '-10' ) { $attrs{"$c.syCt"} = '--'; }
  $attrs{"$c.syUT"} = &parse_secs($attrs{"$c.syUT"});
  CASE: {
    if ( $attrs{"$c.syFl"} eq '0' ) { 
      $attrs{"$c.syFl"} = 'link up';
      last; 
    }
    if ( $attrs{"$c.syFl"} eq '4096' ) { 
      $attrs{"$c.syFl"} = 'link down'; 
      $network_status = "warning";
      $warnings .= "  The $c network link is down.\n";
      last; 
   }
   $attrs{"$c.syFl"} = 'Unknown';
  }
}
CASE: {
  if ( $attrs{'power-state-get'} eq '1' ) { $attrs{'power-state-get'} = 'On';  last; }
  if ( $attrs{'power-state-get'} eq '0' ) { $attrs{'power-state-get'} = 'Off'; last; }
  $attrs{'power-state-get'} = 'Unknown';
}
if ( $attrs{"top.fibre-link-state"} eq 'down' || $attrs{"bottom.fibre-link-state"} eq 'down' ) {
  $fibre_status = 'critical';
} 
if ( $attrs{"top.fibre-link-state"} eq 'down' || $attrs{"bottom.fibre-link-state"} eq 'down' ) {
  $fibre_status = 'critical';
} 

#------------------------------------------------------------------

print <<EOT;

Name: $attrs{'top.syPN'}

States:
  RAIDs: $raid_status
  Components: $component_status
  Fibre Channel: $fibre_status
  Network: $network_status

EOT

if ( $warnings ne '' ) {
  print "Warnings:\n";
  print $warnings;
}

print <<EOT;

Upper Controller Info:
  Status: $attrs{'top.state'}
  Firmware Version: $attrs{'top.syVs'}/$attrs{'top.firmware'}
  Up Time: $attrs{'top.syUT'}
  Temperature: $attrs{'top.temp'}
  Write Cache: $attrs{'top.write-buf'}
  Prefetch Size: $attrs{'bottom.prefetch-size'}
  Fibre Channel: link $attrs{'top.fibre-link-state'}
    Topology: $attrs{'top.topo'}
    Speed: $attrs{'top.speed'}
  Network: $attrs{'top.syFl'}
    IP Address: $attrs{'top.laIP'}
    Subnet Mask: $attrs{'top.laSM'}

Lower Controller Info:
  Status: $attrs{'bottom.state'}
  Firmware Version: $attrs{'bottom.syVs'}/$attrs{'bottom.firmware'}
  Up Time: $attrs{'bottom.syUT'}
  Temperature: $attrs{"bottom.temp"}
  Write Cache: $attrs{'bottom.write-buf'}
  Prefetch Size: $attrs{'bottom.prefetch-size'}
  Fibre Channel: link $attrs{"bottom.fibre-link-state"}
    Topology: $attrs{'bottom.topo'}
    Speed: $attrs{'bottom.speed'}
  Network: $attrs{'bottom.syFl'}
    IP Address: $attrs{'bottom.laIP'}
    Subnet Mask: $attrs{'bottom.laSM'}

EOT

exit;

#==============================================================================

sub read_conf_file {
  my $s = '';
  my $cf_file = "$etc_dir/$conf_file";
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG CONF ** $cf_file **\n"; }
  if ( ! open(IN,"<$cf_file") ) {
    print "xserve-raid-status: $etc_dir/$conf_file: $!\n";
    exit 1;
  }
  while (<IN>) {
    if ( $_ =~ /^\s*$/ ) { next; }
    chop; $_ =~ s/(.*?)\#.*/$1/;
    $s .= $_;
    while ( $_ !~ /;/ && !(eof(IN)) ) {
      $_ = <IN>;
      chop; $_ =~ s/(.*?)\#.*/$1/;
      $s .= $_;
    }
    if ( $s !~ /;/ ) {
      print "xserve-raid-status: $cf_file: syntax error: no semicolon for the last entry\n";
      exit 1;
    }
    $s =~ s/(.*?);.*/$1/;
    if ( $s =~ /(\S+)\s*=\s*(.*)/ ) {
      my $k = $1; my $v = $2;
      if ( $k =~ /_list$/ ) {
        $cf{$k} = [ split(/\s+/,$v) ];
        if ( $debug > 1 ) {
          print "  \$cf{\'$k\'} = wq( ";
          print join " ", @{ $cf{$k} };
          print " );\n";
        }
      } else {
        $cf{$k} = $v;
        if ( $debug > 1 ) { print "  \$cf{\'$k\'} = $v;\n"; }
      }
    } else {
      print "xserve-raid-status: $cf_file: $s: syntax error\n";
      exit 1;
    }
    $s = '';
  }
  close(IN);
}

#==============================================================================

sub make_query_file {
  my ($template,$file,$controller,$other) = @_;
  open(IN,"<$template");
  open(OUT,">$file");
  while(<IN>) {
    $_ =~ s/_ADDR_/$addr/;
    $_ =~ s/_CONTROLLER_/$controller/;
    $_ =~ s/_PASSWD_/$passwd/;
    $_ =~ s/_PAGE_ID_/$other/;
    $_ =~ s/_DEVICE_/$other/;
    $_ =~ s/_PWR_SUPPLY_/$other/;
    print OUT $_;
  }
  close(OUT);
  close(IN);
}
 
#==============================================================================

sub usage {
print <<EOT
usage: xserve-raid-info [args] 
 --passwd passwd    encrypted passwd (default is $passwd aka "public")
 --address a.b.c.d  check status of raid at a.b.c.d (default is $addr)
 --debug            for debug output (use twice to get source xml output)
EOT
}

#==============================================================================

sub get_temp {
  my $controller = $_[0];
  my $prev = '';

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$temp_template","/tmp/xserve-raid-query.$$",$controller);

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG TEMP ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) { 
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;  
    }
  }
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  }

  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }

  #------------------------------------------------------------------
  my $tree = $p->parse($xml);
 
  #------------------------------------------------------------------
  $attrs{"$controller.temp"} = sprintf("%.1f deg F", ($tree->[1][4][8][16][2]*1.8)+32);
  if ( $debug ) { print "** DEBUG TEMP ** $controller.temp is ", $attrs{"$controller.temp"}, "\n"; }
}

#==============================================================================

sub get_attrs {
  my $controller = $_[0];
  my $prev = '';

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$attr_template","/tmp/xserve-raid-query.$$",$controller);

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG ATTRS ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) {
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;
    }
  }
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  }

  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }

  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  for (my $i = 4; $i < $#{$tree->[1][4]}; $i += 8) {
    my $key = $tree->[1][4][$i][2];
    my $val = $tree->[1][4][$i+4][8][2];
    $attrs{"$controller.$key"} = $val;
    if ( $debug ) { print "** DEBUG ATTRS ** $controller.$key is $val\n"; }
  }
}

#==============================================================================

sub parse_secs {
  my $s = $_[0];
  my ($min, $hrs, $days);
  if ( $s < 0 ) { return '** Error **'; }
  $min = sprintf("%d", ($s%(60*60))/60);
  $hrs = sprintf("%d", ($s%(24*60*60))/60/60);
  $days = sprintf("%d", $s/60/60/24);
  if ( $days > 1 ) {
    # X days (zero hrs) or X days Y hrs or X days 1 hr
    $s = "$days days";
    if ( $hrs > 1 ) { $s .= " $hrs hrs "; }
    elsif ( $hrs > 0 ) { $s .= " 1 hr"; }
    return $s;
  }
  if ( $days == 1 ) {
    # 1 day (zero hrs) or 1 day Y hrs or 1 day 1 hr
    $s = "1 day";
    if ( $hrs > 1 ) { $s .= " $hrs hrs"; }
    elsif ( $hrs > 0 ) { $s .= " 1 hour"; }
    return $s;
  }
  if ( $hrs > 1 ) {
    # Y hrs (zero min) or Y hrs Z min
    $s = "$hrs hrs";
    if ( $min > 0 ) { $s .= " $min min"; }
    return $s;
  }
  if ( $hrs == 1 ) {
    # 1 hr (zero min) or 1 hr Z min
    $s = "1 hr";
    if ( $min > 0 ) { $s .= " $min min"; }
    return $s;
  }
  # Z min
  return "$min minutes";
}

#==============================================================================

sub get_power_state {
  my $controller = $_[0];

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$power_template","/tmp/xserve-raid-query.$$",$controller);

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG POWER ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) {
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;
    }
  }
  while(<IN>) {
    $xml .= $_; 
    if ( $debug > 1 ) { print $_; }
  }
  
  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }
  
  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  if ( $tree->[1][4][4][2] eq 'status' ) {
    if ( $debug ) { print "** DEBUG POWER ** query status is $tree->[1][4][8][2] **\n"; }
    if ( $tree->[1][4][8][2] eq '-6745' ) {
      print "$addr is in standby power mode.\n";
      exit 1;
    }
    if ( $tree->[1][4][8][2] eq '-16' ) {
      print "$addr: incorrect password\n";
      exit 1;
    }
    print "$addr: unknown status error: \"$tree->[1][4][8][2]\"\n";
    exit 1;
  }

  #------------------------------------------------------------------
  $attrs{'power-state-get'} = $tree->[1][4][8][8][2];
  if ( $debug ) { print "** DEBUG POWER ** power-state-get is ", $attrs{'power-state-get'}, "\n"; }
}

#==============================================================================

sub get_page0 {
  my ($controller) = @_;

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$status_template","/tmp/xserve-raid-query.$$",$controller,'0');

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG PAGE0 ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) {
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;
    }
  }
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  }

  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }

  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  $attrs{"$controller.firmware"} = $tree->[1][4][8][112][2];
  if ( $debug ) { print "** DEBUG PAGE0 ** $controller.firmware is ", $attrs{"$controller.firmware"}, "\n"; }

  if ( $tree->[1][4][8][132][2] && $tree->[1][4][8][132][2] eq 'prefetch-size' ) {
    # pre-1.5 firmware...
    $attrs{"$controller.prefetch-size"} = $tree->[1][4][8][136][2];
  }
  if ( $tree->[1][4][8][164][2] && $tree->[1][4][8][164][2] eq 'prefetch-size' ) {
    # 1.5 firmware...
    $attrs{"$controller.prefetch-size"} = $tree->[1][4][8][168][2];
  }
  if ( $debug ) { print "** DEBUG PAGE0 ** $controller.prefetch-size is ", $attrs{"$controller.prefetch-size"}, "\n"; }
  CASE: {
    if ( $attrs{"$controller.prefetch-size"} eq '3' ) {
      $attrs{"$controller.prefetch-size"} = '8 stripes (512 KB/disk)';
      last;
    }
    $attrs{"$controller.prefetch-size"} = "unknown (" . $attrs{"$controller.prefetch-size"} . ")";
  }

  $attrs{"$controller.write-buf"} = $tree->[1][4][8][47];
  if ( $debug ) { print "** DEBUG PAGE0 ** $controller.write-buf is ", $attrs{"$controller.write-buf"}, "\n"; }
  if ( $attrs{"$controller.write-buf"} eq 'true' ) {
    $attrs{"$controller.write-buf"} = 'enabled';
  } else {
    $attrs{"$controller.write-buf"} = 'disabled';
  }

  if ( $tree->[1][4][8][248][4][28][2] && $tree->[1][4][8][248][4][28][2] eq 'actual-topology' ) {
    # pre-1.5 firmware...
    $attrs{"$controller.topo"} = $tree->[1][4][8][248][4][32][2];
    $attrs{"$controller.topo"} =~ s/\-/ /g;
    if ( $debug ) { print "** DEBUG PAGE0 ** $controller.topo is ", $attrs{"$controller.topo"}, "\n"; }
    $attrs{"$controller.speed"} = $tree->[1][4][8][248][4][72][2];
    if ( $debug ) { print "** DEBUG PAGE0 ** $controller.speed is ", $attrs{"$controller.speed"}, "\n"; }
  }
  if ( $tree->[1][4][8][280][4][28][2] && $tree->[1][4][8][280][4][28][2] eq 'actual-topology' ) {
    # 1.5 firmware...
    $attrs{"$controller.topo"} = $tree->[1][4][8][280][4][32][2];
    $attrs{"$controller.topo"} =~ s/\-/ /g;
    if ( $debug ) { print "** DEBUG PAGE0 ** $controller.topo is ", $attrs{"$controller.topo"}, "\n"; }
    $attrs{"$controller.speed"} = $tree->[1][4][8][280][4][72][2];
    if ( $debug ) { print "** DEBUG PAGE0 ** $controller.speed is ", $attrs{"$controller.speed"}, "\n"; }
  }

}

#==============================================================================

sub get_page1 {
  my ($controller) = @_;

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$status_template","/tmp/xserve-raid-query.$$",$controller,'1');

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG PAGE1 ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) { 
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;  
    }
  }
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  }

  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }

  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  for (my $i = 4; $i < $#{$tree->[1][4][8][48]}; $i += 4) {
    CASE: {
      if ( $tree->[1][4][8][48][$i][48][2] eq 'online' ) {
        if ( $debug ) { print "** DEBUG PAGE1 ** $controller has an okay raid\n"; }
        last CASE;
      }
      if ( $tree->[1][4][8][48][$i][48][2] eq 'offline' ) {
        $raid_status = 'critical';
        if ( $debug ) { print "** DEBUG PAGE1 ** $controller has an offline raid\n"; }
        $warnings .= "  The $controller controller has an offline RAID.\n";
        last CASE;
      }
      if ( $tree->[1][4][8][48][$i][48][2] eq 'degraded' ) {
        $raid_status = 'warning';
        $warnings .= "  The $controller controller has a degraded RAID.\n";
        if ( $debug ) { print "** DEBUG PAGE1 ** $controller has a degraded raid\n"; }
        last CASE;
      } 
      $raid_status = 'UNKNOWN';
      print "ERROR: $controller has a raid with UNKNOWN status: $tree->[1][4][8][48][$i][48][2]\n";
    }
  }
}

#==============================================================================

sub get_system {
  my ($controller) = @_;

  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$system_template","/tmp/xserve-raid-query.$$",$controller,'1');

  #------------------------------------------------------------------
  if ( $debug ) { print "-" x 78, "\n", "** DEBUG SYSTEM ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

  #------------------------------------------------------------------
  while(<IN>) { 
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;  
    }
  }
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  }

  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  }

  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  if ( $tree->[1][4][8][4][24][8][24][16][2] eq 'on' ) {
    $attrs{"$controller.state"} = "ok";
  } else {
    $attrs{"$controller.state"} = "down";
  }
  if ( $debug ) { print "** DEBUG SYSTEM ** $controller.state is ", $attrs{"$controller.state"}, "\n"; }

  #------------------------------------------------------------------
  $attrs{"$controller.fibre-link-state"} = $tree->[1][4][8][4][24][8][24][8][2];
  if ( $debug ) { print "** DEBUG SYSTEM ** $controller.fibre-link-state is ", $attrs{"$controller.fibre-link-state"}, "\n"; }
}

#==============================================================================

sub get_devs {
  my ($controller) = @_;

  for my $dev qw(blower battery) {

    #------------------------------------------------------------------
    &make_query_file("$lib_dir/$dev_template","/tmp/xserve-raid-query.$$",$controller,$dev);

    #------------------------------------------------------------------
    if ( $debug ) { 
      print "-" x 78, "\n", "** DEBUG $dev DEV ** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; 
    }
    open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");

    #------------------------------------------------------------------
    while(<IN>) { 
      if ( $debug > 1 ) { print $_; }
      if ( $_ =~ /^<\?xml/ ) {
        $xml = $_; last;  
      }
    }
    while(<IN>) {
      $xml .= $_;
      if ( $debug > 1 ) { print $_; }
    }
  
    #------------------------------------------------------------------
    unlink("/tmp/xserve-raid-query.$$");
    if ( ! close(IN) ) {
      print "could not contact Xserve RAID at $addr\n";
      exit 1;
    }

    #------------------------------------------------------------------
    my $tree = $p->parse($xml);

    #------------------------------------------------------------------
    my $val = "$tree->[1][4][8][15]";
    $attrs{"$controller.$dev"} = $val;
    if ( $debug ) { print "** DEBUG $dev DEV ** $controller.$dev is $val\n"; }
    if ( $val eq 'false' ) {
      $component_status = "critical";
      CASE: {
        if ( $dev eq 'blower' ) {
          $warnings .= "  The $controller blower has failed.\n";
          last;
        }
        if ( $controller eq 'top' ) {
          $warnings .= "  The left $dev has failed.\n";
        } else {
          $warnings .= "  The right $dev has failed.\n";
        }
      }
    }
  }
}

#==============================================================================

sub get_pwr_supply {
  my ($controller) = @_;
  my $pwr_supply = '1';

  #------------------------------------------------------------------
  # goofy shit...
  if ( $controller eq 'bottom' ) { $pwr_supply = '2'; }
   
  #------------------------------------------------------------------
  &make_query_file("$lib_dir/$pwr_supply_template","/tmp/xserve-raid-query.$$",$controller,$pwr_supply);
  
  #------------------------------------------------------------------
  if ( $debug ) { 
    print "-" x 78, "\n", "** DEBUG PWR SUPPLY** /bin/nc $addr $port < /tmp/xserve-raid-query.$$  **\n"; 
  }
  open(IN,"/bin/nc $addr $port < /tmp/xserve-raid-query.$$ |");
  
  #------------------------------------------------------------------
  while(<IN>) { 
    if ( $debug > 1 ) { print $_; }
    if ( $_ =~ /^<\?xml/ ) {
      $xml = $_; last;   
    }
  } 
  while(<IN>) {
    $xml .= $_;
    if ( $debug > 1 ) { print $_; }
  } 
  
  #------------------------------------------------------------------
  unlink("/tmp/xserve-raid-query.$$");
  if ( ! close(IN) ) {
    print "could not contact Xserve RAID at $addr\n";
    exit 1;
  } 
  
  #------------------------------------------------------------------
  my $tree = $p->parse($xml);

  #------------------------------------------------------------------
  my $val = "$tree->[1][4][8][24][2]";
  $attrs{"$controller.power-supply"} = $val;
  if ( $debug ) { print "** DEBUG PWR SUPPLY ** $controller.power-supply is $val\n"; }
  if ( $val eq 'failed' ) {
    $component_status = "critical";
    if ( $controller eq 'top' ) {
      $warnings .= "  The left power supply has failed.\n";
    } else {
      $warnings .= "  The right power supply has failed.\n";
    }
  }
}

