Generate libvirt procedure wrappers.
The generated wrappers have an argument for every field in their "Args" struct, and return everything in their "Ret" struct (these structs are defined in the protocol file, and identified by procedure name). Marshaling and unmarshaling is handled inside the generated procedures.
This commit is contained in:
parent
fb16117ff9
commit
deb7a54ff8
1
AUTHORS
1
AUTHORS
@ -16,3 +16,4 @@ Michael Koppmann <me@mkoppmann.at>
|
||||
Simarpreet Singh <simar@linux.com>
|
||||
Alexander Polyakov <apolyakov@beget.com>
|
||||
Amanda Andrade <amanda.andrade@serpro.gov.br>
|
||||
Geoff Hickey <ghickey@digitalocean.com>
|
||||
|
@ -71,10 +71,14 @@ type Generator struct {
|
||||
Consts []ConstItem
|
||||
// Structs holds a list of all the structs found by the parser
|
||||
Structs []Structure
|
||||
// Typedefs hold all the type definitions from 'typedef ...' lines.
|
||||
// StructMap is a map of the structs we find for quick searching.
|
||||
StructMap map[string]int
|
||||
// Typedefs holds all the type definitions from 'typedef ...' lines.
|
||||
Typedefs []Typedef
|
||||
// Unions hold all the discriminated unions
|
||||
// Unions holds all the discriminated unions.
|
||||
Unions []Union
|
||||
// Procs holds all the discovered libvirt procedures.
|
||||
Procs []Proc
|
||||
}
|
||||
|
||||
// Gen accumulates items as the parser runs, and is then used to produce the
|
||||
@ -85,15 +89,48 @@ var Gen Generator
|
||||
// explicitly given a value.
|
||||
var CurrentEnumVal int64
|
||||
|
||||
// oneRuneTokens lists the runes the lexer will consider to be tokens when it
|
||||
// finds them. These are returned to the parser using the integer value of their
|
||||
// runes.
|
||||
var oneRuneTokens = `{}[]<>(),=;:*`
|
||||
|
||||
var reservedIdentifiers = map[string]string{
|
||||
// goEquivTypes maps the basic types defined in the rpc spec to their golang
|
||||
// equivalents.
|
||||
var goEquivTypes = map[string]string{
|
||||
// Some of the identifiers in the rpc specification are reserved words or
|
||||
// pre-existing types in go. This renames them to something safe.
|
||||
"type": "lvtype",
|
||||
"string": "lvstring",
|
||||
"error": "lverror",
|
||||
"nil": "lvnil",
|
||||
|
||||
// The libvirt spec uses this NonnullString type, which is a string with a
|
||||
// specified maximum length. This makes the go code more confusing, and
|
||||
// we're not enforcing the limit anyway, so collapse it here. This also
|
||||
// requires us to ditch the typedef that would otherwise be generated.
|
||||
"NonnullString": "string",
|
||||
|
||||
"String": "string",
|
||||
"Int": "int",
|
||||
"Uint": "uint",
|
||||
"Int8": "int8",
|
||||
"Uint8": "uint8",
|
||||
"Int16": "int16",
|
||||
"Uint16": "uint16",
|
||||
"Int32": "int32",
|
||||
"Uint32": "uint32",
|
||||
"Int64": "int64",
|
||||
"Uint64": "uint64",
|
||||
"Float32": "float32",
|
||||
"Float64": "float64",
|
||||
"Bool": "bool",
|
||||
"Byte": "byte",
|
||||
}
|
||||
|
||||
// These defines are from libvirt-common.h. They should be fetched from there,
|
||||
// but for now they're hardcoded here.
|
||||
var lvTypedParams = map[string]uint32{
|
||||
"VIR_TYPED_PARAM_INT": 1,
|
||||
"VIR_TYPED_PARAM_UINT": 2,
|
||||
"VIR_TYPED_PARAM_LLONG": 3,
|
||||
"VIR_TYPED_PARAM_ULLONG": 4,
|
||||
"VIR_TYPED_PARAM_DOUBLE": 5,
|
||||
"VIR_TYPED_PARAM_BOOLEAN": 6,
|
||||
"VIR_TYPED_PARAM_STRING": 7,
|
||||
}
|
||||
|
||||
// Decl records a declaration, like 'int x' or 'remote_nonnull_string str'
|
||||
@ -123,14 +160,50 @@ type Union struct {
|
||||
|
||||
// Case holds a single case of a discriminated union.
|
||||
type Case struct {
|
||||
CaseName string
|
||||
DiscriminantVal string
|
||||
Type Decl
|
||||
Decl
|
||||
}
|
||||
|
||||
// Proc holds information about a libvirt procedure the parser has found.
|
||||
type Proc struct {
|
||||
Num int64
|
||||
Name string
|
||||
Args []Decl
|
||||
Ret []Decl
|
||||
ArgsStruct string
|
||||
RetStruct string
|
||||
}
|
||||
|
||||
type structStack []*Structure
|
||||
|
||||
// CurrentStruct will point to a struct record if we're in a struct declaration.
|
||||
// When the parser adds a declaration, it will be added to the open struct if
|
||||
// there is one.
|
||||
var CurrentStruct *Structure
|
||||
var CurrentStruct structStack
|
||||
|
||||
// Since it's possible to have an embedded struct definition, this implements
|
||||
// a stack to keep track of the current structure.
|
||||
func (s *structStack) empty() bool {
|
||||
return len(*s) == 0
|
||||
}
|
||||
func (s *structStack) push(st *Structure) {
|
||||
*s = append(*s, st)
|
||||
}
|
||||
func (s *structStack) pop() *Structure {
|
||||
if s.empty() {
|
||||
return nil
|
||||
}
|
||||
st := (*s)[len(*s)-1]
|
||||
*s = (*s)[:len(*s)-1]
|
||||
return st
|
||||
}
|
||||
func (s *structStack) peek() *Structure {
|
||||
if s.empty() {
|
||||
return nil
|
||||
}
|
||||
return (*s)[len(*s)-1]
|
||||
}
|
||||
|
||||
// CurrentTypedef will point to a typedef record if we're parsing one. Typedefs
|
||||
// can define a struct or union type, but the preferred for is struct xxx{...},
|
||||
@ -148,6 +221,7 @@ var CurrentCase *Case
|
||||
// the path to the root of the libvirt source directory to use for the
|
||||
// generation.
|
||||
func Generate(proto io.Reader) error {
|
||||
Gen.StructMap = make(map[string]int)
|
||||
lexer, err := NewLexer(proto)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -162,6 +236,10 @@ func Generate(proto io.Reader) error {
|
||||
return fmt.Errorf("failed to parse libvirt protocol: %v", rv)
|
||||
}
|
||||
|
||||
// When parsing is done, we can link the procedures we've found to their
|
||||
// argument types.
|
||||
procLink()
|
||||
|
||||
// Generate and write the output.
|
||||
constFile, err := os.Create("../constants/constants.gen.go")
|
||||
if err != nil {
|
||||
@ -216,26 +294,44 @@ func genGo(constFile, procFile io.Writer) error {
|
||||
// also tries to upcase abbreviations so a name like DOMAIN_GET_XML becomes
|
||||
// DomainGetXML, not DomainGetXml.
|
||||
func constNameTransform(name string) string {
|
||||
nn := fromSnakeToCamel(strings.TrimPrefix(name, "REMOTE_"), true)
|
||||
decamelize := strings.ContainsRune(name, '_')
|
||||
nn := strings.TrimPrefix(name, "REMOTE_")
|
||||
if decamelize {
|
||||
nn = fromSnakeToCamel(nn, true)
|
||||
}
|
||||
nn = fixAbbrevs(nn)
|
||||
return nn
|
||||
}
|
||||
|
||||
func identifierTransform(name string) string {
|
||||
decamelize := strings.ContainsRune(name, '_')
|
||||
nn := strings.TrimPrefix(name, "remote_")
|
||||
nn = fromSnakeToCamel(nn, false)
|
||||
if decamelize {
|
||||
nn = fromSnakeToCamel(nn, true)
|
||||
} else {
|
||||
nn = publicize(nn)
|
||||
}
|
||||
nn = fixAbbrevs(nn)
|
||||
nn = checkIdentifier(nn)
|
||||
return nn
|
||||
}
|
||||
|
||||
func typeTransform(name string) string {
|
||||
nn := strings.TrimLeft(name, "*")
|
||||
nn := strings.TrimLeft(name, "*[]")
|
||||
diff := len(name) - len(nn)
|
||||
nn = identifierTransform(nn)
|
||||
return name[0:diff] + nn
|
||||
}
|
||||
|
||||
func publicize(name string) string {
|
||||
if len(name) <= 0 {
|
||||
return name
|
||||
}
|
||||
r, n := utf8.DecodeRuneInString(name)
|
||||
name = string(unicode.ToUpper(r)) + name[n:]
|
||||
return name
|
||||
}
|
||||
|
||||
// fromSnakeToCamel transmutes a snake-cased string to a camel-cased one. All
|
||||
// runes that follow an underscore are up-cased, and the underscores themselves
|
||||
// are omitted.
|
||||
@ -292,6 +388,30 @@ func fixAbbrevs(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// procLink associates a libvirt procedure with the types that are its arguments
|
||||
// and return values, filling out those fields in the procedure struct. These
|
||||
// types are extracted by iterating through the argument and return structures
|
||||
// defined in the protocol file. If one or both of these structs is not defined
|
||||
// then either the args or return values are empty.
|
||||
func procLink() {
|
||||
for ix, proc := range Gen.Procs {
|
||||
argsName := proc.Name + "Args"
|
||||
retName := proc.Name + "Ret"
|
||||
argsIx, hasArgs := Gen.StructMap[argsName]
|
||||
retIx, hasRet := Gen.StructMap[retName]
|
||||
if hasArgs {
|
||||
argsStruct := Gen.Structs[argsIx]
|
||||
Gen.Procs[ix].ArgsStruct = argsStruct.Name
|
||||
Gen.Procs[ix].Args = argsStruct.Members
|
||||
}
|
||||
if hasRet {
|
||||
retStruct := Gen.Structs[retIx]
|
||||
Gen.Procs[ix].RetStruct = retStruct.Name
|
||||
Gen.Procs[ix].Ret = retStruct.Members
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Routines called by the parser's actions.
|
||||
//---------------------------------------------------------------------------
|
||||
@ -327,6 +447,7 @@ func addEnumVal(name string, val int64) error {
|
||||
name = constNameTransform(name)
|
||||
Gen.EnumVals = append(Gen.EnumVals, ConstItem{name, fmt.Sprintf("%d", val)})
|
||||
CurrentEnumVal = val
|
||||
addProc(name, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -341,6 +462,17 @@ func AddConst(name, val string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// addProc checks an enum value to see if it's a procedure number. If so, we
|
||||
// add the procedure to our list for later generation.
|
||||
func addProc(name string, val int64) {
|
||||
if !strings.HasPrefix(name, "Proc") {
|
||||
return
|
||||
}
|
||||
name = name[4:]
|
||||
proc := &Proc{Num: val, Name: name}
|
||||
Gen.Procs = append(Gen.Procs, *proc)
|
||||
}
|
||||
|
||||
// parseNumber makes sure that a parsed numerical value can be parsed to a 64-
|
||||
// bit integer.
|
||||
func parseNumber(val string) (int64, error) {
|
||||
@ -357,25 +489,22 @@ func parseNumber(val string) (int64, error) {
|
||||
// before the member declarations are processed.
|
||||
func StartStruct(name string) {
|
||||
name = identifierTransform(name)
|
||||
CurrentStruct = &Structure{Name: name}
|
||||
CurrentStruct.push(&Structure{Name: name})
|
||||
}
|
||||
|
||||
// AddStruct is called when the parser has finished parsing a struct. It adds
|
||||
// the now-complete struct definition to the generator's list.
|
||||
func AddStruct() {
|
||||
Gen.Structs = append(Gen.Structs, *CurrentStruct)
|
||||
CurrentStruct = nil
|
||||
st := *CurrentStruct.pop()
|
||||
Gen.Structs = append(Gen.Structs, st)
|
||||
Gen.StructMap[st.Name] = len(Gen.Structs) - 1
|
||||
}
|
||||
|
||||
// StartTypedef is called when the parser finds a typedef.
|
||||
func StartTypedef() {
|
||||
CurrentTypedef = &Typedef{}
|
||||
}
|
||||
|
||||
// TODO: remove before flight
|
||||
func Beacon(name string) {
|
||||
fmt.Println(name)
|
||||
}
|
||||
|
||||
// StartUnion is called by the parser when it finds a union declaraion.
|
||||
func StartUnion(name string) {
|
||||
name = identifierTransform(name)
|
||||
@ -384,16 +513,34 @@ func StartUnion(name string) {
|
||||
|
||||
// AddUnion is called by the parser when it has finished processing a union
|
||||
// type. It adds the union to the generator's list and clears the CurrentUnion
|
||||
// pointer.
|
||||
// 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.
|
||||
func AddUnion() {
|
||||
Gen.Unions = append(Gen.Unions, *CurrentUnion)
|
||||
CurrentUnion = nil
|
||||
}
|
||||
|
||||
// StartCase is called when the parser finds a case statement within a union.
|
||||
func StartCase(dvalue string) {
|
||||
CurrentCase = &Case{DiscriminantVal: dvalue}
|
||||
// In libvirt, the discriminant values are all C pre- processor definitions.
|
||||
// Since we don't run the C pre-processor on the protocol file, they're
|
||||
// still just names when we get them - we don't actually have their integer
|
||||
// values. We'll use the strings to build the type names, although this is
|
||||
// brittle, because we're defining a type for each of the case values, and
|
||||
// that type needs a name.
|
||||
caseName := dvalue
|
||||
if ix := strings.LastIndexByte(caseName, '_'); ix != -1 {
|
||||
caseName = caseName[ix+1:]
|
||||
}
|
||||
caseName = fromSnakeToCamel(caseName, true)
|
||||
dv, ok := lvTypedParams[dvalue]
|
||||
if ok {
|
||||
dvalue = strconv.FormatUint(uint64(dv), 10)
|
||||
}
|
||||
CurrentCase = &Case{CaseName: caseName, DiscriminantVal: dvalue}
|
||||
}
|
||||
|
||||
// AddCase is called when the parser finishes parsing a case.
|
||||
func AddCase() {
|
||||
CurrentUnion.Cases = append(CurrentUnion.Cases, *CurrentCase)
|
||||
CurrentCase = nil
|
||||
@ -403,27 +550,59 @@ func AddCase() {
|
||||
// The declaration will be added to any open container (such as a struct, if the
|
||||
// parser is working through a struct definition.)
|
||||
func AddDeclaration(identifier, itype string) {
|
||||
// TODO: panic if not in a struct/union/typedef?
|
||||
// fmt.Println("adding", identifier, itype)
|
||||
// If the name is a reserved word, transform it so it isn't.
|
||||
identifier = identifierTransform(identifier)
|
||||
itype = typeTransform(itype)
|
||||
decl := &Decl{Name: identifier, Type: itype}
|
||||
if CurrentStruct != nil {
|
||||
CurrentStruct.Members = append(CurrentStruct.Members, *decl)
|
||||
decl := Decl{Name: identifier, Type: itype}
|
||||
if !CurrentStruct.empty() {
|
||||
st := CurrentStruct.peek()
|
||||
st.Members = append(st.Members, decl)
|
||||
} else if CurrentTypedef != nil {
|
||||
CurrentTypedef.Name = identifier
|
||||
CurrentTypedef.Type = itype
|
||||
if identifier != "string" {
|
||||
// Omit recursive typedefs. These happen because we're massaging
|
||||
// some of the type names.
|
||||
Gen.Typedefs = append(Gen.Typedefs, *CurrentTypedef)
|
||||
}
|
||||
CurrentTypedef = nil
|
||||
} else if CurrentCase != nil {
|
||||
CurrentCase.Type = *decl
|
||||
CurrentCase.Name = identifier
|
||||
CurrentCase.Type = itype
|
||||
} else if CurrentUnion != nil {
|
||||
CurrentUnion.DiscriminantType = itype
|
||||
}
|
||||
}
|
||||
|
||||
// AddFixedArray is called by the parser to add a fixed-length array to the
|
||||
// current container (struct, union, etc). Fixed-length arrays are not length-
|
||||
// prefixed.
|
||||
func AddFixedArray(identifier, itype, len string) {
|
||||
atype := fmt.Sprintf("[%v]%v", len, itype)
|
||||
AddDeclaration(identifier, atype)
|
||||
}
|
||||
|
||||
// AddVariableArray is called by the parser to add a variable-length array.
|
||||
// Variable-length arrays are prefixed with a 32-bit unsigned length, and may
|
||||
// also have a maximum length specified.
|
||||
func AddVariableArray(identifier, itype, len string) {
|
||||
// FIXME: This ignores the length restriction, so as of now we can't check
|
||||
// to make sure that we're not exceeding that restriction when we fill in
|
||||
// message buffers. That may not matter, if libvirt's checking is careful
|
||||
// enough. This could be handled with a map, however.
|
||||
atype := fmt.Sprintf("[]%v", itype)
|
||||
// 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
|
||||
// these to be go strings, so we'll just remove the array specifier.
|
||||
if itype == "string" {
|
||||
atype = itype
|
||||
}
|
||||
AddDeclaration(identifier, atype)
|
||||
}
|
||||
|
||||
func checkIdentifier(i string) string {
|
||||
nn, reserved := reservedIdentifiers[i]
|
||||
nn, reserved := goEquivTypes[i]
|
||||
if reserved {
|
||||
return nn
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ import (
|
||||
// eof is returned by the lexer when there's no more input.
|
||||
const eof = -1
|
||||
|
||||
// oneRuneTokens lists the runes the lexer will consider to be tokens when it
|
||||
// finds them. These are returned to the parser using the integer value of their
|
||||
// runes.
|
||||
var oneRuneTokens = `{}[]<>(),=;:*`
|
||||
|
||||
type item struct {
|
||||
typ int
|
||||
val string
|
||||
|
@ -6,20 +6,82 @@
|
||||
|
||||
package libvirt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/davecgh/go-xdr/xdr2"
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
VirUUIDBuflen = 16
|
||||
)
|
||||
|
||||
// Typedefs:
|
||||
{{range .Typedefs}}type {{.Name}} {{.Type}}
|
||||
{{end}}
|
||||
// Enums:
|
||||
{{range .Enums}} type {{.Name}} {{.Type}}
|
||||
{{range .Enums}}type {{.Name}} {{.Type}}
|
||||
{{end}}
|
||||
// Structs:
|
||||
{{range .Structs}}type {{.Name}} struct {
|
||||
{{range .Members}} {{.Name}} {{.Type}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
{{end}}
|
||||
// Unions:
|
||||
{{range .Unions}}type {{.Name}} struct {
|
||||
discriminant {{.DiscriminantType}}
|
||||
{{range .Unions}}type {{.Name}} interface {
|
||||
Get() interface{}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
{{range .Unions}}{{$uname := .Name}}{{range .Cases}}{{$casetype := printf "%v%v" $uname .CaseName}}
|
||||
type {{$casetype}} struct {
|
||||
DVal uint32
|
||||
{{.Name}} {{.Type}}
|
||||
}
|
||||
func New{{$casetype}}(v {{.Type}}) *{{$casetype}} { return &{{$casetype}}{DVal: {{.DiscriminantVal}}, {{.Name}}: v} }
|
||||
func (c *{{$casetype}}) Get() interface{} { return c.{{.Name}} }
|
||||
{{end}}
|
||||
{{- end}}
|
||||
|
||||
// Procedures:
|
||||
{{range .Procs}}
|
||||
func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Name}} {{.Type}}{{end}}) ({{range .Ret}}r{{.Name}} {{.Type}}, {{end}}err error) {
|
||||
var buf bytes.Buffer
|
||||
{{if .ArgsStruct}}
|
||||
args := {{.ArgsStruct}} {
|
||||
{{range .Args}} {{.Name}}: {{.Name}},
|
||||
{{end}} }
|
||||
|
||||
buf, err = encode(&args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
var resp <-chan response
|
||||
resp, err = l.request({{.Num}}, constants.Program, &buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r := <-resp
|
||||
if r.Status != StatusOK {
|
||||
err = decodeError(r.Payload)
|
||||
return
|
||||
}
|
||||
{{if .RetStruct}}
|
||||
result := {{.RetStruct}}{}
|
||||
rdr := bytes.NewReader(r.Payload)
|
||||
dec := xdr.NewDecoder(rdr)
|
||||
_, err = dec.Decode(&result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
{{range .Ret}} r{{.Name}} = result.{{.Name}}
|
||||
{{end}}{{end}}
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
|
@ -119,7 +119,7 @@ type_specifier
|
||||
| DOUBLE {$$.val = "float64"}
|
||||
| BOOL {$$.val = "bool"}
|
||||
| STRING {$$.val = "string"}
|
||||
| OPAQUE {$$.val = "[]byte"}
|
||||
| OPAQUE {$$.val = "byte"}
|
||||
| enum_definition
|
||||
| struct_definition
|
||||
| union_definition
|
||||
@ -138,12 +138,12 @@ variable_ident
|
||||
;
|
||||
|
||||
fixed_array_declaration
|
||||
: type_specifier variable_ident '[' value ']' { AddDeclaration($2.val, $1.val) } // FIXME: Handle the max size (value)?
|
||||
: type_specifier variable_ident '[' value ']' { AddFixedArray($2.val, $1.val, $4.val) }
|
||||
;
|
||||
|
||||
variable_array_declaration
|
||||
: type_specifier variable_ident '<' value '>' { AddDeclaration($2.val, $1.val) } // FIXME: Handle the max size (value)?
|
||||
| type_specifier variable_ident '<' '>' { AddDeclaration($2.val, $1.val) }
|
||||
: type_specifier variable_ident '<' value '>' { AddVariableArray($2.val, $1.val, $4.val) }
|
||||
| type_specifier variable_ident '<' '>' { AddVariableArray($2.val, $1.val, "") }
|
||||
;
|
||||
|
||||
pointer_declaration
|
||||
@ -151,7 +151,7 @@ pointer_declaration
|
||||
;
|
||||
|
||||
struct_definition
|
||||
: STRUCT struct_ident '{' {StartStruct($2.val)} declaration_list '}' {AddStruct()}
|
||||
: STRUCT struct_ident '{' {StartStruct($2.val)} declaration_list '}' { AddStruct() }
|
||||
;
|
||||
|
||||
struct_ident
|
||||
|
18119
libvirt.gen.go
18119
libvirt.gen.go
File diff suppressed because it is too large
Load Diff
352
libvirt.go
352
libvirt.go
@ -53,11 +53,11 @@ type Libvirt struct {
|
||||
}
|
||||
|
||||
// Domain represents a domain as seen by libvirt.
|
||||
type Domain struct {
|
||||
Name string
|
||||
UUID [constants.UUIDSize]byte
|
||||
ID int
|
||||
}
|
||||
// type Domain struct {
|
||||
// Name string
|
||||
// UUID [constants.UUIDSize]byte
|
||||
// ID int
|
||||
// }
|
||||
|
||||
// DomainEvent represents a libvirt domain event.
|
||||
type DomainEvent struct {
|
||||
@ -71,17 +71,17 @@ type DomainEvent struct {
|
||||
}
|
||||
|
||||
// Secret represents a secret managed by the libvirt daemon.
|
||||
type Secret struct {
|
||||
UUID [constants.UUIDSize]byte
|
||||
UsageType SecretUsageType
|
||||
UsageID string
|
||||
}
|
||||
// type Secret struct {
|
||||
// UUID [constants.UUIDSize]byte
|
||||
// UsageType SecretUsageType
|
||||
// UsageID string
|
||||
// }
|
||||
|
||||
// StoragePool represents a storage pool as seen by libvirt.
|
||||
type StoragePool struct {
|
||||
Name string
|
||||
UUID [constants.UUIDSize]byte
|
||||
}
|
||||
// type StoragePool struct {
|
||||
// Name string
|
||||
// UUID [constants.UUIDSize]byte
|
||||
// }
|
||||
|
||||
// qemuError represents a QEMU process error.
|
||||
type qemuError struct {
|
||||
@ -140,42 +140,42 @@ const (
|
||||
// TypedParam represents libvirt's virTypedParameter, which is used to pass
|
||||
// typed parameters to libvirt functions. This is defined as an interface, and
|
||||
// implemented by TypedParam... concrete types.
|
||||
type TypedParam interface {
|
||||
Field() string
|
||||
Value() interface{}
|
||||
}
|
||||
// type TypedParam interface {
|
||||
// Field() string
|
||||
// Value() interface{}
|
||||
// }
|
||||
|
||||
// TypedParamInt contains a 32-bit signed integer.
|
||||
type TypedParamInt struct {
|
||||
Fld string
|
||||
PType int32
|
||||
Padding [4]byte
|
||||
Val int32
|
||||
}
|
||||
// type TypedParamInt struct {
|
||||
// Fld string
|
||||
// PType int32
|
||||
// Padding [4]byte
|
||||
// Val int32
|
||||
// }
|
||||
|
||||
// Field returns the field name, a string name for the parameter.
|
||||
func (tp *TypedParamInt) Field() string {
|
||||
return tp.Fld
|
||||
}
|
||||
// func (tp *TypedParamInt) Field() string {
|
||||
// return tp.Fld
|
||||
// }
|
||||
|
||||
// Value returns the value for the typed parameter, as an empty interface.
|
||||
func (tp *TypedParamInt) Value() interface{} {
|
||||
return tp.Val
|
||||
}
|
||||
// func (tp *TypedParamInt) Value() interface{} {
|
||||
// return tp.Val
|
||||
// }
|
||||
|
||||
// NewTypedParamInt returns a TypedParam encoding for an int.
|
||||
func NewTypedParamInt(name string, v int32) *TypedParamInt {
|
||||
// Truncate the field name if it's longer than the limit.
|
||||
if len(name) > constants.TypedParamFieldLength {
|
||||
name = name[:constants.TypedParamFieldLength]
|
||||
}
|
||||
tp := TypedParamInt{
|
||||
Fld: name,
|
||||
PType: TypeParamInt,
|
||||
Val: v,
|
||||
}
|
||||
return &tp
|
||||
}
|
||||
// func NewTypedParamInt(name string, v int32) *TypedParamInt {
|
||||
// // Truncate the field name if it's longer than the limit.
|
||||
// if len(name) > constants.TypedParamFieldLength {
|
||||
// name = name[:constants.TypedParamFieldLength]
|
||||
// }
|
||||
// tp := TypedParamInt{
|
||||
// Fld: name,
|
||||
// PType: TypeParamInt,
|
||||
// Val: v,
|
||||
// }
|
||||
// return &tp
|
||||
// }
|
||||
|
||||
// TypedParamULongLong contains a 64-bit unsigned integer.
|
||||
type TypedParamULongLong struct {
|
||||
@ -226,17 +226,17 @@ func (tp *TypedParamString) Value() interface{} {
|
||||
}
|
||||
|
||||
// NewTypedParamString returns a typed parameter containing the passed string.
|
||||
func NewTypedParamString(name string, v string) TypedParam {
|
||||
if len(name) > constants.TypedParamFieldLength {
|
||||
name = name[:constants.TypedParamFieldLength]
|
||||
}
|
||||
tp := TypedParamString{
|
||||
Fld: name,
|
||||
PType: TypeParamString,
|
||||
Val: v,
|
||||
}
|
||||
return &tp
|
||||
}
|
||||
// func NewTypedParamString(name string, v string) TypedParam {
|
||||
// if len(name) > constants.TypedParamFieldLength {
|
||||
// name = name[:constants.TypedParamFieldLength]
|
||||
// }
|
||||
// tp := TypedParamString{
|
||||
// Fld: name,
|
||||
// PType: TypeParamString,
|
||||
// Val: v,
|
||||
// }
|
||||
// return &tp
|
||||
// }
|
||||
|
||||
const (
|
||||
// DomainXMLFlagSecure dumps XML with sensitive information included.
|
||||
@ -507,10 +507,10 @@ const (
|
||||
)
|
||||
|
||||
// DomainMemoryStat specifies memory stats of the domain
|
||||
type DomainMemoryStat struct {
|
||||
Tag DomainMemoryStatTag
|
||||
Val uint64
|
||||
}
|
||||
// type DomainMemoryStat struct {
|
||||
// Tag DomainMemoryStatTag
|
||||
// Val uint64
|
||||
// }
|
||||
|
||||
// Capabilities returns an XML document describing the host's capabilties.
|
||||
func (l *Libvirt) Capabilities() ([]byte, error) {
|
||||
@ -596,76 +596,76 @@ func (l *Libvirt) Domains() ([]Domain, error) {
|
||||
}
|
||||
|
||||
// DomainCreateWithFlags starts specified domain with flags
|
||||
func (l *Libvirt) DomainCreateWithFlags(dom string, flags DomainCreateFlags) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req := struct {
|
||||
Domain Domain
|
||||
Flags DomainCreateFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
buf, err := encode(&req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := l.request(constants.ProcDomainCreateWithFlags, constants.Program, &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := <-resp
|
||||
if r.Status != StatusOK {
|
||||
return decodeError(r.Payload)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// func (l *Libvirt) DomainCreateWithFlags(dom string, flags DomainCreateFlags) error {
|
||||
// d, err := l.lookup(dom)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// req := struct {
|
||||
// Domain Domain
|
||||
// Flags DomainCreateFlags
|
||||
// }{
|
||||
// Domain: *d,
|
||||
// Flags: flags,
|
||||
// }
|
||||
//
|
||||
// buf, err := encode(&req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// resp, err := l.request(constants.ProcDomainCreateWithFlags, constants.Program, &buf)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// r := <-resp
|
||||
// if r.Status != StatusOK {
|
||||
// return decodeError(r.Payload)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// DomainMemoryStats returns memory stats of the domain managed by libvirt.
|
||||
func (l *Libvirt) DomainMemoryStats(dom string) ([]DomainMemoryStat, error) {
|
||||
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := struct {
|
||||
Domain Domain
|
||||
MaxStats uint32
|
||||
Flags uint32
|
||||
}{
|
||||
Domain: *d,
|
||||
MaxStats: 8,
|
||||
Flags: 0,
|
||||
}
|
||||
|
||||
buf, err := encode(&req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := l.request(constants.ProcDomainMemoryStats, constants.Program, &buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := <-resp
|
||||
|
||||
result := struct {
|
||||
DomainMemoryStats []DomainMemoryStat
|
||||
}{}
|
||||
|
||||
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
|
||||
_, err = dec.Decode(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.DomainMemoryStats, nil
|
||||
}
|
||||
// func (l *Libvirt) DomainMemoryStats(dom string) ([]DomainMemoryStat, error) {
|
||||
//
|
||||
// d, err := l.lookup(dom)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// req := struct {
|
||||
// Domain Domain
|
||||
// MaxStats uint32
|
||||
// Flags uint32
|
||||
// }{
|
||||
// Domain: *d,
|
||||
// MaxStats: 8,
|
||||
// Flags: 0,
|
||||
// }
|
||||
//
|
||||
// buf, err := encode(&req)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// resp, err := l.request(constants.ProcDomainMemoryStats, constants.Program, &buf)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// r := <-resp
|
||||
//
|
||||
// result := struct {
|
||||
// DomainMemoryStats []DomainMemoryStat
|
||||
// }{}
|
||||
//
|
||||
// dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
|
||||
// _, err = dec.Decode(&result)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// return result.DomainMemoryStats, nil
|
||||
// }
|
||||
|
||||
// DomainState returns state of the domain managed by libvirt.
|
||||
func (l *Libvirt) DomainState(dom string) (DomainState, error) {
|
||||
@ -678,7 +678,7 @@ func (l *Libvirt) DomainState(dom string) (DomainState, error) {
|
||||
Domain Domain
|
||||
Flags uint32
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: 0,
|
||||
}
|
||||
|
||||
@ -728,7 +728,7 @@ func (l *Libvirt) Events(dom string) (<-chan DomainEvent, error) {
|
||||
Flags [2]byte
|
||||
}{
|
||||
Padding: [4]byte{0x0, 0x0, 0x1, 0x0},
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Event: [2]byte{0x0, 0x0},
|
||||
Flags: [2]byte{0x0, 0x0},
|
||||
}
|
||||
@ -801,7 +801,7 @@ func (l *Libvirt) Migrate(dom string, dest string, flags MigrateFlags) error {
|
||||
CookieIn uint32
|
||||
Flags MigrateFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Padding: [4]byte{0x0, 0x0, 0x0, 0x1},
|
||||
DestinationURI: dest,
|
||||
RemoteParameters: 0,
|
||||
@ -844,7 +844,7 @@ func (l *Libvirt) MigrateSetMaxSpeed(dom string, speed int64) error {
|
||||
Flags uint32
|
||||
}{
|
||||
Padding: [4]byte{0x0, 0x0, 0x1, 0x0},
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Bandwidth: speed,
|
||||
}
|
||||
|
||||
@ -880,7 +880,7 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
|
||||
Command []byte
|
||||
Flags uint32
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Command: cmd,
|
||||
Flags: 0,
|
||||
}
|
||||
@ -959,7 +959,7 @@ func (l *Libvirt) Secrets() ([]Secret, error) {
|
||||
|
||||
// StoragePool returns the storage pool associated with the provided name.
|
||||
// An error is returned if the requested storage pool is not found.
|
||||
func (l *Libvirt) StoragePool(name string) (*StoragePool, error) {
|
||||
func (l *Libvirt) StoragePool(name string) (StoragePool, error) {
|
||||
req := struct {
|
||||
Name string
|
||||
}{
|
||||
@ -991,41 +991,41 @@ func (l *Libvirt) StoragePool(name string) (*StoragePool, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result.Pool, nil
|
||||
return result.Pool, nil
|
||||
}
|
||||
|
||||
// StoragePoolRefresh refreshes the storage pool specified by name.
|
||||
func (l *Libvirt) StoragePoolRefresh(name string) error {
|
||||
pool, err := l.StoragePool(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := struct {
|
||||
Pool StoragePool
|
||||
Flags uint32
|
||||
}{
|
||||
Pool: *pool,
|
||||
Flags: 0, // unused per libvirt source, callers should pass 0
|
||||
}
|
||||
|
||||
buf, err := encode(&req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := l.request(constants.ProcStoragePoolRefresh, constants.Program, &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := <-resp
|
||||
if r.Status != StatusOK {
|
||||
return decodeError(r.Payload)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// func (l *Libvirt) StoragePoolRefresh(name string) error {
|
||||
// pool, err := l.StoragePool(name)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// req := struct {
|
||||
// Pool StoragePool
|
||||
// Flags uint32
|
||||
// }{
|
||||
// Pool: *pool,
|
||||
// Flags: 0, // unused per libvirt source, callers should pass 0
|
||||
// }
|
||||
//
|
||||
// buf, err := encode(&req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// resp, err := l.request(constants.ProcStoragePoolRefresh, constants.Program, &buf)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// r := <-resp
|
||||
// if r.Status != StatusOK {
|
||||
// return decodeError(r.Payload)
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// StoragePools returns a list of defined storage pools. Pools are filtered by
|
||||
// the provided flags. See StoragePools*.
|
||||
@ -1081,7 +1081,7 @@ func (l *Libvirt) Undefine(dom string, flags UndefineFlags) error {
|
||||
Domain Domain
|
||||
Flags UndefineFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
@ -1117,7 +1117,7 @@ func (l *Libvirt) Destroy(dom string, flags DestroyFlags) error {
|
||||
Domain Domain
|
||||
Flags DestroyFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
@ -1151,7 +1151,7 @@ func (l *Libvirt) XML(dom string, flags DomainXMLFlags) ([]byte, error) {
|
||||
Domain Domain
|
||||
Flags DomainXMLFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
@ -1255,7 +1255,7 @@ func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error {
|
||||
Domain Domain
|
||||
Flags ShutdownFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
@ -1289,7 +1289,7 @@ func (l *Libvirt) Reboot(dom string, flags RebootFlags) error {
|
||||
Domain Domain
|
||||
Flags RebootFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: flags,
|
||||
}
|
||||
|
||||
@ -1322,7 +1322,7 @@ func (l *Libvirt) Reset(dom string) error {
|
||||
Domain Domain
|
||||
Flags uint32
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Flags: 0,
|
||||
}
|
||||
|
||||
@ -1405,14 +1405,15 @@ func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit)
|
||||
Params []TypedParam
|
||||
Flags DomainAffectFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Disk: disk,
|
||||
Flags: FlagDomainAffectLive,
|
||||
}
|
||||
|
||||
for _, limit := range limits {
|
||||
tp := NewTypedParamULongLong(limit.Name, limit.Value)
|
||||
payload.Params = append(payload.Params, tp)
|
||||
tpval := NewTypedParamValueUllong(limit.Value)
|
||||
tp := &TypedParam{Field: limit.Name, Value: tpval}
|
||||
payload.Params = append(payload.Params, *tp)
|
||||
}
|
||||
|
||||
buf, err := encode(&payload)
|
||||
@ -1446,7 +1447,7 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
|
||||
ParamCount uint32
|
||||
Flags DomainAffectFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Domain: d,
|
||||
Disk: []string{disk},
|
||||
ParamCount: 32,
|
||||
Flags: FlagTypedParamStringOkay,
|
||||
@ -1516,7 +1517,7 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
|
||||
}
|
||||
|
||||
// lookup returns a domain as seen by libvirt.
|
||||
func (l *Libvirt) lookup(name string) (*Domain, error) {
|
||||
func (l *Libvirt) lookup(name string) (Domain, error) {
|
||||
payload := struct {
|
||||
Name string
|
||||
}{name}
|
||||
@ -1538,7 +1539,8 @@ func (l *Libvirt) lookup(name string) (*Domain, error) {
|
||||
|
||||
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
|
||||
|
||||
var d Domain
|
||||
// var d Domain
|
||||
var d NonnullDomain
|
||||
_, err = dec.Decode(&d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -107,7 +107,7 @@ func TestDomains(t *testing.T) {
|
||||
|
||||
for i, d := range domains {
|
||||
wantID := i + 1
|
||||
if d.ID != wantID {
|
||||
if d.ID != int32(wantID) {
|
||||
t.Errorf("expected domain ID %q, got %q", wantID, d.ID)
|
||||
}
|
||||
|
||||
@ -148,17 +148,27 @@ func TestDomainMemoryStats(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
gotDomainMemoryStats, err := l.DomainMemoryStats("test")
|
||||
d, err := l.lookup("test")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
gotDomainMemoryStats, err := l.DomainMemoryStats(*d, 8, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
t.Log(gotDomainMemoryStats)
|
||||
|
||||
if len(gotDomainMemoryStats) == 0 {
|
||||
t.Error("No memory stats returned!")
|
||||
}
|
||||
|
||||
for i := range wantDomainMemoryStats {
|
||||
if wantDomainMemoryStats[i] != gotDomainMemoryStats[i] {
|
||||
t.Errorf("expected domain memory stat %v, got %v", wantDomainMemoryStats[i], gotDomainMemoryStats[i])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestEvents(t *testing.T) {
|
||||
@ -265,7 +275,7 @@ func TestSecrets(t *testing.T) {
|
||||
}
|
||||
|
||||
s := secrets[0]
|
||||
wantType := SecretUsageTypeVolume
|
||||
wantType := int32(SecretUsageTypeVolume)
|
||||
if s.UsageType != wantType {
|
||||
t.Errorf("expected usage type %d, got %d", wantType, s.UsageType)
|
||||
}
|
||||
@ -347,7 +357,11 @@ func TestStoragePoolRefresh(t *testing.T) {
|
||||
conn := libvirttest.New()
|
||||
l := New(conn)
|
||||
|
||||
err := l.StoragePoolRefresh("default")
|
||||
pool, err := l.StoragePool("default")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = l.StoragePoolRefresh(*pool, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -403,8 +417,12 @@ func TestDomainCreateWithFlags(t *testing.T) {
|
||||
conn := libvirttest.New()
|
||||
l := New(conn)
|
||||
|
||||
var flags DomainCreateFlags
|
||||
if err := l.DomainCreateWithFlags("test", flags); err != nil {
|
||||
d, err := l.lookup("test")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to lookup domain: %v", err)
|
||||
}
|
||||
var flags uint32
|
||||
if _, err := l.DomainCreateWithFlags(*d, flags); err != nil {
|
||||
t.Fatalf("unexpected create error: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ var (
|
||||
0x00, 0x00, 0x00, 0x02,
|
||||
}
|
||||
|
||||
testDomain = Domain{
|
||||
testDomain = &NonnullDomain{
|
||||
Name: "test-domain",
|
||||
UUID: testUUID,
|
||||
ID: 1,
|
||||
@ -177,7 +177,7 @@ func TestDecodeEvent(t *testing.T) {
|
||||
t.Errorf("expected uuid:\t%x, got\n\t\t\t%x", expUUID, e.Domain.UUID)
|
||||
}
|
||||
|
||||
expID := 14
|
||||
expID := int32(14)
|
||||
if e.Domain.ID != expID {
|
||||
t.Errorf("expected id %d, got %d", expID, e.Domain.ID)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user