diff --git a/tests/observability/metrics/conftest.py b/tests/observability/metrics/conftest.py index f2efd40849..8892e16a38 100644 --- a/tests/observability/metrics/conftest.py +++ b/tests/observability/metrics/conftest.py @@ -396,3 +396,16 @@ def pvc_size_bytes(vm_for_vm_disk_allocation_size_test): name=vm_for_vm_disk_allocation_size_test.instance.spec.dataVolumeTemplates[0].metadata.name, namespace=vm_for_vm_disk_allocation_size_test.namespace, ).instance.spec.resources.requests.storage + + +@pytest.fixture(scope="class") +def expected_cpu_affinity_metric_value(vm_with_cpu_spec): + """Calculate expected kubevirt_vmi_node_cpu_affinity metric value.""" + # Calculate VM CPU count + vm_cpu = vm_with_cpu_spec.vmi.instance.spec.domain.cpu + cpu_count_from_vm = (vm_cpu.threads or 1) * (vm_cpu.cores or 1) * (vm_cpu.sockets or 1) + # Get node CPU capacity + cpu_count_from_vm_node = int(vm_with_cpu_spec.privileged_vmi.node.instance.status.capacity.cpu) + + # return multiplication for multi-CPU VMs + return str(cpu_count_from_vm_node * cpu_count_from_vm) diff --git a/tests/observability/metrics/constants.py b/tests/observability/metrics/constants.py index a4e0c453fd..e7a1d8fe28 100644 --- a/tests/observability/metrics/constants.py +++ b/tests/observability/metrics/constants.py @@ -48,3 +48,5 @@ KUBEVIRT_VMI_MIGRATION_DATA_TOTAL_BYTES = "kubevirt_vmi_migration_data_total_bytes{{name='{vm_name}'}}" BINDING_NAME = "binding_name" BINDING_TYPE = "binding_type" + +KUBEVIRT_VMI_NODE_CPU_AFFINITY = "kubevirt_vmi_node_cpu_affinity{{kubernetes_vmi_label_kubevirt_io_domain='{vm_name}'}}" diff --git a/tests/observability/metrics/test_general_metrics.py b/tests/observability/metrics/test_general_metrics.py index 4daa7dea3f..6afbf4fcc1 100644 --- a/tests/observability/metrics/test_general_metrics.py +++ b/tests/observability/metrics/test_general_metrics.py @@ -3,13 +3,9 @@ import pytest from ocp_resources.resource import Resource from ocp_resources.virtual_machine import VirtualMachine -from pytest_testconfig import config as py_config -from tests.observability.metrics.utils import ( - validate_vmi_node_cpu_affinity_with_prometheus, -) +from tests.observability.metrics.constants import KUBEVIRT_VMI_NODE_CPU_AFFINITY from tests.observability.utils import validate_metrics_value -from tests.os_params import RHEL_LATEST, RHEL_LATEST_LABELS, RHEL_LATEST_OS from utilities.virt import VirtualMachineForTests, fedora_vm_body, running_vm KUBEVIRT_VM_TAG = f"{Resource.ApiGroup.KUBEVIRT_IO}/vm" @@ -41,36 +37,17 @@ def fedora_vm_without_name_in_label( client=unprivileged_client, run_strategy=VirtualMachine.RunStrategy.ALWAYS, ) as vm: - running_vm(vm=vm, check_ssh_connectivity=False) + running_vm(vm=vm, wait_for_interfaces=False, check_ssh_connectivity=False) yield vm -@pytest.mark.parametrize( - "golden_image_data_volume_scope_class, vm_from_template_scope_class", - [ - pytest.param( - { - "dv_name": RHEL_LATEST_OS, - "image": RHEL_LATEST["image_path"], - "storage_class": py_config["default_storage_class"], - "dv_size": RHEL_LATEST["dv_size"], - }, - { - "vm_name": "rhel-latest", - "template_labels": RHEL_LATEST_LABELS, - "guest_agent": False, - "ssh": False, - }, - ), - ], - indirect=True, -) class TestVmiNodeCpuAffinity: @pytest.mark.polarion("CNV-7295") - def test_kubevirt_vmi_node_cpu_affinity(self, prometheus, vm_from_template_scope_class): - validate_vmi_node_cpu_affinity_with_prometheus( - vm=vm_from_template_scope_class, + def test_kubevirt_vmi_node_cpu_affinity(self, prometheus, vm_with_cpu_spec, expected_cpu_affinity_metric_value): + validate_metrics_value( prometheus=prometheus, + metric_name=KUBEVIRT_VMI_NODE_CPU_AFFINITY.format(vm_name=vm_with_cpu_spec.name), + expected_value=expected_cpu_affinity_metric_value, ) diff --git a/tests/observability/metrics/utils.py b/tests/observability/metrics/utils.py index 57aba333c9..7a619f6538 100644 --- a/tests/observability/metrics/utils.py +++ b/tests/observability/metrics/utils.py @@ -3,9 +3,8 @@ import re import shlex import time -import urllib from datetime import datetime, timezone -from typing import Any, Optional +from typing import Any from kubernetes.dynamic import DynamicClient from ocp_resources.resource import Resource @@ -205,45 +204,6 @@ def enable_swap_fedora_vm(vm: VirtualMachineForTests) -> None: vm.ssh_exec.executor(sudo=True).run_cmd(cmd=shlex.split("sysctl vm.swappiness=100")) -def get_vm_cpu_info_from_prometheus(prometheus: Prometheus, vm_name: str) -> Optional[int]: - query = urllib.parse.quote_plus( - f'kubevirt_vmi_node_cpu_affinity{{kubernetes_vmi_label_kubevirt_io_domain="{vm_name}"}}' - ) - samples = TimeoutSampler( - wait_timeout=TIMEOUT_1MIN, - sleep=2, - func=prometheus.query_sampler, - query=query, - ) - sample = None - try: - for sample in samples: - if sample: - return int(sample[0]["value"][1]) - except TimeoutExpiredError: - LOGGER.error(f"Failed to get data from query '{query}' in time. Current data: {sample}") - raise - return None - - -def validate_vmi_node_cpu_affinity_with_prometheus(prometheus: Prometheus, vm: VirtualMachineForTests) -> None: - vm_cpu = vm.instance.spec.template.spec.domain.cpu - cpu_count_from_vm = (vm_cpu.threads or 1) * (vm_cpu.cores or 1) * (vm_cpu.sockets or 1) - LOGGER.info(f"Cpu count from vm {vm.name}: {cpu_count_from_vm}") - cpu_info_from_prometheus = get_vm_cpu_info_from_prometheus(prometheus=prometheus, vm_name=vm.name) - LOGGER.info(f"CPU information from prometheus: {cpu_info_from_prometheus}") - cpu_count_from_vm_node = int(vm.privileged_vmi.node.instance.status.capacity.cpu) - LOGGER.info(f"Cpu count from node {vm.privileged_vmi.node.name}: {cpu_count_from_vm_node}") - - if cpu_count_from_vm > 1: - cpu_count_from_vm_node = cpu_count_from_vm_node * cpu_count_from_vm - - assert cpu_count_from_vm_node == cpu_info_from_prometheus, ( - f"Actual CPU count {cpu_count_from_vm_node} not matching with " - f"expected CPU count {cpu_info_from_prometheus} for VM CPU {cpu_count_from_vm}" - ) - - def get_resource_object( admin_client: DynamicClient, related_objects: list, resource_kind, resource_name: str ) -> Resource: