From 3130c956724cc40d9b860de603eea384555feb38 Mon Sep 17 00:00:00 2001 From: Stefan Catargiu <13122921+5kt@users.noreply.github.com> Date: Tue, 4 Mar 2025 05:08:28 +0000 Subject: [PATCH] Add root-hints to hack --- hack/root-hints/README.md | 118 ++++++++++++++++++++++++++++++++++ hack/root-hints/root-hints.sh | 53 +++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 hack/root-hints/README.md create mode 100644 hack/root-hints/root-hints.sh diff --git a/hack/root-hints/README.md b/hack/root-hints/README.md new file mode 100644 index 00000000..2bb50671 --- /dev/null +++ b/hack/root-hints/README.md @@ -0,0 +1,118 @@ +## root-hints for deployments + +When installing/persisting the OS to disk, a method of selecting the +proper disk is needed. +This is needed because on servers with more than one disk, the order of the device nodes under /dev is arbitrary. +e.g. /dev/sda and /dev/sdb can inter-change on each boot of the server and point to the wrong disk device. + +With root-hints.sh we are proving a simple/small script that is going to be used with a set of roothints provided via a +yaml file in order to properly select the right device. + +This is nothing more than a way of constructing a filter for lsblk by leveraging scols-filter. + +This is supposed to be run inside the initrd together with the installer in order to choose the proper disk. +The actual root-hints.yaml should be provided via ignition. + +At the moment it can be used to filter on all colums provided by lsblk, but in the future this should be limited. +``` + ALIGNMENT alignment offset + ID-LINK the shortest udev /dev/disk/by-id link name + ID udev ID (based on ID-LINK) + DISC-ALN discard alignment offset + DAX dax-capable device + DISC-GRAN discard granularity, use if --bytes is given + DISK-SEQ disk sequence number + DISC-MAX discard max bytes, use if --bytes is given + DISC-ZERO discard zeroes data + FSAVAIL filesystem size available for unprivileged users, use if --bytes is given + FSROOTS mounted filesystem roots + FSSIZE filesystem size, use if --bytes is given + FSTYPE filesystem type + FSUSED filesystem size used, use if --bytes is given + FSUSE% filesystem use percentage + FSVER filesystem version + GROUP group name + HCTL Host:Channel:Target:Lun for SCSI + HOTPLUG removable or hotplug device (usb, pcmcia, ...) + KNAME internal kernel device name + LABEL filesystem LABEL + LOG-SEC logical sector size + MAJ:MIN major:minor device number + MAJ major device number + MIN minor device number + MIN-IO minimum I/O size + MODE device node permissions + MODEL device identifier + MQ device queues + NAME device name + OPT-IO optimal I/O size + OWNER user name + PARTFLAGS partition flags + PARTLABEL partition LABEL + PARTN partition number as read from the partition table + PARTTYPE partition type code or UUID +PARTTYPENAME partition type name + PARTUUID partition UUID + PATH path to the device node + PHY-SEC physical sector size + PKNAME internal parent kernel device name + PTTYPE partition table type + PTUUID partition table identifier (usually UUID) + RA read-ahead of the device + RAND adds randomness + REV device revision + RM removable device + RO read-only device + ROTA rotational device + RQ-SIZE request queue size + SCHED I/O scheduler name + SERIAL disk serial number + SIZE size of the device, use if --bytes is given + START partition start offset (in 512-byte sectors) + STATE state of the device + SUBSYSTEMS de-duplicated chain of subsystems + MOUNTPOINT where the device is mounted + MOUNTPOINTS all locations where device is mounted + TRAN device transport type + TYPE device type + UUID filesystem UUID + VENDOR device vendor + WSAME write same max bytes, use if --bytes is given + WWN unique storage identifier + ZONED zone model + ZONE-SZ zone size, use if --bytes is given + ZONE-WGRAN zone write granularity, use if --bytes is given + ZONE-APP zone append max bytes, use if --bytes is given + ZONE-NR number of zones + ZONE-OMAX maximum number of open zones + ZONE-AMAX maximum number of active zones + ``` + +The following operators can be used, as supported by scols-filter. +``` +expr == expr | expr EQ expr +expr != expr | expr NE expr +expr >= expr | expr GE expr +expr <= expr | expr LE expr +expr > expr | expr GT expr +expr < expr | expr LT expr +expr =~ string +expr !~ string +``` + +root-hints.yaml example: +``` +size: lt 13T +size: gt 500G +``` +this is providing the filters to select the disks with a size greater than 500GB AND less than 13TB. + +How to use: +```shell +./root-hints.sh hints.yaml +sda +``` + +Nota bene: +When using this mechanism to filter the disks, some extra logic should be used with the installer/any other way of +persisting the data that only one device is selected, otherwise the filter is not specific enough. diff --git a/hack/root-hints/root-hints.sh b/hack/root-hints/root-hints.sh new file mode 100644 index 00000000..1b51eb85 --- /dev/null +++ b/hack/root-hints/root-hints.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +set -eu + +function err() { + echo "$@" 1>&2 +} + +function filter() { + col=$(echo "$1" | cut -d: -f1) + f=$(echo "$1" | cut -d: -f2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' ) + r="([a-zA-Z0-9-]+) ([a-zA-Z0-9-]+)" + if [[ $f =~ $r ]]; then + op="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + else + op="eq" + val="$f" + fi + if [ "$op" == "re" ]; then + op="=~" + fi + if [[ $val =~ ^[0-9]+[KMGT]+$ ]]; then + val=$(echo "$val" | numfmt --from=iec) + echo "and ${col^^} $op ${val}" + else + echo "and ${col^^} $op \"${val}\"" + fi + +} + +yamlFile="$1" + +# validate yaml + +#if ! yq . "$yamlFile" &> /dev/null; then +# err "invalid yaml file provided, exiting" +# exit 1 +#fi + +#if dev=$(yq -e .dev "$yamlFile" 2> /dev/null); then +# echo "$dev" +# exit 0 +#fi + +flsblk="TYPE eq \"disk\"" +while IFS= read -r r; do + f=$(filter "$r") + flsblk="$flsblk $f" +done < <(cat "$yamlFile") + +#echo "$flsblk" +lsblk --filter "$flsblk" --noheadings -o kname