fix: support user disks via symlinks
The core blockdevice library already supported resolving symlinks, we just need to get the raw block device name from it, and use it afterwards. In QEMU provisioner, leave the first (system) disk as virtio (for performance), and mount user disks as 'ata', which allows `udevd` to pick up the disk IDs (not available for `virtio`), and use the symlink path in the tests. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
4f195dd271
commit
270604bead
@ -128,6 +128,12 @@ cluster:
|
||||
extraArgs:
|
||||
- --iface-can-reach=192.168.1.1
|
||||
```
|
||||
"""
|
||||
|
||||
[notes.user-disks]
|
||||
title = "User Disks"
|
||||
description = """\
|
||||
Talos Linux now supports specifying user disks in `.machine.disks` machine configuration links via `udev` symlinks, e.g. `/dev/disk/by-id/XXXX`.
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
@ -816,7 +816,7 @@ func MountUserDisks(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
|
||||
return err
|
||||
}
|
||||
|
||||
return mountDisks(r)
|
||||
return mountDisks(logger, r)
|
||||
}, "mountUserDisks"
|
||||
}
|
||||
|
||||
@ -838,6 +838,12 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
||||
return err
|
||||
}
|
||||
|
||||
deviceName := bd.Device().Name()
|
||||
|
||||
if disk.Device() != deviceName {
|
||||
logger.Printf("using device name %q instead of %q", deviceName, disk.Device())
|
||||
}
|
||||
|
||||
//nolint:errcheck
|
||||
defer bd.Close()
|
||||
|
||||
@ -857,21 +863,21 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
||||
|
||||
if pt != nil {
|
||||
if len(pt.Partitions().Items()) > 0 {
|
||||
logger.Printf(("skipping setup of %q, found existing partitions"), disk.Device())
|
||||
logger.Printf(("skipping setup of %q, found existing partitions"), deviceName)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
m.Devices[disk.Device()] = installer.Device{
|
||||
Device: disk.Device(),
|
||||
m.Devices[deviceName] = installer.Device{
|
||||
Device: deviceName,
|
||||
ResetPartitionTable: true,
|
||||
SkipOverlayMountsCheck: true,
|
||||
}
|
||||
|
||||
for _, part := range disk.Partitions() {
|
||||
extraTarget := &installer.Target{
|
||||
Device: disk.Device(),
|
||||
Device: deviceName,
|
||||
FormatOptions: &partition.FormatOptions{
|
||||
Force: true,
|
||||
FileSystemType: partition.FilesystemTypeXFS,
|
||||
@ -882,7 +888,7 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
||||
},
|
||||
}
|
||||
|
||||
m.Targets[disk.Device()] = append(m.Targets[disk.Device()], extraTarget)
|
||||
m.Targets[deviceName] = append(m.Targets[deviceName], extraTarget)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -894,14 +900,29 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
||||
return m.Execute()
|
||||
}
|
||||
|
||||
func mountDisks(r runtime.Runtime) (err error) {
|
||||
func mountDisks(logger *log.Logger, r runtime.Runtime) (err error) {
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
for _, disk := range r.Config().Machine().Disks() {
|
||||
bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deviceName := bd.Device().Name()
|
||||
|
||||
if disk.Device() != deviceName {
|
||||
logger.Printf("using device name %q instead of %q", deviceName, disk.Device())
|
||||
}
|
||||
|
||||
if err = bd.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, part := range disk.Partitions() {
|
||||
var partname string
|
||||
|
||||
partname, err = util.PartPath(disk.Device(), i+1)
|
||||
partname, err = util.PartPath(deviceName, i+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1137,10 +1158,25 @@ func UnmountUserDisks(runtime.Sequence, any) (runtime.TaskExecutionFunc, string)
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
for _, disk := range r.Config().Machine().Disks() {
|
||||
bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deviceName := bd.Device().Name()
|
||||
|
||||
if deviceName != disk.Device() {
|
||||
logger.Printf("using device name %q instead of %q", deviceName, disk.Device())
|
||||
}
|
||||
|
||||
if err = bd.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, part := range disk.Partitions() {
|
||||
var partname string
|
||||
|
||||
partname, err = util.PartPath(disk.Device(), i+1)
|
||||
partname, err = util.PartPath(deviceName, i+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -279,8 +279,14 @@ func launchVM(config *LaunchConfig) error {
|
||||
"virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
|
||||
}
|
||||
|
||||
for _, disk := range config.DiskPaths {
|
||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=virtio,file=%s,cache=unsafe", disk))
|
||||
for i, disk := range config.DiskPaths {
|
||||
driver := "virtio"
|
||||
|
||||
if i > 0 {
|
||||
driver = "ide"
|
||||
}
|
||||
|
||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=%s,file=%s,cache=unsafe", driver, disk))
|
||||
}
|
||||
|
||||
machineArg := config.MachineType
|
||||
|
@ -14,24 +14,11 @@ import (
|
||||
|
||||
// UserDiskName returns disk device path.
|
||||
func (p *Provisioner) UserDiskName(index int) string {
|
||||
res := "/dev/vd"
|
||||
|
||||
var convert func(i int) string
|
||||
|
||||
convert = func(i int) string {
|
||||
remainder := i % 26
|
||||
divider := i / 26
|
||||
|
||||
prefix := ""
|
||||
|
||||
if divider != 0 {
|
||||
prefix = convert(divider - 1)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%s", prefix, string(rune('a'+remainder)))
|
||||
}
|
||||
|
||||
return res + convert(index)
|
||||
// the disk IDs are assigned in the following way:
|
||||
// * ata-QEMU_HARDDISK_QM00001
|
||||
// * ata-QEMU_HARDDISK_QM00003
|
||||
// * ata-QEMU_HARDDISK_QM00005
|
||||
return fmt.Sprintf("/dev/disk/by-id/ata-QEMU_HARDDISK_QM%05d", (index-1)*2+1)
|
||||
}
|
||||
|
||||
// CreateDisks creates empty disk files for each disk.
|
||||
|
Loading…
Reference in New Issue
Block a user