Hardware
As a tester I want to specify detailed hardware requirements for the guest on which the tests will be executed.
As part of the provision step it is
possible to use the hardware
key to specify additional
requirements for the testing environment. This provides a
generic and an extensible way to write down essential hardware
requirements. For example one consistent way how to specify
at least 2 GB of RAM for all supported provisioners.
The current state of support of HW requirements among plugins bundled with tmt is available at Hardware requirement support.
Introduction
Individual requirements are provided as a simple key:
value
pairs, for example the minimum amount of
memory, or the related information is
grouped under a common parent, for example cores
or
model
under the cpu key.
Comparison operators
The value
part of the constraint follows the schema [operator] actual-value
.
The operator
is optional, it may be any of the following: =
, !=
,
>
, >=
, <
, >=
, ~
(regex match), and !~
(regex not
matches). When operator is omitted, =
is assumed.
Warning
Only =
, !=
, >
, >=
, <
and <=
operators are
accepted for requirements that accept numeric values, e.g.
cpu.cores or
tpm.version.
Only =
and !=
operators are accepted for flag-like requirements,
e.g. virtualization.is-virtualized.
Only =
, !=
, ~
and !~
operators are accepted for
requirements that accept string values, e.g.
cpu.model-name or
virtualization.hypervisor.
Note
It is highly recommended to wrap values with single or double quotes,
i.e. memory: '>= 8 GiB'
rather than memory: >= 8 GiB
. This should
prevent any unexpected processing by parsers loading the fmf content.
Without explicit quotes, some operators might lead to unexpected outcome.
# This...
memory: '8 GB'
# ... is the same as this:
memory: '= 8 GB'
# Optional operators at the start of the value
memory: '!= 8 GB'
memory: '> 8 GB'
memory: '>= 8 GB'
memory: '< 8 GB'
memory: '<= 8 GB'
Search
Regular expressions can be used for selected fields such as
the cpu model name or
hostname. Use ~
for positive and
!~
for negative regular expressions at the beginning of
the string. Any leading or trailing white space from the
search string is removed.
# Search for processors using a cpu model name
cpu:
model-name: "~ AMD"
# Select guests with a non-matching hostname
hostname: "!~ kvm-01.*"
Note
The full extent of regular expressions might not be supported
across all provision implementations. However, the “any
character” pattern, .*
, should be supported everywhere.
Logic operators
When multiple environment requirements are provided the
provision implementation should attempt to satisfy all of
them. It is also possible to write this explicitly using the
and
operator containing a list of dictionaries with
individual requirements. When the or
operator is used, any
of the alternatives provided in the list should be
sufficient:
# By default exact value expected, these are equivalent:
cpu:
model: 37
cpu:
model: '= 37'
# Using advanced logic operators
and:
- cpu:
family: 15
- or:
- cpu:
model: 65
- cpu:
model: 67
- cpu:
model: 69
Units
The pint library is used for processing various units, both decimal and binary prefixes can be used:
1 MB = 1 000 000 B
1 MiB = 1 048 576 B
Names and IDs
When looking for specific devices, it is often possible to request them either by their name or by some kind of ID. The specification follows a simple naming scheme when a property of a device can be expressed as a name as well as an ID:
keys with
-name
suffix represent human-comprehensible string names - model name, vendor name, microarchitecture code name, brand names, and so on. For example,Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz
would be acpu.model-name
requirement.IDs are left without a suffix. IDs tend to be integers, or groups of integers. For example,
62
would be acpu.model
requirement.
Requirements given by a name can often make use of regular
expression operators (~
and !~
) while IDs can be used
very reasonably with other comparison operators like >=
.
Device and vendor IDs
Besides the names, provisioning infrastructures may support searching for devices by device and/or vendor ID. The ID namespace would be determined by the guest architecture, the buses and other specifications the guest HW is built from.
For example, probably the most common namespace would be the PCI ID Repository, collecting IDs and names of PCI devices, easy to encounter in both bare-metal and virtualized x86_64 guests. However, this ID database is not the only one in existence, and guest architecture may allow for additional device and vendor ID schemas.
Notes
The implementation for this common hardware
key is in
progress. Features under this section marked as implemented
are already supported by the artemis
plugin. Support in
other provision plugins is on the way. Check individual
plugin documentation for additional information on the
hardware requirement support.
Note
Some plugins may require additional configuration. For example, Artemis can provision machines with disks of a particular size, but to do so, Artemis maintainers must configure disk sizes for various AWS / OpenStack / Azure flavors. The constraint is supported and implemented, but it will not deliver the required virtual machine when the plugin’s backend, the Artemis deployment, isn’t configured correctly.
Note
Some plugins may support requirements that are impossible
to satisfy, e.g. the local
plugin can support the cpu.family
requirement, but it
is hard-locked to the CPU of one’s own machine.
When facing impossible requirements, plugins will emit a warning reporting this situation to the user, but in general, plugins will try to continue provisioning the guest.
Examples:
# Use the artemis plugin to provision the latest Fedora on
# a guest with the x86_64 architecture and 8 GB of memory
provision:
how: artemis
image: fedora
hardware:
arch: x86_64
memory: 8 GB
arch
Select or provision a guest with a given CPU architecture.
Note
This is a draft, the story is not implemented yet.
# String, any of well-known short architecture names.
arch: "aarch64"|"i386"|"ppc64"|"ppc64le"|"s390x"|"x86_64"|...
Warning
This field is not supported under hardware
. It is planned
to be supported in the future. Use the arch
field of specific
provision plugins to select the architecture. If this field
is used in Testing Farm’s hardware requirements the request
will abort.
Examples:
# Require a good old x86_64 box
arch: x86_64
Status: idea
beaker
Select or provision a guest with Beaker-specific parameters.
beaker:
# String, name of the Beaker pool to use for provisioning.
pool: "some-pool"
Note
The requirements are consumed by Beaker-aware provision
plugins only, and cannot be enforced in any other
infrastructure.
Added in version 1.35.
Examples:
# Select any system, as long as it is not from the given Beaker pool
beaker:
pool: "!= very-rare-machines"
Status: implemented
Implemented by provision/beaker (
==
and!=
operators only)
boot
Select or provision a guest with requested boot properties.
boot:
# String, a boot method the guest must boot with.
method: "bios"|"uefi"
Examples:
# Require a guest with a UEFI boot method.
boot:
method: uefi
# Require a guest without a legacy BIOS.
boot:
method: "!= bios"
Status: implemented
Implemented by provision/artemis
compatible
Select or provision a guest compatible with given areas.
compatible:
# List of strings, any of distro names.
distro:
- distro1
- distro2
...
See the context dimension definitions for
the list of supported values of the distro
items.
Examples:
# Select a guest compatible with both rhel-8 and rhel-9
compatible:
distro:
- rhel-8
- rhel-9
Status: implemented
Implemented by provision/artemis
cpu
Select or provision a guest with given CPU properties.
cpu:
# Integer or string, number of CPU sockets in the system.
sockets: 1|">= 1"
# Integer or string, number of CPU cores in the system.
cores: 4|">= 4"
# Integer or string, number of CPU threads in the system.
threads: 8|">= 8"
# Integer or string, number of CPU cores per socket.
cores-per-socket: 4|">= 4"
# Integer or string, number of CPU threads per core.
threads-per-core: 2|">= 2"
# Integer or string, total number of logical CPUs.
processors: 8|">= 8"
# String, CPU family name.
family-name: Comet Lake
# Integer or string, CPU family.
family: 6|">= 6"
# String, CPU model name.
model-name: Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz
# Integer or string, CPU model.
model: 142|">= 142"
# String, CPU vendor name.
vendor-name: GenuineIntel
# Number or string, an ID of CPU vendor.
vendor: 1234|"> 1234"
# Float or string, CPU frequency.
# MHz are assumed when no unit is specified.
frequency: 2300.0|">= 2300.0"
# Integer or string, CPU stepping.
stepping: 10|">= 10"
# List of strings, CPU flags as reported
# Field applies an implicit "and" to listed flags, all items of the
# list must match.
# Items may contain a nested operator, "=" and "!=" are only two allowed.
flag:
- flag1
- flag2
- "= flag3"
- "!= flag4"
...
# Request a CPU with hyper-threading enabled.
hyper-threading: true|false
See e.g. https://virtual-dba.com/blog/sockets-cores-and-threads/ for the socket, core and thread distinction.
See e.g. https://en.wikichip.org/wiki/WikiChip for information on family,
model, stepping and corresponding names. /proc/cpuinfo
and lscpu
are also useful resources.
Changed in version 1.39: beaker
plugins supports family
and frequency
Changed in version 1.38: beaker
plugins supports stepping
Changed in version 1.35: beaker
plugins supports vendor-name
Changed in version 1.33: beaker
plugin supports cpu.cores
Changed in version 1.31: beaker
plugin supports cpu.flag
Changed in version 1.30: artemis
plugin supports cpu.flag
with Artemis 0.0.67
Changed in version 1.27: beaker
plugin supports cpu.model
and cpu.processors
Examples:
# Request a rather stronger guest.
cpu:
processors: ">= 16"
# Request a CPU of a specific model set.
cpu:
model-name: "~ Intel(R) Core(TM) i7-.+"
# Request a CPU with AVX support
cpu:
flag:
- avx
- avx2
# Request a CPU with more than 4 cores.
cpu:
cores: ">= 4"
# Request a CPU with hyper-threading enabled.
cpu:
hyper-threading: true
# Request a CPU with specified stepping.
cpu:
stepping: 9
Status: implemented
Implemented by provision/artemis (
cpu.vendor
,cpu.vendor-name
,cpu.frequency
andcpu.hyper-threading
not implemented yet)Implemented by provision/beaker (
cpu.sockets
,cpu.threads
,cpu.cores-per-socket
,cpu.threads-per-core
,cpu.family-name
,cpu.vendor
not implemented yet)Implemented by provision/virtual (
cpu.processors
only)
device
Select or provision a guest with a given device.
Note
This is a draft, the story is not implemented yet.
This is a generalization of various device-like requirements like gpu
or network
. It provides a generic way for requesting devices for
which tmt defines no special HW requirements. The specialized requirements
are recommended, as they express the desired guest properties in a more
explicit way.
device:
# String, a network device name.
device-name: "A Generic Ethernet Card"
# Number or string, a network device ID.
device: 1234|"> 1234"
# String, a name of the device vendor.
vendor-name: "A Well-Known Device Manufacturer"
# Number or string, an ID of the device vendor.
vendor: 1234|"> 1234"
# String, name of the kernel driver module for the device.
driver: noveau
Added in version 1.29.
Examples:
# Request a guest with a Thunderbolt controller
device:
device-name: "~ Intel Corporation .* Thunderbolt 3"
driver: thunderbolt
Status: idea
disk
Select or provision a guest with a given disk storage.
# A list of dictionaries, each describing one disk storage.
disk:
# Number or string, the amount of storage requested.
# Bytes are assumed when no unit is specified.
- size: 1234|">= 512 GiB"
# String, disk model requested.
- model-name: "well-known disk model"
# String, disk driver requested.
- driver: "well-known disk driver"
# Number or string, logical sector size.
# Bytes are assumed when no unit is specified.
- logical-sector-size: 512|">= 512"
# Number or string, physical sector size.
# Bytes are assumed when no unit is specified.
- physical-sector-size: 4096|">= 4096"
The Guest Topology Format may include the following fields in its description of the actual guest hardware:
# String, path to the block device representing this disk.
block-device: "/dev/vda"
Changed in version 1.32: Added driver and model-name into specification.
Changed in version 1.34: Added block-device
into specification.
Examples:
# Require a disk big enough for testing
disk:
- size: 500 GB
# Require a disk with specified model
disk:
- model-name: 'PERC H310'
# Require a disk with specified driver
disk:
- driver: mpt3sas
# Multiple disks can be requested as well
disk:
- size: '>= 2 GB'
- model-name: 'PERC H310'
- driver: '~ sas.*'
# Guest topology exposing details about the actual disks
disk:
- size: 21474836480
model-name: PERC H310
driver: megaraid_sas
block-device: /dev/sda
logical-sector-size: "512 byte"
- size: 21474836480
model-name: PERC H310
driver: megaraid_sas
block-device: /dev/sdb
physical-sector-size: "4096 byte"
Status: implemented
Implemented by provision/artemis (
size
andmodel-name
only)Implemented by provision/beaker (
block-device
not implemented yet)Implemented by provision/virtual (
size
only with=
,>=
and<=
operators only)
gpu
Select or provision a guest with a given GPU properties.
Note
This is a draft, the story is not implemented yet.
gpu:
# String, a network device name.
device-name: "A Generic Graphics Card"
# Number or string, a network device ID.
device: 1234|"> 1234"
# String, a name of the device vendor.
vendor-name: "A Well-Known GPU Manufacturer"
# Number or string, an ID of the device vendor.
vendor: 1234|"> 1234"
# String, name of the kernel driver module for the device.
driver: a_generic_vga_driver
Added in version 1.29.
Examples:
# Request a guest with particular GPU
gpu:
# By the device name...
device-name: C51 [GeForce 6150 LE]
# ... or by its ID.
device: 0241
driver: nouveau
# Request a guest with any NVIDIA GPU
gpu:
vendor-name: NVIDIA
Status: idea
hostname
Select a guest with a specific hostname.
# String, the hostname requested.
hostname: foo.bar.com
Examples:
# Choose machine with given hostname
hostname: kvm-01.lab.us-east-2.company.com
# Hostname matching a regular expression
hostname: "~ kvm-01.*"
# Hostname not matching a regular expression
hostname: "!~ kvm-01.*"
Status: implemented
Implemented by provision/artemis
Implemented by provision/beaker
iommu
Select or provision a guest with the Input–output memory management unit.
iommu:
# Boolean, whether the guest supports IOMMU
is-supported: true|false
# String, the model name for IOMMU
model-name: "virtio"|"intel"|"smmuv3"|...
Added in version 1.37.
Changed in version 1.37: beaker
plugin supports iommu
Examples:
# Require a guest that supports IOMMU
iommu:
is-supported: true
# Require a guest with the IOMMU of virtio model
iommu:
is-supported: true
model-name: virtio
Status: implemented
Implemented by provision/beaker (
iommu.is-supported
only)
location
Select or provision a guest from a particular location.
location:
# String, which labcontroller to use or to avoid.
# Note: this field is consumed by Beaker and Artemis plugins only.
lab-controller: "lab-01.foo.bar.com"
Changed in version 1.35: beaker
plugin supports location.lab-controller
Changed in version 1.33: Added location.lab-controller
into specification.
Examples:
# Select a system that is not managed lab-01.foo.bar.com lab controller
location:
lab-controller: "!= lab-01.foo.bar.com"
Status: implemented
Implemented by provision/beaker (
==
and!=
operators only)
memory
Select or provision a guest with the desired amount of memory.
# Number or string, the amount of memory requested.
# Bytes are assumed when no unit is specified.
memory: 1234|"2 GiB"
Examples:
# Require an exact amount of memory
memory: 8 GB
# Pick a guest with at least 8 GB
memory: ">= 8 GB"
Status: implemented
Implemented by provision/artemis
Implemented by provision/beaker
Implemented by provision/virtual (
=
,>=
and<=
operators only)
network
Select or provision a guest with given network devices.
# A list of dictionaries, each describing one network device.
network:
# String, a network device type.
- type: "eth"|"bridge"|"ipip"|...
# String, a network device name.
device-name: "A Generic Ethernet Card"
# Number or string, a network device ID.
device: 1234|"> 1234"
# String, a name of the device vendor.
vendor-name: "A Well-Known Device Manufacturer"
# Number or string, an ID of the device vendor.
vendor: 1234|"> 1234"
# String, name of the kernel driver module for the device.
driver: a_generic_nic_driver
Changed in version 1.29: Added missing device
and vendor
into specification.
Examples:
# Select by vendor and device name
network:
- type: eth
vendor-name: ~ ^Broadcom
device-name: ~ ^NetXtreme II BCM
Status: implemented
Implemented by provision/artemis (
network.type
only,network.type: eth
only)
system
Select or provision a guest with given system properties.
system:
# Number or string, an ID of the device vendor.
vendor: 1234|"> 1234"
# String, a name of the device vendor.
vendor-name: "A Well-Known Device Manufacturer"
# Integer or string, system model ID.
model: 1234|"> 1234"
# String, system model name.
model-name: ProLiant DL385 Gen10
# Integer or string, required number of NUMA nodes.
numa-nodes: 2|">= 2"
Changed in version 1.39: beaker
plugin supports vendor-name
Changed in version 1.38: beaker
plugin supports model-name
Examples:
# Select any system by a given vendor
system:
vendor-name: "~ HPE"
# Select any system by a given model name
system:
model-name: "~ PowerEdge R750"
# Select any HPE system with enough NUMA nodes.
system:
vendor-name: "~ HPE"
numa-nodes: ">= 4"
Status: implemented
Implemented by provision/beaker (
system.vendor
andsystem.model
not implemented yet)
tpm
Select or provision a guest with the Trusted Platform Module.
tpm:
# String, TPM version requested.
version: "x.y"
Changed in version 1.32: virtual
plugin supports tpm.version
Examples:
# Require a presence of TPM of a specific version.
tpm:
version: "2.0"
Status: implemented
Implemented by provision/artemis
Implemented by provision/beaker
Implemented by provision/virtual (
version: 2.0
only)
virtualization
Select or provision a guest with requested virtualization properties.
Changed in version 1.33: beaker
plugin supports virtualization.hypervisor
Changed in version 1.31: beaker
plugin supports virtualization.is-virtualized
virtualization:
# String, any of well-known hypervisor names.
hypervisor: "hyperv"|"powerkvm"|"kvm"|"xen"|"nitro"|...
# Boolean, whether the guest itself is virtualized or not.
is-virtualized: true|false
# Boolean, whether the guest supports hardware-assisted
# virtualization.
is-supported: true|false
Examples:
# Require a guest which supports virtualization
virtualization:
is-supported: true
# Require a bare-metal guest
virtualization:
is-virtualized: false
# Ask for a virtualized guest on top of a kvm hypervisor
virtualization:
is-virtualized: true
hypervisor: kvm
Status: implemented
Implemented by provision/artemis
Implemented by provision/beaker (
virtualization.is-virtualized
andvirtualization.hypervisor
only)
zcrypt
Select or provision a guest with the System z cryptographic adapter.
zcrypt:
# String, adapter requested.
adapter: "x"
# String, mode requested.
mode: "y"
Added in version 1.31.
Changed in version 1.32: beaker
plugin supports zcrypt
Examples:
# Require a presence of CEX8C adapter in the CCA mode
zcrypt:
adapter: "CEX8C"
mode: "CCA"
Status: implemented
Implemented by provision/beaker
Implemented by provision/artemis