Skip to content

Commit 140cf31

Browse files
committed
tests: add integration tests for block flush
Signed-off-by: George Pisaltu <[email protected]>
1 parent 8dcfda5 commit 140cf31

File tree

4 files changed

+138
-3
lines changed

4 files changed

+138
-3
lines changed

tests/framework/microvm.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,14 +611,16 @@ def add_drive(
611611
root_device=False,
612612
is_read_only=False,
613613
partuuid=None,
614+
cache_type=None,
614615
):
615616
"""Add a block device."""
616617
response = self.drive.put(
617618
drive_id=drive_id,
618619
path_on_host=self.create_jailed_resource(file_path),
619620
is_root_device=root_device,
620621
is_read_only=is_read_only,
621-
partuuid=partuuid
622+
partuuid=partuuid,
623+
cache_type=cache_type
622624
)
623625
assert self.api_session.is_status_no_content(response.status_code)
624626

tests/framework/resources.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ def create_json(
231231
is_root_device=None,
232232
partuuid=None,
233233
is_read_only=None,
234-
rate_limiter=None):
234+
rate_limiter=None,
235+
cache_type=None):
235236
"""Compose the json associated to this type of API request."""
236237
datax = {}
237238

@@ -250,6 +251,9 @@ def create_json(
250251
if is_read_only is not None:
251252
datax['is_read_only'] = is_read_only
252253

254+
if cache_type is not None:
255+
datax['cache_type'] = cache_type
256+
253257
if rate_limiter is not None:
254258
datax['rate_limiter'] = rate_limiter
255259

tests/integration_tests/build/test_coverage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# this contains the frequency while on AMD it does not.
2424
# Checkout the cpuid crate. In the future other
2525
# differences may appear.
26-
COVERAGE_DICT = {"Intel": 85.44, "AMD": 84.77, "ARM": 83.42}
26+
COVERAGE_DICT = {"Intel": 85.44, "AMD": 84.74, "ARM": 83.60}
2727

2828
PROC_MODEL = proc.proc_type()
2929

tests/integration_tests/functional/test_drives.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import host_tools.drive as drive_tools
1212
import host_tools.network as net_tools # pylint: disable=import-error
13+
import host_tools.logging as log_tools
1314

1415
PARTUUID = {"x86_64": "0eaa91a0-01", "aarch64": "7bf14469-01"}
1516
MB = 1024 * 1024
@@ -337,6 +338,134 @@ def test_patch_drive(test_microvm_with_ssh, network_config):
337338
assert stdout.readline().strip() == size_bytes_str
338339

339340

341+
def test_no_flush(test_microvm_with_ssh, network_config):
342+
"""Verify default block ignores flush."""
343+
test_microvm = test_microvm_with_ssh
344+
test_microvm.spawn()
345+
346+
test_microvm.basic_config(
347+
vcpu_count=1,
348+
add_root_device=False
349+
)
350+
351+
_tap, _, _ = test_microvm.ssh_network_config(network_config, '1')
352+
353+
# Add the block device
354+
test_microvm.add_drive(
355+
'rootfs',
356+
test_microvm.rootfs_file,
357+
root_device=True,
358+
)
359+
360+
# Configure the metrics.
361+
metrics_fifo_path = os.path.join(test_microvm.path, 'metrics_fifo')
362+
metrics_fifo = log_tools.Fifo(metrics_fifo_path)
363+
response = test_microvm.metrics.put(
364+
metrics_path=test_microvm.create_jailed_resource(metrics_fifo.path)
365+
)
366+
assert test_microvm.api_session.is_status_no_content(response.status_code)
367+
368+
test_microvm.start()
369+
370+
# Verify all flush commands were ignored during boot.
371+
fc_metrics = test_microvm.flush_metrics(metrics_fifo)
372+
assert fc_metrics['block']['flush_count'] == 0
373+
374+
# Have the guest drop the caches to generate flush requests.
375+
ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)
376+
cmd = "sync; echo 1 > /proc/sys/vm/drop_caches"
377+
_, _, stderr = ssh_connection.execute_command(cmd)
378+
assert stderr.read() == ''
379+
380+
# Verify all flush commands were ignored even after
381+
# dropping the caches.
382+
fc_metrics = test_microvm.flush_metrics(metrics_fifo)
383+
assert fc_metrics['block']['flush_count'] == 0
384+
385+
386+
def test_flush(test_microvm_with_ssh, network_config):
387+
"""Verify block with flush actually flushes."""
388+
test_microvm = test_microvm_with_ssh
389+
test_microvm.spawn()
390+
391+
test_microvm.basic_config(
392+
vcpu_count=1,
393+
add_root_device=False
394+
)
395+
396+
_tap, _, _ = test_microvm.ssh_network_config(network_config, '1')
397+
398+
# Add the block device with explicitly enabling flush.
399+
test_microvm.add_drive(
400+
'rootfs',
401+
test_microvm.rootfs_file,
402+
root_device=True,
403+
cache_type="Writeback",
404+
)
405+
406+
# Configure metrics, to get later the `flush_count`.
407+
metrics_fifo_path = os.path.join(test_microvm.path, 'metrics_fifo')
408+
metrics_fifo = log_tools.Fifo(metrics_fifo_path)
409+
response = test_microvm.metrics.put(
410+
metrics_path=test_microvm.create_jailed_resource(metrics_fifo.path)
411+
)
412+
assert test_microvm.api_session.is_status_no_content(response.status_code)
413+
414+
test_microvm.start()
415+
416+
# Have the guest drop the caches to generate flush requests.
417+
ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)
418+
cmd = "sync; echo 1 > /proc/sys/vm/drop_caches"
419+
_, _, stderr = ssh_connection.execute_command(cmd)
420+
assert stderr.read() == ''
421+
422+
# On average, dropping the caches right after boot generates
423+
# about 6 block flush requests.
424+
fc_metrics = test_microvm.flush_metrics(metrics_fifo)
425+
assert fc_metrics['block']['flush_count'] > 0
426+
427+
428+
def test_block_default_cache_old_version(test_microvm_with_ssh):
429+
"""Verify that saving a snapshot for old versions works correctly."""
430+
test_microvm = test_microvm_with_ssh
431+
test_microvm.spawn()
432+
433+
test_microvm.basic_config(
434+
vcpu_count=1,
435+
add_root_device=False
436+
)
437+
438+
# Add the block device with explicitly enabling flush.
439+
test_microvm.add_drive(
440+
'rootfs',
441+
test_microvm.rootfs_file,
442+
root_device=True,
443+
cache_type="Writeback",
444+
)
445+
446+
test_microvm.start()
447+
448+
# Pause the VM to create the snapshot.
449+
response = test_microvm.vm.patch(state='Paused')
450+
assert test_microvm.api_session.is_status_no_content(response.status_code)
451+
452+
# Create the snapshot for a version without block cache type.
453+
response = test_microvm.snapshot.create(
454+
mem_file_path='memfile',
455+
snapshot_path='snapsfile',
456+
diff=False,
457+
version='0.24.0'
458+
)
459+
assert test_microvm.api_session.is_status_no_content(response.status_code)
460+
461+
# We should find a warning in the logs for this case as this
462+
# cache type was not supported in 0.24.0 and we should default
463+
# to "Unsafe" mode.
464+
log_data = test_microvm.log_data
465+
assert "Target version does not implement the current cache type. "\
466+
"Defaulting to \"unsafe\" mode." in log_data
467+
468+
340469
def check_iops_limit(ssh_connection, block_size, count, min_time, max_time):
341470
"""Verify if the rate limiter throttles block iops using dd."""
342471
byte_count = block_size * count

0 commit comments

Comments
 (0)