Skip to content

Commit

Permalink
Add UEFI HTTP Boot provisioning test
Browse files Browse the repository at this point in the history
Signed-off-by: Shubham Ganar <[email protected]>
  • Loading branch information
shubhamsg199 committed Nov 6, 2023
1 parent 17d6f86 commit 8bf7d4f
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
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
161 changes: 161 additions & 0 deletions tests/foreman/api/test_provisioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,41 @@
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 +311,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'

0 comments on commit 8bf7d4f

Please sign in to comment.