Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UEFI HTTP Boot provisioning test #12908

Merged
merged 1 commit into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pytest_fixtures/component/provision_pxe.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ def pxe_loader(request):
'bios': {'vm_firmware': 'bios', 'pxe_loader': 'PXELinux BIOS'},
'uefi': {'vm_firmware': 'uefi', 'pxe_loader': 'Grub2 UEFI'},
'ipxe': {'vm_firmware': 'bios', 'pxe_loader': 'iPXE Embedded'},
'http_uefi': {'vm_firmware': 'uefi', 'pxe_loader': 'Grub2 UEFI HTTP'},
}
return Box(PXE_LOADER_MAP[getattr(request, 'param', 'bios')])

Expand Down
167 changes: 166 additions & 1 deletion tests/foreman/api/test_provisioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,53 @@

:Upstream: No
"""
import re

from fauxfactory import gen_string
import pytest
from wait_for import wait_for
from wait_for import TimedOutError, wait_for

from robottelo.config import settings
from robottelo.logging import logger
from robottelo.utils.installer import InstallerCommand


def _read_log(ch, pattern):
"""Read the first line from the given channel buffer and return the matching line"""
# read lines until the buffer is empty
for log_line in ch.stdout().splitlines():
logger.debug(f'foreman-tail: {log_line}')
if re.search(pattern, log_line):
return log_line
else:
return None


def _wait_for_log(channel, pattern, timeout=5, delay=0.2):
"""_read_log method enclosed in wait_for method"""
matching_log = wait_for(
_read_log,
func_args=(
channel,
pattern,
),
fail_condition=None,
timeout=timeout,
delay=delay,
logger=logger,
)
return matching_log.out


def assert_host_logs(channel, pattern):
"""Reads foreman logs until given pattern found"""
try:
log = _wait_for_log(channel, pattern, timeout=300, delay=10)
assert pattern in log
except TimedOutError:
raise AssertionError(f'Timed out waiting for {pattern} from VM')


@pytest.mark.e2e
@pytest.mark.parametrize('pxe_loader', ['bios', 'uefi'], indirect=True)
@pytest.mark.on_premises_provisioning
Expand Down Expand Up @@ -276,3 +315,129 @@ def test_rhel_ipxe_provisioning(
# assert that the host is subscribed and consumes
# subsctiption provided by the activation key
assert provisioning_host.subscribed, 'Host is not subscribed'


@pytest.mark.skip_if_open("BZ:2242925")
@pytest.mark.e2e
@pytest.mark.parametrize('pxe_loader', ['http_uefi'], indirect=True)
@pytest.mark.on_premises_provisioning
@pytest.mark.rhel_ver_match('[^6]')
def test_rhel_httpboot_provisioning(
request,
module_provisioning_sat,
module_sca_manifest_org,
module_location,
provisioning_host,
pxe_loader,
module_provisioning_rhel_content,
provisioning_hostgroup,
module_lce_library,
module_default_org_view,
):
"""Provision a host using httpboot workflow

:id: 98c2865e-5d21-402e-ad01-c474b7fc4eee

:steps:
1. Configure satellite for provisioning
2. provision a host using pxe loader as Grub2 UEFI HTTP
3. Check that resulting host is registered to Satellite
4. Check host is subscribed to Satellite

:expectedresults:
1. Provisioning via HTTP is successful
2. Host installs right version of RHEL
3. Satellite is able to run REX job on the host
4. Host is registered to Satellite and subscription status is 'Success'

:parametrized: yes

:BZ: 2242925
"""
sat = module_provisioning_sat.sat
# update grub2-efi package
sat.cli.Packages.update(packages='grub2-efi', options={'assumeyes': True})

host_mac_addr = provisioning_host._broker_args['provisioning_nic_mac_addr']
host = sat.api.Host(
hostgroup=provisioning_hostgroup,
organization=module_sca_manifest_org,
location=module_location,
name=gen_string('alpha').lower(),
mac=host_mac_addr,
operatingsystem=module_provisioning_rhel_content.os,
subnet=module_provisioning_sat.subnet,
host_parameters_attributes=[
{'name': 'remote_execution_connect_by_ip', 'value': 'true', 'parameter_type': 'boolean'}
],
build=True, # put the host in build mode
).create(create_missing=False)
# Clean up the host to free IP leases on Satellite.
# broker should do that as a part of the teardown, putting here just to make sure.
request.addfinalizer(host.delete)
# Start the VM, do not ensure that we can connect to SSHD
provisioning_host.power_control(ensure=False)
# check for proper HTTP requests
shell = module_provisioning_sat.session.shell()
shell.send('foreman-tail')
assert_host_logs(shell, f'GET /httpboot/grub2/grub.cfg-{host_mac_addr} with 200')
# Host should do call back to the Satellite reporting
# the result of the installation. Wait until Satellite reports that the host is installed.
wait_for(
lambda: host.read().build_status_label != 'Pending installation',
timeout=1500,
delay=10,
)
host = host.read()
assert host.build_status_label == 'Installed'

# Change the hostname of the host as we know it already.
# In the current infra environment we do not support
# addressing hosts using FQDNs, falling back to IP.
provisioning_host.hostname = host.ip
# Host is not blank anymore
provisioning_host.blank = False

# Wait for the host to be rebooted and SSH daemon to be started.
provisioning_host.wait_for_connection()

# Perform version check and check if root password is properly updated
host_os = host.operatingsystem.read()
expected_rhel_version = f'{host_os.major}.{host_os.minor}'

if int(host_os.major) >= 9:
assert (
provisioning_host.execute(
'echo -e "\nPermitRootLogin yes" >> /etc/ssh/sshd_config; systemctl restart sshd'
).status
== 0
)
host_ssh_os = sat.execute(
f'sshpass -p {settings.provisioning.host_root_password} '
'ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no -o PasswordAuthentication=yes '
f'-o UserKnownHostsFile=/dev/null root@{provisioning_host.hostname} cat /etc/redhat-release'
)
assert host_ssh_os.status == 0
assert (
expected_rhel_version in host_ssh_os.stdout
), f'The installed OS version differs from the expected version {expected_rhel_version}'

# Run a command on the host using REX to verify that Satellite's SSH key is present on the host
template_id = (
sat.api.JobTemplate().search(query={'search': 'name="Run Command - Script Default"'})[0].id
)
job = sat.api.JobInvocation().run(
data={
'job_template_id': template_id,
'inputs': {
'command': f'subscription-manager config | grep "hostname = {sat.hostname}"'
},
'search_query': f"name = {host.name}",
'targeting_type': 'static_query',
},
)
assert job['result'] == 'success', 'Job invocation failed'

# assert that the host is subscribed and consumes
# subsctiption provided by the activation key
assert provisioning_host.subscribed, 'Host is not subscribed'
Loading