#!/usr/bin/perl
# This is a wrapper around the locfg.pl from HP. It's pretty silly to do
# this as a wrapper, but that program is not licensed and I didn't feel
# like doing a clean room reimplementation of it.
#
# This wrapper knows how to do different simple actions, controlled by the
# first parameter. It generates the XML commands and feeds them to
# locfg.pl. See the top-level README for documentation of the environment
# variables it expects to be set.
#
# GPL Copyright 2004 by Joey Hess.
use strict;
use IPC::Open2;
use Expect;
my $action=shift;
if ($action eq 'reset') {
print "Resetting..\n";
send_command('server_info', qq{});
exit process_result();
}
elsif ($action eq 'poweron') {
print "Powering on..\n";
send_command('server_info', qq{});
exit process_result();
}
elsif ($action eq 'poweroff') {
# Do a warm boot before turning off since iLO may not allow turning
# the power off if certain kernels (2.6) are running.
# This is done using the telnet interface and expect because
# I do not know how to accomplish a warm boot using the xml
# interface. it requires iLO 1.60.
my $exp = new Expect;
$exp->raw_pty(1);
#$exp->debug(2);
#$exp->exp_internal(1);
$exp->spawn("nc", $ENV{HP_ILO_HOST}, "telnet") or die "cannot spawn nc: $!\n";
$exp->expect(60, "Login Name:");
$exp->send(getuser()."\r");
$exp->expect(10, "Password:");
$exp->send(getpassword()."\r");
$exp->expect(10, "iLO>");
$exp->send("power\r");
my $power;
$exp->expect(10,
[ "Off" => sub { $power=0 } ],
[ "On" => sub { $power=1 } ],
);
$exp->expect(10, "iLO>");
if ($power) {
$exp->send("power warm\r");
}
$exp->soft_close;
sleep 2;
print "Powering off..\n";
send_command('server_info', qq{});
exit process_result();
}
elsif ($action eq 'force_restart') {
# This is done using the telnet interface and expect because
# I do not know how to accomplish a warm boot using the xml
# interface. it requires iLO 1.60.
my $exp = new Expect;
$exp->raw_pty(1);
#$exp->debug(2);
#$exp->exp_internal(1);
$exp->spawn("nc", $ENV{HP_ILO_HOST}, "telnet") or die "cannot spawn nc: $!\n";
$exp->expect(60, "Login Name:");
$exp->send(getuser()."\r");
$exp->expect(10, "Password:");
$exp->send(getpassword()."\r");
$exp->expect(10, "iLO>");
$exp->send("power\r");
my $power;
$exp->expect(10,
[ "Off" => sub { $power=0 } ],
[ "On" => sub { $power=1 } ],
);
$exp->expect(10, "iLO>");
if ($power) {
$exp->send("power warm\r");
}
else {
$exp->send("power on\r");
}
$exp->expect(10, "iLO>");
sleep 1;
$exp->send("exit\r");
sleep 1;
$exp->interact;
}
elsif ($action eq 'get_host_power') {
send_command('server_info', qq{});
print "Power: ".scan_result("HOST_POWER")."\n";
}
elsif ($action eq 'connect_cd') {
send_command('rib_info', qq{});
process_result();
send_command('rib_info', qq{});
process_result();
send_command('rib_info', qq{
});
exit process_result();
}
elsif ($action eq 'boot_cd') {
send_command('rib_info', qq{
});
exit process_result();
}
else {
print STDERR "unknown action $action\n";
}
sub send_command {
my $command=gen_command(@_);
if (! defined $ENV{HP_ILO_HOST}) {
die "Please set HP_ILO_HOST\n";
}
my $pid = open2 (\*RDRFH, \*WTRFH, "locfg.pl", "-s", $ENV{HP_ILO_HOST}, "-f", "-");
if (! $pid) {
die "failed to run locfg.pl: $!\n";
}
print WTRFH $command;
close WTRFH;
}
sub scan_result {
my $token=shift;
my $ret;
while () {
if (/$token="(.*?)"/) {
$ret=$1;
}
}
return $ret;
}
sub process_result {
my $error;
while () {
if (/MESSAGE='(.*?)'/) {
my $msg=$1;
if ($msg=~/error/i && lc($msg) ne "no error") {
$error=1;
}
elsif (lc($msg) eq 'no error') {
$error=0 unless defined $error;
}
else {
print "Message: $msg\n";
}
}
}
close RDRFH;
if (! defined $error) {
print STDERR "Parse failure or locfg run failed.\n";
}
if (! defined $error || $error) {
return 1;
}
else {
return 0;
}
}
sub gen_command {
my $type=uc(shift);
my $password=getpassword();
my $user=getuser();
return <<"EOF"
<$type MODE="write">
@_
$type>
EOF
}
sub getpassword {
if (exists $ENV{HP_ILO_PASSWORD}) {
return $ENV{HP_ILO_PASSWORD};
}
die "Please set HP_ILO_PASSWORD\n";
}
sub getuser {
if (exists $ENV{HP_ILO_USER}) {
return $ENV{HP_ILO_USER}
}
die "Please set HP_ILO_USER\n";
}