Cleanup, and fix decoding of TypedParams.
This commit is contained in:
parent
deb7a54ff8
commit
a3bd42a5b1
@ -23,11 +23,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TODO: make these an argument
|
// TODO: make these an argument
|
||||||
const lvPath = "../../../libvirt"
|
|
||||||
const protoPath = "src/remote/remote_protocol.x"
|
const protoPath = "src/remote/remote_protocol.x"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Generating golang bindings for libvirt")
|
lvPath := os.Getenv("LIBVIRT_SOURCE")
|
||||||
|
if lvPath == "" {
|
||||||
|
fmt.Println("set $LIBVIRT_SOURCE to point to the root of the libvirt sources and retry")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
lvFile := path.Join(lvPath, protoPath)
|
lvFile := path.Join(lvPath, protoPath)
|
||||||
rdr, err := os.Open(lvFile)
|
rdr, err := os.Open(lvFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -14,10 +14,6 @@
|
|||||||
|
|
||||||
package lvgen
|
package lvgen
|
||||||
|
|
||||||
// The libvirt API is divided into several categories. (Gallia est omnis divisa
|
|
||||||
// in partes tres.) The generator will output code for each category in a
|
|
||||||
// package underneath the go-libvirt directory.
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -29,30 +25,6 @@ import (
|
|||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
var keywords = map[string]int{
|
|
||||||
"hyper": HYPER,
|
|
||||||
"int": INT,
|
|
||||||
"short": SHORT,
|
|
||||||
"char": CHAR,
|
|
||||||
"bool": BOOL,
|
|
||||||
"case": CASE,
|
|
||||||
"const": CONST,
|
|
||||||
"default": DEFAULT,
|
|
||||||
"double": DOUBLE,
|
|
||||||
"enum": ENUM,
|
|
||||||
"float": FLOAT,
|
|
||||||
"opaque": OPAQUE,
|
|
||||||
"string": STRING,
|
|
||||||
"struct": STRUCT,
|
|
||||||
"switch": SWITCH,
|
|
||||||
"typedef": TYPEDEF,
|
|
||||||
"union": UNION,
|
|
||||||
"unsigned": UNSIGNED,
|
|
||||||
"void": VOID,
|
|
||||||
"program": PROGRAM,
|
|
||||||
"version": VERSION,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstItem stores an const's symbol and value from the parser. This struct is
|
// ConstItem stores an const's symbol and value from the parser. This struct is
|
||||||
// also used for enums.
|
// also used for enums.
|
||||||
type ConstItem struct {
|
type ConstItem struct {
|
||||||
@ -77,6 +49,8 @@ type Generator struct {
|
|||||||
Typedefs []Typedef
|
Typedefs []Typedef
|
||||||
// Unions holds all the discriminated unions.
|
// Unions holds all the discriminated unions.
|
||||||
Unions []Union
|
Unions []Union
|
||||||
|
// UnionMap is a map of the unions we find for quick searching.
|
||||||
|
UnionMap map[string]int
|
||||||
// Procs holds all the discovered libvirt procedures.
|
// Procs holds all the discovered libvirt procedures.
|
||||||
Procs []Proc
|
Procs []Proc
|
||||||
}
|
}
|
||||||
@ -104,6 +78,9 @@ var goEquivTypes = map[string]string{
|
|||||||
// requires us to ditch the typedef that would otherwise be generated.
|
// requires us to ditch the typedef that would otherwise be generated.
|
||||||
"NonnullString": "string",
|
"NonnullString": "string",
|
||||||
|
|
||||||
|
// TODO: Get rid of these. They're only needed because we lose information
|
||||||
|
// that the parser has (the parser knows it has emitted a go type), and then
|
||||||
|
// we capitalize types to make them public.
|
||||||
"String": "string",
|
"String": "string",
|
||||||
"Int": "int",
|
"Int": "int",
|
||||||
"Uint": "uint",
|
"Uint": "uint",
|
||||||
@ -122,7 +99,8 @@ var goEquivTypes = map[string]string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These defines are from libvirt-common.h. They should be fetched from there,
|
// These defines are from libvirt-common.h. They should be fetched from there,
|
||||||
// but for now they're hardcoded here.
|
// but for now they're hardcoded here. (These are the discriminant values for
|
||||||
|
// TypedParams.)
|
||||||
var lvTypedParams = map[string]uint32{
|
var lvTypedParams = map[string]uint32{
|
||||||
"VIR_TYPED_PARAM_INT": 1,
|
"VIR_TYPED_PARAM_INT": 1,
|
||||||
"VIR_TYPED_PARAM_UINT": 2,
|
"VIR_TYPED_PARAM_UINT": 2,
|
||||||
@ -222,6 +200,7 @@ var CurrentCase *Case
|
|||||||
// generation.
|
// generation.
|
||||||
func Generate(proto io.Reader) error {
|
func Generate(proto io.Reader) error {
|
||||||
Gen.StructMap = make(map[string]int)
|
Gen.StructMap = make(map[string]int)
|
||||||
|
Gen.UnionMap = make(map[string]int)
|
||||||
lexer, err := NewLexer(proto)
|
lexer, err := NewLexer(proto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -257,6 +236,8 @@ func Generate(proto io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// genGo is called when the parsing is done; it generates the golang output
|
||||||
|
// files using templates.
|
||||||
func genGo(constFile, procFile io.Writer) error {
|
func genGo(constFile, procFile io.Writer) error {
|
||||||
t, err := template.ParseFiles("constants.tmpl")
|
t, err := template.ParseFiles("constants.tmpl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -273,18 +254,6 @@ func genGo(constFile, procFile io.Writer) error {
|
|||||||
if err := t.Execute(procFile, Gen); err != nil {
|
if err := t.Execute(procFile, Gen); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Now generate the wrappers for libvirt's various public API functions.
|
|
||||||
// for _, c := range Gen.Enums {
|
|
||||||
// This appears to be the name of a libvirt procedure, so sort it into
|
|
||||||
// the right list based on the next part of its name.
|
|
||||||
// segs := camelcase.Split(c.Name)
|
|
||||||
// if len(segs) < 3 || segs[0] != "Proc" {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
//category := segs[1]
|
|
||||||
|
|
||||||
//fmt.Println(segs)
|
|
||||||
// }
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -297,7 +266,7 @@ func constNameTransform(name string) string {
|
|||||||
decamelize := strings.ContainsRune(name, '_')
|
decamelize := strings.ContainsRune(name, '_')
|
||||||
nn := strings.TrimPrefix(name, "REMOTE_")
|
nn := strings.TrimPrefix(name, "REMOTE_")
|
||||||
if decamelize {
|
if decamelize {
|
||||||
nn = fromSnakeToCamel(nn, true)
|
nn = fromSnakeToCamel(nn)
|
||||||
}
|
}
|
||||||
nn = fixAbbrevs(nn)
|
nn = fixAbbrevs(nn)
|
||||||
return nn
|
return nn
|
||||||
@ -307,7 +276,7 @@ func identifierTransform(name string) string {
|
|||||||
decamelize := strings.ContainsRune(name, '_')
|
decamelize := strings.ContainsRune(name, '_')
|
||||||
nn := strings.TrimPrefix(name, "remote_")
|
nn := strings.TrimPrefix(name, "remote_")
|
||||||
if decamelize {
|
if decamelize {
|
||||||
nn = fromSnakeToCamel(nn, true)
|
nn = fromSnakeToCamel(nn)
|
||||||
} else {
|
} else {
|
||||||
nn = publicize(nn)
|
nn = publicize(nn)
|
||||||
}
|
}
|
||||||
@ -337,10 +306,10 @@ func publicize(name string) string {
|
|||||||
// are omitted.
|
// are omitted.
|
||||||
//
|
//
|
||||||
// ex: "PROC_DOMAIN_GET_METADATA" -> "ProcDomainGetMetadata"
|
// ex: "PROC_DOMAIN_GET_METADATA" -> "ProcDomainGetMetadata"
|
||||||
func fromSnakeToCamel(s string, public bool) string {
|
func fromSnakeToCamel(s string) string {
|
||||||
buf := make([]rune, 0, len(s))
|
buf := make([]rune, 0, len(s))
|
||||||
// Start rune may be either upper or lower case.
|
// Start rune will be upper case - we generate all public symbols.
|
||||||
hump := public
|
hump := true
|
||||||
|
|
||||||
for _, r := range s {
|
for _, r := range s {
|
||||||
if r == '_' {
|
if r == '_' {
|
||||||
@ -496,8 +465,8 @@ func StartStruct(name string) {
|
|||||||
// the now-complete struct definition to the generator's list.
|
// the now-complete struct definition to the generator's list.
|
||||||
func AddStruct() {
|
func AddStruct() {
|
||||||
st := *CurrentStruct.pop()
|
st := *CurrentStruct.pop()
|
||||||
|
Gen.StructMap[st.Name] = len(Gen.Structs)
|
||||||
Gen.Structs = append(Gen.Structs, st)
|
Gen.Structs = append(Gen.Structs, st)
|
||||||
Gen.StructMap[st.Name] = len(Gen.Structs) - 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartTypedef is called when the parser finds a typedef.
|
// StartTypedef is called when the parser finds a typedef.
|
||||||
@ -516,6 +485,7 @@ func StartUnion(name string) {
|
|||||||
// pointer. We handle unions by declaring an interface for the union type, and
|
// pointer. We handle unions by declaring an interface for the union type, and
|
||||||
// adding methods to each of the cases so that they satisfy the interface.
|
// adding methods to each of the cases so that they satisfy the interface.
|
||||||
func AddUnion() {
|
func AddUnion() {
|
||||||
|
Gen.UnionMap[CurrentUnion.Name] = len(Gen.Unions)
|
||||||
Gen.Unions = append(Gen.Unions, *CurrentUnion)
|
Gen.Unions = append(Gen.Unions, *CurrentUnion)
|
||||||
CurrentUnion = nil
|
CurrentUnion = nil
|
||||||
}
|
}
|
||||||
@ -532,7 +502,7 @@ func StartCase(dvalue string) {
|
|||||||
if ix := strings.LastIndexByte(caseName, '_'); ix != -1 {
|
if ix := strings.LastIndexByte(caseName, '_'); ix != -1 {
|
||||||
caseName = caseName[ix+1:]
|
caseName = caseName[ix+1:]
|
||||||
}
|
}
|
||||||
caseName = fromSnakeToCamel(caseName, true)
|
caseName = fromSnakeToCamel(caseName)
|
||||||
dv, ok := lvTypedParams[dvalue]
|
dv, ok := lvTypedParams[dvalue]
|
||||||
if ok {
|
if ok {
|
||||||
dvalue = strconv.FormatUint(uint64(dv), 10)
|
dvalue = strconv.FormatUint(uint64(dv), 10)
|
||||||
@ -587,11 +557,11 @@ func AddFixedArray(identifier, itype, len string) {
|
|||||||
// Variable-length arrays are prefixed with a 32-bit unsigned length, and may
|
// Variable-length arrays are prefixed with a 32-bit unsigned length, and may
|
||||||
// also have a maximum length specified.
|
// also have a maximum length specified.
|
||||||
func AddVariableArray(identifier, itype, len string) {
|
func AddVariableArray(identifier, itype, len string) {
|
||||||
// FIXME: This ignores the length restriction, so as of now we can't check
|
// This code ignores the length restriction (array<MAXLEN>), so as of now we
|
||||||
// to make sure that we're not exceeding that restriction when we fill in
|
// can't check to make sure that we're not exceeding that restriction when
|
||||||
// message buffers. That may not matter, if libvirt's checking is careful
|
// we fill in message buffers. That may not matter, if libvirt's checking is
|
||||||
// enough. This could be handled with a map, however.
|
// careful enough.
|
||||||
atype := fmt.Sprintf("[]%v", itype)
|
atype := "[]" + itype
|
||||||
// Handle strings specially. In the rpcgen definition a string is specified
|
// Handle strings specially. In the rpcgen definition a string is specified
|
||||||
// as a variable-length array, either with or without a max length. We want
|
// as a variable-length array, either with or without a max length. We want
|
||||||
// these to be go strings, so we'll just remove the array specifier.
|
// these to be go strings, so we'll just remove the array specifier.
|
||||||
@ -608,3 +578,13 @@ func checkIdentifier(i string) string {
|
|||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUnion returns the type information for a union. If the provided type name
|
||||||
|
// isn't a union, the second return value will be false.
|
||||||
|
func (decl *Decl) GetUnion() Union {
|
||||||
|
ix, ok := Gen.UnionMap[decl.Type]
|
||||||
|
if ok {
|
||||||
|
return Gen.Unions[ix]
|
||||||
|
}
|
||||||
|
return Union{}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,16 @@
|
|||||||
package lvgen
|
package lvgen
|
||||||
|
|
||||||
|
// This file contains the instructions for regenerating the libvirt bindings.
|
||||||
|
// We do this by parsing the remote_protocol.x file included in the libvirt
|
||||||
|
// sources. Bindings will be generated if you run `go generate` in this
|
||||||
|
// directory.
|
||||||
|
|
||||||
|
// Before running `go generate`:
|
||||||
|
// 1) Make sure goyacc is installed from golang.org/x/tools (you can use this
|
||||||
|
// command: `go get golang.org/x/tools/...`)
|
||||||
|
// 2) Set the environment variable LIBVIRT_SOURCE to point to the top level
|
||||||
|
// directory containing the version of libvirt for which you want to generate
|
||||||
|
// bindings.
|
||||||
|
|
||||||
//go:generate goyacc sunrpc.y
|
//go:generate goyacc sunrpc.y
|
||||||
//go:generate go run gen/main.go
|
//go:generate go run gen/main.go
|
||||||
|
@ -31,6 +31,31 @@ const eof = -1
|
|||||||
// runes.
|
// runes.
|
||||||
var oneRuneTokens = `{}[]<>(),=;:*`
|
var oneRuneTokens = `{}[]<>(),=;:*`
|
||||||
|
|
||||||
|
var keywords = map[string]int{
|
||||||
|
"hyper": HYPER,
|
||||||
|
"int": INT,
|
||||||
|
"short": SHORT,
|
||||||
|
"char": CHAR,
|
||||||
|
"bool": BOOL,
|
||||||
|
"case": CASE,
|
||||||
|
"const": CONST,
|
||||||
|
"default": DEFAULT,
|
||||||
|
"double": DOUBLE,
|
||||||
|
"enum": ENUM,
|
||||||
|
"float": FLOAT,
|
||||||
|
"opaque": OPAQUE,
|
||||||
|
"string": STRING,
|
||||||
|
"struct": STRUCT,
|
||||||
|
"switch": SWITCH,
|
||||||
|
"typedef": TYPEDEF,
|
||||||
|
"union": UNION,
|
||||||
|
"unsigned": UNSIGNED,
|
||||||
|
"void": VOID,
|
||||||
|
"program": PROGRAM,
|
||||||
|
"version": VERSION,
|
||||||
|
}
|
||||||
|
|
||||||
|
// item is a lexeme, or what the lexer returns to the parser.
|
||||||
type item struct {
|
type item struct {
|
||||||
typ int
|
typ int
|
||||||
val string
|
val string
|
||||||
|
@ -8,6 +8,7 @@ package libvirt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/davecgh/go-xdr/xdr2"
|
"github.com/davecgh/go-xdr/xdr2"
|
||||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||||
@ -42,10 +43,64 @@ type {{$casetype}} struct {
|
|||||||
{{.Name}} {{.Type}}
|
{{.Name}} {{.Type}}
|
||||||
}
|
}
|
||||||
func New{{$casetype}}(v {{.Type}}) *{{$casetype}} { return &{{$casetype}}{DVal: {{.DiscriminantVal}}, {{.Name}}: v} }
|
func New{{$casetype}}(v {{.Type}}) *{{$casetype}} { return &{{$casetype}}{DVal: {{.DiscriminantVal}}, {{.Name}}: v} }
|
||||||
|
func Decode{{$casetype}}(dec *xdr.Decoder) (*{{$casetype}}, error) {
|
||||||
|
var v {{.Type}}
|
||||||
|
_, err := dec.Decode(&v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return New{{$casetype}}(v), nil
|
||||||
|
}
|
||||||
func (c *{{$casetype}}) Get() interface{} { return c.{{.Name}} }
|
func (c *{{$casetype}}) Get() interface{} { return c.{{.Name}} }
|
||||||
{{end}}
|
{{end}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
|
// TODO: Generate this.
|
||||||
|
func decodeTypedParams(dec *xdr.Decoder) ([]TypedParam, error) {
|
||||||
|
count, _, err := dec.DecodeInt()
|
||||||
|
params := make([]TypedParam, count)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for ix := int32(0); ix < count; ix++ {
|
||||||
|
name, _, err := dec.DecodeString()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ptype, _, err := dec.DecodeInt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var tpv TypedParamValue
|
||||||
|
switch ptype {
|
||||||
|
case 1: // TypedParamValueInt
|
||||||
|
tpv, err = DecodeTypedParamValueInt(dec)
|
||||||
|
case 2: // TypedParamValueUint
|
||||||
|
tpv, err = DecodeTypedParamValueUint(dec)
|
||||||
|
case 3: // TypedParamValueLlong
|
||||||
|
tpv, err = DecodeTypedParamValueLlong(dec)
|
||||||
|
case 4: // TypedParamValueUllong
|
||||||
|
tpv, err = DecodeTypedParamValueUllong(dec)
|
||||||
|
case 5: // TypedParamValueDouble
|
||||||
|
tpv, err = DecodeTypedParamValueDouble(dec)
|
||||||
|
case 6: // TypedParamValueBoolean
|
||||||
|
tpv, err = DecodeTypedParamValueBoolean(dec)
|
||||||
|
case 7: // TypedParamValueString
|
||||||
|
tpv, err = DecodeTypedParamValueString(dec)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid parameter type %v", ptype)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
params[ix] = TypedParam{name, tpv}
|
||||||
|
}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Procedures:
|
// Procedures:
|
||||||
{{range .Procs}}
|
{{range .Procs}}
|
||||||
func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Name}} {{.Type}}{{end}}) ({{range .Ret}}r{{.Name}} {{.Type}}, {{end}}err error) {
|
func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Name}} {{.Type}}{{end}}) ({{range .Ret}}r{{.Name}} {{.Type}}, {{end}}err error) {
|
||||||
@ -72,16 +127,21 @@ func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Na
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
{{if .RetStruct}}
|
{{if .RetStruct}}
|
||||||
result := {{.RetStruct}}{}
|
// Return value unmarshaling
|
||||||
rdr := bytes.NewReader(r.Payload)
|
rdr := bytes.NewReader(r.Payload)
|
||||||
dec := xdr.NewDecoder(rdr)
|
dec := xdr.NewDecoder(rdr)
|
||||||
_, err = dec.Decode(&result)
|
{{range .Ret}} // {{.Name}}: {{.Type}}
|
||||||
|
{{if eq .Type "[]TypedParam"}} // {{.Name}}
|
||||||
|
r{{.Name}}, err = decodeTypedParams(dec)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
{{else}} _, err = dec.Decode(&r{{.Name}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
{{range .Ret}} r{{.Name}} = result.{{.Name}}
|
|
||||||
{{end}}{{end}}
|
{{end}}{{end}}
|
||||||
|
{{end}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
1982
libvirt.gen.go
1982
libvirt.gen.go
File diff suppressed because it is too large
Load Diff
166
libvirt.go
166
libvirt.go
@ -1398,39 +1398,13 @@ func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainSetBlockIoTune
|
params := make([]TypedParam, len(limits))
|
||||||
payload := struct {
|
for ix, limit := range limits {
|
||||||
Domain Domain
|
|
||||||
Disk string
|
|
||||||
Params []TypedParam
|
|
||||||
Flags DomainAffectFlags
|
|
||||||
}{
|
|
||||||
Domain: d,
|
|
||||||
Disk: disk,
|
|
||||||
Flags: FlagDomainAffectLive,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, limit := range limits {
|
|
||||||
tpval := NewTypedParamValueUllong(limit.Value)
|
tpval := NewTypedParamValueUllong(limit.Value)
|
||||||
tp := &TypedParam{Field: limit.Name, Value: tpval}
|
params[ix] = TypedParam{Field: limit.Name, Value: tpval}
|
||||||
payload.Params = append(payload.Params, *tp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := encode(&payload)
|
return l.DomainSetBlockIOTune(*d, disk, params, FlagDomainAffectLive)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resp, err := l.request(constants.ProcDomainSetBlockIOTune, constants.Program, &buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r := <-resp
|
|
||||||
if r.Status != StatusOK {
|
|
||||||
return decodeError(r.Payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockIOTune returns a slice containing the current block I/O tunables for
|
// GetBlockIOTune returns a slice containing the current block I/O tunables for
|
||||||
@ -1441,78 +1415,92 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
payload := struct {
|
lims, _, err := l.DomainGetBlockIOTune(*d, disk, 32, FlagTypedParamStringOkay)
|
||||||
Domain Domain
|
|
||||||
Disk []string
|
|
||||||
ParamCount uint32
|
|
||||||
Flags DomainAffectFlags
|
|
||||||
}{
|
|
||||||
Domain: d,
|
|
||||||
Disk: []string{disk},
|
|
||||||
ParamCount: 32,
|
|
||||||
Flags: FlagTypedParamStringOkay,
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err := encode(&payload)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// payload := struct {
|
||||||
resp, err := l.request(constants.ProcDomainGetBlockIOTune, constants.Program, &buf)
|
// Domain Domain
|
||||||
if err != nil {
|
// Disk []string
|
||||||
return nil, err
|
// ParamCount uint32
|
||||||
}
|
// Flags DomainAffectFlags
|
||||||
|
// }{
|
||||||
r := <-resp
|
// Domain: d,
|
||||||
if r.Status != StatusOK {
|
// Disk: []string{disk},
|
||||||
return nil, decodeError(r.Payload)
|
// ParamCount: 32,
|
||||||
}
|
// Flags: FlagTypedParamStringOkay,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// buf, err := encode(&payload)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// resp, err := l.request(constants.ProcDomainGetBlockIOTune, constants.Program, &buf)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// r := <-resp
|
||||||
|
// if r.Status != StatusOK {
|
||||||
|
// return nil, decodeError(r.Payload)
|
||||||
|
// }
|
||||||
|
|
||||||
var limits []BlockLimit
|
var limits []BlockLimit
|
||||||
rdr := bytes.NewReader(r.Payload)
|
// rdr := bytes.NewReader(r.Payload)
|
||||||
dec := xdr.NewDecoder(rdr)
|
// dec := xdr.NewDecoder(rdr)
|
||||||
|
|
||||||
// find out how many params were returned
|
// find out how many params were returned
|
||||||
paramCount, _, err := dec.DecodeInt()
|
// paramCount, _, err := dec.DecodeInt()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
// now decode each of the returned TypedParams. To do this we read the field
|
// now decode each of the returned TypedParams. To do this we read the field
|
||||||
// name and type, then use the type information to decode the value.
|
// name and type, then use the type information to decode the value.
|
||||||
for param := int32(0); param < paramCount; param++ {
|
for _, lim := range lims {
|
||||||
// Get the field name
|
var l BlockLimit
|
||||||
name, _, err := dec.DecodeString()
|
name := lim.Field
|
||||||
if err != nil {
|
switch lim.Value.Get().(type) {
|
||||||
return nil, err
|
case uint64:
|
||||||
}
|
l = BlockLimit{Name: name, Value: lim.Value.Get().(uint64)}
|
||||||
// ...and the type
|
|
||||||
ptype, _, err := dec.DecodeInt()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we can read the actual value.
|
|
||||||
switch ptype {
|
|
||||||
case TypeParamULLong:
|
|
||||||
var val uint64
|
|
||||||
_, err = dec.Decode(&val)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
lim := BlockLimit{name, val}
|
|
||||||
limits = append(limits, lim)
|
|
||||||
case TypeParamString:
|
|
||||||
var val string
|
|
||||||
_, err = dec.Decode(&val)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// This routine doesn't currently return strings. As of libvirt 3+,
|
|
||||||
// there's one string here, `group_name`.
|
|
||||||
}
|
}
|
||||||
|
limits = append(limits, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for param := int32(0); param < paramCount; param++ {
|
||||||
|
// // Get the field name
|
||||||
|
// name, _, err := dec.DecodeString()
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// // ...and the type
|
||||||
|
// ptype, _, err := dec.DecodeInt()
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Now we can read the actual value.
|
||||||
|
// switch ptype {
|
||||||
|
// case TypeParamULLong:
|
||||||
|
// var val uint64
|
||||||
|
// _, err = dec.Decode(&val)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// lim := BlockLimit{name, val}
|
||||||
|
// limits = append(limits, lim)
|
||||||
|
// case TypeParamString:
|
||||||
|
// var val string
|
||||||
|
// _, err = dec.Decode(&val)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// // This routine doesn't currently return strings. As of libvirt 3+,
|
||||||
|
// // there's one string here, `group_name`.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return limits, nil
|
return limits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user