mirror of
https://github.com/mangosfour/server.git
synced 2025-12-16 04:37:00 +00:00
(based on cipherCOM's repo commit d3d8934) Signed-off-by: VladimirMangos <vladimir@getmangos.com>
464 lines
11 KiB
Perl
464 lines
11 KiB
Perl
#! /usr/bin/perl
|
|
# $Id: ProcessVX.pm 89840 2010-04-12 09:36:32Z mcorino $
|
|
|
|
package PerlACE::ProcessVX;
|
|
|
|
use strict;
|
|
use English;
|
|
use POSIX qw(:time_h);
|
|
|
|
$PerlACE::ProcessVX::ExeSubDir = './';
|
|
$PerlACE::ProcessVX::DoVxInit = (defined $ENV{"ACE_RUN_VX_NO_INITIAL_REBOOT"}) ? 0 : 1;
|
|
$PerlACE::ProcessVX::VxDefGw = 1;
|
|
$PerlACE::ProcessVX::RebootTime = (defined $ENV{"ACE_RUN_VX_REBOOT_TIME"}) ? $ENV{"ACE_RUN_VX_REBOOT_TIME"} : 90;
|
|
$PerlACE::ProcessVX::ExeExt = ($PerlACE::VxWorks_RTP_Test) ? '.vxe' : '.out';
|
|
$PerlACE::ProcessVX::RebootCmd = $ENV{"ACE_RUN_VX_REBOOT_CMD"};
|
|
|
|
# Wait for the process to exit or kill after a time period
|
|
|
|
sub WaitKill ($)
|
|
{
|
|
my $self = shift;
|
|
my $timeout = shift;
|
|
|
|
my $status = $self->TimedWait ($timeout);
|
|
|
|
if ($status == -1) {
|
|
print STDERR "ERROR: $self->{EXECUTABLE} timedout\n";
|
|
$self->Kill ();
|
|
# Don't need to Wait since we are on Win32
|
|
|
|
$PerlACE::ProcessVX::DoVxInit = 1; # force reboot on next run
|
|
}
|
|
|
|
$self->{RUNNING} = 0;
|
|
|
|
return $status;
|
|
}
|
|
|
|
|
|
# Do a Spawn and immediately WaitKill
|
|
|
|
sub SpawnWaitKill ($)
|
|
{
|
|
my $self = shift;
|
|
my $timeout = shift;
|
|
|
|
if ($self->Spawn () == -1) {
|
|
return -1;
|
|
}
|
|
|
|
return $self->WaitKill ($timeout);
|
|
}
|
|
|
|
|
|
###############################################################################
|
|
|
|
### Some Accessors
|
|
|
|
sub Normalize_Executable_Name
|
|
{
|
|
my $self = shift;
|
|
my $executable = shift;
|
|
|
|
my $basename = basename ($executable);
|
|
my $dirname = dirname ($executable). '/';
|
|
|
|
$executable = $dirname.$PerlACE::ProcessVX::ExeSubDir.$basename.$PerlACE::ProcessVX::ExeExt;
|
|
|
|
## Installed executables do not conform to the ExeSubDir
|
|
if (! -e $executable && -e $dirname.$basename.$PerlACE::ProcessVX::ExeExt) {
|
|
$executable = $dirname.$basename.$PerlACE::ProcessVX::ExeExt;
|
|
}
|
|
|
|
return $executable;
|
|
}
|
|
|
|
|
|
sub Executable
|
|
{
|
|
my $self = shift;
|
|
|
|
if (@_ != 0) {
|
|
$self->{EXECUTABLE} = shift;
|
|
}
|
|
|
|
my $executable = $self->{EXECUTABLE};
|
|
|
|
if ($self->{IGNOREEXESUBDIR} == 0) {
|
|
$executable = $self->Normalize_Executable_Name ($executable);
|
|
}
|
|
else {
|
|
$executable = $executable.$PerlACE::ProcessVX::ExeExt;
|
|
}
|
|
|
|
return $executable;
|
|
}
|
|
|
|
sub Arguments
|
|
{
|
|
my $self = shift;
|
|
|
|
if (@_ != 0) {
|
|
$self->{ARGUMENTS} = shift;
|
|
}
|
|
|
|
return $self->{ARGUMENTS};
|
|
}
|
|
|
|
sub CommandLine ()
|
|
{
|
|
my $self = shift;
|
|
|
|
my $commandline = $self->Executable ();
|
|
|
|
if (defined $self->{ARGUMENTS}) {
|
|
$commandline .= ' '.$self->{ARGUMENTS};
|
|
}
|
|
|
|
return $commandline;
|
|
}
|
|
|
|
sub IgnoreExeSubDir
|
|
{
|
|
my $self = shift;
|
|
|
|
if (@_ != 0) {
|
|
$self->{IGNOREEXESUBDIR} = shift;
|
|
}
|
|
|
|
return $self->{IGNOREEXESUBDIR};
|
|
}
|
|
|
|
sub IgnoreHostRoot
|
|
{
|
|
my $self = shift;
|
|
|
|
if (@_ != 0) {
|
|
$self->{IGNOREHOSTROOT} = shift;
|
|
}
|
|
|
|
return $self->{IGNOREHOSTROOT};
|
|
}
|
|
|
|
sub delay_factor {
|
|
my($lps) = 128;
|
|
my($factor) = 1;
|
|
|
|
## Keep increasing the loops per second until the amount of time
|
|
## exceeds the number of clocks per second. The original code
|
|
## did not multiply $ticks by 8 but, for faster machines, it doesn't
|
|
## seem to return false values. The multiplication is done to minimize
|
|
## the amount of time it takes to determine the correct factor.
|
|
while(($lps <<= 1)) {
|
|
my($ticks) = clock();
|
|
for(my $i = $lps; $i >= 0; $i--) {
|
|
}
|
|
$ticks = clock() - $ticks;
|
|
if ($ticks * 8 >= CLOCKS_PER_SEC) {
|
|
$factor = 500000 / (($lps / $ticks) * CLOCKS_PER_SEC);
|
|
last;
|
|
}
|
|
}
|
|
|
|
return $factor;
|
|
}
|
|
|
|
sub iboot_cycle_power {
|
|
my $self = shift;
|
|
my $mode = shift;
|
|
|
|
# mode 0 is reboot, mode 1 is just shutdown
|
|
|
|
my ($iboot_host,
|
|
$iboot_outlet,
|
|
$iboot_user,
|
|
$iboot_passwd ) = ($ENV{'ACE_RUN_VX_IBOOT'},
|
|
$ENV{'ACE_RUN_VX_IBOOT_OUTLET'},
|
|
$ENV{'ACE_RUN_VX_IBOOT_USER'},
|
|
$ENV{'ACE_RUN_VX_IBOOT_PASSWORD'});
|
|
|
|
my $v = $ENV{'ACE_TEST_VERBOSE'};
|
|
|
|
if ($v) {
|
|
print "Using iBoot: $iboot_host\n";
|
|
if (defined $iboot_outlet) {
|
|
print "Using iBoot Outlet #: $iboot_outlet\n";
|
|
}
|
|
}
|
|
|
|
# There are three cases to handle here:
|
|
# 1. using a single-outlet iBoot
|
|
# 2. using a multi-outlet iBootBar with custom firmware
|
|
# 3. using a multi-outlet iBootBar with standard firmware
|
|
#
|
|
# In cases 1 & 2, we use the iPAL protocol; in case 3 we
|
|
# use a telnet connection and the command-line syntax.
|
|
#
|
|
# We determine that it's case #3 by the concurrent presence
|
|
# of an outlet number, an iboot username, and an iboot password
|
|
# in the environment.
|
|
#
|
|
|
|
if (defined($iboot_outlet) && defined($iboot_user) && defined($iboot_passwd)) {
|
|
# We perform case #3
|
|
# This case doesn't support shutdown
|
|
return if $mode == 1;
|
|
|
|
my $t = new Net::Telnet();
|
|
|
|
$t->prompt('/iBootBar \> /');
|
|
my $savedmode = $t->errmode();
|
|
$t->errmode("return");
|
|
|
|
my $retries = 5;
|
|
my $is_open = 0;
|
|
|
|
while ($retries--) {
|
|
my $r = $t->open($iboot_host);
|
|
if ($r == 1) {
|
|
$is_open = 1;
|
|
last;
|
|
}
|
|
}
|
|
continue {
|
|
print "Couldn't open connection; sleeping then retrying\n" if ($v);
|
|
sleep(5);
|
|
}
|
|
|
|
if (! $is_open) {
|
|
print "Unable to open $iboot_host.\n" if ($v);
|
|
return 0;
|
|
}
|
|
|
|
$t->errmode($savedmode);
|
|
|
|
# Simple login b/c Net::Telnet::login hardcodes the prompts
|
|
$t->waitfor('/User Name:\s*$/i');
|
|
$t->print($iboot_user);
|
|
$t->waitfor('/password:\s*/i');
|
|
$t->print($iboot_passwd);
|
|
|
|
$t->waitfor($t->prompt);
|
|
|
|
print "successfully logged in to $iboot_host\n" if ($v);
|
|
|
|
my $output = $t->cmd("set outlet $iboot_outlet cycle");
|
|
|
|
print "successfully cycled power on outlet $iboot_outlet\n" if ($v);
|
|
|
|
$t->close();
|
|
}
|
|
else {
|
|
# Perform cases 1 & 2
|
|
my $iboot;
|
|
my $text;
|
|
if (!defined($iboot_passwd)) {
|
|
$iboot_passwd = "PASS";
|
|
}
|
|
|
|
my $ipal_command_series;
|
|
if (defined $iboot_outlet) {
|
|
$ipal_command_series = ($mode == 0 ? ['E', 'D'] : ['E']);
|
|
} else {
|
|
$ipal_command_series = ($mode == 0 ? ['f', 'n'] : ['f']);
|
|
}
|
|
|
|
foreach my $ipal_cmd (@$ipal_command_series) {
|
|
my $retries = 3;
|
|
my $is_open = 0;
|
|
while ($retries--) {
|
|
$iboot = IO::Socket::INET->new ("$iboot_host");
|
|
if ($iboot) {
|
|
# if ACE_RUN_VX_IBOOT_OUTLET is defined, we're using
|
|
# the iBootBar, and we're using the iPAL Protocol
|
|
# to communicate with the iBootBar
|
|
if (defined $iboot_outlet) {
|
|
$iboot->send ("\e".$iboot_passwd."\e".$iboot_outlet.$ipal_cmd);
|
|
}
|
|
else {
|
|
$iboot->send ("\e".$iboot_passwd."\e$ipal_cmd\r");
|
|
}
|
|
$iboot->recv ($text,128);
|
|
print "iBoot is currently: $text\n" if ($v);
|
|
$iboot->close();
|
|
if (defined $iboot_outlet) {
|
|
$text = substr $text, $iboot_outlet - 1, 1;
|
|
if ($text eq "0" || $text eq "1") {
|
|
$is_open = 1;
|
|
last;
|
|
}
|
|
else {
|
|
print "iBoot is $text; sleeping then retrying\n" if ($v);
|
|
sleep(5);
|
|
}
|
|
}
|
|
else {
|
|
if ($text eq "OFF" || $text eq "ON") {
|
|
$is_open = 1;
|
|
last;
|
|
}
|
|
else {
|
|
print "iBoot is $text; sleeping then retrying\n" if ($v);
|
|
sleep(5);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
print "ERROR: FAILED to execute 'reboot' command!\n";
|
|
}
|
|
}
|
|
if (!$is_open) {
|
|
print "Unable to reboot using $iboot_host.\n" if ($v);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub reboot {
|
|
my $self = shift;
|
|
my $iboot;
|
|
my $text;
|
|
my $t;
|
|
my $ok;
|
|
|
|
my $target_login = $ENV{'ACE_RUN_VX_LOGIN'};
|
|
my $target_password = $ENV{'ACE_RUN_VX_PASSWORD'};
|
|
|
|
##
|
|
## initialize VxWorks kernel (reboot!) if needed
|
|
if ($PerlACE::ProcessVX::DoVxInit || $ENV{'ACE_RUN_VX_TGT_REBOOT'}) {
|
|
if (defined $ENV{'ACE_RUN_VX_REBOOT_TOOL'}) {
|
|
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
|
|
print "Calling: $ENV{'ACE_RUN_VX_REBOOT_TOOL'}\n";
|
|
}
|
|
system ($ENV{'ACE_RUN_VX_REBOOT_TOOL'});
|
|
}
|
|
else {
|
|
if (defined $ENV{'ACE_RUN_VX_IBOOT'}) {
|
|
$self->iboot_cycle_power(0);
|
|
}
|
|
else {
|
|
if (defined $ENV{'ACE_TEST_VERBOSE'}) {
|
|
print "Executing 'reboot' command over Telnet to ".$ENV{'ACE_RUN_VX_TGTHOST'}.".\n";
|
|
}
|
|
$t = new Net::Telnet(Timeout => 10,
|
|
Prompt => '/-> $/',
|
|
Errmode => 'return');
|
|
$t->open($ENV{'ACE_RUN_VX_TGTHOST'});
|
|
$t->print("");
|
|
if (defined $target_login) {
|
|
$t->waitfor('/VxWorks login: $/');
|
|
$t->print("$target_login");
|
|
}
|
|
if (defined $target_password) {
|
|
$t->waitfor('/Password: $/');
|
|
$t->print("$target_password");
|
|
}
|
|
$ok = $t->waitfor('/-> $/');
|
|
if ($ok) {
|
|
$t->print($PerlACE::ProcessVX::RebootCmd);
|
|
}
|
|
else {
|
|
print "ERROR: FAILED to execute 'reboot' command!\n";
|
|
}
|
|
$t->close();
|
|
}
|
|
}
|
|
$PerlACE::ProcessVX::VxDefGw = 1;
|
|
$PerlACE::ProcessVX::DoVxInit = 0;
|
|
sleep($PerlACE::ProcessVX::RebootTime);
|
|
}
|
|
}
|
|
|
|
# Helper for spawning with list of kernel modules in a .vxtest file
|
|
sub handle_vxtest_file
|
|
{
|
|
my $self = shift;
|
|
my $vxtestfile = shift;
|
|
my $vx_ref = shift;
|
|
my $unld_ref = shift;
|
|
my $fh = new FileHandle;
|
|
if (open ($fh, $vxtestfile)) {
|
|
my $line1 = <$fh>;
|
|
chomp $line1;
|
|
while(<$fh>) {
|
|
$line1 = $_;
|
|
chomp $line1;
|
|
push @$vx_ref, "ld < lib$line1" . ".so";
|
|
unshift @$unld_ref, "unld \"lib$line1" . ".so\"";
|
|
}
|
|
close $fh;
|
|
} else {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
# Load a file that is used as startup script. This script has to be
|
|
# located on the host system
|
|
sub handle_startup_script
|
|
{
|
|
my $script = shift;
|
|
my $cmds = shift;
|
|
my $fh = new FileHandle;
|
|
if (open ($fh, $script)) {
|
|
while(<$fh>) {
|
|
my $line1 = $_;
|
|
chomp $line1;
|
|
push @$cmds, "$line1";
|
|
}
|
|
close $fh;
|
|
} else {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
### Check for -ExeSubDir commands, store the last one
|
|
my @new_argv = ();
|
|
|
|
for(my $i = 0; $i <= $#ARGV; ++$i) {
|
|
if ($ARGV[$i] eq '-ExeSubDir') {
|
|
if (defined $ARGV[$i + 1]) {
|
|
$PerlACE::ProcessVX::ExeSubDir = $ARGV[++$i].'/';
|
|
}
|
|
else {
|
|
print STDERR "You must pass a directory with ExeSubDir\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
else {
|
|
push @new_argv, $ARGV[$i];
|
|
}
|
|
}
|
|
@ARGV = @new_argv;
|
|
|
|
$PerlACE::ProcessVX::WAIT_DELAY_FACTOR = $ENV{"ACE_RUNTEST_DELAY"};
|
|
|
|
if (defined $ENV{'ACE_TEST_WINCE'}) {
|
|
if ($OSNAME eq "MSWin32") {
|
|
require PerlACE::ProcessWinCE;
|
|
} else {
|
|
require PerlACE::ProcessWinCE_Unix;
|
|
}
|
|
} else {
|
|
if ($OSNAME eq "MSWin32") {
|
|
require PerlACE::ProcessVX_Win32;
|
|
}
|
|
else {
|
|
require PerlACE::ProcessVX_Unix;
|
|
}
|
|
}
|
|
|
|
###
|
|
|
|
sub kill_all
|
|
{
|
|
my $procmask = shift;
|
|
my $target = shift;
|
|
## NOT IMPLEMENTED YET
|
|
}
|
|
|
|
1;
|