setup: deal with btrfs subvolumes when checking mapped storage
When the container storage is checked it may come from a btrfs subvolume. In /proc/self/mountinfo this looks like: ``` 1364 1345 0:33 /root/var/lib/containers/storage /var/lib/containers/storage rw,relatime - btrfs /dev/mapper/luks-1356123c-c7b9-1bd7-a8bf-e13d4cbb5500 rw,seclabel,compress=zstd:1,ssd,discard=async,space_cache,subvolid=257,subvol=/root ``` as a quick fix just compare the suffix of the root instead of the full path. Thanks for Ondrej!
This commit is contained in:
parent
280f7626d5
commit
2f0d81288a
3 changed files with 123 additions and 7 deletions
13
bib/internal/setup/export_test.go
Normal file
13
bib/internal/setup/export_test.go
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package setup
|
||||
|
||||
var (
|
||||
ValidateHasContainerStorageMountedFromReader = validateHasContainerStorageMountedFromReader
|
||||
)
|
||||
|
||||
func MockInsideContainer(f func() (bool, error)) (restore func()) {
|
||||
saved := insideContainer
|
||||
insideContainer = f
|
||||
return func() {
|
||||
insideContainer = saved
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,11 @@ package setup
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/sys/mountinfo"
|
||||
"golang.org/x/sys/unix"
|
||||
|
|
@ -100,23 +102,43 @@ func Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidateHasContainerStorageMounted checks that the container storage
|
||||
// is mounted inside the container
|
||||
func ValidateHasContainerStorageMounted() error {
|
||||
var insideContainer = func() (bool, error) {
|
||||
if err := exec.Command("systemd-detect-virt", "-c").Run(); err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
// not running in a container, just exit
|
||||
if exitErr.ExitCode() == 1 {
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ValidateHasContainerStorageMounted checks that the container storage
|
||||
// is mounted inside the container
|
||||
func ValidateHasContainerStorageMounted() error {
|
||||
inside, err := insideContainer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if inside {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.Open("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return validateHasContainerStorageMountedFromReader(f)
|
||||
}
|
||||
|
||||
func validateHasContainerStorageMountedFromReader(r io.Reader) error {
|
||||
containersStorage := "/var/lib/containers/storage"
|
||||
containerStorageMountFound := false
|
||||
|
||||
mnts, err := mountinfo.GetMounts(nil)
|
||||
mnts, err := mountinfo.GetMountsFromReader(r, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -125,8 +147,10 @@ func ValidateHasContainerStorageMounted() error {
|
|||
continue
|
||||
}
|
||||
containerStorageMountFound = true
|
||||
if mnt.Root != containersStorage {
|
||||
return fmt.Errorf("not the host /var/lib/storage/containers but %q", mnt.Root)
|
||||
// on btrfs the containers storage might be on a subvolume
|
||||
// so we just compare the final part of the path
|
||||
if !strings.HasSuffix(mnt.Root, containersStorage) {
|
||||
return fmt.Errorf("cannot find suffix %q in mounted %q", containersStorage, mnt.Root)
|
||||
}
|
||||
}
|
||||
if !containerStorageMountFound {
|
||||
|
|
|
|||
79
bib/internal/setup/setup_test.go
Normal file
79
bib/internal/setup/setup_test.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package setup_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/osbuild/bootc-image-builder/bib/internal/setup"
|
||||
)
|
||||
|
||||
var (
|
||||
procSelfMountinfoBtrfs = `1345 1307 0:92 / / rw,relatime - overlay overlay rw,context="system_u:object_r:container_file_t:s0:c98,c684",lowerdir=/var/lib/containers/storage/overlay/l/T4G5ED56VRUEC2ID7JMJSGW3QT:/var/lib/containers/storage/overlay/l/KZGLWVLLUSCKZYWV57JF6WSK2I:/var/lib/containers/storage/overlay/l/HXWMTP6IYXVK4KUZ2UCSNJXOIW:/var/lib/containers/storage/overlay/l/YLBHA4OHH25PNVUIUV7LKJA67Q:/var/lib/containers/storage/overlay/l/7IH6AODKJYPJSHYY3KTKRAGDZO:/var/lib/containers/storage/overlay/l/EELW6SDH3FRQMJJEGMTWJ223DL:/var/lib/containers/storage/overlay/l/GNKPUG6OGVJANN4MB447IM4JK7,upperdir=/var/lib/containers/storage/overlay/f2d065994b6e5d208732fc71a7421f882a6b2f73809bcc210a00d4c49309c10f/diff,workdir=/var/lib/containers/storage/overlay/f2d065994b6e5d208732fc71a7421f882a6b2f73809bcc210a00d4c49309c10f/work,redirect_dir=on,uuid=on,metacopy=on,volatile
|
||||
1346 1345 0:96 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw,seclabel
|
||||
1348 1345 0:97 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
|
||||
1349 1345 0:99 / /dev rw,nosuid - tmpfs tmpfs rw,context="system_u:object_r:container_file_t:s0:c98,c684",size=65536k,mode=755,inode64
|
||||
1352 1349 0:100 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,context="system_u:object_r:container_file_t:s0:c98,c684",gid=5,mode=620,ptmxmode=666
|
||||
1361 1349 0:85 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,context="system_u:object_r:container_file_t:s0:c98,c684",size=64000k,inode64
|
||||
1363 1346 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw,seclabel,nsdelegate,memory_recursiveprot
|
||||
1364 1345 0:33 /root/var/lib/containers/storage /var/lib/containers/storage rw,relatime - btrfs /dev/mapper/luks-12345678-1234-1234-1234-123456789012 rw,seclabel,compress=zstd:1,ssd,discard=async,space_cache,subvolid=257,subvol=/root
|
||||
1365 1364 0:33 /root/var/lib/containers/storage/overlay /var/lib/containers/storage/overlay rw,relatime - btrfs /dev/mapper/luks-12345678-1234-1234-1234-123456789012 rw,seclabel,compress=zstd:1,ssd,discard=async,space_cache,subvolid=257,subvol=/root
|
||||
`
|
||||
procSelfMountinfoWithVolume = `735 665 0:83 / / rw,relatime - overlay overlay rw,lowerdir=/var/lib/containers/storage/overlay/l/2BFF257G6Q5T5OWGW4JVUDTM3R:/var/lib/containers/storage/overlay/l/AEC37A7HVU4SH5Q4GWQLB7KCZU:/var/lib/containers/storage/overlay/l/JFOUQY5ZWN3DIZQP22SYYLXEV7,upperdir=/var/lib/containers/storage/overlay/d545c8ca670b6820eae79e43836175558d71f9f927fb68feffa608a2b3020f09/diff,workdir=/var/lib/containers/storage/overlay/d545c8ca670b6820eae79e43836175558d71f9f927fb68feffa608a2b3020f09/work,uuid=on,volatile
|
||||
736 735 259:2 /var/lib/containers/storage/volumes/e14ef96e3db8bdc3dcdbd340208995e6770cd7873f78788e737c8b7b5d17fdaa/_data /output rw,nosuid,nodev,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
737 735 0:86 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
|
||||
738 735 0:87 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
|
||||
741 735 0:88 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
|
||||
742 738 0:89 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
|
||||
743 738 0:85 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
|
||||
744 735 0:24 /containers/storage/overlay-containers/5e5914d9351994648b28b8b58ba3c67ce06a48ccdd3a52679b82ae4dc693fa53/userdata/.containerenv /run/.containerenv rw,relatime - tmpfs tmpfs rw,size=3262508k,mode=755,inode64
|
||||
745 735 0:24 /containers/storage/overlay-containers/5e5914d9351994648b28b8b58ba3c67ce06a48ccdd3a52679b82ae4dc693fa53/userdata/hostname /etc/hostname rw,relatime - tmpfs tmpfs rw,size=3262508k,mode=755,inode64
|
||||
746 735 0:24 /containers/storage/overlay-containers/5e5914d9351994648b28b8b58ba3c67ce06a48ccdd3a52679b82ae4dc693fa53/userdata/resolv.conf /etc/resolv.conf rw,relatime - tmpfs tmpfs rw,size=3262508k,mode=755,inode64
|
||||
747 735 0:24 /containers/storage/overlay-containers/5e5914d9351994648b28b8b58ba3c67ce06a48ccdd3a52679b82ae4dc693fa53/userdata/hosts /etc/hosts rw,relatime - tmpfs tmpfs rw,size=3262508k,mode=755,inode64
|
||||
748 738 0:82 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=64000k,inode64
|
||||
749 741 0:28 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw,nsdelegate,memory_recursiveprot
|
||||
750 735 259:2 /var/lib/containers/storage /var/lib/containers/storage rw,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
751 750 259:2 /var/lib/containers/storage/overlay /var/lib/containers/storage/overlay rw,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
`
|
||||
|
||||
procSelfMountinfoNoVolume = `736 735 259:2 /var/lib/containers/storage/volumes/5c45612492556520d9549b3ee24d6a11ac3a0e9266c0900bf427a3bdaafadeb8/_data /rpmmd rw,nosuid,nodev,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
737 735 259:2 /var/lib/containers/storage/volumes/e17849f054757adebabc844a1fd510308a1c22b6668526e84511a8dfd617aec8/_data /output rw,nosuid,nodev,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
738 735 0:86 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
|
||||
739 735 259:2 /var/lib/containers/storage/volumes/8b15ab68602eaee4923cfddd7c0cbb19d7d33190c9d2f97adeea357370f5ba3b/_data /store rw,nosuid,nodev,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
740 735 0:87 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw
|
||||
741 735 0:88 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,inode64
|
||||
742 741 0:85 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
|
||||
743 741 0:89 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
|
||||
745 741 0:82 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=64000k,inode64
|
||||
750 735 259:2 /var/lib/containers/storage/volumes/8612bf74115e4610cf4a57da8a0209fa07d1782584752bf4a1991d773f9c608f/_data /var/lib/containers/storage rw,nosuid,nodev,relatime - ext4 /dev/nvme0n1p2 rw,errors=remount-ro
|
||||
666 741 0:89 /0 /dev/console rw,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666
|
||||
`
|
||||
)
|
||||
|
||||
func TestValidateHasContainerStorageMountedBtrfs(t *testing.T) {
|
||||
restore := setup.MockInsideContainer(func() (bool, error) {
|
||||
return true, nil
|
||||
})
|
||||
defer restore()
|
||||
|
||||
for _, tc := range []struct {
|
||||
fakeMountinfo string
|
||||
expectedErr string
|
||||
}{
|
||||
// good
|
||||
{procSelfMountinfoBtrfs, ""},
|
||||
{procSelfMountinfoWithVolume, ""},
|
||||
// bad
|
||||
{procSelfMountinfoNoVolume, `cannot find suffix "/var/lib/containers/storage" in mounted "/var/lib/containers/storage/volumes/8612bf74115e4610cf4a57da8a0209fa07d1782584752bf4a1991d773f9c608f/_data"`},
|
||||
} {
|
||||
buf := bytes.NewBufferString(tc.fakeMountinfo)
|
||||
err := setup.ValidateHasContainerStorageMountedFromReader(buf)
|
||||
if tc.expectedErr == "" {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, tc.expectedErr, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue