From ddb5e4e49dc9e7acc903020804a3c60a5a284ab6 Mon Sep 17 00:00:00 2001 From: Christophe Robin Date: Wed, 7 May 2014 23:06:27 +0900 Subject: [PATCH] Add VirDomain.GetCPUStats and VirDomain.GetInterfaceParameters Remove integration tests as they will not work with this version. Replace virTypedParamsFree with manual C.free calls to alloc'ed strings, since it is not available before libvirt 1.0.2. --- domain.go | 99 +++++++++++++++++++++++++++++++++++++++++++++ integration_test.go | 1 - 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/domain.go b/domain.go index 9c3d0bb..2c09e15 100644 --- a/domain.go +++ b/domain.go @@ -10,6 +10,8 @@ import "C" import ( "errors" + "reflect" + "strings" "unsafe" ) @@ -21,6 +23,56 @@ type VirDomainInfo struct { ptr C.virDomainInfo } +type VirTypedParameter struct { + Name string + Value interface{} +} + +type VirTypedParameters []VirTypedParameter + +func (dest *VirTypedParameters) loadFromCPtr(params C.virTypedParameterPtr, nParams int) { + // reset slice + *dest = VirTypedParameters{} + + // transform that C array to a go slice + hdr := reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(params)), + Len: int(nParams), + Cap: int(nParams), + } + rawParams := *(*[]C.struct__virTypedParameter)(unsafe.Pointer(&hdr)) + + // there is probably a more elegant way to deal with that union + for _, rawParam := range rawParams { + name := C.GoStringN(&rawParam.field[0], C.VIR_TYPED_PARAM_FIELD_LENGTH) + if nbIdx := strings.Index(name, "\x00"); nbIdx != -1 { + name = name[:nbIdx] + } + switch rawParam._type { + case C.VIR_TYPED_PARAM_INT: + *dest = append(*dest, VirTypedParameter{name, int(*(*C.int)(unsafe.Pointer(&rawParam.value[0])))}) + case C.VIR_TYPED_PARAM_UINT: + *dest = append(*dest, VirTypedParameter{name, uint32(*(*C.uint)(unsafe.Pointer(&rawParam.value[0])))}) + case C.VIR_TYPED_PARAM_LLONG: + *dest = append(*dest, VirTypedParameter{name, int64(*(*C.longlong)(unsafe.Pointer(&rawParam.value[0])))}) + case C.VIR_TYPED_PARAM_ULLONG: + *dest = append(*dest, VirTypedParameter{name, uint64(*(*C.ulonglong)(unsafe.Pointer(&rawParam.value[0])))}) + case C.VIR_TYPED_PARAM_DOUBLE: + *dest = append(*dest, VirTypedParameter{name, float64(*(*C.double)(unsafe.Pointer(&rawParam.value[0])))}) + case C.VIR_TYPED_PARAM_BOOLEAN: + if int(*(*C.char)(unsafe.Pointer(&rawParam.value[0]))) == 1 { + *dest = append(*dest, VirTypedParameter{name, true}) + } else { + *dest = append(*dest, VirTypedParameter{name, false}) + } + case C.VIR_TYPED_PARAM_STRING: + ptr := (*C.char)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&rawParam.value[0])))) + *dest = append(*dest, VirTypedParameter{name, C.GoString(ptr)}) + C.free(unsafe.Pointer(ptr)) + } + } +} + func (d *VirDomain) Free() error { if result := C.virDomainFree(d.ptr); result != 0 { return errors.New(GetLastError()) @@ -182,6 +234,53 @@ func (i *VirDomainInfo) GetCpuTime() uint64 { return uint64(i.ptr.cpuTime) } +func (d *VirDomain) GetCPUStats(params *VirTypedParameters, nParams int, startCpu int, nCpus uint32, flags uint32) (int, error) { + var cParams C.virTypedParameterPtr + var cParamsLen int + + cParamsLen = int(nCpus) * nParams + + if params != nil && cParamsLen > 0 { + cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(cParamsLen), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{})))) + } else { + cParamsLen = 0 + cParams = nil + } + + result := int(C.virDomainGetCPUStats(d.ptr, (C.virTypedParameterPtr)(cParams), C.uint(nParams), C.int(startCpu), C.uint(nCpus), C.uint(flags))) + if result == -1 { + return result, errors.New(GetLastError()) + } + + if cParamsLen > 0 { + params.loadFromCPtr(cParams, cParamsLen) + } + + return result, nil +} + +// Warning: No test written for this function +func (d *VirDomain) GetInterfaceParameters(device string, params *VirTypedParameters, nParams *int, flags uint32) (int, error) { + var cParams C.virTypedParameterPtr + + if params != nil && *nParams > 0 { + cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(*nParams), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{})))) + } else { + cParams = nil + } + + result := int(C.virDomainGetInterfaceParameters(d.ptr, C.CString(device), (C.virTypedParameterPtr)(cParams), (*C.int)(unsafe.Pointer(nParams)), C.uint(flags))) + if result == -1 { + return result, errors.New(GetLastError()) + } + + if params != nil && *nParams > 0 { + params.loadFromCPtr(cParams, *nParams) + } + + return result, nil +} + func (d *VirDomain) Undefine() error { result := C.virDomainUndefine(d.ptr) if result == -1 { diff --git a/integration_test.go b/integration_test.go index a8c4524..2d9efdd 100644 --- a/integration_test.go +++ b/integration_test.go @@ -536,4 +536,3 @@ func TestIntegrationLookupSecretByUsage(t *testing.T) { t.Fatal(err) } } -