mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-25 17:27:18 +00:00
381 lines
8.4 KiB
Perl
381 lines
8.4 KiB
Perl
# Copyright (c) 2017-present, Facebook, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This source code is licensed under the BSD-style license found in the
|
|
# LICENSE file in the root directory of this source tree. An additional grant
|
|
# of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
package mods::sock_sess;
|
|
#
|
|
# File: sock_sess.pm
|
|
#
|
|
#
|
|
use Exporter;
|
|
our (@ISA, @EXPORT);
|
|
@ISA = qw/Exporter/;
|
|
@EXPORT = qw/ detect_sock run_sock $Sname /;
|
|
use strict;
|
|
use v5.14;
|
|
no warnings 'experimental::smartmatch';
|
|
use Cwd;
|
|
use Socket;
|
|
use IO::Handle;
|
|
use Time::HiRes qw/usleep/;
|
|
use mods::walker qw/ro_user w_user/;
|
|
use mods::fbt_config qw/@Ttable/;
|
|
use mods::misc qw/ shess check_pon pon power_off ping_safe
|
|
mk_net_ping ssh_login port_22_available/;
|
|
use mods::Logio;
|
|
use threads;
|
|
use Carp;
|
|
my $Sock = undef;
|
|
my $Tsock = undef;
|
|
our $Sname = '/tmp/fbt_sock';
|
|
my $Lfh = undef;
|
|
my $Lfn = '/var/log/fbt/sock.log';
|
|
my $Tconf = {};
|
|
my $Uhr = {};
|
|
my $Wh = undef; # My walk handle.
|
|
my ($Written, $Wusr, $Wsno);
|
|
|
|
sub detect_sock {
|
|
return 0 unless -S $Sname;
|
|
socket($Sock, PF_UNIX, SOCK_STREAM, 0)
|
|
or croak("Cannot open socket stream: $!.\n");
|
|
my $dest = sockaddr_un($Sname);
|
|
connect($Sock, $dest) or croak("Cannot connect to $Sname: $!.\n");
|
|
$Sock->autoflush(1);
|
|
|
|
$Lfh = get_sock_log_file($Lfn);
|
|
$Lfh->autoflush(1);
|
|
|
|
# For some reason, strict barks at the bareword SH used in this call
|
|
# to tie. However, I cannot use a scalar in its place or tie will
|
|
# think it is tying a scalar, not a file handle.
|
|
{
|
|
no strict;
|
|
tie(*SH, 'mods::Logio', $Lfh, $Sock);
|
|
$Tsock = *SH;
|
|
}
|
|
return $Tsock;
|
|
}
|
|
|
|
sub run_sock {
|
|
my $dir = shift;
|
|
my $v = shift;
|
|
state_1($dir, $v);
|
|
state_2();
|
|
state_3();
|
|
state_4();
|
|
}
|
|
|
|
sub std_ok { print $Tsock "ok.\n"; }
|
|
sub std_exit { my $ec = shift; print $Tsock "ok.\n"; exit $ec; }
|
|
|
|
sub sock_pon {
|
|
if (!defined $Tconf->{pon}) {
|
|
print $Tsock "na\n";
|
|
return 'na';
|
|
}
|
|
|
|
my $dir = $Tconf->{dir} // '/var/log/fbt';
|
|
$Tconf->{plfn} = $Tconf->{plfn} // "$dir/fbt.pwr.log";
|
|
$Tconf->{ppoke} = $Tconf->{ppoke} // qr/xyz\$ /;
|
|
$Tconf->{peh} = shess($Tconf);
|
|
pon($Tconf);
|
|
std_ok();
|
|
return 'on';
|
|
}
|
|
|
|
sub sock_poff {
|
|
if (!defined $Tconf->{pon}) {
|
|
print $Tsock "na\n";
|
|
return 'na';
|
|
}
|
|
|
|
power_off('return');
|
|
std_ok();
|
|
return 'off';
|
|
}
|
|
|
|
sub mk_sess {
|
|
my $hr = shift;
|
|
my $tip = $hr->{tip} // croak "Need test network defined.\n";
|
|
my $p = mk_net_ping($tip);
|
|
my $ret;
|
|
|
|
# usleep(10 * 1_000_000);
|
|
unless (defined $hr->{useip}) { # We want a local shell
|
|
print "mk_sess() wants local shell.\n";
|
|
$hr->{eh} = shess($hr);
|
|
for (my $i = 10; $i < 50; $i += 10) {
|
|
usleep(10_000_000);
|
|
print $Tsock "waiting $i seconds of 100\n";
|
|
}
|
|
std_ok();
|
|
return 't';
|
|
}
|
|
elsif (!defined $hr->{pon}) {
|
|
print "mk_sess() wants shell with $hr->{ip}.\n";
|
|
$ret = ping_safe($p, $hr->{ip});
|
|
do { report_error("ping", 2); return 'f'; } if ($ret);
|
|
goto ssh_login;
|
|
}
|
|
|
|
# This pathway needs to wait for the UUT to power up.
|
|
my ($n, $s, $p22, $last) = (0, 0, 0, 70);
|
|
until ($n > $last) {
|
|
usleep(5_000_000);
|
|
$n += 5;
|
|
$ret = ping_safe($p, $hr->{ip});
|
|
$p22 = port_22_available($hr->{ip});
|
|
if ($ret && $p22) {
|
|
$s++;
|
|
last if ($s == 2); # Ping and port 22 twice.
|
|
}
|
|
print $Tsock "waiting $n seconds of $last ($ret, $p22)\n";
|
|
}
|
|
$p->close();
|
|
do { report_error(2, "ping"); return 'f'; } unless ($ret);
|
|
do { report_error(2, "port 22"); return 'f'; } unless ($p22);
|
|
|
|
ssh_login:
|
|
$hr->{eh} = ssh_login($hr);
|
|
do { report_error(2, "ssh login"); return 'f';}
|
|
unless (defined $hr->{eh});
|
|
std_ok();
|
|
return 't';
|
|
}
|
|
|
|
sub pull_from_w_ {
|
|
my $dir = shift;
|
|
my $txt = shift;
|
|
chomp $txt;
|
|
my ($cmd, $ret) = $txt =~ m/^w_(\w+):\s([^\n]*)$/;
|
|
|
|
if (defined $ret) {
|
|
$Wusr = $ret if ($cmd eq 'uname');
|
|
$Wsno = $ret if ($cmd eq 'serno');
|
|
if (defined $Wusr and defined $Wsno) {
|
|
$Uhr->{test_info}->{sn} = $Wsno;
|
|
$Uhr->{test_info}->{user} = $Wusr;
|
|
w_user($dir, $Uhr);
|
|
undef $Wsno;
|
|
undef $Wusr;
|
|
$Written++;
|
|
}
|
|
std_ok();
|
|
}
|
|
else { print $Tsock "Error, no text for w_*: command.\n"; }
|
|
}
|
|
|
|
sub set_test_mode {
|
|
my $txt = shift;
|
|
|
|
$Tconf->{tmode}++;
|
|
my ($ret) = $txt =~ m/^test_mode:\s(\d+)/;
|
|
if (defined $ret) { std_ok(); }
|
|
else { print $Tsock "Error, test_mode: command had no value?\n"; }
|
|
return $ret // 0;
|
|
}
|
|
|
|
sub report_error {
|
|
my $state = shift;
|
|
my $cmd = shift;
|
|
chomp($cmd);
|
|
print $Tsock "Error, cannot $cmd in state $state.\n";
|
|
}
|
|
|
|
sub send_list {
|
|
my $i = shift;
|
|
my $maj = 1;
|
|
my $min = 0;
|
|
my $hr = $Ttable[$i];
|
|
# print "send_list() I'm looking to get Ttable[$i].\n";
|
|
|
|
my @tst = @{$hr->{tests}};
|
|
|
|
# This is a check to see if there are really power suppies out
|
|
# there. If not, we just undef the pon key.
|
|
$hr->{pon} = check_pon($hr->{pon}) if (defined $hr->{pon});
|
|
for my $thr (@tst) {
|
|
print $Tsock "$maj.$min: $thr->{name}\n";
|
|
if (defined $thr->{res}) {
|
|
my @rtst = @{$thr->{res}};
|
|
for my $rhr (@rtst) {
|
|
$min++;
|
|
print $Tsock "$maj.$min: $rhr->{name}\n";
|
|
}
|
|
}
|
|
$min = 0;
|
|
$maj++;
|
|
}
|
|
$hr->{scomm} = $Tsock;
|
|
if (defined $hr->{pon}) {
|
|
print $Tsock "test_list still needs power sequence.\n";
|
|
}
|
|
else {
|
|
print $Tsock "test_list end.\n";
|
|
return $hr;
|
|
}
|
|
my @psq = @{$hr->{pon}};
|
|
$maj = 1;
|
|
$min = 0;
|
|
|
|
for my $phr (@psq) {
|
|
print $Tsock "$maj.$min: $phr->{name}\n";
|
|
if (defined $phr->{res}) {
|
|
my @rpwr = @{$phr->{res}};
|
|
for my $rhr (@rpwr) {
|
|
$min++;
|
|
print $Tsock "$maj.$min: $rhr->{name}\n";
|
|
}
|
|
}
|
|
$min = 0;
|
|
$maj++;
|
|
}
|
|
|
|
print $Tsock "test_list end.\n";
|
|
return $hr;
|
|
}
|
|
|
|
sub state_1 {
|
|
my $dir = shift;
|
|
my $v = shift;
|
|
my $smsg = "state: 1, pwr: off, sess: f";
|
|
my $ti = $ENV{FBT_TEST_TABLE_INDEX} // 0;
|
|
$Written = undef;
|
|
$Wsno = undef;
|
|
$Wusr = undef;
|
|
my $cmd;
|
|
|
|
$Uhr = ro_user($dir, $v);
|
|
my $sno = $Uhr->{test_info}->{sn};
|
|
my $usr = $Uhr->{test_info}->{user};
|
|
|
|
until (defined $Tconf->{tests} and defined $Written) {
|
|
return unless (defined($cmd = <$Tsock>));
|
|
|
|
for ($cmd) {
|
|
print $Tsock "$v\n" when /^id$/;
|
|
print $Tsock "$usr\n" when /^uname$/;
|
|
print $Tsock "$sno\n" when /^serno$/;
|
|
print $Tsock "$smsg\n" when /^status$/;
|
|
pull_from_w_($dir, $cmd) when /^w_uname:\s/;
|
|
pull_from_w_($dir, $cmd) when /^w_serno:\s/;
|
|
$Tconf = send_list($ti) when /^test_list$/;
|
|
$ti = set_test_mode($cmd) when /^test_mode:\s/;
|
|
std_exit(1) when /^exit$/;
|
|
do { undef $Written;
|
|
undef $Wusr;
|
|
undef $Wsno;
|
|
std_ok(); } when /^clr_info$/;
|
|
default { report_error(1, $cmd); }
|
|
}
|
|
}
|
|
}
|
|
|
|
sub print_status_2 {
|
|
my ($pwr, $sess) = @_;
|
|
print $Tsock "state: 2, pwr: $pwr, sess: $sess\n";
|
|
}
|
|
|
|
sub state_2 {
|
|
my $cmd;
|
|
|
|
my $pwr = 'off';
|
|
my $sess = 'f';
|
|
my $status = 0;
|
|
until ($status) {
|
|
return unless (defined($cmd = <$Tsock>));
|
|
|
|
for ($cmd) {
|
|
$pwr = sock_pon() when /^pon$/;
|
|
$sess = mk_sess($Tconf) when /^mk_sess$/;
|
|
std_exit(2) when /^exit$/;
|
|
do { print_status_2($pwr, $sess);
|
|
$status++;} when /^status$/;
|
|
default { report_error(2, $cmd); }
|
|
}
|
|
}
|
|
}
|
|
|
|
sub report_nops {
|
|
my $hr = shift;
|
|
my $tn = $hr->{tnum} . '.0';
|
|
|
|
print $Tsock "$tn: pass_NOPS\n";
|
|
|
|
return unless defined $hr->{res};
|
|
for my $rhr (@{$hr->{res}}) {
|
|
$tn += 0.1;
|
|
print $Tsock "$tn: pass_NOPS\n";
|
|
}
|
|
}
|
|
|
|
sub walk_all { # This is an automated test.
|
|
my $uhr = shift;
|
|
my $hr = shift;
|
|
my $wh = mods::walker->new($uhr, $hr);
|
|
|
|
$wh->_report_ok(); # Enable reporting.
|
|
my $n = 1;
|
|
foreach my $th (@{$hr->{tests}}) {
|
|
$th->{tnum} = $n++;
|
|
if ((!defined $hr->{peh})
|
|
&& $th->{prog} =~ m{^/usr/local/fbin}) {
|
|
report_nops($th);
|
|
next;
|
|
}
|
|
$wh->_walk_this($th);
|
|
}
|
|
print $Tsock "Tests complete. Total errors: $wh->{nerr}.\n";
|
|
return $wh;
|
|
}
|
|
|
|
|
|
sub state_3 {
|
|
my $cmd;
|
|
|
|
until (defined $Wh) {
|
|
return unless (defined($cmd = <$Tsock>));
|
|
|
|
for ($cmd) {
|
|
$Wh = walk_all($Uhr,$Tconf) when /^run_tests$/;
|
|
std_exit(3) when /^exit$/;
|
|
default { report_error(3, $cmd); }
|
|
}
|
|
}
|
|
}
|
|
|
|
sub state_4 {
|
|
my $cmd;
|
|
my ($off, $report) = (0, 0);
|
|
|
|
until ($off and $report) {
|
|
return unless (defined($cmd = <$Tsock>));
|
|
|
|
for ($cmd) {
|
|
do { sock_poff(); $off++; } when /^poff$/;
|
|
do { $Wh->_report_ok();
|
|
$report++;
|
|
std_ok();
|
|
} when /^report$/;
|
|
std_exit(0) when /^exit$/;
|
|
default { report_error(4, $cmd); }
|
|
}
|
|
}
|
|
}
|
|
|
|
sub get_sock_log_file {
|
|
my $fn = shift;
|
|
my $ofn = "$fn.old";
|
|
|
|
unlink $ofn if (-e $ofn);
|
|
rename $fn, $ofn if (-e $fn);
|
|
open my $fh, '>', $fn or croak "Cannot open $fn for write: $!.\n";
|
|
return $fh;
|
|
}
|
|
|
|
1;
|