add an iscsi test, and a support_server test to support it

Summary:
this is following a SUSE model for tests where we need a server
end but don't want setting up the server to constitute a real
test in itself, we want it to be stable. The 'support_server'
test just boots a pre-built (by createhdds) disk image, sets up
networking, and runs the iSCSI server.

To run the iSCSI test we need to handle networking config in
anaconda (or we would need to set the support server up as a
DHCP server, which may be worth considering), so this adds that.
We also need to be able to specify the target device for a
volume in custom partitioning, so this adds that too.

Test Plan:
Build the necessary support server disk image (use
D883), then run the test and make sure it works. Also make sure
all other tests continue to work.

Reviewers: jskladan, garretraziel

Reviewed By: garretraziel

Subscribers: tflink

Differential Revision: https://phab.qadevel.cloud.fedoraproject.org/D884
This commit is contained in:
Adam Williamson 2016-06-09 08:43:46 -07:00
parent 046d7e128e
commit 7a8ae3a357
40 changed files with 479 additions and 20 deletions

View File

@ -72,8 +72,13 @@ sub root_console {
} }
sub select_disks { sub select_disks {
my ($self, $disks) = @_; my $self = shift;
$disks ||= 1; my %args = (
disks => 1,
iscsi => {},
@_
);
my %iscsi = %{$args{iscsi}};
# Anaconda hub # Anaconda hub
assert_screen "anaconda_main_hub", 300; # assert_screen "anaconda_main_hub", 300; #
# Damn animation delay can cause bad clicks here too - wait for it # Damn animation delay can cause bad clicks here too - wait for it
@ -83,22 +88,44 @@ sub select_disks {
if (get_var('NUMDISKS') > 1) { if (get_var('NUMDISKS') > 1) {
# Multi-disk case. Select however many disks the test needs. If # Multi-disk case. Select however many disks the test needs. If
# $disks is 0, this will do nothing, and 0 disks will be selected. # $disks is 0, this will do nothing, and 0 disks will be selected.
for my $n (1 .. $disks) { for my $n (1 .. $args{disks}) {
assert_and_click "anaconda_install_destination_select_disk_$n"; assert_and_click "anaconda_install_destination_select_disk_$n";
} }
} }
else { else {
# Single disk case. # Single disk case.
if ($disks == 0) { if ($args{disks} == 0) {
# Clicking will *de*-select. # Clicking will *de*-select.
assert_and_click "anaconda_install_destination_select_disk_1"; assert_and_click "anaconda_install_destination_select_disk_1";
} }
elsif ($disks > 1) { elsif ($args{disks} > 1) {
die "Only one disk is connected! Cannot select $disks disks."; die "Only one disk is connected! Cannot select $args{disks} disks.";
} }
# For exactly 1 disk, we don't need to do anything. # For exactly 1 disk, we don't need to do anything.
} }
# Handle network disks.
if (%iscsi) {
assert_and_click "anaconda_install_destination_add_network_disk";
foreach my $target (keys %iscsi) {
my $ip = $iscsi{$target};
assert_and_click "anaconda_install_destination_add_iscsi_target";
type_string $ip;
wait_still_screen 2;
send_key "tab";
type_string $target;
wait_still_screen 2;
# start discovery
send_key "tab";
send_key "tab";
send_key "tab";
send_key "ret";
assert_and_click "anaconda_install_destination_target_login";
assert_and_click "anaconda_install_destination_select_target";
}
assert_and_click "anaconda_spoke_done";
}
# If this is a custom partitioning test, select custom partitioning. # If this is a custom partitioning test, select custom partitioning.
if (get_var('PARTITIONING') =~ /^custom_/) { if (get_var('PARTITIONING') =~ /^custom_/) {
assert_and_click "anaconda_manual_partitioning"; assert_and_click "anaconda_manual_partitioning";
@ -137,6 +164,17 @@ sub custom_change_fs {
assert_and_click "anaconda_part_update_settings"; assert_and_click "anaconda_part_update_settings";
} }
sub custom_change_device {
my ($self, $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";
}
sub custom_delete_part { sub custom_delete_part {
my ($self, $part) = @_; my ($self, $part) = @_;
return if not $part; return if not $part;

View File

@ -212,6 +212,18 @@ sub console_switch_layout {
} }
} }
sub get_host_dns {
# get DNS server addresses from the host
my @forwards;
open(FH, '<', "/etc/resolv.conf");
while (<FH>) {
if ($_ =~ m/^nameserver +(.+)/) {
push @forwards, $1;
}
}
return @forwards;
}
1; 1;
# vim: set sw=4 et: # vim: set sw=4 et:

14
main.pm
View File

@ -119,6 +119,11 @@ sub load_install_tests() {
# if this is a kickstart install, that's all folks # if this is a kickstart install, that's all folks
return if (get_var("KICKSTART")); return if (get_var("KICKSTART"));
## Networking
if (get_var('ANACONDA_STATIC')) {
autotest::loadtest "tests/_network_static.pm";
}
## Installation source ## Installation source
if (get_var('MIRRORLIST_GRAPHICAL') || get_var("REPOSITORY_GRAPHICAL")){ if (get_var('MIRRORLIST_GRAPHICAL') || get_var("REPOSITORY_GRAPHICAL")){
autotest::loadtest "tests/install_source_graphical.pm"; autotest::loadtest "tests/install_source_graphical.pm";
@ -182,8 +187,9 @@ sub load_postinstall_tests() {
# of PARTITIONING # of PARTITIONING
my $storagepost = ''; my $storagepost = '';
if (get_var('PARTITIONING')) { if (get_var('PARTITIONING')) {
my $loc = "tests/disk_".get_var('PARTITIONING')."_postinstall.pm"; my $casedir = get_var("CASEDIR");
$storagepost = $loc if (-e $loc); my $loc = "tests/disk_" . get_var('PARTITIONING') . "_postinstall.pm";
$storagepost = $loc if (-e "$casedir/$loc");
} }
autotest::loadtest $storagepost if ($storagepost); autotest::loadtest $storagepost if ($storagepost);
@ -216,8 +222,8 @@ if (get_var("ENTRYPOINT")) {
elsif (get_var("UPGRADE")) { elsif (get_var("UPGRADE")) {
load_upgrade_tests; load_upgrade_tests;
} }
elsif (!get_var("START_AFTER_TEST")) { elsif (!get_var("BOOTFROM")) {
# for now we can assume START_AFTER_TEST means this test picks up # for now we can assume BOOTFROM means this test picks up
# after an install, so we skip to post-install # after an install, so we skip to post-install
load_install_tests; load_install_tests;
} }

View File

@ -0,0 +1,15 @@
{
"tags": [
"anaconda_install_destination_add_iscsi_target"
],
"area": [
{
"xpos": 569,
"ypos": 690,
"width": 117,
"height": 16,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"area": [
{
"xpos": 44,
"ypos": 369,
"width": 65,
"height": 17,
"type": "match"
}
],
"tags": [
"anaconda_install_destination_add_network_disk"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,16 @@
{
"area": [
{
"xpos": 19,
"ypos": 239,
"width": 18,
"height": 17,
"type": "match"
}
],
"tags": [
"ENV-DISTRI-fedora",
"anaconda_install_destination_select_target"
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,15 @@
{
"tags": [
"anaconda_install_destination_target_login"
],
"area": [
{
"xpos": 747,
"ypos": 557,
"width": 43,
"height": 18,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"area": [
{
"xpos": 613,
"ypos": 459,
"width": 76,
"height": 72,
"type": "match"
}
],
"tags": [
"anaconda_main_hub_network_host_name"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,15 @@
{
"area": [
{
"xpos": 773,
"ypos": 332,
"width": 35,
"height": 18,
"type": "match"
}
],
"tags": [
"anaconda_network_address_add"
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"tags": [
"anaconda_network_configure"
],
"area": [
{
"xpos": 901,
"ypos": 618,
"width": 74,
"height": 19,
"type": "match"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"area": [
{
"xpos": 578,
"ypos": 145,
"width": 68,
"height": 19,
"type": "match"
}
],
"tags": [
"anaconda_network_connected"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1,15 @@
{
"tags": [
"anaconda_network_ipv4"
],
"area": [
{
"xpos": 598,
"ypos": 213,
"width": 101,
"height": 17,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"tags": [
"anaconda_network_method"
],
"area": [
{
"xpos": 484,
"ypos": 262,
"width": 342,
"height": 15,
"type": "match"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,15 @@
{
"properties": [],
"tags": [
"anaconda_network_method_manual"
],
"area": [
{
"xpos": 269,
"ypos": 315,
"width": 52,
"height": 16,
"type": "match"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -0,0 +1,15 @@
{
"tags": [
"anaconda_part_device_modify"
],
"area": [
{
"xpos": 664,
"ypos": 185,
"width": 55,
"height": 20,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1,16 @@
{
"tags": [
"anaconda_part_device_sda",
"anaconda_part_device_sda_selected"
],
"area": [
{
"xpos": 644,
"ypos": 342,
"width": 41,
"height": 13,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -0,0 +1,15 @@
{
"tags": [
"anaconda_part_device_select"
],
"area": [
{
"xpos": 713,
"ypos": 476,
"width": 46,
"height": 18,
"type": "match"
}
],
"properties": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -358,6 +358,17 @@
}, },
test_suite => { name => "realmd_join_cockpit" }, test_suite => { name => "realmd_join_cockpit" },
}, },
{
machine => { name => "64bit" },
prio => 10,
product => {
arch => "x86_64",
distri => "fedora",
flavor => "universal",
version => "*",
},
test_suite => { name => "support_server" },
},
{ {
machine => { name => "64bit" }, machine => { name => "64bit" },
prio => 20, prio => 20,
@ -567,6 +578,17 @@
}, },
test_suite => { name => "install_no_swap" }, test_suite => { name => "install_no_swap" },
}, },
{
machine => { name => "64bit" },
prio => 40,
product => {
arch => "x86_64",
distri => "fedora",
flavor => "universal",
version => "*",
},
test_suite => { name => "install_iscsi" },
},
{ {
machine => { name => "64bit" }, machine => { name => "64bit" },
prio => 50, prio => 50,
@ -1259,6 +1281,20 @@
} }
], ],
TestSuites => [ TestSuites => [
{
name => "support_server",
settings => [
{ key => "NUMDISKS", value => "2" },
{ key => "HDD_1", value => "disk_f%CURRREL%_support_x86_64.img" },
{ key => "POSTINSTALL", value => "_support_server" },
{ key => "USER_LOGIN", value => "false" },
{ key => "ROOT_PASSWORD", value => "weakpassword" },
{ key => "BOOTFROM", value => "c" },
{ key => "NICTYPE", value => "tap" },
{ key => "WORKER_CLASS", value => "tap" },
{ key => "GRUB_POSTINSTALL", value => "net.ifnames=0 biosdevname=0" },
],
},
{ {
name => "install_default", name => "install_default",
settings => [ settings => [
@ -1587,6 +1623,18 @@
{ key => "ROOT_PASSWORD", value => "weakpassword" }, { key => "ROOT_PASSWORD", value => "weakpassword" },
], ],
}, },
{
name => "install_iscsi",
settings => [
{ key => "PARTITIONING", value => "custom_iscsi" },
{ key => "ANACONDA_STATIC", value => "10.0.2.111" },
{ key => "ROOT_PASSWORD", value => "weakpassword" },
{ key => "PARALLEL_WITH", value => "support_server" },
{ key => "INSTALL_UNLOCK", value => "support_ready" },
{ key => "NICTYPE", value => "tap" },
{ key => "WORKER_CLASS", value => "tap" },
],
},
{ {
name => "install_package_set_kde", name => "install_package_set_kde",
settings => [ settings => [

52
tests/_network_static.pm Normal file
View File

@ -0,0 +1,52 @@
use base "anacondatest";
use strict;
use testapi;
sub run {
my $self = shift;
assert_and_click "anaconda_main_hub_network_host_name";
assert_and_click "anaconda_network_configure";
assert_and_click "anaconda_network_ipv4";
assert_and_click "anaconda_network_method";
assert_and_click "anaconda_network_method_manual";
assert_and_click "anaconda_network_address_add";
type_string get_var('ANACONDA_STATIC');
wait_still_screen 2;
send_key "tab";
# netmask is automatically set
send_key "tab";
# assume gateway
wait_still_screen 2;
type_string "10.0.2.2";
wait_still_screen 2;
send_key "ret";
# move to DNS servers
send_key "tab";
send_key "tab";
send_key "tab";
wait_still_screen 2;
# set DNS from host
type_string join(',', $self->get_host_dns());
send_key "tab";
send_key "tab";
send_key "tab";
send_key "tab";
send_key "tab";
send_key "ret";
# can take a bit of time as it seems to wait for all the pending
# DHCP requests to time out before applying the static config
assert_screen "anaconda_network_connected", 90;
assert_and_click "anaconda_spoke_done";
}
sub test_flags {
# without anything - rollback to 'lastgood' snapshot if failed
# 'fatal' - whole test suite is in danger if this fails
# 'milestone' - after this test succeeds, update 'lastgood'
# 'important' - if this fails, set the overall state to 'fail'
return { fatal => 1 };
}
1;
# vim: set sw=4 et:

View File

@ -0,0 +1,37 @@
use base "installedtest";
use strict;
use testapi;
use lockapi;
use mmapi;
sub run {
my $self=shift;
# clone host's /etc/hosts (for phx2 internal routing to work)
# must come *before* setup_tap_static or else it would overwrite
# its changes
$self->clone_host_file("/etc/hosts");
# set up networking
$self->setup_tap_static("10.0.2.110", "support.domain.local");
$self->clone_host_file("/etc/resolv.conf");
# start up iscsi target
assert_script_run "printf '<target iqn.2016-06.local.domain:support.target1>\n backing-store /dev/vdb\n</target>' > /etc/tgt/conf.d/openqa.conf";
# open firewall port
assert_script_run "firewall-cmd --add-service=iscsi-target";
assert_script_run "systemctl start tgtd.service";
assert_script_run 'systemctl is-active tgtd.service';
# report ready, wait for children
mutex_create('support_ready');
wait_for_children;
}
sub test_flags {
# without anything - rollback to 'lastgood' snapshot if failed
# 'fatal' - whole test suite is in danger if this fails
# 'milestone' - after this test succeeds, update 'lastgood'
# 'important' - if this fails, set the overall state to 'fail'
return { fatal => 1 };
}
1;
# vim: set sw=4 et:

View File

@ -0,0 +1,36 @@
use base "anacondatest";
use strict;
use testapi;
sub run {
my $self = shift;
# iscsi config hash
my %iscsi;
$iscsi{'iqn.2016-06.local.domain:support.target1'} = '10.0.2.110';
# Anaconda hub
# Go to INSTALLATION DESTINATION and ensure one regular disk
# and the iscsi target are selected.
$self->select_disks(iscsi=>\%iscsi);
assert_and_click "anaconda_spoke_done";
# now we're at custom part. let's use standard partitioning for
# simplicity
$self->custom_scheme_select("standard");
# Do 'automatic' partition creation
assert_and_click "anaconda_part_automatic";
# Make sure / is on the iSCSI target (which appears as sda)
$self->custom_change_device("root", "sda");
assert_and_click "anaconda_spoke_done";
assert_and_click "anaconda_part_accept_changes";
}
sub test_flags {
# without anything - rollback to 'lastgood' snapshot if failed
# 'fatal' - whole test suite is in danger if this fails
# 'milestone' - after this test succeeds, update 'lastgood'
# 'important' - if this fails, set the overall state to 'fail'
return { fatal => 1 };
}
1;
# vim: set sw=4 et:

View File

@ -0,0 +1,24 @@
use base "installedtest";
use strict;
use testapi;
sub run {
assert_screen "root_console";
# check we have a node for the target. realistically speaking we
# don't need a lot of checking here, it seems extremely unlikely
# that the system could ever actually boot unless everything is
# working.
assert_script_run "test -d '/var/lib/iscsi/nodes/iqn.2016-06.local.domain:support.target1'";
}
sub test_flags {
# without anything - rollback to 'lastgood' snapshot if failed
# 'fatal' - whole test suite is in danger if this fails
# 'milestone' - after this test succeeds, update 'lastgood'
# 'important' - if this fails, set the overall state to 'fail'
return { fatal => 1 };
}
1;
# vim: set sw=4 et:

View File

@ -6,7 +6,7 @@ sub run {
my $self = shift; my $self = shift;
# Go to INSTALLATION DESTINATION and ensure two disks are selected. # Go to INSTALLATION DESTINATION and ensure two disks are selected.
# Because PARTITIONING starts with 'custom_', this will select custom. # Because PARTITIONING starts with 'custom_', this will select custom.
$self->select_disks(2); $self->select_disks(disks=>2);
assert_and_click "anaconda_spoke_done"; assert_and_click "anaconda_spoke_done";
# Manual partitioning spoke should be displayed # Manual partitioning spoke should be displayed

View File

@ -6,7 +6,7 @@ sub run {
my $self = shift; my $self = shift;
# Anaconda hub # Anaconda hub
# Go to INSTALLATION DESTINATION and select only one disk. # Go to INSTALLATION DESTINATION and select only one disk.
$self->select_disks(1); $self->select_disks(disks=>1);
assert_and_click "anaconda_spoke_done"; assert_and_click "anaconda_spoke_done";
# Anaconda hub # Anaconda hub

View File

@ -6,7 +6,7 @@ sub run {
my $self = shift; my $self = shift;
# Anaconda hub # Anaconda hub
# Go to INSTALLATION DESTINATION and select two disks. # Go to INSTALLATION DESTINATION and select two disks.
$self->select_disks(2); $self->select_disks(disks=>2);
assert_and_click "anaconda_spoke_done"; assert_and_click "anaconda_spoke_done";
# Anaconda hub # Anaconda hub

View File

@ -28,13 +28,7 @@ sub run {
assert_script_run 'systemctl start haveged.service'; assert_script_run 'systemctl start haveged.service';
# read DNS server IPs from host's /etc/resolv.conf for passing to # read DNS server IPs from host's /etc/resolv.conf for passing to
# rolectl # rolectl
my @forwards; my @forwards = $self->get_host_dns();
open(FH, '<', "/etc/resolv.conf");
while (<FH>) {
if ($_ =~ m/^nameserver +(.+)/) {
push @forwards, $1;
}
}
# we are now gonna work around a stupid bug in rolekit. we want to # we are now gonna work around a stupid bug in rolekit. we want to
# pass it a list of ipv4 DNS forwarders and have no ipv6 DNS # pass it a list of ipv4 DNS forwarders and have no ipv6 DNS
# forwarders. but it won't allow you to have a dns_forwarders array # forwarders. but it won't allow you to have a dns_forwarders array