Migrate all libvirt calls to the generated code.

- Update libvirt.go so that all libvirt calls now go through the
generated routines.
- Remove some libvirt routines that had the same name as generated ones,
leave the rest as convenience routines.
- Fix the handling of Optional-values (the declarations of which in the
.x file look like pointers)
This commit is contained in:
Geoff Hickey 2017-11-16 14:17:46 -05:00
parent a3bd42a5b1
commit b59e9d42f4
7 changed files with 297 additions and 1101 deletions

View File

@ -25,6 +25,10 @@ import (
"unicode/utf8" "unicode/utf8"
) )
// If you're making changes to the generator, or troubleshooting the generated
// code, the docs for sunrpc and xdr (the line encoding) are helpful:
// https://docs.oracle.com/cd/E26502_01/html/E35597/
// 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 {
@ -81,7 +85,6 @@ var goEquivTypes = map[string]string{
// TODO: Get rid of these. They're only needed because we lose information // 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 // that the parser has (the parser knows it has emitted a go type), and then
// we capitalize types to make them public. // we capitalize types to make them public.
"String": "string",
"Int": "int", "Int": "int",
"Uint": "uint", "Uint": "uint",
"Int8": "int8", "Int8": "int8",
@ -580,7 +583,7 @@ func checkIdentifier(i string) string {
} }
// GetUnion returns the type information for a union. If the provided type name // GetUnion returns the type information for a union. If the provided type name
// isn't a union, the second return value will be false. // isn't a union, this will return a zero-value Union type.
func (decl *Decl) GetUnion() Union { func (decl *Decl) GetUnion() Union {
ix, ok := Gen.UnionMap[decl.Type] ix, ok := Gen.UnionMap[decl.Type]
if ok { if ok {

View File

@ -42,8 +42,10 @@ type {{$casetype}} struct {
DVal uint32 DVal uint32
{{.Name}} {{.Type}} {{.Name}} {{.Type}}
} }
func New{{$casetype}}(v {{.Type}}) *{{$casetype}} { return &{{$casetype}}{DVal: {{.DiscriminantVal}}, {{.Name}}: v} } func New{{$casetype}}(v {{.Type}}) *{{$casetype}} {
func Decode{{$casetype}}(dec *xdr.Decoder) (*{{$casetype}}, error) { return &{{$casetype}}{DVal: {{.DiscriminantVal}}, {{.Name}}: v}
}
func decode{{$casetype}}(dec *xdr.Decoder) (*{{$casetype}}, error) {
var v {{.Type}} var v {{.Type}}
_, err := dec.Decode(&v) _, err := dec.Decode(&v)
if err != nil { if err != nil {
@ -53,49 +55,46 @@ func Decode{{$casetype}}(dec *xdr.Decoder) (*{{$casetype}}, error) {
} }
func (c *{{$casetype}}) Get() interface{} { return c.{{.Name}} } func (c *{{$casetype}}) Get() interface{} { return c.{{.Name}} }
{{end}} {{end}}
{{- end}} func decode{{.Name}}(dec *xdr.Decoder) ({{.Name}}, error) {
discriminant, _, err := dec.DecodeInt()
// TODO: Generate this.
func decodeTypedParams(dec *xdr.Decoder) ([]TypedParam, error) {
count, _, err := dec.DecodeInt()
params := make([]TypedParam, count)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for ix := int32(0); ix < count; ix++ { var caseval {{.Name}}
switch discriminant {
{{range .Cases}}{{$casetype := printf "%v%v" $uname .CaseName}} case {{.DiscriminantVal}}:
caseval, err = decode{{$casetype}}(dec)
{{end}}
default:
err = fmt.Errorf("invalid parameter type %v", discriminant)
}
return caseval, err
}
{{- end}}
// TODO: Generate these.
func decodeTypedParam(dec *xdr.Decoder) (*TypedParam, error) {
name, _, err := dec.DecodeString() name, _, err := dec.DecodeString()
if err != nil { if err != nil {
return nil, err return nil, err
} }
ptype, _, err := dec.DecodeInt() val, err := decodeTypedParamValue(dec)
return &TypedParam{name, val}, nil
}
func decodeTypedParams(dec *xdr.Decoder) ([]TypedParam, error) {
count, _, err := dec.DecodeInt()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var tpv TypedParamValue params := make([]TypedParam, count)
switch ptype { for ix := int32(0); ix < count; ix++ {
case 1: // TypedParamValueInt p, err := decodeTypedParam(dec)
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 { if err != nil {
return nil, err return nil, err
} }
params[ix] = *p
params[ix] = TypedParam{name, tpv}
} }
return params, nil return params, nil
@ -131,17 +130,16 @@ func (l *Libvirt) {{.Name}}({{range $ix, $arg := .Args}}{{if $ix}}, {{end}}{{.Na
rdr := bytes.NewReader(r.Payload) rdr := bytes.NewReader(r.Payload)
dec := xdr.NewDecoder(rdr) dec := xdr.NewDecoder(rdr)
{{range .Ret}} // {{.Name}}: {{.Type}} {{range .Ret}} // {{.Name}}: {{.Type}}
{{if eq .Type "[]TypedParam"}} // {{.Name}} {{if eq .Type "[]TypedParam"}} r{{.Name}}, err = decodeTypedParams(dec)
r{{.Name}}, err = decodeTypedParams(dec)
if err != nil { if err != nil {
fmt.Println("error decoding typedparams")
return return
} }
{{else}} _, err = dec.Decode(&r{{.Name}}) {{else}} _, err = dec.Decode(&r{{.Name}})
if err != nil { if err != nil {
return return
} }
{{end}}{{end}} {{end}}{{end}}{{end}}
{{end}}
return return
} }
{{end}} {{end}}

View File

@ -146,8 +146,12 @@ variable_array_declaration
| type_specifier variable_ident '<' '>' { AddVariableArray($2.val, $1.val, "") } | type_specifier variable_ident '<' '>' { AddVariableArray($2.val, $1.val, "") }
; ;
// while pointer_declarations may look like their familiar c-equivalents, in the
// XDR language they actually declare "Optional-data". The simplest
// representation to use for these is a variable-length array with a size of 1.
// See the XDR spec for a more complete explanation of this.
pointer_declaration pointer_declaration
: type_specifier '*' variable_ident { AddDeclaration($3.val, "*"+$1.val) } : type_specifier '*' variable_ident { AddVariableArray($3.val, $1.val, "1") }
; ;
struct_definition struct_definition

File diff suppressed because it is too large Load Diff

View File

@ -52,17 +52,10 @@ type Libvirt struct {
s uint32 s uint32
} }
// Domain represents a domain as seen by libvirt.
// type Domain struct {
// Name string
// UUID [constants.UUIDSize]byte
// ID int
// }
// DomainEvent represents a libvirt domain event. // DomainEvent represents a libvirt domain event.
type DomainEvent struct { type DomainEvent struct {
CallbackID uint32 CallbackID uint32
Domain Domain Domain NonnullDomain
Event string Event string
Seconds uint64 Seconds uint64
Microseconds uint32 Microseconds uint32
@ -70,19 +63,6 @@ type DomainEvent struct {
Details []byte Details []byte
} }
// Secret represents a secret managed by the libvirt daemon.
// 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
// }
// qemuError represents a QEMU process error. // qemuError represents a QEMU process error.
type qemuError struct { type qemuError struct {
Error struct { Error struct {
@ -137,46 +117,6 @@ const (
TypeParamLast TypeParamLast
) )
// 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{}
// }
// TypedParamInt contains a 32-bit signed integer.
// 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
// }
// Value returns the value for the typed parameter, as an empty interface.
// 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
// }
// TypedParamULongLong contains a 64-bit unsigned integer. // TypedParamULongLong contains a 64-bit unsigned integer.
type TypedParamULongLong struct { type TypedParamULongLong struct {
Fld string Fld string
@ -506,27 +446,9 @@ const (
DomainMemoryStatTagNr DomainMemoryStatTagNr
) )
// DomainMemoryStat specifies memory stats of the domain
// type DomainMemoryStat struct {
// Tag DomainMemoryStatTag
// Val uint64
// }
// Capabilities returns an XML document describing the host's capabilties. // Capabilities returns an XML document describing the host's capabilties.
func (l *Libvirt) Capabilities() ([]byte, error) { func (l *Libvirt) Capabilities() ([]byte, error) {
resp, err := l.request(constants.ProcConnectGetCapabilities, constants.Program, nil) caps, err := l.ConnectGetCapabilities()
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
caps, _, err := dec.DecodeString()
return []byte(caps), err return []byte(caps), err
} }
@ -555,118 +477,13 @@ func (l *Libvirt) Disconnect() error {
} }
// Domains returns a list of all domains managed by libvirt. // Domains returns a list of all domains managed by libvirt.
func (l *Libvirt) Domains() ([]Domain, error) { func (l *Libvirt) Domains() ([]NonnullDomain, error) {
// these are the flags as passed by `virsh`, defined in: // these are the flags as passed by `virsh`, defined in:
// src/remote/remote_protocol.x # remote_connect_list_all_domains_args // src/remote/remote_protocol.x # remote_connect_list_all_domains_args
req := struct { domains, _, err := l.ConnectListAllDomains(1, 3)
NeedResults uint32 return domains, err
Flags uint32
}{
NeedResults: 1,
Flags: 3,
}
buf, err := encode(&req)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcConnectListAllDomains, constants.Program, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
result := struct {
Domains []Domain
Count uint32
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return nil, err
}
return result.Domains, nil
} }
// 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
// }
// 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
// }
// DomainState returns state of the domain managed by libvirt. // DomainState returns state of the domain managed by libvirt.
func (l *Libvirt) DomainState(dom string) (DomainState, error) { func (l *Libvirt) DomainState(dom string) (DomainState, error) {
d, err := l.lookup(dom) d, err := l.lookup(dom)
@ -674,41 +491,8 @@ func (l *Libvirt) DomainState(dom string) (DomainState, error) {
return DomainStateNoState, err return DomainStateNoState, err
} }
req := struct { state, _, err := l.DomainGetState(d, 0)
Domain Domain return DomainState(state), err
Flags uint32
}{
Domain: d,
Flags: 0,
}
buf, err := encode(&req)
if err != nil {
return DomainStateNoState, err
}
resp, err := l.request(constants.ProcDomainGetState, constants.Program, &buf)
if err != nil {
return DomainStateNoState, err
}
r := <-resp
if r.Status != StatusOK {
return DomainStateNoState, decodeError(r.Payload)
}
result := struct {
State uint32
Reason uint32
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return DomainStateNoState, err
}
return DomainState(result.State), nil
} }
// Events streams domain events. // Events streams domain events.
@ -723,7 +507,7 @@ func (l *Libvirt) Events(dom string) (<-chan DomainEvent, error) {
payload := struct { payload := struct {
Padding [4]byte Padding [4]byte
Domain Domain Domain NonnullDomain
Event [2]byte Event [2]byte
Flags [2]byte Flags [2]byte
}{ }{
@ -793,39 +577,11 @@ func (l *Libvirt) Migrate(dom string, dest string, flags MigrateFlags) error {
// and CookieIn. In testing both values are always set to 0 by virsh // and CookieIn. In testing both values are always set to 0 by virsh
// and the source does not provide clear definitions of their purpose. // and the source does not provide clear definitions of their purpose.
// For now, using the same zero'd values as done by virsh will be Good Enough. // For now, using the same zero'd values as done by virsh will be Good Enough.
payload := struct { destURI := []string{dest}
Domain Domain remoteParams := []TypedParam{}
Padding [4]byte cookieIn := []byte{}
DestinationURI string _, err = l.DomainMigratePerform3Params(d, destURI, remoteParams, cookieIn, uint32(flags))
RemoteParameters uint32
CookieIn uint32
Flags MigrateFlags
}{
Domain: d,
Padding: [4]byte{0x0, 0x0, 0x0, 0x1},
DestinationURI: dest,
RemoteParameters: 0,
CookieIn: 0,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err return err
}
resp, err := l.request(constants.ProcDomainMigratePerform3Params,
constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// MigrateSetMaxSpeed set the maximum migration bandwidth (in MiB/s) for a // MigrateSetMaxSpeed set the maximum migration bandwidth (in MiB/s) for a
@ -837,33 +593,7 @@ func (l *Libvirt) MigrateSetMaxSpeed(dom string, speed int64) error {
return err return err
} }
payload := struct { return l.DomainMigrateSetMaxSpeed(d, uint64(speed), 0)
Padding [4]byte
Domain Domain
Bandwidth int64
Flags uint32
}{
Padding: [4]byte{0x0, 0x0, 0x1, 0x0},
Domain: d,
Bandwidth: speed,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainMigrateSetMaxSpeed, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// Run executes the given QAPI command against a domain's QEMU instance. // Run executes the given QAPI command against a domain's QEMU instance.
@ -876,7 +606,7 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
} }
payload := struct { payload := struct {
Domain Domain Domain NonnullDomain
Command []byte Command []byte
Flags uint32 Flags uint32
}{ }{
@ -919,7 +649,7 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) {
} }
// Secrets returns all secrets managed by the libvirt daemon. // Secrets returns all secrets managed by the libvirt daemon.
func (l *Libvirt) Secrets() ([]Secret, error) { func (l *Libvirt) Secrets() ([]NonnullSecret, error) {
req := struct { req := struct {
NeedResults uint32 NeedResults uint32
Flags uint32 Flags uint32
@ -944,7 +674,7 @@ func (l *Libvirt) Secrets() ([]Secret, error) {
} }
result := struct { result := struct {
Secrets []Secret Secrets []NonnullSecret
Count uint32 Count uint32
}{} }{}
@ -959,112 +689,15 @@ func (l *Libvirt) Secrets() ([]Secret, error) {
// StoragePool returns the storage pool associated with the provided name. // StoragePool returns the storage pool associated with the provided name.
// An error is returned if the requested storage pool is not found. // 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) (NonnullStoragePool, error) {
req := struct { return l.StoragePoolLookupByName(name)
Name string
}{
Name: name,
}
buf, err := encode(&req)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcStoragePoolLookupByName, constants.Program, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
result := struct {
Pool StoragePool
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return nil, err
}
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
// }
// StoragePools returns a list of defined storage pools. Pools are filtered by // StoragePools returns a list of defined storage pools. Pools are filtered by
// the provided flags. See StoragePools*. // the provided flags. See StoragePools*.
func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]StoragePool, error) { func (l *Libvirt) StoragePools(flags StoragePoolsFlags) ([]NonnullStoragePool, error) {
req := struct { pools, _, err := l.ConnectListAllStoragePools(1, uint32(flags))
NeedResults uint32 return pools, err
Flags StoragePoolsFlags
}{
NeedResults: 1,
Flags: flags,
}
buf, err := encode(&req)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcConnectListAllStoragePools, constants.Program, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
result := struct {
Pools []StoragePool
Count uint32
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil {
return nil, err
}
return result.Pools, nil
} }
// Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'. // Undefine undefines the domain specified by dom, e.g., 'prod-lb-01'.
@ -1077,30 +710,7 @@ func (l *Libvirt) Undefine(dom string, flags UndefineFlags) error {
return err return err
} }
payload := struct { return l.DomainUndefineFlags(d, uint32(flags))
Domain Domain
Flags UndefineFlags
}{
Domain: d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainUndefineFlags, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'. // Destroy destroys the domain specified by dom, e.g., 'prod-lb-01'.
@ -1113,30 +723,7 @@ func (l *Libvirt) Destroy(dom string, flags DestroyFlags) error {
return err return err
} }
payload := struct { return l.DomainDestroyFlags(d, uint32(flags))
Domain Domain
Flags DestroyFlags
}{
Domain: d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainDestroyFlags, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// XML returns a domain's raw XML definition, akin to `virsh dumpxml <domain>`. // XML returns a domain's raw XML definition, akin to `virsh dumpxml <domain>`.
@ -1147,85 +734,19 @@ func (l *Libvirt) XML(dom string, flags DomainXMLFlags) ([]byte, error) {
return nil, err return nil, err
} }
payload := struct { xml, err := l.DomainGetXMLDesc(d, uint32(flags))
Domain Domain return []byte(xml), err
Flags DomainXMLFlags
}{
Domain: d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return nil, err
}
resp, err := l.request(constants.ProcDomainGetXMLDesc, constants.Program, &buf)
if err != nil {
return nil, err
}
r := <-resp
if r.Status != StatusOK {
return nil, decodeError(r.Payload)
}
pl := bytes.NewReader(r.Payload)
dec := xdr.NewDecoder(pl)
s, _, err := dec.DecodeString()
if err != nil {
return nil, err
}
return []byte(s), nil
} }
// DefineXML defines a domain, but does not start it. // DefineXML defines a domain, but does not start it.
func (l *Libvirt) DefineXML(x []byte, flags DomainDefineXMLFlags) error { func (l *Libvirt) DefineXML(x []byte, flags DomainDefineXMLFlags) error {
payload := struct { _, err := l.DomainDefineXMLFlags(string(x), uint32(flags))
Domain []byte
Flags DomainDefineXMLFlags
}{
Domain: x,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err return err
}
resp, err := l.request(constants.ProcDomainDefineXMLFlags, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// Version returns the version of the libvirt daemon. // Version returns the version of the libvirt daemon.
func (l *Libvirt) Version() (string, error) { func (l *Libvirt) Version() (string, error) {
resp, err := l.request(constants.ProcConnectGetLibVersion, constants.Program, nil) ver, err := l.ConnectGetLibVersion()
if err != nil {
return "", err
}
r := <-resp
if r.Status != StatusOK {
return "", decodeError(r.Payload)
}
result := struct {
Version uint64
}{}
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
_, err = dec.Decode(&result)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -1233,11 +754,11 @@ func (l *Libvirt) Version() (string, error) {
// The version is provided as an int following this formula: // The version is provided as an int following this formula:
// version * 1,000,000 + minor * 1000 + micro // version * 1,000,000 + minor * 1000 + micro
// See src/libvirt-host.c # virConnectGetLibVersion // See src/libvirt-host.c # virConnectGetLibVersion
major := result.Version / 1000000 major := ver / 1000000
result.Version %= 1000000 ver %= 1000000
minor := result.Version / 1000 minor := ver / 1000
result.Version %= 1000 ver %= 1000
micro := result.Version micro := ver
versionString := fmt.Sprintf("%d.%d.%d", major, minor, micro) versionString := fmt.Sprintf("%d.%d.%d", major, minor, micro)
return versionString, nil return versionString, nil
@ -1251,30 +772,7 @@ func (l *Libvirt) Shutdown(dom string, flags ShutdownFlags) error {
return err return err
} }
payload := struct { return l.DomainShutdownFlags(d, uint32(flags))
Domain Domain
Flags ShutdownFlags
}{
Domain: d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainShutdownFlags, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// Reboot reboots the domain. Note that the guest OS may ignore the request. // Reboot reboots the domain. Note that the guest OS may ignore the request.
@ -1285,30 +783,7 @@ func (l *Libvirt) Reboot(dom string, flags RebootFlags) error {
return err return err
} }
payload := struct { return l.DomainReboot(d, uint32(flags))
Domain Domain
Flags RebootFlags
}{
Domain: d,
Flags: flags,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainReboot, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// Reset resets domain immediately without any guest OS shutdown // Reset resets domain immediately without any guest OS shutdown
@ -1318,30 +793,7 @@ func (l *Libvirt) Reset(dom string) error {
return err return err
} }
payload := struct { return l.DomainReset(d, 0)
Domain Domain
Flags uint32
}{
Domain: d,
Flags: 0,
}
buf, err := encode(&payload)
if err != nil {
return err
}
resp, err := l.request(constants.ProcDomainReset, constants.Program, &buf)
if err != nil {
return err
}
r := <-resp
if r.Status != StatusOK {
return decodeError(r.Payload)
}
return nil
} }
// BlockLimit contains a name and value pair for a Get/SetBlockIOTune limit. The // BlockLimit contains a name and value pair for a Get/SetBlockIOTune limit. The
@ -1404,7 +856,7 @@ func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit)
params[ix] = TypedParam{Field: limit.Name, Value: tpval} params[ix] = TypedParam{Field: limit.Name, Value: tpval}
} }
return l.DomainSetBlockIOTune(*d, disk, params, FlagDomainAffectLive) return l.DomainSetBlockIOTune(d, disk, params, FlagDomainAffectLive)
} }
// GetBlockIOTune returns a slice containing the current block I/O tunables for // GetBlockIOTune returns a slice containing the current block I/O tunables for
@ -1415,46 +867,12 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
return nil, err return nil, err
} }
lims, _, err := l.DomainGetBlockIOTune(*d, disk, 32, FlagTypedParamStringOkay) lims, _, err := l.DomainGetBlockIOTune(d, []string{disk}, 32, FlagTypedParamStringOkay)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// payload := struct {
// Domain Domain
// Disk []string
// ParamCount uint32
// Flags DomainAffectFlags
// }{
// Domain: d,
// Disk: []string{disk},
// 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)
// dec := xdr.NewDecoder(rdr)
// find out how many params were returned
// paramCount, _, err := dec.DecodeInt()
// if err != nil {
// 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.
@ -1468,73 +886,40 @@ func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error)
limits = append(limits, l) 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
} }
// lookup returns a domain as seen by libvirt. // lookup returns a domain as seen by libvirt.
func (l *Libvirt) lookup(name string) (Domain, error) { func (l *Libvirt) lookup(name string) (NonnullDomain, error) {
var d NonnullDomain
payload := struct { payload := struct {
Name string Name string
}{name} }{name}
buf, err := encode(&payload) buf, err := encode(&payload)
if err != nil { if err != nil {
return nil, err return d, err
} }
resp, err := l.request(constants.ProcDomainLookupByName, constants.Program, &buf) resp, err := l.request(constants.ProcDomainLookupByName, constants.Program, &buf)
if err != nil { if err != nil {
return nil, err return d, err
} }
r := <-resp r := <-resp
if r.Status != StatusOK { if r.Status != StatusOK {
return nil, decodeError(r.Payload) return d, decodeError(r.Payload)
} }
dec := xdr.NewDecoder(bytes.NewReader(r.Payload)) dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
// var d Domain // var d Domain
var d NonnullDomain
_, err = dec.Decode(&d) _, err = dec.Decode(&d)
if err != nil { if err != nil {
return nil, err return d, err
} }
return &d, nil return d, nil
} }
// getQEMUError checks the provided response for QEMU process errors. // getQEMUError checks the provided response for QEMU process errors.

View File

@ -153,7 +153,7 @@ func TestDomainMemoryStats(t *testing.T) {
t.Error(err) t.Error(err)
} }
gotDomainMemoryStats, err := l.DomainMemoryStats(*d, 8, 0) gotDomainMemoryStats, err := l.DomainMemoryStats(d, 8, 0)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -361,7 +361,7 @@ func TestStoragePoolRefresh(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
err = l.StoragePoolRefresh(*pool, 0) err = l.StoragePoolRefresh(pool, 0)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -422,7 +422,7 @@ func TestDomainCreateWithFlags(t *testing.T) {
t.Fatalf("failed to lookup domain: %v", err) t.Fatalf("failed to lookup domain: %v", err)
} }
var flags uint32 var flags uint32
if _, err := l.DomainCreateWithFlags(*d, flags); err != nil { if _, err := l.DomainCreateWithFlags(d, flags); err != nil {
t.Fatalf("unexpected create error: %v", err) t.Fatalf("unexpected create error: %v", err)
} }
} }

View File

@ -340,10 +340,6 @@ func TestLookup(t *testing.T) {
t.Error(err) t.Error(err)
} }
if d == nil {
t.Error("nil domain returned")
}
if d.Name != name { if d.Name != name {
t.Errorf("expected domain %s, got %s", name, d.Name) t.Errorf("expected domain %s, got %s", name, d.Name)
} }