Skip to content

Commit acdde58

Browse files
committed
virtio: add vm level flush tests
This adds python tests to verify the correct operation of flush. The features file in /sys/block/<drive>/device/features is checked to ensure that it is correct with respect to the optional 'want_flush' drive setting. Metrics also verify that by default, no flushes are received. Only when 'want_flush' is true should the 'flush_count' block metric increase. Signed-off-by: Peter Lawthers [email protected]
1 parent 4599f6d commit acdde58

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

tests/framework/microvm.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,14 +558,16 @@ def add_drive(
558558
root_device=False,
559559
is_read_only=False,
560560
partuuid=None,
561+
want_flush=False,
561562
):
562563
"""Add a block device."""
563564
response = self.drive.put(
564565
drive_id=drive_id,
565566
path_on_host=self.create_jailed_resource(file_path),
566567
is_root_device=root_device,
567568
is_read_only=is_read_only,
568-
partuuid=partuuid
569+
partuuid=partuuid,
570+
want_flush=want_flush
569571
)
570572
assert self.api_session.is_status_no_content(response.status_code)
571573

tests/framework/resources.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ def create_json(
142142
is_root_device=None,
143143
partuuid=None,
144144
is_read_only=None,
145-
rate_limiter=None):
145+
rate_limiter=None,
146+
want_flush=None):
146147
"""Compose the json associated to this type of API request."""
147148
datax = {}
148149

@@ -164,6 +165,9 @@ def create_json(
164165
if rate_limiter is not None:
165166
datax['rate_limiter'] = rate_limiter
166167

168+
if want_flush is not None:
169+
datax['want_flush'] = want_flush
170+
167171
return datax
168172

169173

tests/integration_tests/functional/test_drives.py

Lines changed: 103 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 # metrics
1314

1415

1516
def test_rescan_file(test_microvm_with_ssh, network_config):
@@ -329,6 +330,108 @@ def test_patch_drive(test_microvm_with_ssh, network_config):
329330
assert stdout.readline().strip() == size_bytes_str
330331

331332

333+
def test_rootfs_rw_noflush(test_microvm_with_ssh, network_config):
334+
"""Verify default rootfs does not invoke flush."""
335+
test_microvm = test_microvm_with_ssh
336+
test_microvm.spawn()
337+
338+
# Set up the microVM with 1 vCPUs, 256 MiB of RAM, no network ifaces and
339+
# a root file system with the rw permission. The network interfaces is
340+
# added after we get a unique MAC and IP.
341+
test_microvm.basic_config(
342+
vcpu_count=1,
343+
add_root_device=False
344+
)
345+
346+
_tap, _, _ = test_microvm.ssh_network_config(network_config, '1')
347+
348+
# Add the root block device
349+
test_microvm.add_drive(
350+
'rootfs',
351+
test_microvm.rootfs_file,
352+
root_device=True,
353+
)
354+
355+
# Configure metrics, to get later the `flush_count`.
356+
metrics_fifo_path = os.path.join(test_microvm.path, 'metrics_fifo')
357+
metrics_fifo = log_tools.Fifo(metrics_fifo_path)
358+
response = test_microvm.metrics.put(
359+
metrics_path=test_microvm.create_jailed_resource(metrics_fifo.path)
360+
)
361+
assert test_microvm.api_session.is_status_no_content(response.status_code)
362+
363+
test_microvm.start()
364+
365+
# From spec: pub const VIRTIO_F_VERSION_1: u32 = 32;
366+
lo32 = "00000000000000000000000000000000"
367+
hi32 = "10000000000000000000000000000000"
368+
default_features = lo32 + hi32
369+
370+
ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)
371+
cmd = "cat /sys/block/vda/device/features"
372+
_, stdout, stderr = ssh_connection.execute_command(cmd)
373+
assert stderr.read() == ''
374+
assert stdout.readline().strip() == default_features
375+
376+
# Verify no flush commands were generated during boot. By
377+
# default, on a RW device with flush enabled, there will be
378+
# +- six virtio flush commands
379+
fc_metrics = test_microvm.flush_metrics(metrics_fifo)
380+
assert fc_metrics['block']['flush_count'] == 0
381+
382+
383+
def test_rootfs_rw_flush(test_microvm_with_ssh, network_config):
384+
"""Verify rootfs with flush does invoke flush."""
385+
test_microvm = test_microvm_with_ssh
386+
test_microvm.spawn()
387+
388+
# Set up the microVM with 1 vCPUs, 256 MiB of RAM, no network ifaces and
389+
# a root file system with the rw permission. The network interfaces is
390+
# added after we get a unique MAC and IP.
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 root block device
399+
test_microvm.add_drive(
400+
'rootfs',
401+
test_microvm.rootfs_file,
402+
root_device=True,
403+
want_flush=True,
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+
# From spec: pub const VIRTIO_F_VERSION_1: u32 = 32;
417+
# pub const VIRTIO_BLK_F_FLUSH: u32 = 9;
418+
lo32 = "00000000010000000000000000000000"
419+
hi32 = "10000000000000000000000000000000"
420+
default_features = lo32 + hi32
421+
422+
ssh_connection = net_tools.SSHConnection(test_microvm.ssh_config)
423+
cmd = "cat /sys/block/vda/device/features"
424+
_, stdout, stderr = ssh_connection.execute_command(cmd)
425+
assert stderr.read() == ''
426+
assert stdout.readline().strip() == default_features
427+
428+
# Verify no flush commands were generated during boot. By
429+
# default, on a RW device with flush enabled, there will be
430+
# +- six virtio flush commands
431+
fc_metrics = test_microvm.flush_metrics(metrics_fifo)
432+
assert fc_metrics['block']['flush_count'] > 0
433+
434+
332435
def _check_block_size(ssh_connection, dev_path, size):
333436
_, stdout, stderr = ssh_connection.execute_command(
334437
'blockdev --getsize64 {}'.format(dev_path)

0 commit comments

Comments
 (0)