Release URBM 2026.06.15.r007

This commit is contained in:
Mikei386
2026-06-15 07:14:24 +02:00
parent 706f8b997b
commit b0fa11a40a
14 changed files with 214 additions and 13 deletions
+54 -1
View File
@@ -14,7 +14,12 @@ import (
"git.casaderoll.de/michael/urbm/internal/model"
)
type WorkloadManager struct{ RuntimeDir string }
type WorkloadManager struct {
RuntimeDir string
FindmntPath string
LsblkPath string
Stat func(string) (os.FileInfo, error)
}
type Workload struct {
ID string `json:"id"`
@@ -149,6 +154,54 @@ func (w *WorkloadManager) Prepare(ctx context.Context, job model.Job) (Prepared,
return prepared, nil
}
func (w *WorkloadManager) FlashDevice(ctx context.Context) (string, error) {
findmnt := w.FindmntPath
if findmnt == "" {
findmnt = "findmnt"
}
output, err := exec.CommandContext(ctx, findmnt, "--noheadings", "--output", "SOURCE", "--target", "/boot").Output()
if err != nil {
return "", fmt.Errorf("source: determine USB flash partition: %w", err)
}
partition := strings.TrimSpace(string(output))
if index := strings.IndexByte(partition, '['); index >= 0 {
partition = partition[:index]
}
partition = filepath.Clean(partition)
if !strings.HasPrefix(partition, "/dev/") || strings.ContainsAny(partition, "\r\n\x00") {
return "", fmt.Errorf("source: /boot is not backed by a device: %q", partition)
}
lsblk := w.LsblkPath
if lsblk == "" {
lsblk = "lsblk"
}
output, err = exec.CommandContext(ctx, lsblk, "--noheadings", "--output", "PKNAME", "--", partition).Output()
if err != nil {
return "", fmt.Errorf("source: determine USB flash device for %s: %w", partition, err)
}
parent := strings.TrimSpace(string(output))
device := partition
if parent != "" {
if strings.ContainsAny(parent, "/\r\n\x00") {
return "", fmt.Errorf("source: invalid USB flash parent device %q", parent)
}
device = filepath.Join("/dev", parent)
}
stat := w.Stat
if stat == nil {
stat = os.Stat
}
info, err := stat(device)
if err != nil {
return "", fmt.Errorf("source: access USB flash device %s: %w", device, err)
}
if info.Mode()&os.ModeDevice == 0 {
return "", fmt.Errorf("source: USB flash source %s is not a block device", device)
}
return device, nil
}
func (w *WorkloadManager) Cleanup(ctx context.Context, prepared Prepared) error {
var first error
for i := len(prepared.Stopped) - 1; i >= 0; i-- {
+40
View File
@@ -1,11 +1,22 @@
package platform
import (
"context"
"os"
"path/filepath"
"testing"
"time"
)
type blockDeviceInfo struct{ name string }
func (i blockDeviceInfo) Name() string { return i.name }
func (blockDeviceInfo) Size() int64 { return 0 }
func (blockDeviceInfo) Mode() os.FileMode { return os.ModeDevice }
func (blockDeviceInfo) ModTime() time.Time { return time.Time{} }
func (blockDeviceInfo) IsDir() bool { return false }
func (blockDeviceInfo) Sys() any { return nil }
func TestUnraidServiceEnabled(t *testing.T) {
path := filepath.Join(t.TempDir(), "domain.cfg")
for _, test := range []struct {
@@ -24,3 +35,32 @@ func TestUnraidServiceEnabled(t *testing.T) {
}
}
}
func TestFlashDeviceResolvesWholeDiskBehindBootPartition(t *testing.T) {
dir := t.TempDir()
findmnt := filepath.Join(dir, "findmnt")
lsblk := filepath.Join(dir, "lsblk")
if err := os.WriteFile(findmnt, []byte("#!/bin/sh\nprintf '/dev/sda1\\n'\n"), 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(lsblk, []byte("#!/bin/sh\nprintf 'sda\\n'\n"), 0700); err != nil {
t.Fatal(err)
}
w := &WorkloadManager{
FindmntPath: findmnt,
LsblkPath: lsblk,
Stat: func(path string) (os.FileInfo, error) {
if path != "/dev/sda" {
t.Fatalf("stat path = %q", path)
}
return blockDeviceInfo{name: "sda"}, nil
},
}
device, err := w.FlashDevice(context.Background())
if err != nil {
t.Fatal(err)
}
if device != "/dev/sda" {
t.Fatalf("device = %q", device)
}
}