Skip to content

Commit 32a5a25

Browse files
pb8ozulinx86
andcommitted
test: simplify and stabilize ballon device-related tests
- Specify memory size arg in MiB in make_guest_dirty_memory() - Add retries of "cat /tmp/fillmem.txt" - Lower threshold for a stable RSS Signed-off-by: Pablo Barbáchano <pablob@amazon.com> Co-authored-by: Takahiro Itazuri <itazur@amazon.com>
1 parent 0a006e8 commit 32a5a25

File tree

1 file changed

+32
-26
lines changed

1 file changed

+32
-26
lines changed

tests/integration_tests/functional/test_balloon.py

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,39 @@
1111
from framework.builder import MicrovmBuilder, SnapshotBuilder, SnapshotType
1212
from framework.utils import get_free_mem_ssh, run_cmd
1313

14-
MB_TO_PAGES = 256
1514
STATS_POLLING_INTERVAL_S = 1
1615

1716

1817
@retry(delay=0.5, tries=10)
19-
def get_stable_rss_mem_by_pid(pid, percentage_delta=0.5):
18+
def get_stable_rss_mem_by_pid(pid, percentage_delta=1):
2019
"""
2120
Get the RSS memory that a guest uses, given the pid of the guest.
2221
2322
Wait till the fluctuations in RSS drop below percentage_delta. If timeout
2423
is reached before the fluctuations drop, raise an exception.
2524
"""
2625

26+
# All values are reported as KiB
27+
2728
def get_rss_from_pmap():
2829
_, output, _ = run_cmd("pmap -X {}".format(pid))
2930
return int(output.split("\n")[-2].split()[1], 10)
3031

3132
first_rss = get_rss_from_pmap()
3233
time.sleep(1)
3334
second_rss = get_rss_from_pmap()
34-
35-
delta = (abs(first_rss - second_rss) / float(first_rss)) * 100
36-
assert delta < percentage_delta
37-
35+
print(f"RSS readings: {first_rss}, {second_rss}")
36+
abs_diff = abs(first_rss - second_rss)
37+
abs_delta = 100 * abs_diff / first_rss
38+
assert abs_delta < percentage_delta or abs_diff < 2**10
3839
return second_rss
3940

4041

41-
def make_guest_dirty_memory(ssh_connection, should_oom=False, amount=8192):
42+
def make_guest_dirty_memory(ssh_connection, should_oom=False, amount_mib=32):
4243
"""Tell the guest, over ssh, to dirty `amount` pages of memory."""
4344
logger = logging.getLogger("make_guest_dirty_memory")
4445

45-
amount_in_mbytes = amount / MB_TO_PAGES
46-
47-
cmd = f"/sbin/fillmem {amount_in_mbytes}"
46+
cmd = f"/sbin/fillmem {amount_mib}"
4847
exit_code, stdout, stderr = ssh_connection.execute_command(cmd)
4948
# add something to the logs for troubleshooting
5049
if exit_code != 0:
@@ -53,18 +52,23 @@ def make_guest_dirty_memory(ssh_connection, should_oom=False, amount=8192):
5352
logger.error("stderr: %s", stderr)
5453

5554
cmd = "cat /tmp/fillmem_output.txt"
56-
_, stdout, _ = ssh_connection.execute_command(cmd)
55+
tries = 3
56+
while tries > 0:
57+
# it may take a bit of time to dirty the memory and the OOM to kick-in
58+
time.sleep(0.5)
59+
_, stdout, _ = ssh_connection.execute_command(cmd)
60+
if stdout != "":
61+
break
62+
tries -= 1
63+
5764
if should_oom:
58-
assert (
59-
"OOM Killer stopped the program with "
60-
"signal 9, exit code 0" in stdout
61-
)
65+
assert "OOM Killer stopped the program with signal 9, exit code 0" in stdout
6266
else:
6367
assert exit_code == 0, stderr
6468
assert "Memory filling was successful" in stdout, stdout
6569

6670

67-
def _test_rss_memory_lower(test_microvm):
71+
def _test_rss_memory_lower(test_microvm, stable_delta=1):
6872
"""Check inflating the balloon makes guest use less rss memory."""
6973
# Get the firecracker pid, and open an ssh connection.
7074
firecracker_pid = test_microvm.jailer_clone_pid
@@ -75,20 +79,22 @@ def _test_rss_memory_lower(test_microvm):
7579
assert test_microvm.api_session.is_status_no_content(response.status_code)
7680

7781
# Get initial rss consumption.
78-
init_rss = get_stable_rss_mem_by_pid(firecracker_pid)
82+
init_rss = get_stable_rss_mem_by_pid(firecracker_pid, percentage_delta=stable_delta)
7983

