Changed from V3: use new virDomainGetCPUStats() libvirt-API. use C code to construct the typed_param list array Acked-by: "Richard W.M. Jones" <rjones@xxxxxxxxxx> Signed-off-by: Lai Jiangshan <laijs@xxxxxxxxxxxxxx> --- libvirt/libvirt.ml | 8 ++++ libvirt/libvirt.mli | 11 +++++ libvirt/libvirt_c_oneoffs.c | 91 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 0 deletions(-) diff --git a/libvirt/libvirt.ml b/libvirt/libvirt.ml index fc29264..08c501b 100644 --- a/libvirt/libvirt.ml +++ b/libvirt/libvirt.ml @@ -343,6 +343,13 @@ struct | SchedFieldInt64 of int64 | SchedFieldUInt64 of int64 | SchedFieldFloat of float | SchedFieldBool of bool + type typed_param = string * typed_param_value + and typed_param_value = + | TypedFieldInt32 of int32 | TypedFieldUInt32 of int32 + | TypedFieldInt64 of int64 | TypedFieldUInt64 of int64 + | TypedFieldFloat of float | TypedFieldBool of bool + | TypedFieldString of string + type migrate_flag = Live type memory_flag = Virtual @@ -419,6 +426,7 @@ struct external set_vcpus : [>`W] t -> int -> unit = "ocaml_libvirt_domain_set_vcpus" external pin_vcpu : [>`W] t -> int -> string -> unit = "ocaml_libvirt_domain_pin_vcpu" external get_vcpus : [>`R] t -> int -> int -> int * vcpu_info array * string = "ocaml_libvirt_domain_get_vcpus" + external get_cpu_stats : [>`R] t -> int -> typed_param list array = "ocaml_libvirt_domain_get_cpu_stats" external get_max_vcpus : [>`R] t -> int = "ocaml_libvirt_domain_get_max_vcpus" external attach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_attach_device" external detach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_detach_device" diff --git a/libvirt/libvirt.mli b/libvirt/libvirt.mli index 7bda889..31f2ca2 100644 --- a/libvirt/libvirt.mli +++ b/libvirt/libvirt.mli @@ -439,6 +439,13 @@ sig | SchedFieldInt64 of int64 | SchedFieldUInt64 of int64 | SchedFieldFloat of float | SchedFieldBool of bool + type typed_param = string * typed_param_value + and typed_param_value = + | TypedFieldInt32 of int32 | TypedFieldUInt32 of int32 + | TypedFieldInt64 of int64 | TypedFieldUInt64 of int64 + | TypedFieldFloat of float | TypedFieldBool of bool + | TypedFieldString of string + type migrate_flag = Live type memory_flag = Virtual @@ -586,6 +593,10 @@ sig for a domain. See the libvirt documentation for details of the array and bitmap returned from this function. *) + val get_cpu_stats : [>`R] t -> int -> typed_param list array + (** [get_pcpu_stats dom nr_pcpu] returns the physic CPU stats + for a domain. See the libvirt documentation for details. + *) val get_max_vcpus : [>`R] t -> int (** Returns the maximum number of vCPUs supported for this domain. *) val attach_device : [>`W] t -> xml -> unit diff --git a/libvirt/libvirt_c_oneoffs.c b/libvirt/libvirt_c_oneoffs.c index d87dd21..a0c74be 100644 --- a/libvirt/libvirt_c_oneoffs.c +++ b/libvirt/libvirt_c_oneoffs.c @@ -604,6 +604,97 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv) CAMLreturn (rv); } +CAMLprim value +ocaml_libvirt_domain_get_cpu_stats (value domv, value nr_pcpusv) +{ + CAMLparam2 (domv, nr_pcpusv); + CAMLlocal5 (cpustats, param_head, param_node, typed_param, typed_param_value); + virDomainPtr dom = Domain_val (domv); + virConnectPtr conn = Connect_domv (domv); + int nr_pcpus = Int_val (nr_pcpusv); + virTypedParameterPtr params; + int r, cpu, ncpus, nparams, i, j, pos; + + /* get percpu information */ + NONBLOCKING (nparams = virDomainGetCPUStats(dom, NULL, 0, -1, 1, 0)); + CHECK_ERROR (nparams < 0, conn, "virDomainGetCPUStats"); + + if ((params = malloc(sizeof(*params) * nparams * 128)) == NULL) + caml_failwith ((char *)__FUNCTION__); + + cpustats = caml_alloc (nr_pcpus, 0); /* cpustats: array of params(list of typed_param) */ + cpu = 0; + while (cpu < nr_pcpus) { + ncpus = nr_pcpus - cpu > 128 ? 128 : nr_pcpus - cpu; + + NONBLOCKING (r = virDomainGetCPUStats(dom, params, nparams, cpu, ncpus, 0)); + CHECK_ERROR (r < 0, conn, "virDomainGetCPUStats"); + + for (i = 0; i < ncpus; i++) { + /* list of typed_param: single linked list of param_nodes */ + param_head = Val_emptylist; /* param_head: the head param_node of list of typed_param */ + + if (params[i * nparams].type == 0) { + Store_field(cpustats, cpu + i, param_head); + continue; + } + + for (j = nparams - 1; j >= 0; j--) { + pos = i * nparams + j; + if (params[pos].type == 0) + continue; + + param_node = caml_alloc(2, 0); /* param_node: typed_param, next param_node */ + Store_field(param_node, 1, param_head); + param_head = param_node; + + typed_param = caml_alloc(2, 0); /* typed_param: field name(string), typed_param_value */ + Store_field(param_node, 0, typed_param); + Store_field(typed_param, 0, caml_copy_string(params[pos].field)); + + /* typed_param_value: value with the corresponding type tag */ + switch(params[pos].type) { + case VIR_TYPED_PARAM_INT: + typed_param_value = caml_alloc (1, 0); + Store_field(typed_param_value, 0, caml_copy_int32(params[pos].value.i)); + break; + case VIR_TYPED_PARAM_UINT: + typed_param_value = caml_alloc (1, 1); + Store_field(typed_param_value, 0, caml_copy_int32(params[pos].value.ui)); + break; + case VIR_TYPED_PARAM_LLONG: + typed_param_value = caml_alloc (1, 2); + Store_field(typed_param_value, 0, caml_copy_int64(params[pos].value.l)); + break; + case VIR_TYPED_PARAM_ULLONG: + typed_param_value = caml_alloc (1, 3); + Store_field(typed_param_value, 0, caml_copy_int64(params[pos].value.ul)); + break; + case VIR_TYPED_PARAM_DOUBLE: + typed_param_value = caml_alloc (1, 4); + Store_field(typed_param_value, 0, caml_copy_double(params[pos].value.d)); + break; + case VIR_TYPED_PARAM_BOOLEAN: + typed_param_value = caml_alloc (1, 5); + Store_field(typed_param_value, 0, Int_val(!!(params[pos].value.b))); + break; + case VIR_TYPED_PARAM_STRING: + typed_param_value = caml_alloc (1, 6); + Store_field(typed_param_value, 0, caml_copy_string(params[pos].value.s)); + break; + default: + free(params); + caml_failwith ((char *)__FUNCTION__); + } + Store_field(typed_param, 1, typed_param_value); + } + Store_field(cpustats, cpu + i, param_head); + } + cpu += ncpus; + } + free(params); + CAMLreturn (cpustats); +} #ifdef HAVE_WEAK_SYMBOLS #ifdef HAVE_VIRDOMAINMIGRATE extern virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list