2017-01-18 07:15:44 +00:00
package anaconda ;
use strict ;
use base 'Exporter' ;
use Exporter ;
use testapi ;
use utils ;
2021-04-27 11:02:53 +00:00
use bugzilla ;
2017-01-18 07:15:44 +00:00
2023-11-29 20:08:49 +00:00
our @ EXPORT = qw/select_disks custom_scheme_select custom_blivet_add_partition custom_blivet_format_partition custom_blivet_resize_partition custom_change_type custom_change_fs custom_change_device custom_delete_part get_full_repo get_mirrorlist_url crash_anaconda_text report_bug_text/ ;
2017-01-18 07:15:44 +00:00
sub select_disks {
# Handles disk selection. Has one optional argument - number of
# disks to select. Should be run when main Anaconda hub is
# displayed. Enters disk selection spoke and then ensures that
# required number of disks are selected. Additionally, if
# PARTITIONING variable starts with custom_, selects "custom
# partitioning" checkbox. Example usage:
# after calling `select_disks(2);` from Anaconda main hub,
# installation destination spoke will be displayed and two
# attached disks will be selected for installation.
my % args = (
disks = > 1 ,
iscsi = > { } ,
@ _
) ;
my % iscsi = % { $ args { iscsi } } ;
# Anaconda hub
2022-07-28 20:32:57 +00:00
assert_screen "anaconda_main_hub" , 300 ;
2017-01-18 07:15:44 +00:00
# Damn animation delay can cause bad clicks here too - wait for it
2024-10-16 19:49:57 +00:00
wait_still_screen 3 ;
2017-01-18 07:15:44 +00:00
assert_and_click "anaconda_main_hub_install_destination" ;
2024-10-16 19:49:57 +00:00
# it seems that sometimes the first click doesn't work with wayland
# on anaconda. we can't reproduce this manually, so work around it
# by just clicking again, this is safe even if the first click
# *did* work
sleep 1 ;
click_lastmatch ;
2017-01-18 07:15:44 +00:00
Handle anaconda 'protecting' the disk we're installing from
In install_repository_hd_variation , we have two disks attached,
so when we reach the INSTALLATION DESTINATION screen we expect
we have to select the correct target disk. However, as of the
most recent anaconda build in Rawhide, anaconda realizes we're
using a file from the other disk as our install repo, and
'protects' it - i.e. it does not show it on the INSTALLATION
DESTINATION screen, meaning only one disk is shown there, and
when only one disk is shown, it's pre-selected. So when we click,
we actually *un*select it, and the test fails.
Fixing this is a bit awkward; I wanted to add a new variable,
ANACONDA_PROTECTED_DISKS or something, and subtract that from
the NUMDISKS count; but we can't really do that as the enhanced
protection isn't in F38, and we can't easily set variables
differently on different releases (we'd have to set them in the
scheduler code, not just put them in the templates). So we just
code in a doofy condition for this instead. Maybe when F38 is
EOL we can change to the variable approach.
Signed-off-by: Adam Williamson <awilliam@redhat.com>
2023-03-29 19:59:39 +00:00
# this is awkward, but on the install_repository_hd_variation test,
2024-07-05 16:48:33 +00:00
# we have two disks but in F39 and F40 anaconda knows we're using
# one of them as an install source and 'protects' the entire disk
# (doesn't show it on INSTALLATION DESTINATION), so we need to go
# down the single disk branch in that case. On F41+ it protects
# only the partition being used as a source
Handle anaconda 'protecting' the disk we're installing from
In install_repository_hd_variation , we have two disks attached,
so when we reach the INSTALLATION DESTINATION screen we expect
we have to select the correct target disk. However, as of the
most recent anaconda build in Rawhide, anaconda realizes we're
using a file from the other disk as our install repo, and
'protects' it - i.e. it does not show it on the INSTALLATION
DESTINATION screen, meaning only one disk is shown there, and
when only one disk is shown, it's pre-selected. So when we click,
we actually *un*select it, and the test fails.
Fixing this is a bit awkward; I wanted to add a new variable,
ANACONDA_PROTECTED_DISKS or something, and subtract that from
the NUMDISKS count; but we can't really do that as the enhanced
protection isn't in F38, and we can't easily set variables
differently on different releases (we'd have to set them in the
scheduler code, not just put them in the templates). So we just
code in a doofy condition for this instead. Maybe when F38 is
EOL we can change to the variable approach.
Signed-off-by: Adam Williamson <awilliam@redhat.com>
2023-03-29 19:59:39 +00:00
my $ relnum = get_release_number ;
2024-07-05 16:48:33 +00:00
if ( get_var ( 'NUMDISKS' ) > 1 && ! ( get_var ( 'TEST' ) eq 'install_repository_hd_variation' && $ relnum < 41 ) ) {
2017-08-28 07:55:04 +00:00
# Multi-disk case. Select however many disks the test needs. If
# $disks is 0, this will do nothing, and 0 disks will be selected.
for my $ n ( 1 .. $ args { disks } ) {
assert_and_click "anaconda_install_destination_select_disk_$n" ;
2017-01-18 07:15:44 +00:00
}
}
else {
2020-02-26 22:30:08 +00:00
# Single disk case.
2017-01-18 07:15:44 +00:00
if ( $ args { disks } == 0 ) {
2020-02-26 22:30:08 +00:00
# Clicking will *de*-select.
assert_and_click "anaconda_install_destination_select_disk_1" ;
2017-01-18 07:15:44 +00:00
}
elsif ( $ args { disks } > 1 ) {
die "Only one disk is connected! Cannot select $args{disks} disks." ;
}
2020-02-26 22:30:08 +00:00
# For exactly 1 disk, we don't need to do anything.
2017-01-18 07:15:44 +00:00
}
# Handle network disks.
if ( % iscsi ) {
assert_and_click "anaconda_install_destination_add_network_disk" ;
foreach my $ target ( keys % iscsi ) {
my $ ip = $ iscsi { $ target } - > [ 0 ] ;
my $ user = $ iscsi { $ target } - > [ 1 ] ;
my $ password = $ iscsi { $ target } - > [ 2 ] ;
assert_and_click "anaconda_install_destination_add_iscsi_target" ;
wait_still_screen 2 ;
type_safely $ ip ;
wait_screen_change { send_key "tab" ; } ;
type_safely $ target ;
# start discovery - three tabs, enter
type_safely "\t\t\t\n" ;
if ( $ user && $ password ) {
assert_and_click "anaconda_install_destination_target_auth_type" ;
assert_and_click "anaconda_install_destination_target_auth_type_chap" ;
send_key "tab" ;
type_safely $ user ;
send_key "tab" ;
type_safely $ password ;
}
assert_and_click "anaconda_install_destination_target_login" ;
assert_and_click "anaconda_install_destination_select_target" ;
}
assert_and_click "anaconda_spoke_done" ;
}
2017-04-24 12:23:35 +00:00
# If this is a custom partitioning test, select custom partitioning. For testing blivet-gui,
# name of test module should start with custom_blivet_, otherwise it should start with custom_.
if ( get_var ( 'PARTITIONING' ) =~ /^custom_blivet_/ ) {
assert_and_click "anaconda_manual_blivet_partitioning" ;
} elsif ( get_var ( 'PARTITIONING' ) =~ /^custom_/ ) {
2017-01-18 07:15:44 +00:00
assert_and_click "anaconda_manual_partitioning" ;
}
}
sub custom_scheme_select {
# Used for setting custom partitioning scheme (such as LVM).
# Should be called when custom partitioning spoke is displayed.
# Pass the name of the partitioning scheme. Needle
# `anaconda_part_scheme_$scheme` should exist. Example usage:
# `custom_scheme_select("btrfs");` uses needle
# `anaconda_part_scheme_btrfs` to set partition scheme to Btrfs.
my ( $ scheme ) = @ _ ;
assert_and_click "anaconda_part_scheme" ;
# Move the mouse away from the menu
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_part_scheme_$scheme" ;
}
2017-04-24 12:23:35 +00:00
sub custom_blivet_add_partition {
# Used to add partition on blivet-gui partitioning screen
# in Anaconda. Should be called when blivet-gui is displayed and free space is selected.
# You can pass device type for partition (needle tagged anaconda_blivet_devicetype_$devicetype should exist),
# whether partitions should be of RAID1 (devicetype is then automatically handled) - you then
2017-05-05 07:29:55 +00:00
# need to have two disks added, size of that partition in MiBs, desired filesystem of that partition
2017-04-24 12:23:35 +00:00
# (anaconda_blivet_part_fs_$filesystem should exist) and mountpoint of that partition (e. g. string "/boot").
my % args = (
devicetype = > "" ,
raid1 = > 0 ,
size = > 0 ,
filesystem = > "" ,
mountpoint = > "" ,
@ _
) ;
$ args { devicetype } = "raid" if $ args { raid1 } ;
2021-08-11 19:15:46 +00:00
assert_and_click "anaconda_add" ;
2017-04-24 12:23:35 +00:00
mouse_set ( 10 , 10 ) ;
if ( $ args { devicetype } ) {
assert_and_click "anaconda_blivet_part_devicetype" ;
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_blivet_part_devicetype_$args{devicetype}" ;
}
if ( $ args { raid1 } ) {
# for RAID1, two disks should be selected
send_key "tab" ;
send_key "down" ;
send_key "spc" ;
assert_screen "anaconda_blivet_vdb_selected" ;
assert_and_click "anaconda_blivet_raidlevel_select" ;
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_blivet_raidlevel_raid1" ;
}
if ( $ args { size } ) {
2017-05-05 07:29:55 +00:00
assert_and_click "anaconda_blivet_size_unit" ;
assert_and_click "anaconda_blivet_size_unit_mib" ;
2022-07-28 20:32:57 +00:00
send_key "shift-tab" ; # input is one tab back from unit selection listbox
2017-05-05 07:29:55 +00:00
2017-04-24 12:23:35 +00:00
# size input can contain whole set of different values, so we can't match it with needle
type_safely $ args { size } . "\n" ;
}
# if no filesystem was specified or filesystem is already selected, do nothing
if ( $ args { filesystem } && ! check_screen ( "anaconda_blivet_part_fs_$args{filesystem}_selected" , 5 ) ) {
assert_and_click "anaconda_blivet_part_fs" ;
# Move the mouse away from the menu
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_blivet_part_fs_$args{filesystem}" ;
}
if ( $ args { mountpoint } ) {
assert_and_click "anaconda_blivet_mountpoint" ;
type_safely $ args { mountpoint } . "\n" ;
}
2020-03-12 00:22:26 +00:00
# seems we can get a lost click here if we click too soon
wait_still_screen 3 ;
2017-04-24 12:23:35 +00:00
assert_and_click "anaconda_blivet_btn_ok" ;
# select "free space" in blivet-gui if it exists, so we could run this function again to add another partition
2020-10-07 22:21:17 +00:00
if ( check_screen ( "anaconda_blivet_free_space" , 15 ) ) {
2017-04-24 12:23:35 +00:00
assert_and_click "anaconda_blivet_free_space" ;
}
}
2020-05-05 09:38:18 +00:00
sub custom_blivet_format_partition {
2022-07-28 20:32:57 +00:00
# This subroutine formats a selected partition. To use it, you must select the
2020-05-05 09:38:18 +00:00
# partition by other means before you format it using this routine.
# You have to create a needle for any non-existing filesystem that is
2020-05-28 09:40:34 +00:00
# passed via the $type, such as anaconda_blivet_part_fs_ext4.
2020-05-05 09:38:18 +00:00
my % args = @ _ ;
# Start editing the partition and select the Format option
assert_and_click "anaconda_blivet_part_edit" ;
2024-11-06 19:42:12 +00:00
# workaround another case where first click doesn't always work
# on Wayland
unless ( check_screen "anaconda_blivet_part_format" , 10 ) {
assert_and_click "anaconda_blivet_part_edit" ;
}
2020-05-05 09:38:18 +00:00
assert_and_click "anaconda_blivet_part_format" ;
# Select the appropriate filesystem type.
assert_and_click "anaconda_blivet_part_drop_select" ;
2024-11-06 19:42:12 +00:00
unless ( check_screen "anaconda_blivet_part_fs_$args{type}" , 5 ) {
record_soft_failure "https://bugzilla.redhat.com/show_bug.cgi?id=2324231" ;
for ( 1 .. 15 ) {
send_key "up" ;
}
}
2020-05-27 09:16:42 +00:00
assert_and_click "anaconda_blivet_part_fs_$args{type}" ;
2020-05-05 09:38:18 +00:00
wait_still_screen 2 ;
# Fill in the label if needed.
send_key "tab" ;
if ( $ args { label } ) {
type_very_safely $ args { label } ;
}
# Fill in the mountpoint.
send_key "tab" ;
type_very_safely $ args { mountpoint } ;
assert_and_click "anaconda_blivet_part_format_button" ;
}
sub custom_blivet_resize_partition {
# This subroutine resizes the selected (active) partition to a given value. Note, that
# if the selected value is bigger than the available space, it will only be
2022-07-28 20:32:57 +00:00
# resized to fill up the available space no matter the number.
2020-05-05 09:38:18 +00:00
# This routine cannot will not be able to select a particular partition!!!
my % args = @ _ ;
# Start editing the partition and select the Resize option
assert_and_click "anaconda_blivet_part_edit" ;
assert_and_click "anaconda_blivet_part_resize" ;
# Select the appropriate units. Note, that there must a be needle existing
2022-07-28 20:32:57 +00:00
# for each possible unit that you might want to use, such as
2020-05-05 09:38:18 +00:00
# "anaconda_blivet_size_unit_gib".
assert_and_click "anaconda_blivet_part_drop_select" ;
assert_and_click "anaconda_blivet_size_unit_$args{units}" ;
# Move back to the value field.
send_key "shift-tab" ;
# Type in the new size.
type_very_safely $ args { size } ;
assert_and_click "anaconda_blivet_part_resize_button" ;
}
2017-01-18 07:15:44 +00:00
sub custom_change_type {
# Used to set different device types for specified partition (e.g.
# RAID). Should be called when custom partitioning spoke is
# displayed. Pass it type of partition and name of partition.
# Needles `anaconda_part_select_$part` and
# `anaconda_part_device_type_$type` should exist. Example usage:
# `custom_change_type("raid", "root");` uses
# `anaconda_part_select_root` and `anaconda_part_device_type_raid`
# needles to set RAID for root partition.
my ( $ type , $ part ) = @ _ ;
$ part || = "root" ;
assert_and_click "anaconda_part_select_$part" ;
assert_and_click "anaconda_part_device_type" ;
# Move the mouse away from the menu
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_part_device_type_$type" ;
assert_and_click "anaconda_part_update_settings" ;
2021-03-17 21:19:20 +00:00
wait_still_screen 5 ;
2017-01-18 07:15:44 +00:00
}
sub custom_change_fs {
# Used to set different file systems for specified partition.
# Should be called when custom partitioning spoke is displayed.
# Pass filesystem name and name of partition. Needles
# `anaconda_part_select_$part` and `anaconda_part_fs_$fs` should
# exist. Example usage:
2021-08-09 22:09:15 +00:00
# `custom_change_fs("ext4", "root");` uses
# `anaconda_part_select_root` and `anaconda_part_fs_ext4` needles
# to set ext4 file system for root partition.
2017-01-18 07:15:44 +00:00
my ( $ fs , $ part ) = @ _ ;
$ part || = "root" ;
assert_and_click "anaconda_part_select_$part" ;
2020-12-05 00:15:33 +00:00
wait_still_screen 5 ;
2017-01-18 07:15:44 +00:00
# if fs is already set correctly, do nothing
return if ( check_screen "anaconda_part_fs_${fs}_selected" , 5 ) ;
assert_and_click "anaconda_part_fs" ;
# Move the mouse away from the menu
mouse_set ( 10 , 10 ) ;
assert_and_click "anaconda_part_fs_$fs" ;
assert_and_click "anaconda_part_update_settings" ;
2021-03-17 21:19:20 +00:00
wait_still_screen 5 ;
2017-01-18 07:15:44 +00:00
}
sub custom_change_device {
my ( $ part , $ devices ) = @ _ ;
assert_and_click "anaconda_part_select_$part" ;
assert_and_click "anaconda_part_device_modify" ;
foreach my $ device ( split ( / / , $ devices ) ) {
assert_and_click "anaconda_part_device_${device}" ;
}
assert_and_click "anaconda_part_device_select" ;
assert_and_click "anaconda_part_update_settings" ;
2021-03-17 21:19:20 +00:00
wait_still_screen 5 ;
2017-01-18 07:15:44 +00:00
}
sub custom_delete_part {
# Used for deletion of previously added partitions in custom
# partitioning spoke. Should be called when custom partitioning
# spoke is displayed. Pass the partition name. Needle
# `anaconda_part_select_$part` should exist. Example usage:
# `custom_delete_part('swap');` uses needle
# `anaconda_part_select_swap` to delete previously added swap
# partition.
my ( $ part ) = @ _ ;
return if not $ part ;
assert_and_click "anaconda_part_select_$part" ;
assert_and_click "anaconda_part_delete" ;
}
sub get_full_repo {
my ( $ repourl ) = @ _ ;
# trivial thing we kept repeating: fill out an HTTP or HTTPS
2019-02-04 14:46:31 +00:00
# repo URL with flavor and arch, leave hd & NFS ones alone
# (as for those tests we just use a mounted ISO and URL is complete)
if ( $ repourl !~ m/^(nfs|hd:)/ ) {
2022-12-15 19:10:40 +00:00
my $ arch = get_var ( "ARCH" ) ;
$ repourl . = "/Everything/$arch/os" ;
2017-01-18 07:15:44 +00:00
}
return $ repourl ;
}
sub get_mirrorlist_url {
return "mirrors.fedoraproject.org/mirrorlist?repo=fedora-" . lc ( get_var ( "VERSION" ) ) . "&arch=" . get_var ( 'ARCH' ) ;
}
2021-05-03 15:37:46 +00:00
2021-04-27 11:02:53 +00:00
sub crash_anaconda_text {
# This routine uses the Anaconda crash trigger to break the ongoing Anaconda installation to simulate
# an Anaconda crash and runs a series of steps that results in creating a bug in Bugzilla.
# It is used in the `install_text.pm` test and can be switched on by using the CRASH_REPORT
2022-07-28 20:32:57 +00:00
# variable set to 1.
2021-04-27 11:02:53 +00:00
#
2024-01-09 18:37:57 +00:00
# tty3 has a shell on all f31+ installer and live images
select_console "tty3-console" ;
2021-04-27 11:02:53 +00:00
assert_screen ( "anaconda_text_install_shell" ) ;
# We use the trigger command to do the simulated crash.
type_string "kill -USR1 `cat /var/run/anaconda.pid`\n" ;
# And navigate back to the main panel of Anaconda. This should require
2024-01-09 18:37:57 +00:00
select_console "tty1-console" ;
2021-04-27 11:02:53 +00:00
assert_screen ( "anaconda_text_install_main" ) ;
# We wait until the crash menu appears. This usually takes some time,
# so let's try for 300 seconds, this should be long enough.
my $ trials = 1 ;
until ( check_screen ( "anaconda_text_crash_menu_ready" ) || $ trials > 30 ) {
sleep 10 ;
+ + $ trials ;
}
# If the crash menu never appears, let's assert it to fail.
if ( $ trials > 30 ) {
assert_screen ( "anaconda_text_crash_menu_ready" ) ;
}
}
sub report_bug_text {
# This routine handles the Bugzilla reporting after a simulated crash on
# a textual console.
# We will not create a needle for every menu item, and we will fail,
# if there will be no positive Bugzilla confirmation shown at the end
2022-07-28 20:32:57 +00:00
# of the process and then we will fail.
2021-04-27 11:02:53 +00:00
#
# Let us record the time of this test run. Later, we will use it to
# limit the Bugzilla search.
my $ timestamp = time ( ) ;
#
# First, collect the credentials.
2022-07-28 20:32:57 +00:00
my $ login = get_var ( "BUGZILLA_LOGIN" ) ;
2021-04-27 11:02:53 +00:00
my $ password = get_var ( "_SECRET_BUGZILLA_PASSWORD" ) ;
my $ apikey = get_var ( "_SECRET_BUGZILLA_APIKEY" ) ;
# Choose item 1 - Report the bug.
type_string "1\n" ;
sleep 2 ;
# Choose item 1 - Report to Bugzilla
type_string "1\n" ;
sleep 5 ;
# Do login.
type_string $ login ;
type_string "\n" ;
sleep 5 ;
# Enter the name of the Zilla.
type_password $ password ;
type_string "\n" ;
sleep 10 ;
2022-07-28 20:32:57 +00:00
# Save the report without changing it.
2021-04-27 11:02:53 +00:00
# It would need some more tweaking to actually type into the report, but since
# it is reported even if unchanged, we leave it as such.
type_string ":wq\n" ;
# Wait until the Crash menu appears again.
2022-07-28 20:32:57 +00:00
# The same screen shows the result of the Bugzilla operation,
2021-04-27 11:02:53 +00:00
# so if the needle matches, the bug has been created in Bugzilla.
# Bugzilla connection is slow so we need to wait out some time,
# therefore let's use a cycle that will check each 10 seconds and
# ends if there is no correct answer from Bugzilla in 120 seconds.
my $ counter = 0 ;
until ( check_screen ( "anaconda_text_bug_reported" ) || $ counter > 12 ) {
sleep 10 ;
+ + $ counter ;
}
# Sometimes, Bugzilla throws out a communication error although the bug has been
2022-07-28 20:32:57 +00:00
# created successfully. If this happens, we will softfail and leave the creation
2021-04-27 11:02:53 +00:00
# check to a later step.
if ( $ counter > 12 ) {
record_soft_failure "Warning: Bugzilla has reported an error which could mean that the bug has not been created correctly, but it probably is not a real problem, if the test has not failed completely. " ;
}
# Now, let us check with Bugzilla directly, if the bug has been created.
# First, we shall get a Bugzilla format timestamp to use it in the query.
2022-07-28 20:32:57 +00:00
# The timestamp will limit the list of bugs to those that have been created since
2021-04-27 11:02:53 +00:00
# the then -> resulting with high probability in the one that this test run
# has just created.
$ timestamp = convert_to_bz_timestamp ( $ timestamp ) ;
# Then we fetch the latest bug from Bugzilla.
my $ lastbug = get_newest_bug ( $ timestamp , $ login ) ;
unless ( $ lastbug ) {
die "Bugzilla returned no newly created bug. It seems that the bug has not been created." ;
}
else {
print ( "BUGZILLA: The last bug was found: $lastbug\n" ) ;
}
2022-07-28 20:32:57 +00:00
# We have found that the bug indeed is in the bugzilla (otherwise
2021-04-27 11:02:53 +00:00
# we would have died already) so now we close it to clean up after this test run.
my $ result = close_notabug ( $ lastbug , $ apikey ) ;
unless ( $ result ) {
record_soft_failure "The bug has not been closed for some reason. Check manually." ;
}
else {
print ( "BUGZILLA: The last bug $lastbug changed status to CLOSED.\n" ) ;
}
# Quit anaconda
type_string "4\n" ;
2022-07-28 20:32:57 +00:00
2021-04-27 11:02:53 +00:00
}