fix(hostman): use losetup --json to match device (#21276)

This commit is contained in:
Zexi Li
2024-09-20 22:21:25 +08:00
committed by GitHub
parent 80d6aee90d
commit 449c1140ab
4 changed files with 114 additions and 27 deletions
+4 -11
View File
@@ -67,19 +67,12 @@ func parseDevice(line string) (Device, error) {
if len(fields) == 0 {
return Device{}, fmt.Errorf("Invalid line: %q", line)
}
sizeLimit := false
ro := false
if fields[2] != "0" {
sizeLimit = true
}
if fields[3] != "0" {
ro = true
if len(fields) < 2 {
return Device{}, fmt.Errorf("Invalid line: %q", line)
}
return Device{
Name: fields[0],
BackFile: fields[1],
SizeLimit: sizeLimit,
ReadOnly: ro,
Name: fields[0],
BackFile: strings.Join(fields[1:], " "),
}, nil
}
+9 -13
View File
@@ -21,9 +21,9 @@ import (
var (
losetupOutput string = `
NAME BACK-FILE SIZELIMIT RO
/dev/loop0 /disks/2b917686-2ace-4a57-a4af-44ece2303dd2 0 0
/dev/loop1 /disks/033d6bc0-4ce4-48c4-89d3-125077bcc28e 0 1
NAME BACK-FILE
/dev/loop0 /disks/2b917686-2ace-4a57-a4af-44ece2303dd2 (deleted)
/dev/loop1 /disks/033d6bc0-4ce4-48c4-89d3-125077bcc28e
`
)
@@ -42,17 +42,13 @@ func Test_parseDevices(t *testing.T) {
args: args{losetupOutput},
want: &Devices{
[]Device{
Device{
Name: "/dev/loop0",
BackFile: "/disks/2b917686-2ace-4a57-a4af-44ece2303dd2",
SizeLimit: false,
ReadOnly: false,
{
Name: "/dev/loop0",
BackFile: "/disks/2b917686-2ace-4a57-a4af-44ece2303dd2 (deleted)",
},
Device{
Name: "/dev/loop1",
BackFile: "/disks/033d6bc0-4ce4-48c4-89d3-125077bcc28e",
SizeLimit: false,
ReadOnly: true,
{
Name: "/dev/loop1",
BackFile: "/disks/033d6bc0-4ce4-48c4-89d3-125077bcc28e",
},
},
},
+32 -3
View File
@@ -72,8 +72,37 @@ func NewLosetupCommand() *LosetupCommand {
}
}
func parseJsonOutput(content string) (*Devices, error) {
obj, err := jsonutils.ParseString(content)
if err != nil {
return nil, errors.Wrapf(err, "parse json: %s", content)
}
devs := new(Devices)
if err := obj.Unmarshal(devs); err != nil {
return nil, errors.Wrapf(err, "unmarshal json: %s", content)
}
return devs, nil
}
func ListDevices() (*Devices, error) {
cmd, err := NewLosetupCommand().AddArgs("-l", "-O", "NAME,BACK-FILE,SIZELIMIT,RO").Run()
cmd, err := NewLosetupCommand().AddArgs("--json").Run()
errs := make([]error, 0)
if err != nil {
errs = append(errs, errors.Wrap(err, "list by json"))
devs, err2 := listDevicesOldVersion()
if err2 != nil {
errs = append(errs, errors.Wrap(err, "list by using old way"))
} else {
return devs, nil
}
return nil, errors.NewAggregate(errs)
}
output := cmd.Output()
return parseJsonOutput(output)
}
func listDevicesOldVersion() (*Devices, error) {
cmd, err := NewLosetupCommand().AddArgs("-l", "-O", "NAME,BACK-FILE").Run()
if err != nil {
return nil, err
}
@@ -156,13 +185,13 @@ func DetachDevice(devPath string) error {
return errors.Wrapf(err, "detach device")
}
// recheck
dev, err = getDev()
/*dev, err = getDev()
if err != nil {
return errors.Wrapf(err, "get device by %s for rechecking", devPath)
}
if dev != nil {
return errors.Errorf("device %s still exists, %s", devPath, jsonutils.Marshal(dev))
}
}*/
return nil
}
+69
View File
@@ -0,0 +1,69 @@
package losetup
import (
"reflect"
"testing"
)
func Test_parseJsonOutput(t *testing.T) {
tests := []struct {
name string
content string
want *Devices
wantErr bool
}{
{
name: "normal input",
content: `{
"loopdevices": [
{
"name": "/dev/loop1",
"sizelimit": 0,
"offset": 0,
"autoclear": true,
"ro": false,
"back-file": "/opt/cloud/workspace/disks/recycle_bin/20240911160650/194767a9-556f-4072-8a20-7ab1086f22ff.1726070810",
"dio": false,
"log-sec": 512
},{
"name": "/dev/loop57",
"sizelimit": 0,
"offset": 0,
"autoclear": false,
"ro": false,
"back-file": "/opt/cloud/workspace/disks/2c10325f-7109-4cf0-8a9f-4c3724920245 (deleted)",
"dio": false,
"log-sec": 512
}]}`,
want: &Devices{
LoopDevs: []Device{
{
Name: "/dev/loop1",
BackFile: "/opt/cloud/workspace/disks/recycle_bin/20240911160650/194767a9-556f-4072-8a20-7ab1086f22ff.1726070810",
SizeLimit: false,
ReadOnly: false,
},
{
Name: "/dev/loop57",
BackFile: "/opt/cloud/workspace/disks/2c10325f-7109-4cf0-8a9f-4c3724920245 (deleted)",
SizeLimit: false,
ReadOnly: false,
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseJsonOutput(tt.content)
if (err != nil) != tt.wantErr {
t.Errorf("parseJsonOutput() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseJsonOutput() got = %v, want %v", got, tt.want)
}
})
}
}