From 7abbc51ed9acb12e846308a857bda04adca089d2 Mon Sep 17 00:00:00 2001 From: Aditya Nagesh Date: Fri, 21 Nov 2025 04:15:25 +0000 Subject: [PATCH] Hibernation: Add check for disk space requirement 1. Hibernation requires free disk space proportional to RAM of the machine. LISA currently does not support os disk size as a requirement. 2. Azure does not support Hibernation for VM with memory larger than 256 GB --- lisa/microsoft/testsuites/power/common.py | 54 +++++++++++++++++++++++ lisa/microsoft/testsuites/power/power.py | 3 ++ lisa/tools/hibernation_setup.py | 20 +++++++-- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/lisa/microsoft/testsuites/power/common.py b/lisa/microsoft/testsuites/power/common.py index 19640c6118..f2db8f5861 100644 --- a/lisa/microsoft/testsuites/power/common.py +++ b/lisa/microsoft/testsuites/power/common.py @@ -15,6 +15,7 @@ Df, Dmesg, Fio, + Free, HibernationSetup, Hwclock, Iperf3, @@ -49,6 +50,59 @@ def is_distro_supported(node: Node) -> None: ) +def check_hibernation_disk_requirements(node: Node) -> None: + """ + Check if the VM has sufficient disk space for hibernation. + Hibernation requires disk space based on RAM size using the formula: + - 2 × RAM if RAM ≤ 8 GB + - 1.5 × RAM if 8 < RAM ≤ 64 GB + - RAM if 64 < RAM ≤ 256 GB + - Not supported if RAM > 256 GB + """ + free_tool = node.tools[Free] + df_tool = node.tools[Df] + + # Get total memory in GB + total_memory_gb = float(free_tool.get_total_memory_gb()) + + # Skip hibernation check for VMs with > 256 GB RAM + if total_memory_gb > 256: + raise SkippedException( + f"Hibernation is not supported for VMs with RAM > 256 GB. " + f"Current RAM: {total_memory_gb:.2f} GB" + ) + + # Calculate required disk space based on RAM size + if total_memory_gb <= 8: + required_space_gb = 2 * total_memory_gb + formula = "2*RAM" + elif total_memory_gb <= 64: + required_space_gb = 1.5 * total_memory_gb + formula = "1.5*RAM" + else: + required_space_gb = total_memory_gb + formula = "RAM" + + # Add 20% buffer for filesystem overhead, defragmentation, and safety margin + required_space_with_buffer = required_space_gb * 1.2 + + root_partition = df_tool.get_partition_by_mountpoint("/", force_run=True) + assert root_partition is not None, "Unable to determine root partition disk space" + + # available_blocks is in 1K blocks, convert to GB + available_space_gb = root_partition.available_blocks / 1024 / 1024 + + if available_space_gb < required_space_with_buffer: + raise LisaException( + f"Insufficient disk space for hibernation. " + f"Memory size: {total_memory_gb:.2f} GB, " + f"Available space: {available_space_gb:.2f} GB, " + f"Required space: {required_space_gb:.2f} GB ({formula}), " + f"Recommended (20% buffer): {required_space_with_buffer:.2f} GB. " + f"Please increase 'osdisk_size_in_gb'." + ) + + def _prepare_hibernation_environment(node: Node) -> None: """ Prepare the hibernation environment by handling OS-specific requirements. diff --git a/lisa/microsoft/testsuites/power/power.py b/lisa/microsoft/testsuites/power/power.py index d803ca9369..0f3692be2b 100644 --- a/lisa/microsoft/testsuites/power/power.py +++ b/lisa/microsoft/testsuites/power/power.py @@ -7,6 +7,7 @@ from assertpy import assert_that from func_timeout import func_timeout from microsoft.testsuites.power.common import ( + check_hibernation_disk_requirements, cleanup_env, is_distro_supported, run_network_workload, @@ -46,6 +47,8 @@ def before_case(self, log: Logger, **kwargs: Any) -> None: if isinstance(node.os, BSD) or isinstance(node.os, Windows): raise SkippedException(f"{node.os} is not supported.") + check_hibernation_disk_requirements(node) + @TestCaseMetadata( description=""" This case is to verify vm hibernation with synthetic network. diff --git a/lisa/tools/hibernation_setup.py b/lisa/tools/hibernation_setup.py index 8b67ff7425..a2586aed28 100644 --- a/lisa/tools/hibernation_setup.py +++ b/lisa/tools/hibernation_setup.py @@ -36,6 +36,12 @@ class HibernationSetup(Tool): re.MULTILINE, ) + # Defrag size is larger than filesystem's free space + _defrag_space_error_pattern = re.compile( + r"Defrag size is larger than filesystem's free space", + re.MULTILINE, + ) + """ The below shows an example output of `filefrag -v /hibfile.sys` We are interested in the physical offset of the hibfile. @@ -90,9 +96,17 @@ def check_uevent(self) -> int: def _analyze_stdout_for_errors(self, stdout: str) -> None: # Check for insufficient swap space error - error_message = get_matched_str(stdout, self._insufficient_swap_space_pattern) - if error_message: - raise LisaException(f"Hibernation setup failed: {error_message}") + swap_error = get_matched_str(stdout, self._insufficient_swap_space_pattern) + if swap_error: + raise LisaException(f"Hibernation setup failed: {swap_error}") + + # Check for defrag space error + defrag_error = get_matched_str(stdout, self._defrag_space_error_pattern) + if defrag_error: + raise LisaException( + f"Hibernation setup failed: {defrag_error}. " + "Please increase osdisk_size_in_gb." + ) def hibernate(self) -> None: self.node.tools[Systemctl].hibernate()