From 416a729a9ba2b1cf7a7adf0d19ced9c33b3e9a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Tue, 9 Jun 2026 16:18:29 +0300 Subject: [PATCH 01/14] feat: add layer with java support --- .gitmodules | 4 ++++ layers/meta-openjdk-temurin | 1 + scripts/add-layers.sh | 3 +++ 3 files changed, 8 insertions(+) create mode 160000 layers/meta-openjdk-temurin diff --git a/.gitmodules b/.gitmodules index 4b527be9..71e675ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,3 +33,7 @@ path = layers/meta-cloud-services url = https://github.com/ni/meta-cloud-services branch = nilrt/master/next +[submodule "layers/meta-openjdk-temurin"] + path = layers/meta-openjdk-temurin + url = https://github.com/lucimber/meta-openjdk-temurin.git + branch = scarthgap diff --git a/layers/meta-openjdk-temurin b/layers/meta-openjdk-temurin new file mode 160000 index 00000000..5804d9a8 --- /dev/null +++ b/layers/meta-openjdk-temurin @@ -0,0 +1 @@ +Subproject commit 5804d9a8b33c40b7a6c6ecae9fc8799b8df61108 diff --git a/scripts/add-layers.sh b/scripts/add-layers.sh index cdb42b79..525e8231 100755 --- a/scripts/add-layers.sh +++ b/scripts/add-layers.sh @@ -26,6 +26,7 @@ LAYERS=( "meta-security" "meta-virtualization" "meta-cloud-services" + "meta-openjdk-temurin" ) for layer in "${LAYERS[@]}"; do @@ -39,3 +40,5 @@ for layer in "${LAYERS[@]}"; do echo "Warning: Layer $layer not found!" fi done + +rm -rf /home/user/poky/meta-openjdk-temurin/recipes-java/helloworld-java From 68415197deb1e9f1cb863c5a450a4a21fe65db11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Tue, 9 Jun 2026 16:27:32 +0300 Subject: [PATCH 02/14] feat: add wrap recipe for vdbench --- conf/added_packages.conf | 1 + .../recipes-vdbench/vdbench/README.md | 9 +++++++++ .../recipes-vdbench/vdbench/vdbench/.gitkeep | 0 .../vdbench/vdbench_5.07.04.bb | 19 +++++++++++++++++++ 4 files changed, 29 insertions(+) create mode 100644 layers/meta-image-tests/recipes-vdbench/vdbench/README.md create mode 100644 layers/meta-image-tests/recipes-vdbench/vdbench/vdbench/.gitkeep create mode 100644 layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb diff --git a/conf/added_packages.conf b/conf/added_packages.conf index 6cf4f6b5..91509419 100644 --- a/conf/added_packages.conf +++ b/conf/added_packages.conf @@ -4,6 +4,7 @@ IMAGE_INSTALL:append = " \ fwts \ iperf3 \ lvm2 \ + openjdk-25-jre \ perf \ phoronix-test-suite \ ptest-runner \ diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/README.md b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md new file mode 100644 index 00000000..72fc5251 --- /dev/null +++ b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md @@ -0,0 +1,9 @@ +Для работы рецепта нужно прикрепить архив со следующим содержимым: + +- Бинарные файлы инструмента; + +- Linux x64 файл и скрипт конфигурации; + +- Лицензию для рецепта. + +Затем нужно добавить рецепт в конфигурацию сборки. diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench/.gitkeep b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb new file mode 100644 index 00000000..91ebd010 --- /dev/null +++ b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb @@ -0,0 +1,19 @@ +SUMMARY = "Vdbench" +# License must be withing the archive and md5sum should be updated. +LICENSE = "GPL-2.0-only" +LIC_FILES_CHKSUM = "file://LICENSE;md5=8a1984b6adf89397460816c68c05c616" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += "file://vdbench.tar.gz" + +S = "${WORKDIR}/vdbench" + +RDEPENDS:${PN} += "bash" + +do_install() { + install -d ${D}${bindir}/vdbench + + cp -r ${S}/* ${D}${bindir}/vdbench/ +} + +FILES:${PN} = "${bindir}/vdbench" From 5db9f2073964bbf52b1d562ca737a349aa3db5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Tue, 9 Jun 2026 16:29:50 +0300 Subject: [PATCH 03/14] feat: add python wrap for vdbench with basic test --- src/imgtests/exec/loaders/vdbench.py | 48 ++++++++++++++++++++++++++++ src/imgtests/suites/drive/vdbench.py | 40 +++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/imgtests/exec/loaders/vdbench.py create mode 100644 src/imgtests/suites/drive/vdbench.py diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py new file mode 100644 index 00000000..5f58ab9e --- /dev/null +++ b/src/imgtests/exec/loaders/vdbench.py @@ -0,0 +1,48 @@ +import logging + +from imgtests.exec.base_util import GenericUtil +from imgtests.exec.exec import ExecResult, SSHClient, common_run_command + +logger = logging.getLogger(__name__) + +VDBENCH_DIR = "/usr/bin/vdbench" +OUTPUT_DIR = VDBENCH_DIR + "/output" + +class Vdbench(GenericUtil): + def __init__(self, ssh_client: SSHClient | None = None) -> None: + super().__init__("vdbench", ssh_client) + + def validate_setup(self) -> None: + result = common_run_command( + ["ls", VDBENCH_DIR], + self.ssh_client, + ) + if result.returncode: + err_msg = f"Tool is not found in {VDBENCH_DIR}" + raise FileNotFoundError(err_msg) + + def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None) -> ExecResult: + block_size = kwargs.get("block_size", 4096) + read_percentage = kwargs.get("read_percentage", 70) + iorate = kwargs.get("iorate", 1000) + configuration = ( + f"sd=sd1,lun=storage.img,size=1024m\n" + f"wd=wd1,sd=sd1,xfersize={block_size},readpct={read_percentage},seekpct=100\n" + f"rd=run1,wd=wd1,iorate={iorate},elapsed={timeout_sec},interval=1" + ) + cmd = [ + "echo", + "-e", + f"'{configuration}'", + ">", + "vdbench-config" + ] + + result = common_run_command(cmd, self.ssh_client) + return result + + def run(self, timeout_sec: int, **kwargs: str | float | bool | None) -> tuple[ExecResult, str]: + self.validate_setup() + self.configure_params(timeout_sec=timeout_sec, **kwargs) + result = common_run_command([f"{VDBENCH_DIR}/vdbench", "-f", "vdbench-config"], self.ssh_client) + return result, OUTPUT_DIR diff --git a/src/imgtests/suites/drive/vdbench.py b/src/imgtests/suites/drive/vdbench.py new file mode 100644 index 00000000..1dbcd67f --- /dev/null +++ b/src/imgtests/suites/drive/vdbench.py @@ -0,0 +1,40 @@ +from datetime import UTC, datetime +from typing import TYPE_CHECKING + +from imgtests.exec.loaders import Vdbench +from imgtests.planning.base import AbstractRunnableTimeLimitedTest +from imgtests.types import Subsystem, TestResult, TestStatus + +if TYPE_CHECKING: + from collections.abc import Iterable + from concurrent.futures import ThreadPoolExecutor + + from imgtests.exec.exec import SSHClient + + +class VdbenchTest(AbstractRunnableTimeLimitedTest): + """Test that runs vdbench on a disk.""" + + def __init__(self, timeout: int) -> None: + super().__init__( + "Load drives with vdbench.", + frozenset({Subsystem.FILE}), + timeout=timeout, + ) + + def _run( + self, + executor: ThreadPoolExecutor, + client: SSHClient | None, + timeout: int, + ) -> Iterable[TestResult]: + vdbench = Vdbench(client) + started_at = datetime.now(UTC) + future = executor.submit(vdbench.run, timeout_sec=timeout, block_size=4096, read_percentage=70, iorate=1000) + result, output_dir = future.result() + yield TestResult( + metrics={"output_dir": output_dir}, + command=" ".join(result.cmd), + started_at=started_at, + status=TestStatus.PASSED if not result.returncode else TestStatus.FAILED, + ) From d0a92801bc4d6726f54105e8a5478ff1585280b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=B8=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=D0=B2?= Date: Tue, 9 Jun 2026 21:38:46 +0300 Subject: [PATCH 04/14] fix: ruff format --- src/imgtests/exec/loaders/vdbench.py | 15 +++++++++------ src/imgtests/suites/drive/vdbench.py | 8 +++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 5f58ab9e..f2fcb7c0 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -8,6 +8,7 @@ VDBENCH_DIR = "/usr/bin/vdbench" OUTPUT_DIR = VDBENCH_DIR + "/output" + class Vdbench(GenericUtil): def __init__(self, ssh_client: SSHClient | None = None) -> None: super().__init__("vdbench", ssh_client) @@ -20,7 +21,7 @@ def validate_setup(self) -> None: if result.returncode: err_msg = f"Tool is not found in {VDBENCH_DIR}" raise FileNotFoundError(err_msg) - + def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None) -> ExecResult: block_size = kwargs.get("block_size", 4096) read_percentage = kwargs.get("read_percentage", 70) @@ -35,14 +36,16 @@ def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None "-e", f"'{configuration}'", ">", - "vdbench-config" + "vdbench-config", ] - result = common_run_command(cmd, self.ssh_client) - return result - + return common_run_command(cmd, self.ssh_client) + def run(self, timeout_sec: int, **kwargs: str | float | bool | None) -> tuple[ExecResult, str]: self.validate_setup() self.configure_params(timeout_sec=timeout_sec, **kwargs) - result = common_run_command([f"{VDBENCH_DIR}/vdbench", "-f", "vdbench-config"], self.ssh_client) + result = common_run_command( + [f"{VDBENCH_DIR}/vdbench", "-f", "vdbench-config"], + self.ssh_client, + ) return result, OUTPUT_DIR diff --git a/src/imgtests/suites/drive/vdbench.py b/src/imgtests/suites/drive/vdbench.py index 1dbcd67f..55741833 100644 --- a/src/imgtests/suites/drive/vdbench.py +++ b/src/imgtests/suites/drive/vdbench.py @@ -30,7 +30,13 @@ def _run( ) -> Iterable[TestResult]: vdbench = Vdbench(client) started_at = datetime.now(UTC) - future = executor.submit(vdbench.run, timeout_sec=timeout, block_size=4096, read_percentage=70, iorate=1000) + future = executor.submit( + vdbench.run, + timeout_sec=timeout, + block_size=4096, + read_percentage=70, + iorate=1000, + ) result, output_dir = future.result() yield TestResult( metrics={"output_dir": output_dir}, From 30dc9f2360abafe45cf620f02eb82866b2722eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Thu, 11 Jun 2026 15:21:21 +0300 Subject: [PATCH 05/14] docs: translate readme --- .../meta-image-tests/recipes-vdbench/vdbench/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/README.md b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md index 72fc5251..737919eb 100644 --- a/layers/meta-image-tests/recipes-vdbench/vdbench/README.md +++ b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md @@ -1,9 +1,9 @@ -Для работы рецепта нужно прикрепить архив со следующим содержимым: +To make the recipe work, you will need to attach an archive containing the following files: -- Бинарные файлы инструмента; +- binary tool files; -- Linux x64 файл и скрипт конфигурации; +- linux x64 file and config script; -- Лицензию для рецепта. +- recipe license. -Затем нужно добавить рецепт в конфигурацию сборки. +After that, you should add the recipe to the poky config. From 30008beb8a5c26bd45e4628efdfffa3afe8ad71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Thu, 11 Jun 2026 15:30:30 +0300 Subject: [PATCH 06/14] refactor: specify vdbench output directory --- src/imgtests/exec/loaders/__init__.py | 1 + src/imgtests/exec/loaders/vdbench.py | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/imgtests/exec/loaders/__init__.py b/src/imgtests/exec/loaders/__init__.py index 56472af8..1a17da9e 100644 --- a/src/imgtests/exec/loaders/__init__.py +++ b/src/imgtests/exec/loaders/__init__.py @@ -11,3 +11,4 @@ from .pts import PhoronixTestSuite as PhoronixTestSuite from .stress_ng import StressNg as StressNg from .stress_ng import StressNgParamVerValidationError as StressNgParamVerValidationError +from .vdbench import Vdbench as Vdbench diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index f2fcb7c0..4b072c41 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -6,7 +6,8 @@ logger = logging.getLogger(__name__) VDBENCH_DIR = "/usr/bin/vdbench" -OUTPUT_DIR = VDBENCH_DIR + "/output" +CONFIG_FILE = "/root/vdbench-config" +OUTPUT_DIR = "/root/vdbench-output" class Vdbench(GenericUtil): @@ -36,7 +37,7 @@ def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None "-e", f"'{configuration}'", ">", - "vdbench-config", + CONFIG_FILE, ] return common_run_command(cmd, self.ssh_client) @@ -45,7 +46,7 @@ def run(self, timeout_sec: int, **kwargs: str | float | bool | None) -> tuple[Ex self.validate_setup() self.configure_params(timeout_sec=timeout_sec, **kwargs) result = common_run_command( - [f"{VDBENCH_DIR}/vdbench", "-f", "vdbench-config"], + [f"{VDBENCH_DIR}/vdbench", "-f", CONFIG_FILE, "-o", OUTPUT_DIR], self.ssh_client, ) return result, OUTPUT_DIR From 9ef46fff6980acbf68f2876749997d0dc1ee9fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Thu, 11 Jun 2026 16:05:03 +0300 Subject: [PATCH 07/14] refactor: swap kwargs for create_opt --- src/imgtests/exec/loaders/vdbench.py | 44 ++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 4b072c41..16c869c9 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -2,6 +2,7 @@ from imgtests.exec.base_util import GenericUtil from imgtests.exec.exec import ExecResult, SSHClient, common_run_command +from imgtests.exec.utils import create_opt logger = logging.getLogger(__name__) @@ -13,6 +14,7 @@ class Vdbench(GenericUtil): def __init__(self, ssh_client: SSHClient | None = None) -> None: super().__init__("vdbench", ssh_client) + self.path = VDBENCH_DIR + "/vdbench" def validate_setup(self) -> None: result = common_run_command( @@ -23,10 +25,13 @@ def validate_setup(self) -> None: err_msg = f"Tool is not found in {VDBENCH_DIR}" raise FileNotFoundError(err_msg) - def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None) -> ExecResult: - block_size = kwargs.get("block_size", 4096) - read_percentage = kwargs.get("read_percentage", 70) - iorate = kwargs.get("iorate", 1000) + def configure_params( + self, + timeout_sec: int = 60, + block_size: int = 4096, + read_percentage: int = 70, + iorate: int = 1000, + ) -> ExecResult: configuration = ( f"sd=sd1,lun=storage.img,size=1024m\n" f"wd=wd1,sd=sd1,xfersize={block_size},readpct={read_percentage},seekpct=100\n" @@ -42,11 +47,32 @@ def configure_params(self, timeout_sec: int, **kwargs: str | float | bool | None return common_run_command(cmd, self.ssh_client) - def run(self, timeout_sec: int, **kwargs: str | float | bool | None) -> tuple[ExecResult, str]: + def run( + self, + timeout_sec: int, + block_size: int = 4096, + read_percentage: int = 70, + iorate: int = 1000, + ) -> tuple[ExecResult, str]: + """Runs the vdbench. + + Args: + timeout_sec (int): Execution time of the vdbench in seconds. + block_size (int): Block size in bytes for IO operations. + read_percentage (int): Percentage of read operations. + iorate (int): IO operations per second. + """ self.validate_setup() - self.configure_params(timeout_sec=timeout_sec, **kwargs) - result = common_run_command( - [f"{VDBENCH_DIR}/vdbench", "-f", CONFIG_FILE, "-o", OUTPUT_DIR], - self.ssh_client, + self.configure_params( + timeout_sec=timeout_sec, + block_size=block_size, + read_percentage=read_percentage, + iorate=iorate, ) + + opts = [ + *create_opt("f", CONFIG_FILE, use_one_dash=True), + *create_opt("o", OUTPUT_DIR, use_one_dash=True), + ] + result = self(opts) return result, OUTPUT_DIR From 3a35e1b1c03aa9b06e7631d2c5a2ab83f3a1c998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Thu, 11 Jun 2026 16:21:25 +0300 Subject: [PATCH 08/14] refactor: change binary dir to sbin --- .../recipes-vdbench/vdbench/vdbench_5.07.04.bb | 6 +++--- src/imgtests/exec/loaders/vdbench.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb index 91ebd010..7a13da06 100644 --- a/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb +++ b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb @@ -11,9 +11,9 @@ S = "${WORKDIR}/vdbench" RDEPENDS:${PN} += "bash" do_install() { - install -d ${D}${bindir}/vdbench + install -d ${D}${sbindir}/vdbench - cp -r ${S}/* ${D}${bindir}/vdbench/ + cp -r ${S}/* ${D}${sbindir}/vdbench/ } -FILES:${PN} = "${bindir}/vdbench" +FILES:${PN} = "${sbindir}/vdbench" diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 16c869c9..2a7bdd92 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -VDBENCH_DIR = "/usr/bin/vdbench" +VDBENCH_DIR = "/usr/sbin/vdbench" CONFIG_FILE = "/root/vdbench-config" OUTPUT_DIR = "/root/vdbench-output" From 1637fa2333e0438e6a7e4d6a23faf1e57db1d3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B8=D0=B2=D0=BE=D0=B5=D0=B2=20=D0=9D=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= Date: Sun, 14 Jun 2026 17:28:21 +0300 Subject: [PATCH 09/14] refactor: add final type --- src/imgtests/exec/loaders/vdbench.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 2a7bdd92..17ffe475 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -1,4 +1,5 @@ import logging +from typing import Final from imgtests.exec.base_util import GenericUtil from imgtests.exec.exec import ExecResult, SSHClient, common_run_command @@ -6,9 +7,9 @@ logger = logging.getLogger(__name__) -VDBENCH_DIR = "/usr/sbin/vdbench" -CONFIG_FILE = "/root/vdbench-config" -OUTPUT_DIR = "/root/vdbench-output" +VDBENCH_DIR: Final = "/usr/sbin/vdbench" +CONFIG_FILE: Final = "/root/vdbench-config" +OUTPUT_DIR: Final = "/root/vdbench-output" class Vdbench(GenericUtil): From d82ae3114d0d2d0142901816cd3429535c1a8e0b Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:31:20 +0300 Subject: [PATCH 10/14] refactor: use LIB_DATA_DIR for store config and output files. --- src/imgtests/exec/loaders/vdbench.py | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 17ffe475..99e60a9d 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -1,30 +1,33 @@ import logging +from pathlib import Path from typing import Final +from imgtests.constant import LIB_DATA_DIR from imgtests.exec.base_util import GenericUtil from imgtests.exec.exec import ExecResult, SSHClient, common_run_command from imgtests.exec.utils import create_opt logger = logging.getLogger(__name__) -VDBENCH_DIR: Final = "/usr/sbin/vdbench" -CONFIG_FILE: Final = "/root/vdbench-config" -OUTPUT_DIR: Final = "/root/vdbench-output" +VDBENCH_DIR: Final = Path("/usr/sbin/vdbench") +CONFIG_FILE: Final = LIB_DATA_DIR / "vdbench-config" +OUTPUT_DIR: Final = LIB_DATA_DIR / "vdbench-output" class Vdbench(GenericUtil): def __init__(self, ssh_client: SSHClient | None = None) -> None: super().__init__("vdbench", ssh_client) - self.path = VDBENCH_DIR + "/vdbench" + self.path = VDBENCH_DIR / "vdbench" - def validate_setup(self) -> None: - result = common_run_command( - ["ls", VDBENCH_DIR], - self.ssh_client, - ) + def validate_setup(self) -> ExecResult: + result = common_run_command(["ls", str(self.path)], self.ssh_client) if result.returncode: - err_msg = f"Tool is not found in {VDBENCH_DIR}" - raise FileNotFoundError(err_msg) + return ExecResult( + cmd=result.cmd, + stderr=f"Failed to locate '{self.name}'.", + returncode=1, + ) + return result def configure_params( self, @@ -43,7 +46,7 @@ def configure_params( "-e", f"'{configuration}'", ">", - CONFIG_FILE, + str(CONFIG_FILE), ] return common_run_command(cmd, self.ssh_client) @@ -54,7 +57,7 @@ def run( block_size: int = 4096, read_percentage: int = 70, iorate: int = 1000, - ) -> tuple[ExecResult, str]: + ) -> tuple[ExecResult, Path | None]: """Runs the vdbench. Args: @@ -63,7 +66,9 @@ def run( read_percentage (int): Percentage of read operations. iorate (int): IO operations per second. """ - self.validate_setup() + result = self.validate_setup() + if result.returncode: + return result, None self.configure_params( timeout_sec=timeout_sec, block_size=block_size, From ac9a6a101d0a52bd2702348037b792ddb9043c6b Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:38:36 +0300 Subject: [PATCH 11/14] refactor: moves vdbench config and output creating into the subfolder. --- src/imgtests/exec/loaders/vdbench.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 99e60a9d..c3bf79e4 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -9,15 +9,16 @@ logger = logging.getLogger(__name__) -VDBENCH_DIR: Final = Path("/usr/sbin/vdbench") -CONFIG_FILE: Final = LIB_DATA_DIR / "vdbench-config" -OUTPUT_DIR: Final = LIB_DATA_DIR / "vdbench-output" +VDBENCH_NAME: Final = "vdbench" +VDBENCH_DIR: Final = Path("/usr/sbin") / VDBENCH_NAME +CONFIG_FILE: Final = LIB_DATA_DIR / VDBENCH_NAME / f"{VDBENCH_NAME}-config" +OUTPUT_DIR: Final = LIB_DATA_DIR / VDBENCH_NAME / f"{VDBENCH_NAME}-output" class Vdbench(GenericUtil): def __init__(self, ssh_client: SSHClient | None = None) -> None: - super().__init__("vdbench", ssh_client) - self.path = VDBENCH_DIR / "vdbench" + super().__init__(VDBENCH_NAME, ssh_client) + self.path = VDBENCH_DIR / VDBENCH_NAME def validate_setup(self) -> ExecResult: result = common_run_command(["ls", str(self.path)], self.ssh_client) @@ -41,6 +42,8 @@ def configure_params( f"wd=wd1,sd=sd1,xfersize={block_size},readpct={read_percentage},seekpct=100\n" f"rd=run1,wd=wd1,iorate={iorate},elapsed={timeout_sec},interval=1" ) + if not CONFIG_FILE.parent.exists(): + CONFIG_FILE.parent.mkdir(parents=True) cmd = [ "echo", "-e", @@ -76,6 +79,8 @@ def run( iorate=iorate, ) + if not OUTPUT_DIR.exists(): + OUTPUT_DIR.mkdir(parents=True) opts = [ *create_opt("f", CONFIG_FILE, use_one_dash=True), *create_opt("o", OUTPUT_DIR, use_one_dash=True), From cb219852b9ff1d74f3f414ad4cba1d2ad78e1531 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:35:42 +0300 Subject: [PATCH 12/14] fix+refactor: correctly create folders for the vdbench config and includes vdbench in the packages.conf. --- .gitignore | 3 +++ conf/packages.conf | 1 + .../recipes-vdbench/vdbench/README.md | 4 +-- .../{vdbench_5.07.04.bb => vdbench.bb} | 0 src/imgtests/exec/loaders/vdbench.py | 26 ++++++++++++------- 5 files changed, 21 insertions(+), 13 deletions(-) rename layers/meta-image-tests/recipes-vdbench/vdbench/{vdbench_5.07.04.bb => vdbench.bb} (100%) diff --git a/.gitignore b/.gitignore index f0e3b842..71768043 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ uv.lock .coverage pytest-coverage.xml imgtests.egg-info + +# External +vdbench.tar.gz diff --git a/conf/packages.conf b/conf/packages.conf index 2a72d4e6..81914ef9 100644 --- a/conf/packages.conf +++ b/conf/packages.conf @@ -168,4 +168,5 @@ IMAGE_INSTALL:append = " \ zip \ zlib \ zstd \ + vdbench \ " diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/README.md b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md index 737919eb..6069a142 100644 --- a/layers/meta-image-tests/recipes-vdbench/vdbench/README.md +++ b/layers/meta-image-tests/recipes-vdbench/vdbench/README.md @@ -1,9 +1,7 @@ -To make the recipe work, you will need to attach an archive containing the following files: +To make the recipe work, you will need to attach an archive (with name vdbench.tar.gz) containing the following files: - binary tool files; - linux x64 file and config script; - recipe license. - -After that, you should add the recipe to the poky config. diff --git a/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb b/layers/meta-image-tests/recipes-vdbench/vdbench/vdbench.bb similarity index 100% rename from layers/meta-image-tests/recipes-vdbench/vdbench/vdbench_5.07.04.bb rename to layers/meta-image-tests/recipes-vdbench/vdbench/vdbench.bb diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index c3bf79e4..90397d4c 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -43,16 +43,22 @@ def configure_params( f"rd=run1,wd=wd1,iorate={iorate},elapsed={timeout_sec},interval=1" ) if not CONFIG_FILE.parent.exists(): - CONFIG_FILE.parent.mkdir(parents=True) - cmd = [ - "echo", - "-e", - f"'{configuration}'", - ">", - str(CONFIG_FILE), - ] - - return common_run_command(cmd, self.ssh_client) + result = common_run_command( + ["mkdir", "--parents", str(CONFIG_FILE.parent)], + self.ssh_client, + ) + if result.returncode: + return result + return common_run_command( + [ + "echo", + "-e", + f"'{configuration}'", + ">", + str(CONFIG_FILE), + ], + self.ssh_client, + ) def run( self, From 64092df1c89117e0f84642259f80bf0c84331721 Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Fri, 19 Jun 2026 20:44:22 +0300 Subject: [PATCH 13/14] refactor: recreate folders if needs on the remote for the vdbench. --- src/imgtests/exec/loaders/vdbench.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 90397d4c..68bb5ce2 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -42,7 +42,7 @@ def configure_params( f"wd=wd1,sd=sd1,xfersize={block_size},readpct={read_percentage},seekpct=100\n" f"rd=run1,wd=wd1,iorate={iorate},elapsed={timeout_sec},interval=1" ) - if not CONFIG_FILE.parent.exists(): + if common_run_command(["test", "-d", str(CONFIG_FILE.parent)], self.ssh_client).returncode: result = common_run_command( ["mkdir", "--parents", str(CONFIG_FILE.parent)], self.ssh_client, @@ -85,8 +85,13 @@ def run( iorate=iorate, ) - if not OUTPUT_DIR.exists(): - OUTPUT_DIR.mkdir(parents=True) + if common_run_command(["test", "-d", str(OUTPUT_DIR)], self.ssh_client).returncode: + result = common_run_command( + ["mkdir", "--parents", str(OUTPUT_DIR)], + self.ssh_client, + ) + if result.returncode: + return result, None opts = [ *create_opt("f", CONFIG_FILE, use_one_dash=True), *create_opt("o", OUTPUT_DIR, use_one_dash=True), From fcad41cb107e0a13cd1b1c7f68101c50130a276f Mon Sep 17 00:00:00 2001 From: Artanias <43622365+Artanias@users.noreply.github.com> Date: Fri, 19 Jun 2026 21:32:30 +0300 Subject: [PATCH 14/14] fix: get home path from the remote for the vdbench. --- src/imgtests/exec/loaders/vdbench.py | 47 +++++++++++++++------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/imgtests/exec/loaders/vdbench.py b/src/imgtests/exec/loaders/vdbench.py index 68bb5ce2..3c838616 100644 --- a/src/imgtests/exec/loaders/vdbench.py +++ b/src/imgtests/exec/loaders/vdbench.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import Final -from imgtests.constant import LIB_DATA_DIR +from imgtests.constant import LIB_NAME from imgtests.exec.base_util import GenericUtil from imgtests.exec.exec import ExecResult, SSHClient, common_run_command from imgtests.exec.utils import create_opt @@ -11,8 +11,6 @@ VDBENCH_NAME: Final = "vdbench" VDBENCH_DIR: Final = Path("/usr/sbin") / VDBENCH_NAME -CONFIG_FILE: Final = LIB_DATA_DIR / VDBENCH_NAME / f"{VDBENCH_NAME}-config" -OUTPUT_DIR: Final = LIB_DATA_DIR / VDBENCH_NAME / f"{VDBENCH_NAME}-output" class Vdbench(GenericUtil): @@ -32,6 +30,7 @@ def validate_setup(self) -> ExecResult: def configure_params( self, + config_file: Path, timeout_sec: int = 60, block_size: int = 4096, read_percentage: int = 70, @@ -42,20 +41,16 @@ def configure_params( f"wd=wd1,sd=sd1,xfersize={block_size},readpct={read_percentage},seekpct=100\n" f"rd=run1,wd=wd1,iorate={iorate},elapsed={timeout_sec},interval=1" ) - if common_run_command(["test", "-d", str(CONFIG_FILE.parent)], self.ssh_client).returncode: - result = common_run_command( - ["mkdir", "--parents", str(CONFIG_FILE.parent)], - self.ssh_client, - ) - if result.returncode: - return result + result = self.__provide_folder(config_file.parent) + if result.returncode: + return result return common_run_command( [ "echo", "-e", f"'{configuration}'", ">", - str(CONFIG_FILE), + str(config_file), ], self.ssh_client, ) @@ -78,23 +73,33 @@ def run( result = self.validate_setup() if result.returncode: return result, None + result = common_run_command(["echo", "$HOME"], self.ssh_client) + home_dir = result.stdout.strip() + if result.returncode or not home_dir: + return result, None + + config_file: Final = Path(home_dir) / LIB_NAME / VDBENCH_NAME / f"{VDBENCH_NAME}-config" self.configure_params( + config_file=config_file, timeout_sec=timeout_sec, block_size=block_size, read_percentage=read_percentage, iorate=iorate, ) - if common_run_command(["test", "-d", str(OUTPUT_DIR)], self.ssh_client).returncode: - result = common_run_command( - ["mkdir", "--parents", str(OUTPUT_DIR)], - self.ssh_client, - ) - if result.returncode: - return result, None + output_dir = Path(home_dir) / LIB_NAME / VDBENCH_NAME / f"{VDBENCH_NAME}-output" + result = self.__provide_folder(output_dir) + if result.returncode: + return result, None opts = [ - *create_opt("f", CONFIG_FILE, use_one_dash=True), - *create_opt("o", OUTPUT_DIR, use_one_dash=True), + *create_opt("f", config_file, use_one_dash=True), + *create_opt("o", output_dir, use_one_dash=True), ] result = self(opts) - return result, OUTPUT_DIR + return result, output_dir + + def __provide_folder(self, folder: Path) -> ExecResult: + result = common_run_command(["test", "-d", str(folder)], self.ssh_client) + if result.returncode: + return common_run_command(["mkdir", "--parents", str(folder)], self.ssh_client) + return result