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:
		| @@ -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) | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user