1 /* OCaml bindings for libvirt.
2 * (C) Copyright 2007-2017 Richard W.M. Jones, Red Hat Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /* Please read libvirt/README file. */
22 /*----------------------------------------------------------------------*/
25 ocaml_libvirt_get_version (value driverv, value unit)
27 CAMLparam2 (driverv, unit);
29 const char *driver = Optstring_val (driverv);
30 unsigned long libVer, typeVer = 0, *typeVer_ptr;
33 typeVer_ptr = driver ? &typeVer : NULL;
34 NONBLOCKING (r = virGetVersion (&libVer, driver, typeVer_ptr));
35 CHECK_ERROR (r == -1, "virGetVersion");
37 rv = caml_alloc_tuple (2);
38 Store_field (rv, 0, Val_int (libVer));
39 Store_field (rv, 1, Val_int (typeVer));
43 /*----------------------------------------------------------------------*/
45 /* Connection object. */
48 ocaml_libvirt_connect_open (value namev, value unit)
50 CAMLparam2 (namev, unit);
52 const char *name = Optstring_val (namev);
55 NONBLOCKING (conn = virConnectOpen (name));
56 CHECK_ERROR (!conn, "virConnectOpen");
58 rv = Val_connect (conn);
64 ocaml_libvirt_connect_open_readonly (value namev, value unit)
66 CAMLparam2 (namev, unit);
68 const char *name = Optstring_val (namev);
71 NONBLOCKING (conn = virConnectOpenReadOnly (name));
72 CHECK_ERROR (!conn, "virConnectOpen");
74 rv = Val_connect (conn);
79 /* Helper struct holding data needed for the helper C authentication
80 * callback (which will call the actual OCaml callback).
82 struct ocaml_auth_callback_data {
83 value *fvp; /* The OCaml auth callback. */
87 _ocaml_auth_callback (virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
90 CAMLlocal4 (listv, elemv, rv, v);
91 struct ocaml_auth_callback_data *s = cbdata;
94 listv = Val_emptylist;
95 for (i = ncred - 1; i >= 0; --i) {
96 elemv = caml_alloc (2, 0);
97 Store_field (elemv, 0, Val_virconnectcredential (&cred[i]));
98 Store_field (elemv, 1, listv);
102 /* Call the auth callback. */
103 rv = caml_callback_exn (*s->fvp, listv);
104 if (Is_exception_result (rv)) {
105 /* The callback raised an exception, so return an error. */
106 CAMLreturnT (int, -1);
109 len = _list_length (rv);
110 if (len != (int) ncred) {
111 /* The callback did not return the same number of results as the
114 CAMLreturnT (int, -1);
117 for (i = 0; rv != Val_emptylist; rv = Field (rv, 1), ++i) {
118 virConnectCredentialPtr c = &cred[i];
119 elemv = Field (rv, 0);
120 if (elemv == Val_int (0)) {
124 v = Field (elemv, 0);
125 len = caml_string_length (v);
126 c->result = malloc (len + 1);
127 if (c->result == NULL)
128 CAMLreturnT (int, -1);
129 memcpy (c->result, String_val (v), len);
130 c->result[len] = '\0';
135 CAMLreturnT (int, 0);
139 _ocaml_libvirt_connect_open_auth_common (value namev, value authv, int flags)
141 CAMLparam2 (namev, authv);
142 CAMLlocal2 (listv, fv);
145 struct ocaml_auth_callback_data data;
149 /* Keep a copy of the 'namev' string, as its value could move around
150 * when calling other OCaml code that allocates memory.
152 if (namev != Val_int (0)) { /* Some string */
153 name = strdup (String_val (Field (namev, 0)));
155 caml_raise_out_of_memory ();
158 fv = Field (authv, 1);
161 listv = Field (authv, 0);
162 auth.ncredtype = _list_length (listv);
163 auth.credtype = malloc (sizeof (int) * auth.ncredtype);
164 if (auth.credtype == NULL)
165 caml_raise_out_of_memory ();
166 for (i = 0; listv != Val_emptylist; listv = Field (listv, 1), ++i) {
167 auth.credtype[i] = Int_val (Field (listv, 0)) + 1;
169 auth.cb = &_ocaml_auth_callback;
172 /* Call virConnectOpenAuth directly, without using the NONBLOCKING
173 * macro, as this will indeed call ocaml_* APIs, and run OCaml code.
175 conn = virConnectOpenAuth (name, &auth, flags);
176 free (auth.credtype);
178 CHECK_ERROR (!conn, "virConnectOpenAuth");
180 CAMLreturnT (virConnectPtr, conn);
184 ocaml_libvirt_connect_open_auth (value namev, value authv)
186 CAMLparam2 (namev, authv);
190 conn = _ocaml_libvirt_connect_open_auth_common (namev, authv, 0);
191 rv = Val_connect (conn);
197 ocaml_libvirt_connect_open_auth_readonly (value namev, value authv)
199 CAMLparam2 (namev, authv);
203 conn = _ocaml_libvirt_connect_open_auth_common (namev, authv, VIR_CONNECT_RO);
204 rv = Val_connect (conn);
210 ocaml_libvirt_connect_get_version (value connv)
213 virConnectPtr conn = Connect_val (connv);
217 NONBLOCKING (r = virConnectGetVersion (conn, &hvVer));
218 CHECK_ERROR (r == -1, "virConnectGetVersion");
220 CAMLreturn (Val_int (hvVer));
224 ocaml_libvirt_connect_get_max_vcpus (value connv, value typev)
226 CAMLparam2 (connv, typev);
227 virConnectPtr conn = Connect_val (connv);
228 const char *type = Optstring_val (typev);
231 NONBLOCKING (r = virConnectGetMaxVcpus (conn, type));
232 CHECK_ERROR (r == -1, "virConnectGetMaxVcpus");
234 CAMLreturn (Val_int (r));
238 ocaml_libvirt_connect_get_node_info (value connv)
242 virConnectPtr conn = Connect_val (connv);
246 NONBLOCKING (r = virNodeGetInfo (conn, &info));
247 CHECK_ERROR (r == -1, "virNodeGetInfo");
249 rv = caml_alloc (8, 0);
250 v = caml_copy_string (info.model); Store_field (rv, 0, v);
251 v = caml_copy_int64 (info.memory); Store_field (rv, 1, v);
252 Store_field (rv, 2, Val_int (info.cpus));
253 Store_field (rv, 3, Val_int (info.mhz));
254 Store_field (rv, 4, Val_int (info.nodes));
255 Store_field (rv, 5, Val_int (info.sockets));
256 Store_field (rv, 6, Val_int (info.cores));
257 Store_field (rv, 7, Val_int (info.threads));
263 ocaml_libvirt_connect_node_get_free_memory (value connv)
267 virConnectPtr conn = Connect_val (connv);
268 unsigned long long r;
270 NONBLOCKING (r = virNodeGetFreeMemory (conn));
271 CHECK_ERROR (r == 0, "virNodeGetFreeMemory");
273 rv = caml_copy_int64 ((int64_t) r);
278 ocaml_libvirt_connect_node_get_cells_free_memory (value connv,
279 value startv, value maxv)
281 CAMLparam3 (connv, startv, maxv);
283 virConnectPtr conn = Connect_val (connv);
284 int start = Int_val (startv);
285 int max = Int_val (maxv);
287 unsigned long long *freemems;
289 freemems = malloc(sizeof (*freemems) * max);
290 if (freemems == NULL)
291 caml_raise_out_of_memory ();
293 NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max));
294 CHECK_ERROR_CLEANUP (r == -1, free (freemems), "virNodeGetCellsFreeMemory");
296 rv = caml_alloc (r, 0);
297 for (i = 0; i < r; ++i) {
298 iv = caml_copy_int64 ((int64_t) freemems[i]);
299 Store_field (rv, i, iv);
307 ocaml_libvirt_connect_set_keep_alive(value connv,
308 value intervalv, value countv)
310 CAMLparam3 (connv, intervalv, countv);
311 virConnectPtr conn = Connect_val(connv);
312 int interval = Int_val(intervalv);
313 unsigned int count = Int_val(countv);
316 NONBLOCKING(r = virConnectSetKeepAlive(conn, interval, count));
317 CHECK_ERROR (r == -1, "virConnectSetKeepAlive");
319 CAMLreturn(Val_unit);
323 ocaml_libvirt_domain_get_id (value domv)
326 virDomainPtr dom = Domain_val (domv);
329 NONBLOCKING (r = virDomainGetID (dom));
330 /* In theory this could return -1 on error, but in practice
331 * libvirt never does this unless you call it with a corrupted
332 * or NULL dom object. So ignore errors here.
335 CAMLreturn (Val_int ((int) r));
339 ocaml_libvirt_domain_get_max_memory (value domv)
343 virDomainPtr dom = Domain_val (domv);
346 NONBLOCKING (r = virDomainGetMaxMemory (dom));
347 CHECK_ERROR (r == 0 /* [sic] */, "virDomainGetMaxMemory");
349 rv = caml_copy_int64 (r);
354 ocaml_libvirt_domain_set_max_memory (value domv, value memv)
356 CAMLparam2 (domv, memv);
357 virDomainPtr dom = Domain_val (domv);
358 unsigned long mem = Int64_val (memv);
361 NONBLOCKING (r = virDomainSetMaxMemory (dom, mem));
362 CHECK_ERROR (r == -1, "virDomainSetMaxMemory");
364 CAMLreturn (Val_unit);
368 ocaml_libvirt_domain_set_memory (value domv, value memv)
370 CAMLparam2 (domv, memv);
371 virDomainPtr dom = Domain_val (domv);
372 unsigned long mem = Int64_val (memv);
375 NONBLOCKING (r = virDomainSetMemory (dom, mem));
376 CHECK_ERROR (r == -1, "virDomainSetMemory");
378 CAMLreturn (Val_unit);
382 ocaml_libvirt_domain_get_info (value domv)
386 virDomainPtr dom = Domain_val (domv);
390 NONBLOCKING (r = virDomainGetInfo (dom, &info));
391 CHECK_ERROR (r == -1, "virDomainGetInfo");
393 rv = caml_alloc (5, 0);
394 Store_field (rv, 0, Val_int (info.state)); // These flags are compatible.
395 v = caml_copy_int64 (info.maxMem); Store_field (rv, 1, v);
396 v = caml_copy_int64 (info.memory); Store_field (rv, 2, v);
397 Store_field (rv, 3, Val_int (info.nrVirtCpu));
398 v = caml_copy_int64 (info.cpuTime); Store_field (rv, 4, v);
404 ocaml_libvirt_domain_get_scheduler_type (value domv)
407 CAMLlocal2 (rv, strv);
408 virDomainPtr dom = Domain_val (domv);
412 NONBLOCKING (r = virDomainGetSchedulerType (dom, &nparams));
413 CHECK_ERROR (!r, "virDomainGetSchedulerType");
415 rv = caml_alloc_tuple (2);
416 strv = caml_copy_string (r); Store_field (rv, 0, strv);
418 Store_field (rv, 1, nparams);
423 ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
425 CAMLparam2 (domv, nparamsv);
426 CAMLlocal4 (rv, v, v2, v3);
427 virDomainPtr dom = Domain_val (domv);
428 int nparams = Int_val (nparamsv);
429 virSchedParameterPtr params;
432 params = malloc (sizeof (*params) * nparams);
434 caml_raise_out_of_memory ();
436 NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams));
437 CHECK_ERROR_CLEANUP (r == -1, free (params), "virDomainGetSchedulerParameters");
439 rv = caml_alloc (nparams, 0);
440 for (i = 0; i < nparams; ++i) {
441 v = caml_alloc_tuple (2); Store_field (rv, i, v);
442 v2 = caml_copy_string (params[i].field); Store_field (v, 0, v2);
443 switch (params[i].type) {
444 case VIR_DOMAIN_SCHED_FIELD_INT:
445 v2 = caml_alloc (1, 0);
446 v3 = caml_copy_int32 (params[i].value.i); Store_field (v2, 0, v3);
448 case VIR_DOMAIN_SCHED_FIELD_UINT:
449 v2 = caml_alloc (1, 1);
450 v3 = caml_copy_int32 (params[i].value.ui); Store_field (v2, 0, v3);
452 case VIR_DOMAIN_SCHED_FIELD_LLONG:
453 v2 = caml_alloc (1, 2);
454 v3 = caml_copy_int64 (params[i].value.l); Store_field (v2, 0, v3);
456 case VIR_DOMAIN_SCHED_FIELD_ULLONG:
457 v2 = caml_alloc (1, 3);
458 v3 = caml_copy_int64 (params[i].value.ul); Store_field (v2, 0, v3);
460 case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
461 v2 = caml_alloc (1, 4);
462 v3 = caml_copy_double (params[i].value.d); Store_field (v2, 0, v3);
464 case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
465 v2 = caml_alloc (1, 5);
466 Store_field (v2, 0, Val_int (params[i].value.b));
469 caml_failwith ((char *)__FUNCTION__);
471 Store_field (v, 1, v2);
478 ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv)
480 CAMLparam2 (domv, paramsv);
482 virDomainPtr dom = Domain_val (domv);
483 int nparams = Wosize_val (paramsv);
484 virSchedParameterPtr params;
488 params = malloc (sizeof (*params) * nparams);
490 caml_raise_out_of_memory ();
492 for (i = 0; i < nparams; ++i) {
493 v = Field (paramsv, i); /* Points to the two-element tuple. */
494 name = String_val (Field (v, 0));
495 strncpy (params[i].field, name, VIR_DOMAIN_SCHED_FIELD_LENGTH);
496 params[i].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
497 v = Field (v, 1); /* Points to the sched_param_value block. */
498 switch (Tag_val (v)) {
500 params[i].type = VIR_DOMAIN_SCHED_FIELD_INT;
501 params[i].value.i = Int32_val (Field (v, 0));
504 params[i].type = VIR_DOMAIN_SCHED_FIELD_UINT;
505 params[i].value.ui = Int32_val (Field (v, 0));
508 params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;
509 params[i].value.l = Int64_val (Field (v, 0));
512 params[i].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
513 params[i].value.ul = Int64_val (Field (v, 0));
516 params[i].type = VIR_DOMAIN_SCHED_FIELD_DOUBLE;
517 params[i].value.d = Double_val (Field (v, 0));
520 params[i].type = VIR_DOMAIN_SCHED_FIELD_BOOLEAN;
521 params[i].value.b = Int_val (Field (v, 0));
524 caml_failwith ((char *)__FUNCTION__);
528 NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams));
530 CHECK_ERROR (r == -1, "virDomainSetSchedulerParameters");
532 CAMLreturn (Val_unit);
536 ocaml_libvirt_domain_set_vcpus (value domv, value nvcpusv)
538 CAMLparam2 (domv, nvcpusv);
539 virDomainPtr dom = Domain_val (domv);
540 int r, nvcpus = Int_val (nvcpusv);
542 NONBLOCKING (r = virDomainSetVcpus (dom, nvcpus));
543 CHECK_ERROR (r == -1, "virDomainSetVcpus");
545 CAMLreturn (Val_unit);
549 ocaml_libvirt_domain_pin_vcpu (value domv, value vcpuv, value cpumapv)
551 CAMLparam3 (domv, vcpuv, cpumapv);
552 virDomainPtr dom = Domain_val (domv);
553 int maplen = caml_string_length (cpumapv);
554 unsigned char *cpumap = (unsigned char *) String_val (cpumapv);
555 int vcpu = Int_val (vcpuv);
558 NONBLOCKING (r = virDomainPinVcpu (dom, vcpu, cpumap, maplen));
559 CHECK_ERROR (r == -1, "virDomainPinVcpu");
561 CAMLreturn (Val_unit);
565 ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
567 CAMLparam3 (domv, maxinfov, maplenv);
568 CAMLlocal5 (rv, infov, strv, v, v2);
569 virDomainPtr dom = Domain_val (domv);
570 int maxinfo = Int_val (maxinfov);
571 int maplen = Int_val (maplenv);
573 unsigned char *cpumaps;
576 info = calloc (maxinfo, sizeof (*info));
578 caml_raise_out_of_memory ();
579 cpumaps = calloc (maxinfo * maplen, sizeof (*cpumaps));
580 if (cpumaps == NULL) {
582 caml_raise_out_of_memory ();
585 NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen));
586 CHECK_ERROR_CLEANUP (r == -1, free (info); free (cpumaps), "virDomainPinVcpu");
588 /* Copy the virVcpuInfo structures. */
589 infov = caml_alloc (maxinfo, 0);
590 for (i = 0; i < maxinfo; ++i) {
591 v2 = caml_alloc (4, 0); Store_field (infov, i, v2);
592 Store_field (v2, 0, Val_int (info[i].number));
593 Store_field (v2, 1, Val_int (info[i].state));
594 v = caml_copy_int64 (info[i].cpuTime); Store_field (v2, 2, v);
595 Store_field (v2, 3, Val_int (info[i].cpu));
598 /* Copy the bitmap. */
599 strv = caml_alloc_string (maxinfo * maplen);
600 memcpy (String_val (strv), cpumaps, maxinfo * maplen);
602 /* Allocate the tuple and return it. */
603 rv = caml_alloc_tuple (3);
604 Store_field (rv, 0, Val_int (r)); /* number of CPUs. */
605 Store_field (rv, 1, infov);
606 Store_field (rv, 2, strv);
615 ocaml_libvirt_domain_get_cpu_stats (value domv)
618 CAMLlocal5 (cpustats, param_head, param_node, typed_param, typed_param_value);
620 virDomainPtr dom = Domain_val (domv);
621 virTypedParameterPtr params;
622 int r, cpu, ncpus, nparams, i, j, pos;
625 /* get number of pcpus */
626 NONBLOCKING (nr_pcpus = virDomainGetCPUStats(dom, NULL, 0, 0, 0, 0));
627 CHECK_ERROR (nr_pcpus < 0, "virDomainGetCPUStats");
629 /* get percpu information */
630 NONBLOCKING (nparams = virDomainGetCPUStats(dom, NULL, 0, 0, 1, 0));
631 CHECK_ERROR (nparams < 0, "virDomainGetCPUStats");
633 if ((params = malloc(sizeof(*params) * nparams * 128)) == NULL)
634 caml_failwith ("virDomainGetCPUStats: malloc");
636 cpustats = caml_alloc (nr_pcpus, 0); /* cpustats: array of params(list of typed_param) */
638 while (cpu < nr_pcpus) {
639 ncpus = nr_pcpus - cpu > 128 ? 128 : nr_pcpus - cpu;
641 NONBLOCKING (r = virDomainGetCPUStats(dom, params, nparams, cpu, ncpus, 0));
642 CHECK_ERROR (r < 0, "virDomainGetCPUStats");
644 for (i = 0; i < ncpus; i++) {
645 /* list of typed_param: single linked list of param_nodes */
646 param_head = Val_emptylist; /* param_head: the head param_node of list of typed_param */
648 if (params[i * nparams].type == 0) {
649 Store_field(cpustats, cpu + i, param_head);
653 for (j = r - 1; j >= 0; j--) {
654 pos = i * nparams + j;
655 if (params[pos].type == 0)
658 param_node = caml_alloc(2, 0); /* param_node: typed_param, next param_node */
659 Store_field(param_node, 1, param_head);
660 param_head = param_node;
662 typed_param = caml_alloc(2, 0); /* typed_param: field name(string), typed_param_value */
663 Store_field(param_node, 0, typed_param);
664 Store_field(typed_param, 0, caml_copy_string(params[pos].field));
666 /* typed_param_value: value with the corresponding type tag */
667 switch(params[pos].type) {
668 case VIR_TYPED_PARAM_INT:
669 typed_param_value = caml_alloc (1, 0);
670 v = caml_copy_int32 (params[pos].value.i);
672 case VIR_TYPED_PARAM_UINT:
673 typed_param_value = caml_alloc (1, 1);
674 v = caml_copy_int32 (params[pos].value.ui);
676 case VIR_TYPED_PARAM_LLONG:
677 typed_param_value = caml_alloc (1, 2);
678 v = caml_copy_int64 (params[pos].value.l);
680 case VIR_TYPED_PARAM_ULLONG:
681 typed_param_value = caml_alloc (1, 3);
682 v = caml_copy_int64 (params[pos].value.ul);
684 case VIR_TYPED_PARAM_DOUBLE:
685 typed_param_value = caml_alloc (1, 4);
686 v = caml_copy_double (params[pos].value.d);
688 case VIR_TYPED_PARAM_BOOLEAN:
689 typed_param_value = caml_alloc (1, 5);
690 v = Val_bool (params[pos].value.b);
692 case VIR_TYPED_PARAM_STRING:
693 typed_param_value = caml_alloc (1, 6);
694 v = caml_copy_string (params[pos].value.s);
695 free (params[pos].value.s);
698 /* XXX Memory leak on this path, if there are more
699 * VIR_TYPED_PARAM_STRING past this point in the array.
702 caml_failwith ("virDomainGetCPUStats: "
703 "unknown parameter type returned");
705 Store_field (typed_param_value, 0, v);
706 Store_field (typed_param, 1, typed_param_value);
708 Store_field (cpustats, cpu + i, param_head);
713 CAMLreturn (cpustats);
717 ocaml_libvirt_domain_get_all_domain_stats (value connv,
718 value statsv, value flagsv)
720 CAMLparam3 (connv, statsv, flagsv);
721 CAMLlocal5 (rv, dsv, tpv, v, v1);
723 virConnectPtr conn = Connect_val (connv);
724 virDomainStatsRecordPtr *rstats;
725 unsigned int stats = 0, flags = 0;
727 unsigned char uuid[VIR_UUID_BUFLEN];
729 /* Get stats and flags. */
730 for (; statsv != Val_int (0); statsv = Field (statsv, 1)) {
731 v = Field (statsv, 0);
732 if (v == Val_int (0))
733 stats |= VIR_DOMAIN_STATS_STATE;
734 else if (v == Val_int (1))
735 stats |= VIR_DOMAIN_STATS_CPU_TOTAL;
736 else if (v == Val_int (2))
737 stats |= VIR_DOMAIN_STATS_BALLOON;
738 else if (v == Val_int (3))
739 stats |= VIR_DOMAIN_STATS_VCPU;
740 else if (v == Val_int (4))
741 stats |= VIR_DOMAIN_STATS_INTERFACE;
742 else if (v == Val_int (5))
743 stats |= VIR_DOMAIN_STATS_BLOCK;
744 else if (v == Val_int (6))
745 stats |= VIR_DOMAIN_STATS_PERF;
747 for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1)) {
748 v = Field (flagsv, 0);
749 if (v == Val_int (0))
750 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE;
751 else if (v == Val_int (1))
752 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE;
753 else if (v == Val_int (2))
754 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_OTHER;
755 else if (v == Val_int (3))
756 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_PAUSED;
757 else if (v == Val_int (4))
758 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT;
759 else if (v == Val_int (5))
760 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_RUNNING;
761 else if (v == Val_int (6))
762 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF;
763 else if (v == Val_int (7))
764 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT;
765 else if (v == Val_int (8))
766 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING;
767 else if (v == Val_int (9))
768 flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS;
771 NONBLOCKING (r = virConnectGetAllDomainStats (conn, stats, &rstats, flags));
772 CHECK_ERROR (r == -1, "virConnectGetAllDomainStats");
774 rv = caml_alloc (r, 0); /* domain_stats_record array. */
775 for (i = 0; i < r; ++i) {
776 dsv = caml_alloc (2, 0); /* domain_stats_record */
778 /* Libvirt returns something superficially resembling a
779 * virDomainPtr, but it's not a real virDomainPtr object
780 * (eg. dom->id == -1, and its refcount is wrong). The only thing
781 * we can safely get from it is the UUID.
783 v = caml_alloc_string (VIR_UUID_BUFLEN);
784 virDomainGetUUID (rstats[i]->dom, uuid);
785 memcpy (String_val (v), uuid, VIR_UUID_BUFLEN);
786 Store_field (dsv, 0, v);
788 tpv = caml_alloc (rstats[i]->nparams, 0); /* typed_param array */
789 for (j = 0; j < rstats[i]->nparams; ++j) {
790 v2 = caml_alloc (2, 0); /* typed_param: field name, value */
791 Store_field (v2, 0, caml_copy_string (rstats[i]->params[j].field));
793 switch (rstats[i]->params[j].type) {
794 case VIR_TYPED_PARAM_INT:
795 v1 = caml_alloc (1, 0);
796 v = caml_copy_int32 (rstats[i]->params[j].value.i);
798 case VIR_TYPED_PARAM_UINT:
799 v1 = caml_alloc (1, 1);
800 v = caml_copy_int32 (rstats[i]->params[j].value.ui);
802 case VIR_TYPED_PARAM_LLONG:
803 v1 = caml_alloc (1, 2);
804 v = caml_copy_int64 (rstats[i]->params[j].value.l);
806 case VIR_TYPED_PARAM_ULLONG:
807 v1 = caml_alloc (1, 3);
808 v = caml_copy_int64 (rstats[i]->params[j].value.ul);
810 case VIR_TYPED_PARAM_DOUBLE:
811 v1 = caml_alloc (1, 4);
812 v = caml_copy_double (rstats[i]->params[j].value.d);
814 case VIR_TYPED_PARAM_BOOLEAN:
815 v1 = caml_alloc (1, 5);
816 v = Val_bool (rstats[i]->params[j].value.b);
818 case VIR_TYPED_PARAM_STRING:
819 v1 = caml_alloc (1, 6);
820 v = caml_copy_string (rstats[i]->params[j].value.s);
823 virDomainStatsRecordListFree (rstats);
824 caml_failwith ("virConnectGetAllDomainStats: "
825 "unknown parameter type returned");
827 Store_field (v1, 0, v);
829 Store_field (v2, 1, v1);
830 Store_field (tpv, j, v2);
833 Store_field (dsv, 1, tpv);
834 Store_field (rv, i, dsv);
837 virDomainStatsRecordListFree (rstats);
842 ocaml_libvirt_domain_migrate_native (value domv, value dconnv, value flagsv, value optdnamev, value opturiv, value optbandwidthv, value unitv)
844 CAMLparam5 (domv, dconnv, flagsv, optdnamev, opturiv);
845 CAMLxparam2 (optbandwidthv, unitv);
846 CAMLlocal2 (flagv, rv);
847 virDomainPtr dom = Domain_val (domv);
848 virConnectPtr dconn = Connect_val (dconnv);
850 const char *dname = Optstring_val (optdnamev);
851 const char *uri = Optstring_val (opturiv);
852 unsigned long bandwidth;
855 /* Iterate over the list of flags. */
856 for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1))
858 flagv = Field (flagsv, 0);
859 if (flagv == Val_int (0))
860 flags |= VIR_MIGRATE_LIVE;
863 if (optbandwidthv == Val_int (0)) /* None */
865 else /* Some bandwidth */
866 bandwidth = Int_val (Field (optbandwidthv, 0));
868 NONBLOCKING (r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth));
869 CHECK_ERROR (!r, "virDomainMigrate");
871 rv = Val_domain (r, dconnv);
877 ocaml_libvirt_domain_migrate_bytecode (value *argv, int argn)
879 return ocaml_libvirt_domain_migrate_native (argv[0], argv[1], argv[2],
880 argv[3], argv[4], argv[5],
885 ocaml_libvirt_domain_block_stats (value domv, value pathv)
887 CAMLparam2 (domv, pathv);
889 virDomainPtr dom = Domain_val (domv);
890 char *path = String_val (pathv);
891 struct _virDomainBlockStats stats;
894 NONBLOCKING (r = virDomainBlockStats (dom, path, &stats, sizeof stats));
895 CHECK_ERROR (r == -1, "virDomainBlockStats");
897 rv = caml_alloc (5, 0);
898 v = caml_copy_int64 (stats.rd_req); Store_field (rv, 0, v);
899 v = caml_copy_int64 (stats.rd_bytes); Store_field (rv, 1, v);
900 v = caml_copy_int64 (stats.wr_req); Store_field (rv, 2, v);
901 v = caml_copy_int64 (stats.wr_bytes); Store_field (rv, 3, v);
902 v = caml_copy_int64 (stats.errs); Store_field (rv, 4, v);
908 ocaml_libvirt_domain_interface_stats (value domv, value pathv)
910 CAMLparam2 (domv, pathv);
912 virDomainPtr dom = Domain_val (domv);
913 char *path = String_val (pathv);
914 struct _virDomainInterfaceStats stats;
917 NONBLOCKING (r = virDomainInterfaceStats (dom, path, &stats, sizeof stats));
918 CHECK_ERROR (r == -1, "virDomainInterfaceStats");
920 rv = caml_alloc (8, 0);
921 v = caml_copy_int64 (stats.rx_bytes); Store_field (rv, 0, v);
922 v = caml_copy_int64 (stats.rx_packets); Store_field (rv, 1, v);
923 v = caml_copy_int64 (stats.rx_errs); Store_field (rv, 2, v);
924 v = caml_copy_int64 (stats.rx_drop); Store_field (rv, 3, v);
925 v = caml_copy_int64 (stats.tx_bytes); Store_field (rv, 4, v);
926 v = caml_copy_int64 (stats.tx_packets); Store_field (rv, 5, v);
927 v = caml_copy_int64 (stats.tx_errs); Store_field (rv, 6, v);
928 v = caml_copy_int64 (stats.tx_drop); Store_field (rv, 7, v);
934 ocaml_libvirt_domain_block_peek_native (value domv, value pathv, value offsetv, value sizev, value bufferv, value boffv)
936 CAMLparam5 (domv, pathv, offsetv, sizev, bufferv);
938 virDomainPtr dom = Domain_val (domv);
939 const char *path = String_val (pathv);
940 unsigned long long offset = Int64_val (offsetv);
941 size_t size = Int_val (sizev);
942 char *buffer = String_val (bufferv);
943 int boff = Int_val (boffv);
946 /* Check that the return buffer is big enough. */
947 if (caml_string_length (bufferv) < boff + size)
948 caml_failwith ("virDomainBlockPeek: return buffer too short");
950 /* NB. not NONBLOCKING because buffer might move (XXX) */
951 r = virDomainBlockPeek (dom, path, offset, size, buffer+boff, 0);
952 CHECK_ERROR (r == -1, "virDomainBlockPeek");
954 CAMLreturn (Val_unit);
958 ocaml_libvirt_domain_block_peek_bytecode (value *argv, int argn)
960 return ocaml_libvirt_domain_block_peek_native (argv[0], argv[1], argv[2],
961 argv[3], argv[4], argv[5]);
965 ocaml_libvirt_domain_memory_peek_native (value domv, value flagsv, value offsetv, value sizev, value bufferv, value boffv)
967 CAMLparam5 (domv, flagsv, offsetv, sizev, bufferv);
970 virDomainPtr dom = Domain_val (domv);
972 unsigned long long offset = Int64_val (offsetv);
973 size_t size = Int_val (sizev);
974 char *buffer = String_val (bufferv);
975 int boff = Int_val (boffv);
978 /* Check that the return buffer is big enough. */
979 if (caml_string_length (bufferv) < boff + size)
980 caml_failwith ("virDomainMemoryPeek: return buffer too short");
983 for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1))
985 flagv = Field (flagsv, 0);
986 if (flagv == Val_int (0))
987 flags |= VIR_MEMORY_VIRTUAL;
990 /* NB. not NONBLOCKING because buffer might move (XXX) */
991 r = virDomainMemoryPeek (dom, offset, size, buffer+boff, flags);
992 CHECK_ERROR (r == -1, "virDomainMemoryPeek");
994 CAMLreturn (Val_unit);
998 ocaml_libvirt_domain_memory_peek_bytecode (value *argv, int argn)
1000 return ocaml_libvirt_domain_memory_peek_native (argv[0], argv[1], argv[2],
1001 argv[3], argv[4], argv[5]);
1005 ocaml_libvirt_domain_get_xml_desc_flags (value domv, value flagsv)
1007 CAMLparam2 (domv, flagsv);
1008 CAMLlocal2 (rv, flagv);
1009 virDomainPtr dom = Domain_val (domv);
1014 for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1))
1016 flagv = Field (flagsv, 0);
1017 if (flagv == Val_int (0))
1018 flags |= VIR_DOMAIN_XML_SECURE;
1019 else if (flagv == Val_int (1))
1020 flags |= VIR_DOMAIN_XML_INACTIVE;
1021 else if (flagv == Val_int (2))
1022 flags |= VIR_DOMAIN_XML_UPDATE_CPU;
1023 else if (flagv == Val_int (3))
1024 flags |= VIR_DOMAIN_XML_MIGRATABLE;
1027 NONBLOCKING (r = virDomainGetXMLDesc (dom, flags));
1028 CHECK_ERROR (!r, "virDomainGetXMLDesc");
1030 rv = caml_copy_string (r);
1035 /*----------------------------------------------------------------------*/
1040 ocaml_libvirt_event_register_default_impl (value unitv)
1044 /* arg is of type unit = void */
1047 NONBLOCKING (r = virEventRegisterDefaultImpl ());
1048 /* must be called before connection, therefore we can't use CHECK_ERROR */
1049 if (r == -1) caml_failwith("virEventRegisterDefaultImpl");
1051 CAMLreturn (Val_unit);
1055 ocaml_libvirt_event_run_default_impl (value unitv)
1059 /* arg is of type unit = void */
1062 NONBLOCKING (r = virEventRunDefaultImpl ());
1063 if (r == -1) caml_failwith("virEventRunDefaultImpl");
1065 CAMLreturn (Val_unit);
1068 /* We register a single C callback function for every distinct
1069 callback signature. We encode the signature itself in the function
1070 name and also in the name of the assocated OCaml callback
1073 i_i64_s_callback(virConnectPtr conn,
1079 would correspond to an OCaml callback
1080 Libvirt.i_i64_s_callback :
1081 int64 -> [`R] Domain.t -> int -> int64 -> string option -> unit
1082 where the initial int64 is a unique ID used by the OCaml to
1083 dispatch to the specific OCaml closure and stored by libvirt
1084 as the "opaque" data. */
1086 /* Every one of the callbacks starts with a DOMAIN_CALLBACK_BEGIN(NAME)
1087 where NAME is the string name of the OCaml callback registered
1089 #define DOMAIN_CALLBACK_BEGIN(NAME) \
1090 value connv, domv, callback_id, result; \
1091 connv = domv = callback_id = result = Val_int(0); \
1092 static value *callback = NULL; \
1093 caml_leave_blocking_section(); \
1094 if (callback == NULL) \
1095 callback = caml_named_value(NAME); \
1096 if (callback == NULL) \
1097 abort(); /* C code out of sync with OCaml code */ \
1098 if ((virDomainRef(dom) == -1) || (virConnectRef(conn) == -1)) \
1099 abort(); /* should never happen in practice? */ \
1101 Begin_roots4(connv, domv, callback_id, result); \
1102 connv = Val_connect(conn); \
1103 domv = Val_domain(dom, connv); \
1104 callback_id = caml_copy_int64(*(long *)opaque);
1106 /* Every one of the callbacks ends with a CALLBACK_END */
1107 #define DOMAIN_CALLBACK_END \
1108 (void) caml_callback3(*callback, callback_id, domv, result); \
1110 caml_enter_blocking_section();
1114 i_i_callback(virConnectPtr conn,
1120 DOMAIN_CALLBACK_BEGIN("Libvirt.i_i_callback")
1121 result = caml_alloc_tuple(2);
1122 Store_field(result, 0, Val_int(x));
1123 Store_field(result, 1, Val_int(y));
1128 u_callback(virConnectPtr conn,
1132 DOMAIN_CALLBACK_BEGIN("Libvirt.u_callback")
1133 result = Val_int(0); /* () */
1138 i64_callback(virConnectPtr conn,
1143 DOMAIN_CALLBACK_BEGIN("Libvirt.i64_callback")
1144 result = caml_copy_int64(int64);
1149 i_callback(virConnectPtr conn,
1154 DOMAIN_CALLBACK_BEGIN("Libvirt.i_callback")
1155 result = Val_int(x);
1160 s_i_callback(virConnectPtr conn,
1166 DOMAIN_CALLBACK_BEGIN("Libvirt.s_i_callback")
1167 result = caml_alloc_tuple(2);
1168 Store_field(result, 0,
1169 Val_opt(x, (Val_ptr_t) caml_copy_string));
1170 Store_field(result, 1, Val_int(y));
1175 s_i_i_callback(virConnectPtr conn,
1182 DOMAIN_CALLBACK_BEGIN("Libvirt.s_i_i_callback")
1183 result = caml_alloc_tuple(3);
1184 Store_field(result, 0,
1185 Val_opt(x, (Val_ptr_t) caml_copy_string));
1186 Store_field(result, 1, Val_int(y));
1187 Store_field(result, 2, Val_int(z));
1192 s_s_i_callback(virConnectPtr conn,
1199 DOMAIN_CALLBACK_BEGIN("Libvirt.s_s_i_callback")
1200 result = caml_alloc_tuple(3);
1201 Store_field(result, 0,
1202 Val_opt(x, (Val_ptr_t) caml_copy_string));
1203 Store_field(result, 1,
1204 Val_opt(y, (Val_ptr_t) caml_copy_string));
1205 Store_field(result, 2, Val_int(z));
1210 s_s_i_s_callback(virConnectPtr conn,
1218 DOMAIN_CALLBACK_BEGIN("Libvirt.s_s_i_s_callback")
1219 result = caml_alloc_tuple(4);
1220 Store_field(result, 0,
1221 Val_opt(x, (Val_ptr_t) caml_copy_string));
1222 Store_field(result, 1,
1223 Val_opt(y, (Val_ptr_t) caml_copy_string));
1224 Store_field(result, 2, Val_int(z));
1225 Store_field(result, 3,
1226 Val_opt(a, (Val_ptr_t) caml_copy_string));
1231 s_s_s_i_callback(virConnectPtr conn,
1239 DOMAIN_CALLBACK_BEGIN("Libvirt.s_s_s_i_callback")
1240 result = caml_alloc_tuple(4);
1241 Store_field(result, 0,
1242 Val_opt(x, (Val_ptr_t) caml_copy_string));
1243 Store_field(result, 1,
1244 Val_opt(y, (Val_ptr_t) caml_copy_string));
1245 Store_field(result, 2,
1246 Val_opt(z, (Val_ptr_t) caml_copy_string));
1247 Store_field(result, 3, Val_int(a));
1252 Val_event_graphics_address(virDomainEventGraphicsAddressPtr x)
1256 result = caml_alloc_tuple(3);
1257 Store_field(result, 0, Val_int(x->family));
1258 Store_field(result, 1,
1259 Val_opt((void *) x->node, (Val_ptr_t) caml_copy_string));
1260 Store_field(result, 2,
1261 Val_opt((void *) x->service, (Val_ptr_t) caml_copy_string));
1266 Val_event_graphics_subject_identity(virDomainEventGraphicsSubjectIdentityPtr x)
1270 result = caml_alloc_tuple(2);
1271 Store_field(result, 0,
1272 Val_opt((void *) x->type, (Val_ptr_t) caml_copy_string));
1273 Store_field(result, 1,
1274 Val_opt((void *) x->name, (Val_ptr_t) caml_copy_string));
1280 Val_event_graphics_subject(virDomainEventGraphicsSubjectPtr x)
1285 result = caml_alloc_tuple(x->nidentity);
1286 for (i = 0; i < x->nidentity; i++ )
1287 Store_field(result, i,
1288 Val_event_graphics_subject_identity(x->identities + i));
1293 i_ga_ga_s_gs_callback(virConnectPtr conn,
1296 virDomainEventGraphicsAddressPtr ga1,
1297 virDomainEventGraphicsAddressPtr ga2,
1299 virDomainEventGraphicsSubjectPtr gs1,
1302 DOMAIN_CALLBACK_BEGIN("Libvirt.i_ga_ga_s_gs_callback")
1303 result = caml_alloc_tuple(5);
1304 Store_field(result, 0, Val_int(i1));
1305 Store_field(result, 1, Val_event_graphics_address(ga1));
1306 Store_field(result, 2, Val_event_graphics_address(ga2));
1307 Store_field(result, 3,
1308 Val_opt(s1, (Val_ptr_t) caml_copy_string));
1309 Store_field(result, 4, Val_event_graphics_subject(gs1));
1314 timeout_callback(int timer, void *opaque)
1316 value callback_id, result;
1317 callback_id = result = Val_int(0);
1318 static value *callback = NULL;
1319 caml_leave_blocking_section();
1320 if (callback == NULL)
1321 callback = caml_named_value("Libvirt.timeout_callback");
1322 if (callback == NULL)
1323 abort(); /* C code out of sync with OCaml code */
1325 Begin_roots2(callback_id, result);
1326 callback_id = caml_copy_int64(*(long *)opaque);
1328 (void)caml_callback_exn(*callback, callback_id);
1330 caml_enter_blocking_section();
1334 ocaml_libvirt_event_add_timeout (value connv, value ms, value callback_id)
1336 CAMLparam3 (connv, ms, callback_id);
1338 virFreeCallback freecb = free;
1339 virEventTimeoutCallback cb = timeout_callback;
1343 /* Store the int64 callback_id as the opaque data so the OCaml
1344 callback can demultiplex to the correct OCaml handler. */
1345 if ((opaque = malloc(sizeof(long))) == NULL)
1346 caml_failwith ("virEventAddTimeout: malloc");
1347 *((long*)opaque) = Int64_val(callback_id);
1348 NONBLOCKING(r = virEventAddTimeout(Int_val(ms), cb, opaque, freecb));
1349 CHECK_ERROR(r == -1, "virEventAddTimeout");
1351 CAMLreturn(Val_int(r));
1355 ocaml_libvirt_event_remove_timeout (value connv, value timer_id)
1357 CAMLparam2 (connv, timer_id);
1360 NONBLOCKING(r = virEventRemoveTimeout(Int_val(timer_id)));
1361 CHECK_ERROR(r == -1, "virEventRemoveTimeout");
1363 CAMLreturn(Val_int(r));
1367 ocaml_libvirt_connect_domain_event_register_any(value connv, value domv, value callback, value callback_id)
1369 CAMLparam4(connv, domv, callback, callback_id);
1371 virConnectPtr conn = Connect_val (connv);
1372 virDomainPtr dom = NULL;
1373 int eventID = Tag_val(callback);
1375 virConnectDomainEventGenericCallback cb;
1377 virFreeCallback freecb = free;
1380 if (domv != Val_int(0))
1381 dom = Domain_val (Field(domv, 0));
1384 case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
1385 cb = VIR_DOMAIN_EVENT_CALLBACK(i_i_callback);
1387 case VIR_DOMAIN_EVENT_ID_REBOOT:
1388 cb = VIR_DOMAIN_EVENT_CALLBACK(u_callback);
1390 case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
1391 cb = VIR_DOMAIN_EVENT_CALLBACK(i64_callback);
1393 case VIR_DOMAIN_EVENT_ID_WATCHDOG:
1394 cb = VIR_DOMAIN_EVENT_CALLBACK(i_callback);
1396 case VIR_DOMAIN_EVENT_ID_IO_ERROR:
1397 cb = VIR_DOMAIN_EVENT_CALLBACK(s_s_i_callback);
1399 case VIR_DOMAIN_EVENT_ID_GRAPHICS:
1400 cb = VIR_DOMAIN_EVENT_CALLBACK(i_ga_ga_s_gs_callback);
1402 case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
1403 cb = VIR_DOMAIN_EVENT_CALLBACK(s_s_i_s_callback);
1405 case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
1406 cb = VIR_DOMAIN_EVENT_CALLBACK(u_callback);
1408 case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
1409 cb = VIR_DOMAIN_EVENT_CALLBACK(s_i_i_callback);
1411 case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
1412 cb = VIR_DOMAIN_EVENT_CALLBACK(s_s_s_i_callback);
1414 case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
1415 cb = VIR_DOMAIN_EVENT_CALLBACK(s_i_callback);
1417 case VIR_DOMAIN_EVENT_ID_PMWAKEUP:
1418 cb = VIR_DOMAIN_EVENT_CALLBACK(i_callback);
1420 case VIR_DOMAIN_EVENT_ID_PMSUSPEND:
1421 cb = VIR_DOMAIN_EVENT_CALLBACK(i_callback);
1423 case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
1424 cb = VIR_DOMAIN_EVENT_CALLBACK(i64_callback);
1426 case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK:
1427 cb = VIR_DOMAIN_EVENT_CALLBACK(i_callback);
1430 caml_failwith("vifConnectDomainEventRegisterAny: unimplemented eventID");
1433 /* Store the int64 callback_id as the opaque data so the OCaml
1434 callback can demultiplex to the correct OCaml handler. */
1435 if ((opaque = malloc(sizeof(long))) == NULL)
1436 caml_failwith ("virConnectDomainEventRegisterAny: malloc");
1437 *((long*)opaque) = Int64_val(callback_id);
1438 NONBLOCKING(r = virConnectDomainEventRegisterAny(conn, dom, eventID, cb, opaque, freecb));
1439 CHECK_ERROR(r == -1, "virConnectDomainEventRegisterAny");
1441 CAMLreturn(Val_int(r));
1445 ocaml_libvirt_storage_pool_get_info (value poolv)
1449 virStoragePoolPtr pool = Pool_val (poolv);
1450 virStoragePoolInfo info;
1453 NONBLOCKING (r = virStoragePoolGetInfo (pool, &info));
1454 CHECK_ERROR (r == -1, "virStoragePoolGetInfo");
1456 rv = caml_alloc (4, 0);
1457 Store_field (rv, 0, Val_int (info.state));
1458 v = caml_copy_int64 (info.capacity); Store_field (rv, 1, v);
1459 v = caml_copy_int64 (info.allocation); Store_field (rv, 2, v);
1460 v = caml_copy_int64 (info.available); Store_field (rv, 3, v);
1466 ocaml_libvirt_storage_vol_get_info (value volv)
1470 virStorageVolPtr vol = Volume_val (volv);
1471 virStorageVolInfo info;
1474 NONBLOCKING (r = virStorageVolGetInfo (vol, &info));
1475 CHECK_ERROR (r == -1, "virStorageVolGetInfo");
1477 rv = caml_alloc (3, 0);
1478 Store_field (rv, 0, Val_int (info.type));
1479 v = caml_copy_int64 (info.capacity); Store_field (rv, 1, v);
1480 v = caml_copy_int64 (info.allocation); Store_field (rv, 2, v);
1485 /*----------------------------------------------------------------------*/
1488 ocaml_libvirt_virterror_get_last_error (value unitv)
1492 virErrorPtr err = virGetLastError ();
1494 rv = Val_opt (err, (Val_ptr_t) Val_virterror);
1500 ocaml_libvirt_virterror_get_last_conn_error (value connv)
1504 virConnectPtr conn = Connect_val (connv);
1506 rv = Val_opt (conn, (Val_ptr_t) Val_connect);
1512 ocaml_libvirt_virterror_reset_last_error (value unitv)
1515 virResetLastError ();
1516 CAMLreturn (Val_unit);
1520 ocaml_libvirt_virterror_reset_last_conn_error (value connv)
1523 virConnectPtr conn = Connect_val (connv);
1524 virConnResetLastError (conn);
1525 CAMLreturn (Val_unit);
1528 /*----------------------------------------------------------------------*/
1531 ignore_errors (void *user_data, virErrorPtr error)
1536 /* Initialise the library. */
1538 ocaml_libvirt_init (value unit)
1542 virSetErrorFunc (NULL, ignore_errors);
1545 CAMLreturn (Val_unit);