diff --git a/pytest_fixtures/component/virtwho_config.py b/pytest_fixtures/component/virtwho_config.py index dee41a817e6..ad18394dd40 100644 --- a/pytest_fixtures/component/virtwho_config.py +++ b/pytest_fixtures/component/virtwho_config.py @@ -83,6 +83,7 @@ def form_data_cli(request, target_sat, org_module): 'filtering-mode': 'none', 'satellite-url': target_sat.hostname, 'hypervisor-username': settings.virtwho.libvirt.hypervisor_username, + 'hypervisor-password': settings.virtwho.libvirt.hypervisor_password, } elif 'nutanix' in hypervisor_type: form = { @@ -158,6 +159,7 @@ def form_data_api(request, target_sat, org_module): 'filtering_mode': 'none', 'satellite_url': target_sat.hostname, 'hypervisor_username': settings.virtwho.libvirt.hypervisor_username, + 'hypervisor_password': settings.virtwho.libvirt.hypervisor_password, } elif 'nutanix' in hypervisor_type: form = { @@ -234,7 +236,50 @@ def form_data_ui(request, target_sat, org_module): @pytest.fixture -def virtwho_config_cli(form_data_cli, target_sat, register_sat_and_enable_aps_repo): +def setup_libvirt_ssh_auth(request, target_sat): + """Automatically configure SSH key authentication for libvirt hypervisor. + + Libvirt uses qemu+ssh:// connection which requires SSH key-based authentication + for non-interactive access by the virt-who service. This fixture: + 1. Generates SSH key on Satellite if it doesn't exist + 2. Adds hypervisor to Satellite's known_hosts + 3. Copies Satellite's public key to hypervisor's authorized_keys + """ + hypervisor_type = request.module.__name__.split('.')[-1].split('_', 1)[-1] + + # Only run for libvirt tests + if 'libvirt' not in hypervisor_type: + yield + return + + hypervisor_server = settings.virtwho.libvirt.hypervisor_server + hypervisor_username = settings.virtwho.libvirt.hypervisor_username + hypervisor_password = settings.virtwho.libvirt.hypervisor_password + + # Generate SSH key on Satellite if it doesn't exist + target_sat.execute('test -f /root/.ssh/id_rsa || ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa') + + # Add hypervisor to known_hosts + target_sat.execute( + f'ssh-keyscan -H {hypervisor_server} >> /root/.ssh/known_hosts 2>/dev/null || true' + ) + + # Copy public key to hypervisor using sshpass + target_sat.execute( + f'sshpass -p "{hypervisor_password}" ssh-copy-id ' + f'-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ' + f'{hypervisor_username}@{hypervisor_server} 2>/dev/null || true' + ) + + yield + + # No cleanup needed - SSH keys can persist for other tests + + +@pytest.fixture +def virtwho_config_cli( + form_data_cli, target_sat, register_sat_and_enable_aps_repo, setup_libvirt_ssh_auth +): virtwho_config_cli = target_sat.cli.VirtWhoConfig.create(form_data_cli)['general-information'] yield virtwho_config_cli target_sat.cli.VirtWhoConfig.delete({'name': virtwho_config_cli['name']}) @@ -242,7 +287,9 @@ def virtwho_config_cli(form_data_cli, target_sat, register_sat_and_enable_aps_re @pytest.fixture -def virtwho_config_api(form_data_api, target_sat, register_sat_and_enable_aps_repo): +def virtwho_config_api( + form_data_api, target_sat, register_sat_and_enable_aps_repo, setup_libvirt_ssh_auth +): virtwho_config_api = target_sat.api.VirtWhoConfig(**form_data_api).create() yield virtwho_config_api virtwho_config_api.delete() @@ -252,7 +299,9 @@ def virtwho_config_api(form_data_api, target_sat, register_sat_and_enable_aps_re @pytest.fixture -def virtwho_config_ui(form_data_ui, target_sat, org_session, register_sat_and_enable_aps_repo): +def virtwho_config_ui( + form_data_ui, target_sat, org_session, register_sat_and_enable_aps_repo, setup_libvirt_ssh_auth +): name = gen_string('alpha') form_data_ui['name'] = name with org_session: diff --git a/robottelo/utils/virtwho.py b/robottelo/utils/virtwho.py index c9fcf54e5b2..ef9a55effd5 100644 --- a/robottelo/utils/virtwho.py +++ b/robottelo/utils/virtwho.py @@ -231,9 +231,11 @@ def _get_hypervisor_mapping(hypervisor_type): :raises: VirtWhoError: If hypervisor_name is None. :return: hypervisor_name and guest_name """ + # Increase timeout for hypervisors like Nutanix Prism Central which can be slower + timeout = 60 if hypervisor_type == 'ahv' else 20 wait_for( lambda: 'Host-to-guest mapping being sent to' in get_rhsm_log(), - timeout=20, + timeout=timeout, delay=2, ) logs = get_rhsm_log() diff --git a/tests/foreman/virtwho/api/test_nutanix_sca.py b/tests/foreman/virtwho/api/test_nutanix_sca.py index d80c0f84995..b54a5d21528 100644 --- a/tests/foreman/virtwho/api/test_nutanix_sca.py +++ b/tests/foreman/virtwho/api/test_nutanix_sca.py @@ -72,7 +72,12 @@ def test_positive_hypervisor_id_option( @pytest.mark.parametrize('deploy_type', ['id', 'script']) def test_positive_prism_central_deploy_configure_by_id_script( - self, module_sca_manifest_org, form_data_api, target_sat, deploy_type + self, + module_sca_manifest_org, + form_data_api, + target_sat, + deploy_type, + register_sat_and_enable_aps_repo, ): """Verify "POST /foreman_virt_who_configure/api/v2/configs" on nutanix prism central mode @@ -85,6 +90,8 @@ def test_positive_prism_central_deploy_configure_by_id_script( :CaseImportance: High """ form_data_api['prism_flavor'] = "central" + # Prism Central doesn't expose hostname property, must use uuid for hypervisor_id + form_data_api['hypervisor_id'] = "uuid" virtwho_config = target_sat.api.VirtWhoConfig(**form_data_api).create() assert virtwho_config.status == 'unknown' if deploy_type == "id": diff --git a/tests/foreman/virtwho/cli/test_nutanix_sca.py b/tests/foreman/virtwho/cli/test_nutanix_sca.py index 36165f7893d..af6621bc447 100644 --- a/tests/foreman/virtwho/cli/test_nutanix_sca.py +++ b/tests/foreman/virtwho/cli/test_nutanix_sca.py @@ -73,7 +73,12 @@ def test_positive_hypervisor_id_option( @pytest.mark.parametrize('deploy_type', ['id', 'script']) def test_positive_prism_central_deploy_configure_by_id_script( - self, module_sca_manifest_org, target_sat, form_data_cli, deploy_type + self, + module_sca_manifest_org, + target_sat, + form_data_cli, + deploy_type, + register_sat_and_enable_aps_repo, ): """Verify "hammer virt-who-config deploy & fetch" on nutanix prism central mode @@ -87,6 +92,8 @@ def test_positive_prism_central_deploy_configure_by_id_script( :CaseImportance: High """ form_data_cli['prism-flavor'] = "central" + # Prism Central doesn't expose hostname property, must use uuid for hypervisor_id + form_data_cli['hypervisor-id'] = "uuid" virtwho_config = target_sat.cli.VirtWhoConfig.create(form_data_cli)['general-information'] assert virtwho_config['status'] == 'No Report Yet' if deploy_type == "id": @@ -96,6 +103,7 @@ def test_positive_prism_central_deploy_configure_by_id_script( form_data_cli['hypervisor-type'], debug=True, org=module_sca_manifest_org.label, + target_sat=target_sat, ) elif deploy_type == "script": script = target_sat.cli.VirtWhoConfig.fetch( @@ -106,6 +114,7 @@ def test_positive_prism_central_deploy_configure_by_id_script( form_data_cli['hypervisor-type'], debug=True, org=module_sca_manifest_org.label, + target_sat=target_sat, ) # Check the option "prism_central=true" should be set in etc/virt-who.d/virt-who.conf config_file = get_configure_file(virtwho_config['id']) diff --git a/tests/foreman/virtwho/ui/test_nutanix_sca.py b/tests/foreman/virtwho/ui/test_nutanix_sca.py index f781956f5bb..7fafae0daa4 100644 --- a/tests/foreman/virtwho/ui/test_nutanix_sca.py +++ b/tests/foreman/virtwho/ui/test_nutanix_sca.py @@ -87,7 +87,13 @@ def test_positive_hypervisor_id_option( @pytest.mark.parametrize('deploy_type', ['id', 'script']) def test_positive_prism_central_deploy_configure_by_id_script( - self, module_sca_manifest_org, org_session, form_data_ui, deploy_type, target_sat + self, + module_sca_manifest_org, + org_session, + form_data_ui, + deploy_type, + target_sat, + register_sat_and_enable_aps_repo, ): """Verify configure created and deployed with id on nutanix prism central mode @@ -106,6 +112,8 @@ def test_positive_prism_central_deploy_configure_by_id_script( name = gen_string('alpha') form_data_ui['name'] = name form_data_ui['hypervisor_content.prism_flavor'] = "Prism Central" + # Prism Central doesn't expose hostname property, must use uuid for hypervisor_id + form_data_ui['hypervisor_id'] = 'uuid' with org_session: org_session.virtwho_configure.create(form_data_ui) values = org_session.virtwho_configure.read(name)