diff --git a/README.md b/README.md index f62e6390..3e458d4a 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ these functions: long still screen should be displayed until openQA decides that system is booted and third is timeout how long it should wait for still screen to appear. Example usage: `$self->boot_to_login_screen("graphical_login", 30);` will wait until screen is not moving for 30 seconds and then checks, whether `graphical_login` needle is displayed. + - `clone_host_resolv()` copies the contents of the host's `/etc/resolv.conf` into the guest, overwriting any existing contents. This is mainly intended for use by openvswitch guests which need external connectivity. - `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()` diff --git a/lib/fedorabase.pm b/lib/fedorabase.pm index ce905097..42d2a75b 100644 --- a/lib/fedorabase.pm +++ b/lib/fedorabase.pm @@ -1,5 +1,6 @@ package fedorabase; use base 'basetest'; +use lockapi; # base class for all Fedora tests @@ -75,6 +76,64 @@ sub console_login { $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 + # not explicitly set. 'postinstall' is whether we're on an + # installed system or at the installer (this matters for how many + # times we press 'down' to find the kernel line when typing args). + # 'args' is a string of extra kernel args, if desired. 'mutex' is + # a parallel test mutex lock to wait for before proceeding, if + # desired. 'first' is whether to hit 'up' a couple of times to + # make sure we boot the first menu entry. + my ($self, $postinstall, $args, $mutex, $first, $bootloader, $uefi) = @_; + $uefi //= get_var("UEFI"); + $postinstall //= 0; + # if not postinstall and not UEFI, syslinux + $bootloader //= ($uefi || $postinstall) ? "grub" : "syslinux"; + $args //= ""; + $mutex //= ""; + $first //= 1; + if ($uefi) { + # we don't just tag all screens with 'bootloader' because we + # want to be sure we actually did a UEFI boot + assert_screen "bootloader_uefi", 30; + } else { + assert_screen "bootloader", 30; + } + if ($mutex) { + # cancel countdown + send_key "left"; + mutex_lock $mutex; + mutex_unlock $mutex; + } + if ($first) { + # press up a couple of times to make sure we're at first entry + send_key "up"; + send_key "up"; + } + if ($args) { + if ($bootloader eq "syslinux") { + send_key "tab"; + } + else { + send_key "e"; + # ternary: 13 'downs' to reach the kernel line for installed + # system, 2 for UEFI installer + my $presses = $postinstall ? 13 : 2; + foreach my $i (1..$presses) { + send_key "down"; + } + send_key "end"; + } + type_string " $args"; + } + # ctrl-X boots from grub editor mode + send_key "ctrl-x"; + # return boots all other cases + send_key "ret"; +} + sub boot_to_login_screen { my $self = shift; my $boot_done_screen = shift; # what to expect when system is booted (e. g. GDM), can be "" @@ -94,6 +153,22 @@ sub get_milestone { return ''; } +sub clone_host_resolv { + # this is pretty crazy, but SUSE do almost the same thing... + # it's for openvswitch jobs to clone the host's resolv.conf, so + # we don't have to hard code 8.8.8.8 or have the templates pass + # in an address or something + my $self = shift; + my $resolv = ''; + open(FH, '<', "/etc/resolv.conf"); + while () { + $resolv .= $_; + } + assert_script_run "printf '$resolv' > /etc/resolv.conf"; + # for debugging... + assert_script_run "cat /etc/resolv.conf"; +} + 1; # vim: set sw=4 et: diff --git a/needles/bootloader_bios_installed.json b/needles/bootloader_bios_installed.json new file mode 100644 index 00000000..83769e6c --- /dev/null +++ b/needles/bootloader_bios_installed.json @@ -0,0 +1,15 @@ +{ + "area": [ + { + "height": 15, + "type": "match", + "width": 160, + "xpos": 50, + "ypos": 335 + } + ], + "tags": [ + "bootloader", + "ENV-DISTRI-fedora" + ] +} diff --git a/needles/bootloader_bios_installed.png b/needles/bootloader_bios_installed.png new file mode 100644 index 00000000..d5ecca37 Binary files /dev/null and b/needles/bootloader_bios_installed.png differ diff --git a/needles/login_permission_denied.json b/needles/login_permission_denied.json new file mode 100644 index 00000000..5029273b --- /dev/null +++ b/needles/login_permission_denied.json @@ -0,0 +1,15 @@ +{ + "area": [ + { + "height": 13, + "type": "match", + "width": 136, + "xpos": 0, + "ypos": 144 + } + ], + "tags": [ + "login_permission_denied", + "ENV-DISTRI-fedora" + ] +} diff --git a/needles/login_permission_denied.png b/needles/login_permission_denied.png new file mode 100644 index 00000000..5dc454e5 Binary files /dev/null and b/needles/login_permission_denied.png differ diff --git a/needles/text_console_login.json b/needles/text_console_login.json index a9a351fc..928208df 100644 --- a/needles/text_console_login.json +++ b/needles/text_console_login.json @@ -1,17 +1,17 @@ -{ - "tags": [ - "text_console_login", - "ENV-DISTRI-fedora", - "ENV-FLAVOR-develop" - ], - "properties": [], - "area": [ - { - "width": 128, - "xpos": 0, - "type": "match", - "ypos": 49, - "height": 30 - } - ] -} +{ + "area": [ + { + "height": 30, + "type": "match", + "width": 56, + "xpos": 72, + "ypos": 49 + } + ], + "properties": [], + "tags": [ + "text_console_login", + "ENV-DISTRI-fedora", + "ENV-FLAVOR-develop" + ] +} \ No newline at end of file diff --git a/needles/user_logged_in-noprofile.json b/needles/user_logged_in-noprofile.json new file mode 100644 index 00000000..45b96854 --- /dev/null +++ b/needles/user_logged_in-noprofile.json @@ -0,0 +1,16 @@ +{ + "area": [ + { + "height": 16, + "type": "match", + "width": 65, + "xpos": 0, + "ypos": 143 + } + ], + "tags": [ + "user_logged_in", + "user_console", + "ENV-DISTRI-fedora" + ] +} diff --git a/needles/user_logged_in-noprofile.png b/needles/user_logged_in-noprofile.png new file mode 100644 index 00000000..b53455c3 Binary files /dev/null and b/needles/user_logged_in-noprofile.png differ diff --git a/templates b/templates index d12c5b2b..2e033e24 100755 --- a/templates +++ b/templates @@ -259,6 +259,28 @@ }, test_suite => { name => "install_package_set_minimal" }, }, + { + machine => { name => "64bit" }, + prio => 40, + product => { + arch => "x86_64", + distri => "fedora", + flavor => "Server-dvd-iso", + version => "*", + }, + test_suite => { name => "server_role_deploy_domain_controller" }, + }, + { + machine => { name => "64bit" }, + prio => 40, + product => { + arch => "x86_64", + distri => "fedora", + flavor => "Server-dvd-iso", + version => "*", + }, + test_suite => { name => "server_realmd_join_kickstart" }, + }, { machine => { name => "64bit" }, prio => 20, @@ -1261,7 +1283,7 @@ { key => "KICKSTART", value => "1" }, { key => "GRUB", value => "inst.ks=hd:vdb1:/root-user-crypted-net.ks" }, { key => "NUMDISKS", value => "2" }, - { key => "HDD_2", value => "disk_ks.img" }, + { key => "HDD_2", value => "disk_ks_2.img" }, { key => "ROOT_PASSWORD", value => "111111" }, { key => "USER_LOGIN", value => "test" }, { key => "USER_PASSWORD", value => "test" }, @@ -1458,5 +1480,31 @@ { key => "USER_LOGIN", value => "false" }, ], }, + { + name => "server_role_deploy_domain_controller", + settings => [ + { key => "ENTRYPOINT", value => "role_deploy_domain_controller" }, + { key => "START_AFTER_TEST", value => "install_default_upload" }, + { key => "BOOTFROM", value => "c" }, + { key => "HDD_1", value => "disk_%FLAVOR%_%MACHINE%.qcow2" }, + { key => "GRUB", value => "net.ifnames=0 biosdevname=0" }, + { key => "NICTYPE", value => "tap" }, + ], + }, + { + name => "server_realmd_join_kickstart", + settings => [ + { key => "KICKSTART", value => "1" }, + { key => "GRUB", value => "inst.ks=hd:vdb1:/freeipaclient.ks" }, + { key => "NUMDISKS", value => "2" }, + { key => "HDD_2", value => "disk_ks_2.img" }, + { key => "POSTINSTALL", value => "freeipa_client" }, + { key => "USER_LOGIN", value => "false" }, + { key => "ROOT_PASSWORD", value => "anaconda" }, + { key => "PARALLEL_WITH", value => "server_role_deploy_domain_controller" }, + { key => "INSTALL_UNLOCK", value => "freeipa_ready" }, + { key => "NICTYPE", value => "tap" }, + ], + }, ], } diff --git a/tests/_boot_to_anaconda.pm b/tests/_boot_to_anaconda.pm index 0423fcd7..199885d0 100644 --- a/tests/_boot_to_anaconda.pm +++ b/tests/_boot_to_anaconda.pm @@ -2,66 +2,33 @@ use base "anacondatest"; use strict; use testapi; -# get_kernel_line switches to menu edit screen and sets the cursor to the end of kernel line -sub get_kernel_line { - if( get_var("UEFI")){ - send_key "e"; - send_key "down"; - send_key "down"; - send_key "end"; - } else { - send_key "tab"; - } -} - sub run { - # Wait for bootloader to appear - if( get_var("UEFI")){ - assert_screen "bootloader_uefi", 30; - } else { - assert_screen "bootloader", 30; + my $self = shift; + # construct the kernel args. the trick here is to wind up with + # spaced args if GRUB or GRUBADD is set, and just spaces if not, + # then check if we got all spaces. We wind up with a harmless + # extra space if GRUBADD is set but GRUB is not. + my $args = ""; + $args .= get_var("GRUB", "") . " "; + $args .= get_var("GRUBADD", "") . " "; + # Construct inst.repo arg for REPOSITORY_VARIATION + my $repourl = get_var("REPOSITORY_VARIATION"); + if ($repourl) { + my $version = lc(get_var("VERSION", "")); + my $arch = get_var("ARCH", ""); + $repourl .= "/$version/Everything/$arch/os"; + $args .= "inst.repo=$repourl"; } + # ternary: set $args to "" if it contains only spaces + $args = $args =~ /^\s+$/ ? "" : $args; - # Make sure we skip media check if it's selected by default. Standard - # 'boot installer' menu entry is always first. - send_key "up"; - send_key "up"; + # set mutex wait if necessary + my $mutex = get_var("INSTALL_UNLOCK"); - # if variable GRUB is set, add its value into kernel line in grub - if( get_var("GRUB")){ - get_kernel_line; - type_string " ".get_var("GRUB"); - - } - - # if GRUBADD is set, add that to kernel line too. this is for doing - # stuff like running the tests with an updates.img to test some - # anaconda change - if (get_var("GRUBADD")) { - # unless GRUB was also set, we need to get to the kernel line now - get_kernel_line unless (get_var("GRUB")); - type_string " ".get_var("GRUBADD"); - } - - # if variable REPOSITORY_VARIATION is set, construct inst.repo url and add it to kernel line - if (get_var("REPOSITORY_VARIATION")){ - unless (get_var("GRUB") || get_var("GRUBADD")) { - get_kernel_line; - } - my $repourl = ""; - - # REPOSITORY_VARIATION should be set to repository URL without version and architecture - # appended (it will be appended automatically) - $repourl = get_var("REPOSITORY_VARIATION")."/".lc(get_var("VERSION"))."/Everything/".get_var("ARCH")."/os"; - type_string " inst.repo=".$repourl; - } - - # now we are on the correct "boot" menu item - # hit Ctrl+x for the case when the uefi kernel line was edited - send_key "ctrl-x"; - # Return starts boot in all other cases - send_key "ret"; + # call do_bootloader with postinstall=0, the args, and the mutex + $self->do_bootloader(0, $args, $mutex); + # proceed to installer unless (get_var("KICKSTART")) { # on lives, we have to explicitly launch anaconda diff --git a/tests/freeipa_client_postinstall.pm b/tests/freeipa_client_postinstall.pm new file mode 100644 index 00000000..e4ef0c3e --- /dev/null +++ b/tests/freeipa_client_postinstall.pm @@ -0,0 +1,45 @@ +use base "installedtest"; +use strict; +use testapi; + +sub run { + my $self=shift; + # check domain is listed in 'realm list' + validate_script_output 'realm list', sub { $_ =~ m/domain-name: domain\.local.*configured: kerberos-member/s }; + # check we can see the admin user in getent + assert_script_run 'getent passwd admin@DOMAIN.LOCAL'; + # check keytab entries + validate_script_output 'klist -k', sub { $_ =~ m/client001\.domain\.local\@DOMAIN.LOCAL/ }; + # check we can kinit with the host principal + assert_script_run 'kinit -k host/client001.domain.local@DOMAIN.LOCAL'; + # kinit as each user and set a new password + assert_script_run 'printf "correcthorse\nbatterystaple\nbatterystaple" | kinit test1@DOMAIN.LOCAL'; + assert_script_run 'printf "correcthorse\nbatterystaple\nbatterystaple" | kinit test2@DOMAIN.LOCAL'; + # switch to tty3 + send_key "ctrl-alt-f3"; + # try and login as test1, should work + $self->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 + # "permission denied" message doesn't last that long + sleep 2; + assert_screen "text_console_login"; + type_string "test2\@DOMAIN.LOCAL\n"; + assert_screen "console_password_required"; + type_string "batterystaple\n"; + assert_screen "login_permission_denied"; +} + + +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: diff --git a/tests/role_deploy_domain_controller.pm b/tests/role_deploy_domain_controller.pm new file mode 100644 index 00000000..771550f0 --- /dev/null +++ b/tests/role_deploy_domain_controller.pm @@ -0,0 +1,77 @@ +use base "installedtest"; +use strict; +use testapi; +use lockapi; +use mmapi; + +sub run { + my $self=shift; + # boot with kernel params to ensure interface is 'eth0' and not whatever + # systemd feels like calling it today + $self->do_bootloader(1, "net.ifnames=0 biosdevname=0"); + $self->boot_to_login_screen("text_console_login", 5, 60); + # login + $self->root_console(); + # set hostname + assert_script_run 'hostnamectl set-hostname ipa001.domain.local'; + # add entry to /etc/hosts + assert_script_run 'echo "10.0.2.100 ipa001.domain.local ipa001" >> /etc/hosts'; + # bring up network. DEFROUTE is *vital* here + assert_script_run 'printf "DEVICE=eth0\nBOOTPROTO=none\nIPADDR=10.0.2.100\nGATEWAY=10.0.2.2\nPREFIX=24\nDEFROUTE=yes" > /etc/sysconfig/network-scripts/ifcfg-eth0'; + script_run "systemctl restart NetworkManager.service"; + # clone host's resolv.conf to get name resolution + $self->clone_host_resolv(); + # we don't want updates-testing for validation purposes + assert_script_run 'dnf config-manager --set-disabled updates-testing'; + # we need a lot of entropy for this, and we don't care how good + # it is, so let's use haveged + assert_script_run 'dnf -y install haveged', 120; + assert_script_run 'systemctl start haveged.service'; + # deploy the domain controller role + assert_script_run 'echo \'{"admin_password":"monkeys123"}\' | rolectl deploy domaincontroller --name=domain.local --settings-stdin', 1200; + # check the role status, should be 'running' + validate_script_output 'rolectl status domaincontroller/domain.local', sub { $_ =~ m/^running/ }; + # check the admin password is listed in 'settings' + validate_script_output 'rolectl settings domaincontroller/domain.local', sub {$_ =~m/dm_password = \w{5,}/ }; + # sanitize the settings + assert_script_run 'rolectl sanitize domaincontroller/domain.local'; + # check the password now shows as 'None' + validate_script_output 'rolectl settings domaincontroller/domain.local', sub {$_ =~ m/dm_password = None/ }; + # kinit as admin + assert_script_run 'echo "monkeys123" | kinit admin'; + # set up an OTP for client001 enrolment (it will enrol with a kickstart) + assert_script_run 'ipa host-add client001.domain.local --password=monkeys --force'; + # create two user accounts, test1 and test2 + assert_script_run 'echo "correcthorse" | ipa user-add test1 --first test --last one --password'; + assert_script_run 'echo "correcthorse" | ipa user-add test2 --first test --last two --password'; + # add a rule allowing access to all hosts and services + assert_script_run 'ipa hbacrule-add testrule --servicecat=all --hostcat=all'; + # add test1 (but not test2) to the rule + assert_script_run 'ipa hbacrule-add-user testrule --users=test1'; + # disable the default 'everyone everywhere' rule + assert_script_run 'ipa hbacrule-disable allow_all'; + # we're all ready for other jobs to run! + mutex_create('freeipa_ready'); + wait_for_children; + # once child jobs are done, stop the role + assert_script_run 'rolectl stop domaincontroller/domain.local'; + # check role is stopped + validate_script_output 'rolectl status domaincontroller/domain.local', sub { $_ =~ m/^ready-to-start/ }; + # decommission the role + assert_script_run 'rolectl decommission domaincontroller/domain.local', 120; + # check role is decommissioned + validate_script_output 'rolectl list instances', sub { $_ eq "" }; +} + + +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: