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:
|
extraArgs:
|
||||||
- --iface-can-reach=192.168.1.1
|
- --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]
|
[make_deps]
|
||||||
|
@ -816,7 +816,7 @@ func MountUserDisks(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return mountDisks(r)
|
return mountDisks(logger, r)
|
||||||
}, "mountUserDisks"
|
}, "mountUserDisks"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -838,6 +838,12 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deviceName := bd.Device().Name()
|
||||||
|
|
||||||
|
if disk.Device() != deviceName {
|
||||||
|
logger.Printf("using device name %q instead of %q", deviceName, disk.Device())
|
||||||
|
}
|
||||||
|
|
||||||
//nolint:errcheck
|
//nolint:errcheck
|
||||||
defer bd.Close()
|
defer bd.Close()
|
||||||
|
|
||||||
@ -857,21 +863,21 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
|||||||
|
|
||||||
if pt != nil {
|
if pt != nil {
|
||||||
if len(pt.Partitions().Items()) > 0 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Devices[disk.Device()] = installer.Device{
|
m.Devices[deviceName] = installer.Device{
|
||||||
Device: disk.Device(),
|
Device: deviceName,
|
||||||
ResetPartitionTable: true,
|
ResetPartitionTable: true,
|
||||||
SkipOverlayMountsCheck: true,
|
SkipOverlayMountsCheck: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, part := range disk.Partitions() {
|
for _, part := range disk.Partitions() {
|
||||||
extraTarget := &installer.Target{
|
extraTarget := &installer.Target{
|
||||||
Device: disk.Device(),
|
Device: deviceName,
|
||||||
FormatOptions: &partition.FormatOptions{
|
FormatOptions: &partition.FormatOptions{
|
||||||
Force: true,
|
Force: true,
|
||||||
FileSystemType: partition.FilesystemTypeXFS,
|
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
|
return nil
|
||||||
@ -894,14 +900,29 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error {
|
|||||||
return m.Execute()
|
return m.Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
func mountDisks(r runtime.Runtime) (err error) {
|
func mountDisks(logger *log.Logger, r runtime.Runtime) (err error) {
|
||||||
mountpoints := mount.NewMountPoints()
|
mountpoints := mount.NewMountPoints()
|
||||||
|
|
||||||
for _, disk := range r.Config().Machine().Disks() {
|
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() {
|
for i, part := range disk.Partitions() {
|
||||||
var partname string
|
var partname string
|
||||||
|
|
||||||
partname, err = util.PartPath(disk.Device(), i+1)
|
partname, err = util.PartPath(deviceName, i+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1137,10 +1158,25 @@ func UnmountUserDisks(runtime.Sequence, any) (runtime.TaskExecutionFunc, string)
|
|||||||
mountpoints := mount.NewMountPoints()
|
mountpoints := mount.NewMountPoints()
|
||||||
|
|
||||||
for _, disk := range r.Config().Machine().Disks() {
|
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() {
|
for i, part := range disk.Partitions() {
|
||||||
var partname string
|
var partname string
|
||||||
|
|
||||||
partname, err = util.PartPath(disk.Device(), i+1)
|
partname, err = util.PartPath(deviceName, i+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -279,8 +279,14 @@ func launchVM(config *LaunchConfig) error {
|
|||||||
"virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
|
"virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, disk := range config.DiskPaths {
|
for i, disk := range config.DiskPaths {
|
||||||
args = append(args, "-drive", fmt.Sprintf("format=raw,if=virtio,file=%s,cache=unsafe", disk))
|
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
|
machineArg := config.MachineType
|
||||||
|
@ -14,24 +14,11 @@ import (
|
|||||||
|
|
||||||
// UserDiskName returns disk device path.
|
// UserDiskName returns disk device path.
|
||||||
func (p *Provisioner) UserDiskName(index int) string {
|
func (p *Provisioner) UserDiskName(index int) string {
|
||||||
res := "/dev/vd"
|
// the disk IDs are assigned in the following way:
|
||||||
|
// * ata-QEMU_HARDDISK_QM00001
|
||||||
var convert func(i int) string
|
// * ata-QEMU_HARDDISK_QM00003
|
||||||
|
// * ata-QEMU_HARDDISK_QM00005
|
||||||
convert = func(i int) string {
|
return fmt.Sprintf("/dev/disk/by-id/ata-QEMU_HARDDISK_QM%05d", (index-1)*2+1)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDisks creates empty disk files for each disk.
|
// CreateDisks creates empty disk files for each disk.
|
||||||
|
Loading…
Reference in New Issue
Block a user