redo console_login with multiple matches, move to main_common

Summary:
Since we can match on multiple needles, we can drop the loop
from console_login and instead do it this way, which is simpler
and should work better on ARM (the timeouts will scale and
allow ARM to be slow here). Also move it to main_common as
there's no logical reason for it to be a class method.

Also remove the `check` arg. `check` was only set to 0 by two
tests, _console_shutdown and anacondatest's _post_fail_hook.

For _console_shutdown, I think I just wanted to give it the
best possible chance of succeeding. But we're really not going
to lose anything significant by checking, the only case where
check=>0 would've helped is if the 'good' needle had stopped
matching, and all sorts of other tests will fail in that case.

anacondatest was only using it to save a screenshot of whatever
was on the tty if it didn't reach a root console, which doesn't
seem that useful, and we'll get screenshots from check_screen
and assert_screen anyway.

Test Plan:
Run all tests, check they behave as expected and
none inappropriately fails on console login.

Reviewers: jskladan, garretraziel

Reviewed By: garretraziel

Subscribers: tflink

Differential Revision: https://phab.qadevel.cloud.fedoraproject.org/D1016
This commit is contained in:
Adam Williamson 2016-09-30 08:42:45 -07:00
parent ab5c97907e
commit bacb6f1f7b
11 changed files with 110 additions and 133 deletions

View File

@ -88,8 +88,8 @@ these functions:
- `anacondatest` should be used in tests where Anaconda is running. It uploads Anaconda logs (for example
`anaconda.log` or `packaging.log`) in `post_fail_hook()`. It also provides these convenient methods for Anaconda:
- `root_console()` tries to login is as a root. It decides to what TTY to switch into and then calls `console_login()`
for root. If you set `check` argument, it dies if it fails to log in. Example usage:
after calling `$self->root_console(check=>1);`, console should be shown with root logged in.
for root. Example usage:
after calling `$self->root_console();`, console should be shown with root logged in.
- `select_disks()` handles disk selecting. It have one optional argument - number of disks to select. It should be
run when main Anaconda hub is displayed. It enters disk selection spoke and then ensures that required number of
disks are selected. Additionally, if `$PARTITIONING` variable (set in Web UI) starts with `custom_`, it selects
@ -116,8 +116,8 @@ these functions:
- `installedtest` should be used in tests that are running on installed system (either in postinstall phase
or in upgrade tests). It uploads `/var/log` in `post_fail_hook()`. It provides these functions:
- `root_console()` tries to login is as a root. It switches to TTY that is set as an argument (default is TTY1)
and then calls `console_login()` for root. If you set `check` argument, it dies if it fails to log in.
Example usage: running `$self->root_console(tty=>2, check=>0);` results in TTY2 displayed with root logged
and then calls `console_login()` for root.
Example usage: running `$self->root_console(tty=>2);` results in TTY2 displayed with root logged
in.
- `check_release()` checks whether the installed release matches a given value. E.g. `check_release(23)`
checks whether the installed system is Fedora 23. The value can be 'Rawhide' or a Fedora release number;

View File

