diff --git a/hack/release.toml b/hack/release.toml index 03e397e9f5..c09930ddc4 100644 --- a/hack/release.toml +++ b/hack/release.toml @@ -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] diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index d91abdaf8f..d9f4b2ca49 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -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 } diff --git a/pkg/provision/providers/qemu/launch.go b/pkg/provision/providers/qemu/launch.go index de8f01e4be..1671b73a4b 100644 --- a/pkg/provision/providers/qemu/launch.go +++ b/pkg/provision/providers/qemu/launch.go @@ -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 diff --git a/pkg/provision/providers/vm/disk.go b/pkg/provision/providers/vm/disk.go index 3838717b8b..f0bcc82f5d 100644 --- a/pkg/provision/providers/vm/disk.go +++ b/pkg/provision/providers/vm/disk.go @@ -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.