1
0
mirror of https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git synced 2026-06-21 00:07:16 +03:00

Merge branch 'lvm' into 'main'

add LVM support for root partition

See merge request alpine/cloud/tiny-cloud!146
This commit is contained in:
Leonardo Arena 2026-05-11 10:11:01 +00:00
commit 8fe26192c8
4 changed files with 120 additions and 8 deletions

View File

@ -49,6 +49,7 @@ IMDS data.
As Tiny Cloud is meant to be tiny, it has few dependencies:
* Busybox (`ash`, `wget`, etc.)
* `e2fsprogs-extra` (for `resize2fs`)
* `lvm2` (for resizing LVM volumes)
* `openssh-server`
* `partx`
* `sfdisk`

View File

@ -20,7 +20,7 @@
* Support for `#network-config`?
* Support LVM partitioning and non-`ext[234]` filesystems?
* Support non-`ext[234]` filesystems?
* Support other cloud providers...
* IBM

View File

@ -38,6 +38,7 @@ init__expand_root() {
local dev=$(awk '$2 == "/" {print $1}' "$PROC"/mounts 2>/dev/null)
local filesystem=$(awk '$2 == "/" {print $3}' "$PROC"/mounts 2>/dev/null)
local partition=$(cat "$SYS/class/block/${dev#/dev/}/partition" 2>/dev/null)
local is_lvm=0
# only support ext2/ext3/ext4 for now
case "$filesystem" in
@ -45,14 +46,53 @@ init__expand_root() {
*) return;;
esac
if [ -n "$partition" ]; then
# it's a partition, resize it
local volume=$(readlink -f "$SYS/class/block/${dev#/dev/}/..")
volume="/dev/${volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
$MOCK partx -u "$volume"
# check if this is an LVM logical volume
if [ -L "$dev" ] && readlink -f "$dev" | grep -q "/dev/mapper/"; then
is_lvm=1
elif echo "$dev" | grep -q "^/dev/mapper/"; then
is_lvm=1
elif echo "$dev" | grep -q "^/dev/[^/]*/[^/]*"; then
# format like /dev/vg/lv
is_lvm=1
fi
# resize filesystem
if [ "$is_lvm" -eq 1 ]; then
# LVM volume detected
# find the physical volume backing this LV
local vg_name=$(lvs --noheadings -o vg_name "$dev" 2>/dev/null | tr -d ' ')
local pv_dev=$(pvs --noheadings -o pv_name -S "vg_name=$vg_name" 2>/dev/null | tr -d ' ' | head -n1)
if [ -n "$pv_dev" ]; then
# get the partition number if PV is on a partition
local pv_partition=$(cat "$SYS/class/block/${pv_dev#/dev/}/partition" 2>/dev/null)
if [ -n "$pv_partition" ]; then
# resize the partition containing the PV
local pv_volume=$(readlink -f "$SYS/class/block/${pv_dev#/dev/}/..")
pv_volume="/dev/${pv_volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$pv_partition" "$pv_volume"
$MOCK partx -u "$pv_volume"
fi
# resize the physical volume
$MOCK pvresize "$pv_dev"
# extend the logical volume
# leave 15% for snapshots
$MOCK lvextend -l +85%VG "$dev"
fi
else
# standard partition handling (non-LVM)
if [ -n "$partition" ]; then
# it's a partition, resize it
local volume=$(readlink -f "$SYS/class/block/${dev#/dev/}/..")
volume="/dev/${volume##*/}"
echo ", +" | $MOCK sfdisk -q --no-reread -N "$partition" "$volume"
$MOCK partx -u "$volume"
fi
fi
# resize filesystem (common for both LVM and non-LVM)
if [ -e "$dev" ] || [ -n "$MOCK" ]; then
$MOCK resize2fs "$dev"
fi

View File

@ -11,6 +11,8 @@ lib="$srcdir"/lib/tiny-cloud/init
init_tests \
expand_root \
expand_root_partition \
expand_root_lvm_partition \
expand_root_lvm_whole_disk \
ethernets \
find_first_interface_up \
auto_detect_ethernet_interface \
@ -69,6 +71,75 @@ expand_root_partition_body() {
done
}
expand_root_lvm_partition_body() {
# Test LVM on a partition (e.g., /dev/sda2 -> PV -> VG -> LV)
mkdir -p proc sys/class/block \
sys/devices/pci0000:00/0000:00:05.0/virtio2/block/vda/vda2 \
sys/devices/pci0000:00/0000:00:05.0/virtio2/block/vda/device \
dev/mapper
ln -s ../../devices/pci0000:00/0000:00:05.0/virtio2/block/vda sys/class/block/vda
ln -s ../../devices/pci0000:00/0000:00:05.0/virtio2/block/vda/vda2 sys/class/block/vda2
echo 2 > sys/class/block/vda2/partition
# Create fake LVM device
mkdir -p sys/class/block/dm-0
ln -s /dev/mapper/vg0-root dev/mapper/vg0-root
# Mock LVM commands
fake_bin lvs <<-EOF
#!/bin/sh
echo " vg0"
EOF
fake_bin pvs <<-EOF
#!/bin/sh
echo " /dev/vda2"
EOF
echo "/dev/mapper/vg0-root / ext4 rw,noatime 0 0" > proc/mounts
for provider in $PROVIDERS; do
CLOUD="$provider" atf_check \
-o match:"sfdisk .*/dev/vda" \
-o match:"partx .*/dev/vda" \
-o match:"pvresize /dev/vda2" \
-o match:"lvextend -l \\+85%VG /dev/mapper/vg0-root" \
-o match:"resize2fs /dev/mapper/vg0-root" \
sh -c ". $lib; init__expand_root"
done
}
expand_root_lvm_whole_disk_body() {
# Test LVM on whole disk (e.g., /dev/sdb -> PV -> VG -> LV, no partition)
mkdir -p proc sys/class/block \
sys/devices/pci0000:00/0000:00:05.0/virtio3/block/vdb/device \
dev/mapper
ln -s ../../devices/pci0000:00/0000:00:05.0/virtio3/block/vdb sys/class/block/vdb
# Create fake LVM device
mkdir -p sys/class/block/dm-1
ln -s /dev/mapper/vg1-root dev/mapper/vg1-root
# Mock LVM commands - PV is on whole disk (no partition)
fake_bin lvs <<-EOF
#!/bin/sh
echo " vg1"
EOF
fake_bin pvs <<-EOF
#!/bin/sh
echo " /dev/vdb"
EOF
echo "/dev/mapper/vg1-root / ext4 rw,noatime 0 0" > proc/mounts
for provider in $PROVIDERS; do
CLOUD="$provider" atf_check \
-o match:"pvresize /dev/vdb" \
-o match:"lvextend -l \\+85%VG /dev/mapper/vg1-root" \
-o match:"resize2fs /dev/mapper/vg1-root" \
-o not-match:"sfdisk" \
-o not-match:"partx" \
sh -c ". $lib; init__expand_root"
done
}
ethernets_body() {
fake_interfaces lo br0 eth0 eth2 eth11