@ -22,8 +22,8 @@ sub post_fail_hook {
$has_traceback = 1;
}
$self->root_console(check=>0);
if (check_screen "root_console", 10) {
save_screenshot;
$self->root_console();
upload_logs "/tmp/X.log", failok=>1;
upload_logs "/tmp/anaconda.log", failok=>1;
upload_logs "/tmp/packaging.log", failok=>1;
@ -52,15 +52,10 @@ sub post_fail_hook {
script_run "ls /tmp/anaconda.core.* && tar czf /tmp/anaconda.core.tar.gz /tmp/anaconda.core.*";
upload_logs "/tmp/anaconda.core.tar.gz", failok=>1;
}
else {
save_screenshot;
}
}
sub root_console {
my $self = shift;
my %args = (
check => 1, # whether to fail when console wasn't reached
@_);
if (get_var("LIVE")) {
@ -72,7 +67,7 @@ sub root_console {
send_key "ctrl-b";
send_key "2";
}
$self->console_login(user=>"root",check=>$args{check});
console_login(user=>"root");
}
sub select_disks {

View File

@ -8,84 +8,6 @@ use lockapi;
use testapi;
# this subroutine handles logging in as a root/specified user into console
# it requires TTY to be already displayed (handled by the root_console() method of subclasses)
sub console_login {
my $self = shift;
my %args = (
user => "root",
password => get_var("ROOT_PASSWORD", "weakpassword"),
check => 1,
@_);
# There's a timing problem when we switch from a logged-in console
# to a non-logged in console and immediately call this function;
# if the switch lags a bit, this function will match one of the
# logged-in needles for the console we switched from, and get out
# of sync (e.g. https://openqa.stg.fedoraproject.org/tests/1664 )
# To avoid this, we'll sleep a couple of seconds before starting
sleep 2;
my $good = "";
my $bad = "";
my $needuser = 1;
my $needpass = 1;
if ($args{user} eq "root") {
$good = "root_console";
$bad = "user_console";
}
else {
$good = "user_console";
$bad = "root_console";
}
for my $n (1 .. 10) {
# This little loop should handle all possibilities quite
# efficiently: already at a prompt (previously logged in, or
# anaconda case), only need to enter username (live case),
# need to enter both username and password (installed system
# case). There are some annoying cases here involving delays
# to various commands and the limitations of needles;
# text_console_login also matches when the password prompt
# is displayed (as the login prompt is still visible), and
# both still match after login is complete, unless something
# runs 'clear'. The sleeps and $needuser / $needpass attempt
# to mitigate these problems.
if (check_screen $good, 0) {
return;
}
elsif (check_screen $bad, 0) {
# we don't want to 'wait' for this as it won't return
script_run "exit", 0;
sleep 2;
}
if ($needuser and check_screen "text_console_login", 0) {
type_string "$args{user}\n";
$needuser = 0;
sleep 2;
}
elsif ($needpass and check_screen "console_password_required", 0) {
type_string "$args{password}";
if (get_var("SWITCHED_LAYOUT") and $args{user} ne "root") {
# see _do_install_and_reboot; when layout is switched
# user password is doubled to contain both US and native
# chars
$self->console_switch_layout();
type_string "$args{password}";
$self->console_switch_layout();
}
send_key "ret";
$needpass = 0;
# Sometimes login takes a bit of time, so add an extra sleep
sleep 2;
}
sleep 1;
}
# If we got here we failed; if 'check' is set, die.
$args{check} && die "Failed to reach console!"
}
sub do_bootloader {
# Handle bootloader screen. 'bootloader' is syslinux or grub.
# 'uefi' is whether this is a UEFI install, will get_var UEFI if
@ -192,14 +114,6 @@ sub setup_tap_static {
script_run "systemctl restart NetworkManager.service";
}
sub console_switch_layout {
# switcher key combo differs between layouts, for console
my $self = shift;
if (get_var("LANGUAGE", "") eq "russian") {
send_key "ctrl-shift";
}
}
sub get_host_dns {
# get DNS server addresses from the host
my @forwards;

View File

@ -13,11 +13,10 @@ sub root_console {
my $self = shift;
my %args = (
tty => 1, # what TTY to login to
check => 1, # whether to fail when console wasn't reached
@_);
send_key "ctrl-alt-f$args{tty}";
$self->console_login(check=>$args{check});
console_login;
}
sub post_fail_hook {

View File

@ -6,7 +6,7 @@ use base 'Exporter';
use Exporter;
use testapi;
our @EXPORT = qw/run_with_error_check check_type_string type_safely type_very_safely desktop_vt boot_to_login_screen/;
our @EXPORT = qw/run_with_error_check check_type_string type_safely type_very_safely desktop_vt boot_to_login_screen console_login console_switch_layout/;
sub run_with_error_check {
my ($func, $error_screen) = @_;
@ -84,3 +84,70 @@ sub boot_to_login_screen {
assert_screen "login_screen";
}
}
# Switch keyboard layouts at a console
sub console_switch_layout {
# switcher key combo differs between layouts, for console
if (get_var("LANGUAGE", "") eq "russian") {
send_key "ctrl-shift";
}
}
# this subroutine handles logging in as a root/specified user into console
# it requires TTY to be already displayed (handled by the root_console()
# method of distribution classes)
sub console_login {
my %args = (
user => "root",
password => get_var("ROOT_PASSWORD", "weakpassword"),
@_);
# There's a timing problem when we switch from a logged-in console
# to a non-logged in console and immediately call this function;
# if the switch lags a bit, this function will match one of the
# logged-in needles for the console we switched from, and get out
# of sync (e.g. https://openqa.stg.fedoraproject.org/tests/1664 )
# To avoid this, we'll sleep a couple of seconds before starting
sleep 2;
my $good = "";
my $bad = "";
if ($args{user} eq "root") {
$good = "root_console";
$bad = "user_console";
}
else {
$good = "user_console";
$bad = "root_console";
}
if (check_screen $bad, 0) {
# we don't want to 'wait' for this as it won't return
script_run "exit", 0;
sleep 2;
}
check_screen [$good, 'text_console_login'], 10;
# if we're already logged in, all is good
return if (match_has_tag $good);
# if we see the login prompt, type the username
type_string("$args{user}\n") if (match_has_tag 'text_console_login');
check_screen [$good, 'console_password_required'], 30;
# on a live image, just the user name will be enough
return if (match_has_tag $good);
# otherwise, type the password if we see the prompt
if (match_has_tag 'console_password_required') {
type_string "$args{password}";
if (get_var("SWITCHED_LAYOUT") and $args{user} ne "root") {
# see _do_install_and_reboot; when layout is switched
# user password is doubled to contain both US and native
# chars
console_switch_layout;
type_string "$args{password}";
console_switch_layout;
}
send_key "ret";
}
# make sure we reached the console
assert_screen($good, 30);
}

View File

@ -10,7 +10,7 @@ sub run {
# use the desktops' graphical shutdown methods, we just go to a
# console and run 'poweroff'. We can write separate tests for
# properly testing shutdown/reboot/log out from desktops.
$self->root_console(tty=>3, check=>0);
$self->root_console(tty=>3);
script_run("poweroff", 0);
assert_shutdown;
}

View File

@ -20,10 +20,10 @@ sub run {
# do user login unless USER_LOGIN is set to string 'false'
unless (get_var("USER_LOGIN") eq "false") {
$self->console_login(user=>get_var("USER_LOGIN", "test"), password=>get_var("USER_PASSWORD", "weakpassword"));
console_login(user=>get_var("USER_LOGIN", "test"), password=>get_var("USER_PASSWORD", "weakpassword"));
}
if (get_var("ROOT_PASSWORD")) {
$self->console_login(user=>"root", password=>get_var("ROOT_PASSWORD"));
console_login(user=>"root", password=>get_var("ROOT_PASSWORD"));
}
}

View File

@ -1,6 +1,7 @@
use base "installedtest";
use strict;
use testapi;
use main_common;
sub run {
my $self=shift;
@ -22,7 +23,7 @@ sub run {
# switch to tty3
send_key "ctrl-alt-f3";
# try and login as test1, should work
$self->console_login(user=>'test1@DOMAIN.LOCAL', password=>'batterystaple');
console_login(user=>'test1@DOMAIN.LOCAL', password=>'batterystaple');
type_string "exit\n";
# try and login as test2, should fail. we cannot use console_login
# as it takes 10 seconds to complete when login fails, and

View File

@ -6,7 +6,7 @@ use freeipa;
sub run {
my $self = shift;
$self->console_login(user=>'root');
console_login(user=>'root');
# clear browser data so we don't go back to the 'admin' login
assert_script_run 'rm -rf /root/.mozilla';
# clear kerberos ticket so we don't auto-auth as 'test4'

View File

@ -52,7 +52,7 @@ sub run {
# switch to tty4 (boy, the tty jugglin')
send_key "ctrl-alt-f4";
# try and login as test3, should work
$self->console_login(user=>'test3@DOMAIN.LOCAL', password=>'batterystaple');
console_login(user=>'test3@DOMAIN.LOCAL', password=>'batterystaple');
type_string "exit\n";
# try and login as test4, should fail. we cannot use console_login
# as it takes 10 seconds to complete when login fails, and

View File

@ -1,6 +1,7 @@
use base "installedtest";
use strict;
use testapi;
use main_common;
sub run {
my $self = shift;
@ -58,7 +59,7 @@ sub run {
assert_screen "text_console_login", 60;
# Try to log in as an user
$self->console_login(user=>get_var("USER_LOGIN", "test"), password=>get_var("USER_PASSWORD", "weakpassword"));
console_login(user=>get_var("USER_LOGIN", "test"), password=>get_var("USER_PASSWORD", "weakpassword"));
}