add FreeIPA server role deploy and kickstart enrolment tests
Summary: These require openQA tap networking to allow the server and client boxes to communicate, and require masquerading (NAT) so the server at least can reach a repository (dnf/rolekit really, really do not want to work without a repo connection). They use the 'parallel' test support to have the server deploy run first while the client enrol test waits at the grub menu until the server is done before it goes ahead. This is all deployed and working on stg. The really tricky bit was getting all the openvswitch and firewall config right in ansible. We *could* do the server deploy test as a follow-on from the default install test to save the install, but then we'd have to teach it to change the hostname and set up static networking post-install. I'm not sure if it's worth doing that. This requires the corresponding openqa_fedora_tools commit that adds the hard disks (containing the kickstarts - it's possible to get them from remote during install, but we have to set up name resolution or hard code the IP of the server). Test Plan: Deploy this and the openqa_fedora_tools commit, generate the disks, configure the networking (good luck! See the docs in openqa_fedora_tools) and see if you can run the tests. If you're using Docker, uh...sorry. You somehow need to set things up so the workers can use tap interfaces that can talk to each other and are NATed to the outside world. Have fun. I can talk you through it on IRC... Reviewers: jskladan, garretraziel Reviewed By: garretraziel Subscribers: tflink Differential Revision: https://phab.qadevel.cloud.fedoraproject.org/D831
This commit is contained in:
parent
d4466100d4
commit
f59343403a
@ -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()`
|
||||
|
@ -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 (<FH>) {
|
||||
$resolv .= $_;
|
||||
}
|
||||
assert_script_run "printf '$resolv' > /etc/resolv.conf";
|
||||
# for debugging...
|
||||
assert_script_run "cat /etc/resolv.conf";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# vim: set sw=4 et:
|
||||
|
15
needles/bootloader_bios_installed.json
Normal file
15
needles/bootloader_bios_installed.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"area": [
|
||||
{
|
||||
"height": 15,
|
||||
"type": "match",
|
||||
"width": 160,
|
||||
"xpos": 50,
|
||||
"ypos": 335
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"bootloader",
|
||||
"ENV-DISTRI-fedora"
|
||||
]
|
||||
}
|
BIN
needles/bootloader_bios_installed.png
Normal file
BIN
needles/bootloader_bios_installed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
15
needles/login_permission_denied.json
Normal file
15
needles/login_permission_denied.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"area": [
|
||||
{
|
||||
"height": 13,
|
||||
"type": "match",
|
||||
"width": 136,
|
||||
"xpos": 0,
|
||||
"ypos": 144
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"login_permission_denied",
|
||||
"ENV-DISTRI-fedora"
|
||||
]
|
||||
}
|
BIN
needles/login_permission_denied.png
Normal file
BIN
needles/login_permission_denied.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
@ -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"
|
||||
]
|
||||
}
|
16
needles/user_logged_in-noprofile.json
Normal file
16
needles/user_logged_in-noprofile.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"area": [
|
||||
{
|
||||
"height": 16,
|
||||
"type": "match",
|
||||
"width": 65,
|
||||
"xpos": 0,
|
||||
"ypos": 143
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"user_logged_in",
|
||||
"user_console",
|
||||
"ENV-DISTRI-fedora"
|
||||
]
|
||||
}
|
BIN
needles/user_logged_in-noprofile.png
Normal file
BIN
needles/user_logged_in-noprofile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
50
templates
50
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" },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -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
|
||||
|
45
tests/freeipa_client_postinstall.pm
Normal file
45
tests/freeipa_client_postinstall.pm
Normal file
@ -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:
|
77
tests/role_deploy_domain_controller.pm
Normal file
77
tests/role_deploy_domain_controller.pm
Normal file
@ -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:
|
Loading…
Reference in New Issue
Block a user