8084
# Get the balloon back to 0.
8185
response = test_microvm.balloon.patch(amount_mib=0)
8286
assert test_microvm.api_session.is_status_no_content(response.status_code)
8387
# This call will internally wait for rss to become stable.
84-
_ = get_stable_rss_mem_by_pid(firecracker_pid)
88+
_ = get_stable_rss_mem_by_pid(firecracker_pid, percentage_delta=stable_delta)
8589

8690
# Dirty memory, then inflate balloon and get ballooned rss consumption.
8791
make_guest_dirty_memory(ssh_connection)
8892

8993
response = test_microvm.balloon.patch(amount_mib=200)
9094
assert test_microvm.api_session.is_status_no_content(response.status_code)
91-
balloon_rss = get_stable_rss_mem_by_pid(firecracker_pid)
95+
balloon_rss = get_stable_rss_mem_by_pid(
96+
firecracker_pid, percentage_delta=stable_delta
97+
)
9298

9399
# Check that the ballooning reclaimed the memory.
94100
assert balloon_rss - init_rss <= 15000
@@ -236,7 +242,7 @@ def test_reinflate_balloon(test_microvm_with_api):
236242
_ = get_stable_rss_mem_by_pid(firecracker_pid)
237243

238244
# Get the guest to dirty memory.
239-
make_guest_dirty_memory(test_microvm.ssh)
245+
make_guest_dirty_memory(test_microvm.ssh, amount_mib=32)
240246
first_reading = get_stable_rss_mem_by_pid(firecracker_pid)
241247

242248
# Now inflate the balloon.
@@ -251,7 +257,7 @@ def test_reinflate_balloon(test_microvm_with_api):
251257
_ = get_stable_rss_mem_by_pid(firecracker_pid)
252258

253259
# Now have the guest dirty memory again.
254-
make_guest_dirty_memory(test_microvm.ssh)
260+
make_guest_dirty_memory(test_microvm.ssh, amount_mib=32)
255261
third_reading = get_stable_rss_mem_by_pid(firecracker_pid)
256262

257263
# Now inflate the balloon again.
@@ -335,7 +341,7 @@ def test_stats(test_microvm_with_api):
335341
initial_stats = test_microvm.balloon.get_stats().json()
336342

337343
# Dirty 10MB of pages.
338-
make_guest_dirty_memory(test_microvm.ssh, amount=10 * MB_TO_PAGES)
344+
make_guest_dirty_memory(test_microvm.ssh, amount_mib=10)
339345
time.sleep(1)
340346
# This call will internally wait for rss to become stable.
341347
_ = get_stable_rss_mem_by_pid(firecracker_pid)
@@ -395,7 +401,7 @@ def test_stats_update(test_microvm_with_api):
395401
firecracker_pid = test_microvm.jailer_clone_pid
396402

397403
# Dirty 30MB of pages.
398-
make_guest_dirty_memory(test_microvm.ssh, amount=30 * MB_TO_PAGES)
404+
make_guest_dirty_memory(test_microvm.ssh, amount_mib=30)
399405

400406
# This call will internally wait for rss to become stable.
401407
_ = get_stable_rss_mem_by_pid(firecracker_pid)
@@ -453,7 +459,7 @@ def test_balloon_snapshot(bin_cloner_path, microvm_factory, guest_kernel, rootfs
453459
vm.start()
454460

455461
# Dirty 60MB of pages.
456-
make_guest_dirty_memory(vm.ssh, amount=60 * MB_TO_PAGES)
462+
make_guest_dirty_memory(vm.ssh, amount_mib=60)
457463
time.sleep(1)
458464

459465
# Get the firecracker pid, and open an ssh connection.
@@ -502,7 +508,7 @@ def test_balloon_snapshot(bin_cloner_path, microvm_factory, guest_kernel, rootfs
502508
third_reading = get_stable_rss_mem_by_pid(firecracker_pid)
503509

504510
# Dirty 60MB of pages.
505-
make_guest_dirty_memory(microvm.ssh, amount=60 * MB_TO_PAGES)
511+
make_guest_dirty_memory(microvm.ssh, amount_mib=60)
506512

507513
# Check memory usage.
508514
fourth_reading = get_stable_rss_mem_by_pid(firecracker_pid)
@@ -583,7 +589,7 @@ def test_memory_scrub(microvm_factory, guest_kernel, rootfs):
583589
microvm.start()
584590

585591
# Dirty 60MB of pages.
586-
make_guest_dirty_memory(microvm.ssh, amount=60 * MB_TO_PAGES)
592+
make_guest_dirty_memory(microvm.ssh, amount_mib=60)
587593

588594
# Now inflate the balloon with 60MB of pages.
589595
response = microvm.balloon.patch(amount_mib=60)

0 commit comments

Comments
 (0)