Add Get/SetBlockIoTune to go-libvirt API. (#45)
* Add Get/SetBlockIoTune to go-libvirt API. This adds two libvirt entry points to the go-libvirt API: virDomainSetBlockIoTune and virDomainGetBlockIoTune. These can be used to control block device throttling for a VM.
This commit is contained in:
parent
85dc33f30e
commit
c8e4b6a7b8
@ -53,6 +53,8 @@ const (
|
||||
ProcDomainUndefineFlags = 231
|
||||
ProcDomainDestroyFlags = 234
|
||||
ProcDomainReset = 245
|
||||
ProcDomainSetBlockIOTune = 252
|
||||
ProcDomainGetBlockIOTune = 253
|
||||
ProcDomainShutdownFlags = 258
|
||||
ProcConnectListAllDomains = 273
|
||||
ProcConnectListAllStoragePools = 281
|
||||
@ -78,4 +80,8 @@ const (
|
||||
|
||||
// UUIDSize is the length of a UUID, in bytes.
|
||||
UUIDSize = 16
|
||||
|
||||
// TypedParamFieldLength is VIR_TYPED_PARAM_FIELD_LENGTH, and is the maximum
|
||||
// length of the Field string in virTypedParameter structs.
|
||||
TypedParamFieldLength = 80
|
||||
)
|
||||
|
225
libvirt.go
225
libvirt.go
@ -19,6 +19,7 @@ package libvirt
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -94,6 +95,86 @@ type qemuError struct {
|
||||
// DomainXMLFlags specifies options for dumping a domain's XML.
|
||||
type DomainXMLFlags uint32
|
||||
|
||||
// DomainAffectFlags specifies options for whether an operation affects the
|
||||
// running VM, or the persistent VM configuration on disk. See FlagDomain...
|
||||
// consts for values.
|
||||
type DomainAffectFlags uint32
|
||||
|
||||
// Consts used for flags
|
||||
|
||||
// virDomainModificationImpact and virTypedParameterFlags values. These are
|
||||
// combined here because they are both used to set the same flags fields in the
|
||||
// libvirt API.
|
||||
const (
|
||||
// FlagDomainAffectCurrent means affect the current domain state
|
||||
FlagDomainAffectCurrent DomainAffectFlags = 0
|
||||
// FlagDomainAffectLive means affect the running domain state
|
||||
FlagDomainAffectLive = 1 << (iota - 1)
|
||||
// FlagDomainAffectConfig means affect the persistent domain state.
|
||||
FlagDomainAffectConfig
|
||||
// FlagTypedParamStringOkay tells the server that this client understands
|
||||
// TypedParameStrings.
|
||||
FlagTypedParamStringOkay
|
||||
)
|
||||
|
||||
// Consts relating to TypedParams:
|
||||
const (
|
||||
// TypedParamInt is a C int.
|
||||
TypedParamInt = iota + 1
|
||||
// TypedParamUInt is a C unsigned int.
|
||||
TypedParamUInt
|
||||
// TypedParamLLong is a C long long int.
|
||||
TypedParamLLong
|
||||
// TypedParamULLong is a C unsigned long long int.
|
||||
TypedParamULLong
|
||||
// TypedParamDouble is a C double.
|
||||
TypedParamDouble
|
||||
// TypedParamBoolean is a C char.
|
||||
TypedParamBoolean
|
||||
// TypedParamString is a C char*.
|
||||
TypedParamString
|
||||
|
||||
// TypedParamLast is just an end-of-enum marker.
|
||||
TypedParamLast
|
||||
)
|
||||
|
||||
// TypedParam represents libvirt's virTypedParameter, which is used to pass
|
||||
// typed parameters to libvirt functions. The `Value` field defined as a union
|
||||
// in libvirt, and given the current set of types inside it, is 8 bytes long.
|
||||
type TypedParam struct {
|
||||
Field string
|
||||
Type int
|
||||
Value [8]byte
|
||||
}
|
||||
|
||||
// NewTypedParamInt returns a TypedParam encoding for an int.
|
||||
func NewTypedParamInt(name string, v int) *TypedParam {
|
||||
// Truncate the field name if it's longer than the limit.
|
||||
if len(name) > constants.TypedParamFieldLength {
|
||||
name = name[:constants.TypedParamFieldLength]
|
||||
}
|
||||
tp := TypedParam{
|
||||
Field: name,
|
||||
Type: TypedParamInt,
|
||||
}
|
||||
binary.BigEndian.PutUint32(tp.Value[:], uint32(v))
|
||||
return &tp
|
||||
}
|
||||
|
||||
// NewTypedParamULongLong returns a TypedParam encoding for an unsigned long long.
|
||||
func NewTypedParamULongLong(name string, v uint64) *TypedParam {
|
||||
// Truncate the field name if it's longer than the limit.
|
||||
if len(name) > constants.TypedParamFieldLength {
|
||||
name = name[:constants.TypedParamFieldLength]
|
||||
}
|
||||
tp := TypedParam{
|
||||
Field: name,
|
||||
Type: TypedParamULLong,
|
||||
}
|
||||
binary.BigEndian.PutUint64(tp.Value[:], v)
|
||||
return &tp
|
||||
}
|
||||
|
||||
const (
|
||||
// DomainXMLFlagSecure dumps XML with sensitive information included.
|
||||
DomainXMLFlagSecure DomainXMLFlags = 1 << iota
|
||||
@ -601,7 +682,7 @@ func (l *Libvirt) Events(dom string) (<-chan DomainEvent, error) {
|
||||
|
||||
res := <-resp
|
||||
if res.Status != StatusOK {
|
||||
err := decodeError(res.Payload)
|
||||
err = decodeError(res.Payload)
|
||||
if err == ErrUnsupported {
|
||||
return nil, ErrEventsNotSupported
|
||||
}
|
||||
@ -1199,6 +1280,148 @@ func (l *Libvirt) Reset(dom string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockLimit contains a name and value pair for a Get/SetBlockIOTune limit. The
|
||||
// Name field is the name of the limit (to see a list of the limits that can be
|
||||
// applied, execute the 'blkdeviotune' command on a VM in virsh). Callers can
|
||||
// use the QEMUBlockIO... constants below for the Name value. The Value field is
|
||||
// the limit to apply.
|
||||
type BlockLimit struct {
|
||||
Name string
|
||||
Value uint64
|
||||
}
|
||||
|
||||
// BlockIOTune-able values. These tunables are different for different
|
||||
// hypervisors; currently only the tunables for QEMU are defined here. These are
|
||||
// not necessarily the only possible values; different libvirt versions may add
|
||||
// or remove parameters from this list.
|
||||
const (
|
||||
QEMUBlockIOTotalBytesSec = "total_bytes_sec"
|
||||
QEMUBlockIOReadBytesSec = "read_bytes_sec"
|
||||
QEMUBlockIOWriteBytesSec = "write_bytes_sec"
|
||||
QEMUBlockIOTotalIOPSSec = "total_iops_sec"
|
||||
QEMUBlockIOReadIOPSSec = "read_iops_sec"
|
||||
QEMUBlockIOWriteIOPSSec = "write_iops_sec"
|
||||
QEMUBlockIOTotalBytesSecMax = "total_bytes_sec_max"
|
||||
QEMUBlockIOReadBytesSecMax = "read_bytes_sec_max"
|
||||
QEMUBlockIOWriteBytesSecMax = "write_bytes_sec_max"
|
||||
QEMUBlockIOTotalIOPSSecMax = "total_iops_sec_max"
|
||||
QEMUBlockIOReadIOPSSecMax = "read_iops_sec_max"
|
||||
QEMUBlockIOWriteIOPSSecMax = "write_iops_sec_max"
|
||||
QEMUBlockIOSizeIOPSSec = "size_iops_sec"
|
||||
QEMUBlockIOTotalBytesSecMaxLength = "total_bytes_sec_max_length"
|
||||
QEMUBlockIOReadBytesSecMaxLength = "read_bytes_sec_max_length"
|
||||
QEMUBlockIOWriteBytesSecMaxLength = "write_bytes_sec_max_length"
|
||||
QEMUBlockIOTotalIOPSSecMaxLength = "total_iops_sec_max_length"
|
||||
QEMUBlockIOReadIOPSSecMaxLength = "read_iops_sec_max_length"
|
||||
QEMUBlockIOWriteIOPSSecMaxLength = "write_iops_sec_max_length"
|
||||
)
|
||||
|
||||
// SetBlockIOTune changes the per-device block I/O tunables within a guest.
|
||||
// Parameters are the name of the VM, the name of the disk device to which the
|
||||
// limits should be applied, and 1 or more BlockLimit structs containing the
|
||||
// actual limits.
|
||||
//
|
||||
// The limits which can be applied here are enumerated in the QEMUBlockIO...
|
||||
// constants above, and you can also see the full list by executing the
|
||||
// 'blkdeviotune' command on a VM in virsh.
|
||||
//
|
||||
// Example usage:
|
||||
// SetBlockIOTune("vm-name", "vda", BlockLimit{libvirt.QEMUBlockIOWriteBytesSec, 1000000})
|
||||
func (l *Libvirt) SetBlockIOTune(dom string, disk string, limits ...BlockLimit) error {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainSetBlockIoTune
|
||||
payload := struct {
|
||||
Domain Domain
|
||||
Disk string
|
||||
Params []TypedParam
|
||||
Flags DomainAffectFlags
|
||||
}{
|
||||
Domain: *d,
|
||||
Disk: disk,
|
||||
Flags: FlagDomainAffectLive,
|
||||
}
|
||||
|
||||
for _, limit := range limits {
|
||||
tp := NewTypedParamULongLong(limit.Name, limit.Value)
|
||||
payload.Params = append(payload.Params, *tp)
|
||||
}
|
||||
|
||||
buf, err := encode(&payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := l.request(constants.ProcDomainSetBlockIOTune, constants.ProgramRemote, &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
|
||||
// a disk.
|
||||
func (l *Libvirt) GetBlockIOTune(dom string, disk string) ([]BlockLimit, error) {
|
||||
d, err := l.lookup(dom)
|
||||
if err != nil {
|
||||
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.ProgramRemote, &buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := <-resp
|
||||
if r.Status != StatusOK {
|
||||
return nil, decodeError(r.Payload)
|
||||
}
|
||||
|
||||
dec := xdr.NewDecoder(bytes.NewReader(r.Payload))
|
||||
result := struct {
|
||||
Limits []TypedParam
|
||||
ParamCount uint32
|
||||
}{}
|
||||
_, err = dec.Decode(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limits := make([]BlockLimit, len(result.Limits))
|
||||
for ix := range result.Limits {
|
||||
limits[ix].Name = result.Limits[ix].Field
|
||||
limits[ix].Value = binary.BigEndian.Uint64(result.Limits[ix].Value[:])
|
||||
}
|
||||
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
// lookup returns a domain as seen by libvirt.
|
||||
func (l *Libvirt) lookup(name string) (*Domain, error) {
|
||||
payload := struct {
|
||||
|
@ -437,3 +437,27 @@ func TestReset(t *testing.T) {
|
||||
t.Fatalf("unexpected reset error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetBlockIOTune(t *testing.T) {
|
||||
conn := libvirttest.New()
|
||||
l := New(conn)
|
||||
|
||||
if err := l.SetBlockIOTune("test", "vda", BlockLimit{"write_bytes_sec", 5000000}); err != nil {
|
||||
t.Fatalf("unexpected SetBlockIOTune error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBlockIOTune(t *testing.T) {
|
||||
conn := libvirttest.New()
|
||||
l := New(conn)
|
||||
|
||||
limits, err := l.GetBlockIOTune("do-test", "vda")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected GetBlockIOTune error: %v", err)
|
||||
}
|
||||
|
||||
lim := BlockLimit{"write_bytes_sec", 500000}
|
||||
if limits[2] != lim {
|
||||
t.Fatalf("unexpected result in limits list: %v", limits[2])
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,9 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"fmt"
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
"os"
|
||||
|
||||
"github.com/digitalocean/go-libvirt/internal/constants"
|
||||
)
|
||||
|
||||
var testDomainResponse = []byte{
|
||||
@ -399,6 +400,128 @@ var testRebootReply = []byte{
|
||||
0x00, 0x00, 0x00, 0x00, // status
|
||||
}
|
||||
|
||||
var testSetBlockIoTuneReply = []byte{
|
||||
0x00, 0x00, 0x00, 0x1c, // length
|
||||
0x20, 0x00, 0x80, 0x86, // program
|
||||
0x00, 0x00, 0x00, 0x01, // version
|
||||
0x00, 0x00, 0x00, 0xfc, // procedure
|
||||
0x00, 0x00, 0x00, 0x00, // type
|
||||
0x00, 0x00, 0x00, 0x00, // serial
|
||||
0x00, 0x00, 0x00, 0x00, // status
|
||||
}
|
||||
|
||||
// This result block was obtained by calling `fmt.Printf("%#v", r.Payload)` on
|
||||
// the result returned by an actual call to GetBlockIoTune, and then adding the
|
||||
// standard header to the beginning. The length parameter has to be correct!
|
||||
var testGetBlockIoTuneReply = []byte{
|
||||
0x00, 0x00, 0x02, 0xe0, // length
|
||||
0x20, 0x00, 0x80, 0x86, // program
|
||||
0x00, 0x00, 0x00, 0x01, // version
|
||||
0x00, 0x00, 0x00, 0xfd, // procedure
|
||||
0x00, 0x00, 0x00, 0x00, // type
|
||||
0x00, 0x00, 0x00, 0x00, // serial
|
||||
0x00, 0x00, 0x00, 0x00, // status
|
||||
|
||||
0x0, 0x0, 0x0, 0x13, // 13 TypedParams follow
|
||||
|
||||
0x0, 0x0, 0x0, 0xf, // field name is 15 bytes, padded to a multiple of 4
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4, // type
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // value
|
||||
|
||||
0x0, 0x0, 0x0, 0xe,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0xf,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xa1, 0x20,
|
||||
|
||||
0x0, 0x0, 0x0, 0xe,
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0xd,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0xe,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x13,
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x12,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x13,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc3, 0x50,
|
||||
|
||||
0x0, 0x0, 0x0, 0x12,
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x11,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x12,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0xd,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x1a,
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x19,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x1a,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
|
||||
|
||||
0x0, 0x0, 0x0, 0x19,
|
||||
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x18,
|
||||
0x72, 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x19,
|
||||
0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6f, 0x70, 0x73, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0, 0x0, 0x0, // End of TypedParams
|
||||
}
|
||||
|
||||
// MockLibvirt provides a mock libvirt server for testing.
|
||||
type MockLibvirt struct {
|
||||
net.Conn
|
||||
@ -486,6 +609,10 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) {
|
||||
conn.Write(m.reply(testCreateWithFlags))
|
||||
case constants.ProcDomainShutdownFlags:
|
||||
conn.Write(m.reply(testShutdownReply))
|
||||
case constants.ProcDomainSetBlockIOTune:
|
||||
conn.Write(m.reply(testSetBlockIoTuneReply))
|
||||
case constants.ProcDomainGetBlockIOTune:
|
||||
conn.Write(m.reply(testGetBlockIoTuneReply))
|
||||
default:
|
||||
fmt.Fprintln(os.Stderr, "unknown procedure", procedure)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user