1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
package qemu
import (
"encoding/json"
"fmt"
"strings"
"github.com/digitalocean/go-qemu/qmp"
)
type qomListRequest struct {
Execute string `json:"execute"`
Arguments qomListRequestArguments `json:"arguments"`
}
type qomListRequestArguments struct {
Path string `json:"path"`
}
type qomListResponse struct {
Return []qomListReturn `json:"return"`
}
type qomListReturn struct {
Name string `json:"name"`
Type string `json:"type"`
}
func qmpQomList(qmpMonitor *qmp.SocketMonitor, path string) ([]qomListReturn, error) {
request, _ := json.Marshal(qomListRequest{
Execute: "qom-list",
Arguments: qomListRequestArguments{
Path: path,
},
})
result, err := qmpMonitor.Run(request)
if err != nil {
return nil, err
}
var response qomListResponse
if err := json.Unmarshal(result, &response); err != nil {
return nil, err
}
return response.Return, nil
}
type qomGetRequest struct {
Execute string `json:"execute"`
Arguments qomGetRequestArguments `json:"arguments"`
}
type qomGetRequestArguments struct {
Path string `json:"path"`
Property string `json:"property"`
}
type qomGetResponse struct {
Return string `json:"return"`
}
func qmpQomGet(qmpMonitor *qmp.SocketMonitor, path string, property string) (string, error) {
request, _ := json.Marshal(qomGetRequest{
Execute: "qom-get",
Arguments: qomGetRequestArguments{
Path: path,
Property: property,
},
})
result, err := qmpMonitor.Run(request)
if err != nil {
return "", err
}
var response qomGetResponse
if err := json.Unmarshal(result, &response); err != nil {
return "", err
}
return response.Return, nil
}
type netDevice struct {
Path string
Name string
Type string
MacAddress string
}
func getNetDevices(qmpMonitor *qmp.SocketMonitor) ([]netDevice, error) {
devices := []netDevice{}
for _, parentPath := range []string{"/machine/peripheral", "/machine/peripheral-anon"} {
listResponse, err := qmpQomList(qmpMonitor, parentPath)
if err != nil {
return nil, fmt.Errorf("failed to get qmp qom list %v: %w", parentPath, err)
}
for _, p := range listResponse {
if strings.HasPrefix(p.Type, "child<") {
path := fmt.Sprintf("%s/%s", parentPath, p.Name)
r, err := qmpQomList(qmpMonitor, path)
if err != nil {
return nil, fmt.Errorf("failed to get qmp qom list %v: %w", path, err)
}
isNetdev := false
for _, d := range r {
if d.Name == "netdev" {
isNetdev = true
break
}
}
if isNetdev {
device := netDevice{
Path: path,
}
for _, d := range r {
if d.Name != "type" && d.Name != "netdev" && d.Name != "mac" {
continue
}
value, err := qmpQomGet(qmpMonitor, path, d.Name)
if err != nil {
return nil, fmt.Errorf("failed to get qmp qom property %v %v: %w", path, d.Name, err)
}
switch d.Name {
case "type":
device.Type = value
case "netdev":
device.Name = value
case "mac":
device.MacAddress = value
}
}
devices = append(devices, device)
}
}
}
}
return devices, nil
}
|