Skip to content

Commit 3ae0d8d

Browse files
committed
tests(vhost-user-block): added initial integration test
Added a simple test that boots a VM with vhost-user-block as root block device. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent 4f1e154 commit 3ae0d8d

File tree

5 files changed

+109
-5
lines changed

5 files changed

+109
-5
lines changed

tests/framework/defs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
# Default test session root directory path
3030
DEFAULT_TEST_SESSION_ROOT_PATH = "/srv"
3131

32+
# Default test session artifacts path
33+
LOCAL_BUILD_PATH = FC_WORKSPACE_DIR / "build/"
34+
3235
# Absolute path to the test results folder
3336
TEST_RESULTS_DIR = FC_WORKSPACE_DIR / "test_results"
3437

@@ -46,6 +49,6 @@
4649

4750
# fall-back to the local directory
4851
if not IMG_DIR.exists():
49-
IMG_DIR = Path(__file__).joinpath("../../../build/img").resolve()
52+
IMG_DIR = LOCAL_BUILD_PATH / "img"
5053

5154
ARTIFACT_DIR = IMG_DIR / platform.machine()

tests/framework/microvm.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,24 @@ def add_drive(
666666
)
667667
self.disks[drive_id] = path_on_host
668668

669+
def add_vhost_user_block(
670+
self,
671+
drive_id,
672+
socket,
673+
partuuid=None,
674+
is_root_device=False,
675+
cache_type=None,
676+
):
677+
"""Add a vhost-user block device."""
678+
679+
self.api.drive.put(
680+
drive_id=drive_id,
681+
socket=socket,
682+
partuuid=partuuid,
683+
is_root_device=is_root_device,
684+
cache_type=cache_type,
685+
)
686+
669687
def patch_drive(self, drive_id, file):
670688
"""Modify/patch an existing block device."""
671689
self.api.drive.patch(

tests/framework/utils.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
from retry import retry
2525
from retry.api import retry_call
2626

27-
from framework.defs import MIN_KERNEL_VERSION_FOR_IO_URING
27+
from framework.defs import (
28+
MIN_KERNEL_VERSION_FOR_IO_URING,
29+
DEFAULT_TEST_SESSION_ROOT_PATH,
30+
LOCAL_BUILD_PATH,
31+
)
2832

2933
FLUSH_CMD = 'screen -S {session} -X colon "logfile flush 0^M"'
3034
CommandReturn = namedtuple("CommandReturn", "returncode stdout stderr")
@@ -376,6 +380,16 @@ def __str__(self):
376380
return "\n\n".join(self.failures)
377381

378382

383+
def to_local_dir_path(tmp_dir_path: str) -> str:
384+
"""
385+
Converts path from tmp dir to path on the host.
386+
"""
387+
388+
return tmp_dir_path.replace(
389+
str(DEFAULT_TEST_SESSION_ROOT_PATH), str(LOCAL_BUILD_PATH)
390+
)
391+
392+
379393
def search_output_from_cmd(cmd: str, find_regex: typing.Pattern) -> typing.Match:
380394
"""
381395
Run a shell command and search a given regex object in stdout.

tests/integration_tests/build/test_binary_static_linking.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
import host_tools.cargo_build as host
99
from framework import utils
1010

11+
1112
@pytest.mark.timeout(500)
1213
def test_firecracker_binary_static_linking():
1314
"""
1415
Test to make sure the firecracker binary is statically linked.
1516
"""
1617
fc_binary_path = host.get_binary("firecracker")
17-
_, stdout,stderr = utils.run_cmd(f"file {fc_binary_path}")
18+
_, stdout, stderr = utils.run_cmd(f"file {fc_binary_path}")
1819
assert "" in stderr
1920
# expected "statically linked" for aarch64 and
2021
# "static-pie linked" for x86_64
21-
assert "statically linked" in stdout or \
22-
"static-pie linked" in stdout
22+
assert "statically linked" in stdout or "static-pie linked" in stdout
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Tests for vhost-user-block device."""
4+
5+
import os
6+
import platform
7+
import subprocess
8+
import stat
9+
import time
10+
import shutil
11+
from pathlib import Path
12+
13+
import pytest
14+
15+
import host_tools.cargo_build as host
16+
from framework import utils
17+
18+
VHOST_USER_SOCKET = "/vub.socket"
19+
20+
21+
def spawn_vhost_user_backend(vm, host_mem_path):
22+
"""Spawn vhost-user-block backend."""
23+
24+
uid = vm.jailer.uid
25+
gid = vm.jailer.gid
26+
27+
sp = f"{vm.chroot()}{VHOST_USER_SOCKET}"
28+
args = ["vhost-user-blk", "-s", sp, "-b", host_mem_path, "-r"]
29+
proc = subprocess.Popen(args)
30+
31+
time.sleep(1)
32+
if proc is None or proc.poll() is not None:
33+
print("vub is not running")
34+
35+
with utils.chroot(vm.chroot()):
36+
# The backend will create the socket path with root rights.
37+
# Change rights to the jailer's.
38+
os.chown(VHOST_USER_SOCKET, uid, gid)
39+
return proc
40+
41+
42+
def test_vhost_user_block(microvm_factory, guest_kernel, rootfs_ubuntu_22):
43+
"""
44+
This test simply tries to boot a VM with
45+
vhost-user-block as a root device.
46+
"""
47+
48+
vm = microvm_factory.build(guest_kernel, None, monitor_memory=False)
49+
50+
vm.jailer.extra_args.update({"no-seccomp": None})
51+
ssh_key = rootfs_ubuntu_22.with_suffix(".id_rsa")
52+
vm.ssh_key = ssh_key
53+
54+
vm.spawn()
55+
56+
# Converting path from tmp dir ("./srv/..") to local
57+
# path on the host ("../build/..")
58+
rootfs_path = utils.to_local_dir_path(str(rootfs_ubuntu_22))
59+
backend = spawn_vhost_user_backend(vm, rootfs_path)
60+
61+
vm.basic_config()
62+
vm.add_vhost_user_block("1", VHOST_USER_SOCKET, is_root_device=True)
63+
vm.add_net_iface()
64+
vm.start()
65+
66+
# Attempt to connect to the VM.
67+
# Verify if guest can run commands.
68+
exit_code, _, _ = vm.ssh.run("ls")
69+
assert exit_code == 0

0 commit comments

Comments
 (0)