improvements
- Consolidate status reads - Pre-allocate descriptors - Add read_only disk label - Remove dead stdin field - Guard nil pool maps - Add error-path tests - Add go vet to flake
This commit is contained in:
@@ -48,7 +48,14 @@ func ParseBlockInfo(raw string) map[string]DiskInfo {
|
||||
blockID := match[2]
|
||||
diskPath := match[3]
|
||||
diskTypeAndMode := match[4]
|
||||
diskType := strings.Split(diskTypeAndMode, ", ")[0]
|
||||
modeParts := strings.Split(diskTypeAndMode, ", ")
|
||||
diskType := modeParts[0]
|
||||
readOnly := false
|
||||
for _, p := range modeParts[1:] {
|
||||
if p == "read-only" {
|
||||
readOnly = true
|
||||
}
|
||||
}
|
||||
|
||||
// Skip EFI disks
|
||||
if strings.Contains(diskName, "efidisk") {
|
||||
@@ -72,6 +79,10 @@ func ParseBlockInfo(raw string) map[string]DiskInfo {
|
||||
Labels: make(map[string]string),
|
||||
}
|
||||
|
||||
if readOnly {
|
||||
info.Labels["read_only"] = "true"
|
||||
}
|
||||
|
||||
// Detect disk type from path
|
||||
classifyDisk(&info)
|
||||
|
||||
|
||||
@@ -130,6 +130,51 @@ func TestHandleJSONPath_NoHostDevice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_ReadOnly(t *testing.T) {
|
||||
raw := `drive-scsi0 (#block100): /dev/zvol/rpool/data/vm-100-disk-0 (raw, read-only)
|
||||
`
|
||||
disks := ParseBlockInfo(raw)
|
||||
d := disks["scsi0"]
|
||||
if d.Labels["read_only"] != "true" {
|
||||
t.Errorf("expected read_only=true, got %q", d.Labels["read_only"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_ReadWrite(t *testing.T) {
|
||||
raw := `drive-scsi0 (#block100): /dev/zvol/rpool/data/vm-100-disk-0 (raw, read-write)
|
||||
`
|
||||
disks := ParseBlockInfo(raw)
|
||||
d := disks["scsi0"]
|
||||
if _, ok := d.Labels["read_only"]; ok {
|
||||
t.Error("read_only label should not be set for read-write disks")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_MalformedHeader(t *testing.T) {
|
||||
raw := `drive-scsi0: this is not a valid header
|
||||
`
|
||||
disks := ParseBlockInfo(raw)
|
||||
if len(disks) != 0 {
|
||||
t.Fatalf("expected 0 disks for malformed header, got %d", len(disks))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_Empty(t *testing.T) {
|
||||
disks := ParseBlockInfo("")
|
||||
if len(disks) != 0 {
|
||||
t.Fatalf("expected 0 disks for empty input, got %d", len(disks))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_JSONError(t *testing.T) {
|
||||
raw := `drive-scsi0 (#block100): json:{invalid json} (raw, read-write)
|
||||
`
|
||||
disks := ParseBlockInfo(raw)
|
||||
if len(disks) != 0 {
|
||||
t.Fatalf("expected 0 disks for invalid JSON path, got %d", len(disks))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBlockInfo_MultiDisk(t *testing.T) {
|
||||
raw := `drive-scsi0 (#block100): /dev/zvol/rpool/data/vm-100-disk-0 (raw, read-write)
|
||||
Attached to: /machine/peripheral/virtioscsi0/virtio-backend
|
||||
|
||||
@@ -63,3 +63,27 @@ func TestParseNetworkInfo_Empty(t *testing.T) {
|
||||
t.Fatalf("expected 0 NICs, got %d", len(nics))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNetworkInfo_MalformedLine(t *testing.T) {
|
||||
// Lines without colon-space or without "net" prefix should be skipped
|
||||
raw := "this is garbage\nnotnet0: index=0,type=tap\nno-colon-here\n"
|
||||
nics := ParseNetworkInfo(raw)
|
||||
if len(nics) != 0 {
|
||||
t.Fatalf("expected 0 NICs for malformed input, got %d", len(nics))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNetworkInfo_MissingFields(t *testing.T) {
|
||||
// NIC with minimal fields
|
||||
raw := "net0: index=0"
|
||||
nics := ParseNetworkInfo(raw)
|
||||
if len(nics) != 1 {
|
||||
t.Fatalf("expected 1 NIC, got %d", len(nics))
|
||||
}
|
||||
if nics[0].Queues != 1 {
|
||||
t.Errorf("queues = %d, want 1", nics[0].Queues)
|
||||
}
|
||||
if nics[0].Model != "" {
|
||||
t.Errorf("model = %q, want empty", nics[0].Model)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ type RealQMMonitor struct {
|
||||
|
||||
type deferredProc struct {
|
||||
cmd *exec.Cmd
|
||||
stdin io.WriteCloser
|
||||
timestamp time.Time
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ func (m *RealQMMonitor) deferCloseProcess(cmd *exec.Cmd, stdin io.WriteCloser) {
|
||||
stdin.Close()
|
||||
if m.deferClose {
|
||||
m.mu.Lock()
|
||||
m.deferredProcs = append(m.deferredProcs, deferredProc{cmd: cmd, stdin: stdin, timestamp: time.Now()})
|
||||
m.deferredProcs = append(m.deferredProcs, deferredProc{cmd: cmd, timestamp: time.Now()})
|
||||
m.mu.Unlock()
|
||||
slog.Warn("deferred closing qm monitor process", "pid", cmd.Process.Pid)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user