Autogenerate all GetUUID and GetUUIDString functions.
[virt-top.git] / libvirt / libvirt_c_oneoffs.c
1 /* OCaml bindings for libvirt.
2  * (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
3  * http://libvirt.org/
4  *
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.
9  *
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.
14  *
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
18  */
19
20 /* Please read libvirt/README file. */
21
22 #ifdef HAVE_WEAK_SYMBOLS
23 #ifdef HAVE_VIRDOMAINBLOCKSTATS
24 extern int virDomainBlockStats (virDomainPtr dom,
25                                 const char *path,
26                                 virDomainBlockStatsPtr stats,
27                                 size_t size)
28   __attribute__((weak));
29 #endif
30 #ifdef HAVE_VIRDOMAINGETSCHEDULERPARAMETERS
31 extern int virDomainGetSchedulerParameters (virDomainPtr domain,
32                                             virSchedParameterPtr params,
33                                             int *nparams)
34   __attribute__((weak));
35 #endif
36 #ifdef HAVE_VIRDOMAINGETSCHEDULERTYPE
37 extern char *virDomainGetSchedulerType(virDomainPtr domain,
38                                        int *nparams)
39   __attribute__((weak));
40 #endif
41 #ifdef HAVE_VIRDOMAININTERFACESTATS
42 extern int virDomainInterfaceStats (virDomainPtr dom,
43                                     const char *path,
44                                     virDomainInterfaceStatsPtr stats,
45                                     size_t size)
46   __attribute__((weak));
47 #endif
48 #ifdef HAVE_VIRDOMAINMIGRATE
49 extern virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn,
50                                       unsigned long flags, const char *dname,
51                                       const char *uri, unsigned long bandwidth)
52   __attribute__((weak));
53 #endif
54 #ifdef HAVE_VIRDOMAINSETSCHEDULERPARAMETERS
55 extern int virDomainSetSchedulerParameters (virDomainPtr domain,
56                                             virSchedParameterPtr params,
57                                             int nparams)
58   __attribute__((weak));
59 #endif
60 #ifdef HAVE_VIRNODEGETFREEMEMORY
61 extern unsigned long long virNodeGetFreeMemory (virConnectPtr conn)
62   __attribute__((weak));
63 #endif
64 #ifdef HAVE_VIRNODEGETCELLSFREEMEMORY
65 extern int virNodeGetCellsFreeMemory (virConnectPtr conn,
66                                       unsigned long long *freeMems,
67                                       int startCell, int maxCells)
68   __attribute__((weak));
69 #endif
70 #endif /* HAVE_WEAK_SYMBOLS */
71
72 /*----------------------------------------------------------------------*/
73
74 CAMLprim value
75 ocaml_libvirt_get_version (value driverv, value unit)
76 {
77   CAMLparam2 (driverv, unit);
78   CAMLlocal1 (rv);
79   const char *driver = Optstring_val (driverv);
80   unsigned long libVer, typeVer = 0, *typeVer_ptr;
81   int r;
82
83   typeVer_ptr = driver ? &typeVer : NULL;
84   NONBLOCKING (r = virGetVersion (&libVer, driver, typeVer_ptr));
85   CHECK_ERROR (r == -1, NULL, "virGetVersion");
86
87   rv = caml_alloc_tuple (2);
88   Store_field (rv, 0, Val_int (libVer));
89   Store_field (rv, 1, Val_int (typeVer));
90   CAMLreturn (rv);
91 }
92
93 /*----------------------------------------------------------------------*/
94
95 /* Connection object. */
96
97 CAMLprim value
98 ocaml_libvirt_connect_open (value namev, value unit)
99 {
100   CAMLparam2 (namev, unit);
101   CAMLlocal1 (rv);
102   const char *name = Optstring_val (namev);
103   virConnectPtr conn;
104
105   NONBLOCKING (conn = virConnectOpen (name));
106   CHECK_ERROR (!conn, NULL, "virConnectOpen");
107
108   rv = Val_connect (conn);
109
110   CAMLreturn (rv);
111 }
112
113 CAMLprim value
114 ocaml_libvirt_connect_open_readonly (value namev, value unit)
115 {
116   CAMLparam2 (namev, unit);
117   CAMLlocal1 (rv);
118   const char *name = Optstring_val (namev);
119   virConnectPtr conn;
120
121   NONBLOCKING (conn = virConnectOpenReadOnly (name));
122   CHECK_ERROR (!conn, NULL, "virConnectOpen");
123
124   rv = Val_connect (conn);
125
126   CAMLreturn (rv);
127 }
128
129 CAMLprim value
130 ocaml_libvirt_connect_close (value connv)
131 {
132   CAMLparam1 (connv);
133   virConnectPtr conn = Connect_val (connv);
134   int r;
135
136   NONBLOCKING (r = virConnectClose (conn));
137   CHECK_ERROR (r == -1, conn, "virConnectClose");
138
139   /* So that we don't double-free in the finalizer: */
140   Connect_val (connv) = NULL;
141
142   CAMLreturn (Val_unit);
143 }
144
145 CAMLprim value
146 ocaml_libvirt_connect_get_version (value connv)
147 {
148   CAMLparam1 (connv);
149   virConnectPtr conn = Connect_val (connv);
150   unsigned long hvVer;
151   int r;
152
153   NONBLOCKING (r = virConnectGetVersion (conn, &hvVer));
154   CHECK_ERROR (r == -1, conn, "virConnectGetVersion");
155
156   CAMLreturn (Val_int (hvVer));
157 }
158
159 CAMLprim value
160 ocaml_libvirt_connect_get_max_vcpus (value connv, value typev)
161 {
162   CAMLparam2 (connv, typev);
163   virConnectPtr conn = Connect_val (connv);
164   const char *type = Optstring_val (typev);
165   int r;
166
167   NONBLOCKING (r = virConnectGetMaxVcpus (conn, type));
168   CHECK_ERROR (r == -1, conn, "virConnectGetMaxVcpus");
169
170   CAMLreturn (Val_int (r));
171 }
172
173 CAMLprim value
174 ocaml_libvirt_connect_get_node_info (value connv)
175 {
176   CAMLparam1 (connv);
177   CAMLlocal2 (rv, v);
178   virConnectPtr conn = Connect_val (connv);
179   virNodeInfo info;
180   int r;
181
182   NONBLOCKING (r = virNodeGetInfo (conn, &info));
183   CHECK_ERROR (r == -1, conn, "virNodeGetInfo");
184
185   rv = caml_alloc (8, 0);
186   v = caml_copy_string (info.model); Store_field (rv, 0, v);
187   v = caml_copy_int64 (info.memory); Store_field (rv, 1, v);
188   Store_field (rv, 2, Val_int (info.cpus));
189   Store_field (rv, 3, Val_int (info.mhz));
190   Store_field (rv, 4, Val_int (info.nodes));
191   Store_field (rv, 5, Val_int (info.sockets));
192   Store_field (rv, 6, Val_int (info.cores));
193   Store_field (rv, 7, Val_int (info.threads));
194
195   CAMLreturn (rv);
196 }
197
198 CAMLprim value
199 ocaml_libvirt_connect_node_get_free_memory (value connv)
200 {
201 #ifdef HAVE_VIRNODEGETFREEMEMORY
202   CAMLparam1 (connv);
203   CAMLlocal1 (rv);
204   virConnectPtr conn = Connect_val (connv);
205   unsigned long long r;
206
207   WEAK_SYMBOL_CHECK (virNodeGetFreeMemory);
208   NONBLOCKING (r = virNodeGetFreeMemory (conn));
209   CHECK_ERROR (r == 0, conn, "virNodeGetFreeMemory");
210
211   rv = caml_copy_int64 ((int64) r);
212   CAMLreturn (rv);
213 #else
214   not_supported ("virNodeGetFreeMemory");
215 #endif
216 }
217
218 CAMLprim value
219 ocaml_libvirt_connect_node_get_cells_free_memory (value connv,
220                                                   value startv, value maxv)
221 {
222 #ifdef HAVE_VIRNODEGETCELLSFREEMEMORY
223   CAMLparam3 (connv, startv, maxv);
224   CAMLlocal2 (rv, iv);
225   virConnectPtr conn = Connect_val (connv);
226   int start = Int_val (startv);
227   int max = Int_val (maxv);
228   int r, i;
229   unsigned long long freemems[max];
230
231   WEAK_SYMBOL_CHECK (virNodeGetCellsFreeMemory);
232   NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max));
233   CHECK_ERROR (r == -1, conn, "virNodeGetCellsFreeMemory");
234
235   rv = caml_alloc (r, 0);
236   for (i = 0; i < r; ++i) {
237     iv = caml_copy_int64 ((int64) freemems[i]);
238     Store_field (rv, i, iv);
239   }
240
241   CAMLreturn (rv);
242 #else
243   not_supported ("virNodeGetCellsFreeMemory");
244 #endif
245 }
246
247 CAMLprim value
248 ocaml_libvirt_domain_create_linux (value connv, value xmlv)
249 {
250   CAMLparam2 (connv, xmlv);
251   CAMLlocal1 (rv);
252   virConnectPtr conn = Connect_val (connv);
253   char *xml = String_val (xmlv);
254   virDomainPtr r;
255
256   NONBLOCKING (r = virDomainCreateLinux (conn, xml, 0));
257   CHECK_ERROR (!r, conn, "virDomainCreateLinux");
258
259   rv = Val_domain (r, connv);
260   CAMLreturn (rv);
261 }
262
263 CAMLprim value
264 ocaml_libvirt_domain_lookup_by_id (value connv, value iv)
265 {
266   CAMLparam2 (connv, iv);
267   CAMLlocal1 (rv);
268   virConnectPtr conn = Connect_val (connv);
269   int i = Int_val (iv);
270   virDomainPtr r;
271
272   NONBLOCKING (r = virDomainLookupByID (conn, i));
273   CHECK_ERROR (!r, conn, "virDomainLookupByID");
274
275   rv = Val_domain (r, connv);
276   CAMLreturn (rv);
277 }
278
279 CAMLprim value
280 ocaml_libvirt_domain_lookup_by_uuid (value connv, value uuidv)
281 {
282   CAMLparam2 (connv, uuidv);
283   CAMLlocal1 (rv);
284   virConnectPtr conn = Connect_val (connv);
285   char *uuid = String_val (uuidv);
286   virDomainPtr r;
287
288   NONBLOCKING (r = virDomainLookupByUUID (conn, (unsigned char *) uuid));
289   CHECK_ERROR (!r, conn, "virDomainLookupByUUID");
290
291   rv = Val_domain (r, connv);
292   CAMLreturn (rv);
293 }
294
295 CAMLprim value
296 ocaml_libvirt_domain_destroy (value domv)
297 {
298   CAMLparam1 (domv);
299   virDomainPtr dom = Domain_val (domv);
300   virConnectPtr conn = Connect_domv (domv);
301   int r;
302
303   NONBLOCKING (r = virDomainDestroy (dom));
304   CHECK_ERROR (r == -1, conn, "virDomainDestroy");
305
306   /* So that we don't double-free in the finalizer: */
307   Domain_val (domv) = NULL;
308
309   CAMLreturn (Val_unit);
310 }
311
312 CAMLprim value
313 ocaml_libvirt_domain_free (value domv)
314 {
315   CAMLparam1 (domv);
316   virDomainPtr dom = Domain_val (domv);
317   virConnectPtr conn = Connect_domv (domv);
318   int r;
319
320   NONBLOCKING (r = virDomainFree (dom));
321   CHECK_ERROR (r == -1, conn, "virDomainFree");
322
323   /* So that we don't double-free in the finalizer: */
324   Domain_val (domv) = NULL;
325
326   CAMLreturn (Val_unit);
327 }
328
329 CAMLprim value
330 ocaml_libvirt_domain_save (value domv, value pathv)
331 {
332   CAMLparam2 (domv, pathv);
333   virDomainPtr dom = Domain_val (domv);
334   virConnectPtr conn = Connect_domv (domv);
335   char *path = String_val (pathv);
336   int r;
337
338   NONBLOCKING (r = virDomainSave (dom, path));
339   CHECK_ERROR (r == -1, conn, "virDomainSave");
340
341   CAMLreturn (Val_unit);
342 }
343
344 CAMLprim value
345 ocaml_libvirt_domain_restore (value connv, value pathv)
346 {
347   CAMLparam2 (connv, pathv);
348   virConnectPtr conn = Connect_val (connv);
349   char *path = String_val (pathv);
350   int r;
351
352   NONBLOCKING (r = virDomainRestore (conn, path));
353   CHECK_ERROR (r == -1, conn, "virDomainRestore");
354
355   CAMLreturn (Val_unit);
356 }
357
358 CAMLprim value
359 ocaml_libvirt_domain_core_dump (value domv, value pathv)
360 {
361   CAMLparam2 (domv, pathv);
362   virDomainPtr dom = Domain_val (domv);
363   virConnectPtr conn = Connect_domv (domv);
364   char *path = String_val (pathv);
365   int r;
366
367   NONBLOCKING (r = virDomainCoreDump (dom, path, 0));
368   CHECK_ERROR (r == -1, conn, "virDomainCoreDump");
369
370   CAMLreturn (Val_unit);
371 }
372
373 CAMLprim value
374 ocaml_libvirt_domain_get_id (value domv)
375 {
376   CAMLparam1 (domv);
377   virDomainPtr dom = Domain_val (domv);
378   virConnectPtr conn = Connect_domv (domv);
379   unsigned int r;
380
381   NONBLOCKING (r = virDomainGetID (dom));
382   /* There's a bug in libvirt which means that if you try to get
383    * the ID of a defined-but-not-running domain, it returns -1,
384    * and there's no way to distinguish that from an error.
385    */
386   CHECK_ERROR (r == (unsigned int) -1, conn, "virDomainGetID");
387
388   CAMLreturn (Val_int ((int) r));
389 }
390
391 CAMLprim value
392 ocaml_libvirt_domain_get_max_memory (value domv)
393 {
394   CAMLparam1 (domv);
395   CAMLlocal1 (rv);
396   virDomainPtr dom = Domain_val (domv);
397   virConnectPtr conn = Connect_domv (domv);
398   unsigned long r;
399
400   NONBLOCKING (r = virDomainGetMaxMemory (dom));
401   CHECK_ERROR (r == 0 /* [sic] */, conn, "virDomainGetMaxMemory");
402
403   rv = caml_copy_int64 (r);
404   CAMLreturn (rv);
405 }
406
407 CAMLprim value
408 ocaml_libvirt_domain_set_max_memory (value domv, value memv)
409 {
410   CAMLparam2 (domv, memv);
411   virDomainPtr dom = Domain_val (domv);
412   virConnectPtr conn = Connect_domv (domv);
413   unsigned long mem = Int64_val (memv);
414   int r;
415
416   NONBLOCKING (r = virDomainSetMaxMemory (dom, mem));
417   CHECK_ERROR (r == -1, conn, "virDomainSetMaxMemory");
418
419   CAMLreturn (Val_unit);
420 }
421
422 CAMLprim value
423 ocaml_libvirt_domain_set_memory (value domv, value memv)
424 {
425   CAMLparam2 (domv, memv);
426   virDomainPtr dom = Domain_val (domv);
427   virConnectPtr conn = Connect_domv (domv);
428   unsigned long mem = Int64_val (memv);
429   int r;
430
431   NONBLOCKING (r = virDomainSetMemory (dom, mem));
432   CHECK_ERROR (r == -1, conn, "virDomainSetMemory");
433
434   CAMLreturn (Val_unit);
435 }
436
437 CAMLprim value
438 ocaml_libvirt_domain_get_info (value domv)
439 {
440   CAMLparam1 (domv);
441   CAMLlocal2 (rv, v);
442   virDomainPtr dom = Domain_val (domv);
443   virConnectPtr conn = Connect_domv (domv);
444   virDomainInfo info;
445   int r;
446
447   NONBLOCKING (r = virDomainGetInfo (dom, &info));
448   CHECK_ERROR (r == -1, conn, "virDomainGetInfo");
449
450   rv = caml_alloc (5, 0);
451   Store_field (rv, 0, Val_int (info.state)); // These flags are compatible.
452   v = caml_copy_int64 (info.maxMem); Store_field (rv, 1, v);
453   v = caml_copy_int64 (info.memory); Store_field (rv, 2, v);
454   Store_field (rv, 3, Val_int (info.nrVirtCpu));
455   v = caml_copy_int64 (info.cpuTime); Store_field (rv, 4, v);
456
457   CAMLreturn (rv);
458 }
459
460 CAMLprim value
461 ocaml_libvirt_domain_get_scheduler_type (value domv)
462 {
463 #ifdef HAVE_VIRDOMAINGETSCHEDULERTYPE
464   CAMLparam1 (domv);
465   CAMLlocal2 (rv, strv);
466   virDomainPtr dom = Domain_val (domv);
467   virConnectPtr conn = Connect_domv (domv);
468   char *r;
469   int nparams;
470
471   WEAK_SYMBOL_CHECK (virDomainGetSchedulerType);
472   NONBLOCKING (r = virDomainGetSchedulerType (dom, &nparams));
473   CHECK_ERROR (!r, conn, "virDomainGetSchedulerType");
474
475   rv = caml_alloc_tuple (2);
476   strv = caml_copy_string (r); Store_field (rv, 0, strv);
477   free (r);
478   Store_field (rv, 1, nparams);
479   CAMLreturn (rv);
480 #else
481   not_supported ("virDomainGetSchedulerType");
482 #endif
483 }
484
485 CAMLprim value
486 ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
487 {
488 #ifdef HAVE_VIRDOMAINGETSCHEDULERPARAMETERS
489   CAMLparam2 (domv, nparamsv);
490   CAMLlocal4 (rv, v, v2, v3);
491   virDomainPtr dom = Domain_val (domv);
492   virConnectPtr conn = Connect_domv (domv);
493   int nparams = Int_val (nparamsv);
494   virSchedParameter params[nparams];
495   int r, i;
496
497   WEAK_SYMBOL_CHECK (virDomainGetSchedulerParameters);
498   NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams));
499   CHECK_ERROR (r == -1, conn, "virDomainGetSchedulerParameters");
500
501   rv = caml_alloc (nparams, 0);
502   for (i = 0; i < nparams; ++i) {
503     v = caml_alloc_tuple (2); Store_field (rv, i, v);
504     v2 = caml_copy_string (params[i].field); Store_field (v, 0, v2);
505     switch (params[i].type) {
506     case VIR_DOMAIN_SCHED_FIELD_INT:
507       v2 = caml_alloc (1, 0);
508       v3 = caml_copy_int32 (params[i].value.i); Store_field (v2, 0, v3);
509       break;
510     case VIR_DOMAIN_SCHED_FIELD_UINT:
511       v2 = caml_alloc (1, 1);
512       v3 = caml_copy_int32 (params[i].value.ui); Store_field (v2, 0, v3);
513       break;
514     case VIR_DOMAIN_SCHED_FIELD_LLONG:
515       v2 = caml_alloc (1, 2);
516       v3 = caml_copy_int64 (params[i].value.l); Store_field (v2, 0, v3);
517       break;
518     case VIR_DOMAIN_SCHED_FIELD_ULLONG:
519       v2 = caml_alloc (1, 3);
520       v3 = caml_copy_int64 (params[i].value.ul); Store_field (v2, 0, v3);
521       break;
522     case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
523       v2 = caml_alloc (1, 4);
524       v3 = caml_copy_double (params[i].value.d); Store_field (v2, 0, v3);
525       break;
526     case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
527       v2 = caml_alloc (1, 5);
528       Store_field (v2, 0, Val_int (params[i].value.b));
529       break;
530     default:
531       caml_failwith ((char *)__FUNCTION__);
532     }
533     Store_field (v, 1, v2);
534   }
535   CAMLreturn (rv);
536 #else
537   not_supported ("virDomainGetSchedulerParameters");
538 #endif
539 }
540
541 CAMLprim value
542 ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv)
543 {
544 #ifdef HAVE_VIRDOMAINSETSCHEDULERPARAMETERS
545   CAMLparam2 (domv, paramsv);
546   CAMLlocal1 (v);
547   virDomainPtr dom = Domain_val (domv);
548   virConnectPtr conn = Connect_domv (domv);
549   int nparams = Wosize_val (paramsv);
550   virSchedParameter params[nparams];
551   int r, i;
552   char *name;
553
554   for (i = 0; i < nparams; ++i) {
555     v = Field (paramsv, i);     /* Points to the two-element tuple. */
556     name = String_val (Field (v, 0));
557     strncpy (params[i].field, name, VIR_DOMAIN_SCHED_FIELD_LENGTH);
558     params[i].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
559     v = Field (v, 1);           /* Points to the sched_param_value block. */
560     switch (Tag_val (v)) {
561     case 0:
562       params[i].type = VIR_DOMAIN_SCHED_FIELD_INT;
563       params[i].value.i = Int32_val (Field (v, 0));
564       break;
565     case 1:
566       params[i].type = VIR_DOMAIN_SCHED_FIELD_UINT;
567       params[i].value.ui = Int32_val (Field (v, 0));
568       break;
569     case 2:
570       params[i].type = VIR_DOMAIN_SCHED_FIELD_LLONG;
571       params[i].value.l = Int64_val (Field (v, 0));
572       break;
573     case 3:
574       params[i].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
575       params[i].value.ul = Int64_val (Field (v, 0));
576       break;
577     case 4:
578       params[i].type = VIR_DOMAIN_SCHED_FIELD_DOUBLE;
579       params[i].value.d = Double_val (Field (v, 0));
580       break;
581     case 5:
582       params[i].type = VIR_DOMAIN_SCHED_FIELD_BOOLEAN;
583       params[i].value.b = Int_val (Field (v, 0));
584       break;
585     default:
586       caml_failwith ((char *)__FUNCTION__);
587     }
588   }
589
590   WEAK_SYMBOL_CHECK (virDomainSetSchedulerParameters);
591   NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams));
592   CHECK_ERROR (r == -1, conn, "virDomainSetSchedulerParameters");
593
594   CAMLreturn (Val_unit);
595 #else
596   not_supported ("virDomainSetSchedulerParameters");
597 #endif
598 }
599
600 CAMLprim value
601 ocaml_libvirt_domain_define_xml (value connv, value xmlv)
602 {
603   CAMLparam2 (connv, xmlv);
604   CAMLlocal1 (rv);
605   virConnectPtr conn = Connect_val (connv);
606   char *xml = String_val (xmlv);
607   virDomainPtr r;
608
609   NONBLOCKING (r = virDomainDefineXML (conn, xml));
610   CHECK_ERROR (!r, conn, "virDomainDefineXML");
611
612   rv = Val_domain (r, connv);
613   CAMLreturn (rv);
614 }
615
616 CAMLprim value
617 ocaml_libvirt_domain_set_vcpus (value domv, value nvcpusv)
618 {
619   CAMLparam2 (domv, nvcpusv);
620   virDomainPtr dom = Domain_val (domv);
621   virConnectPtr conn = Connect_domv (domv);
622   int r, nvcpus = Int_val (nvcpusv);
623
624   NONBLOCKING (r = virDomainSetVcpus (dom, nvcpus));
625   CHECK_ERROR (r == -1, conn, "virDomainSetVcpus");
626
627   CAMLreturn (Val_unit);
628 }
629
630 CAMLprim value
631 ocaml_libvirt_domain_pin_vcpu (value domv, value vcpuv, value cpumapv)
632 {
633   CAMLparam3 (domv, vcpuv, cpumapv);
634   virDomainPtr dom = Domain_val (domv);
635   virConnectPtr conn = Connect_domv (domv);
636   int maplen = caml_string_length (cpumapv);
637   unsigned char *cpumap = (unsigned char *) String_val (cpumapv);
638   int vcpu = Int_val (vcpuv);
639   int r;
640
641   NONBLOCKING (r = virDomainPinVcpu (dom, vcpu, cpumap, maplen));
642   CHECK_ERROR (r == -1, conn, "virDomainPinVcpu");
643
644   CAMLreturn (Val_unit);
645 }
646
647 CAMLprim value
648 ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
649 {
650   CAMLparam3 (domv, maxinfov, maplenv);
651   CAMLlocal5 (rv, infov, strv, v, v2);
652   virDomainPtr dom = Domain_val (domv);
653   virConnectPtr conn = Connect_domv (domv);
654   int maxinfo = Int_val (maxinfov);
655   int maplen = Int_val (maplenv);
656   virVcpuInfo info[maxinfo];
657   unsigned char cpumaps[maxinfo * maplen];
658   int r, i;
659
660   memset (info, 0, sizeof (virVcpuInfo) * maxinfo);
661   memset (cpumaps, 0, maxinfo * maplen);
662
663   NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen));
664   CHECK_ERROR (r == -1, conn, "virDomainPinVcpu");
665
666   /* Copy the virVcpuInfo structures. */
667   infov = caml_alloc (maxinfo, 0);
668   for (i = 0; i < maxinfo; ++i) {
669     v2 = caml_alloc (4, 0); Store_field (infov, i, v2);
670     Store_field (v2, 0, Val_int (info[i].number));
671     Store_field (v2, 1, Val_int (info[i].state));
672     v = caml_copy_int64 (info[i].cpuTime); Store_field (v2, 2, v);
673     Store_field (v2, 3, Val_int (info[i].cpu));
674   }
675
676   /* Copy the bitmap. */
677   strv = caml_alloc_string (maxinfo * maplen);
678   memcpy (String_val (strv), cpumaps, maxinfo * maplen);
679
680   /* Allocate the tuple and return it. */
681   rv = caml_alloc_tuple (3);
682   Store_field (rv, 0, Val_int (r)); /* number of CPUs. */
683   Store_field (rv, 1, infov);
684   Store_field (rv, 2, strv);
685
686   CAMLreturn (rv);
687 }
688
689 CAMLprim value
690 ocaml_libvirt_domain_get_max_vcpus (value domv)
691 {
692   CAMLparam1 (domv);
693   virDomainPtr dom = Domain_val (domv);
694   virConnectPtr conn = Connect_domv (domv);
695   int r;
696
697   NONBLOCKING (r = virDomainGetMaxVcpus (dom));
698   CHECK_ERROR (r == -1, conn, "virDomainGetMaxVcpus");
699
700   CAMLreturn (Val_int (r));
701 }
702
703 CAMLprim value
704 ocaml_libvirt_domain_attach_device (value domv, value xmlv)
705 {
706   CAMLparam2 (domv, xmlv);
707   virDomainPtr dom = Domain_val (domv);
708   virConnectPtr conn = Connect_domv (domv);
709   char *xml = String_val (xmlv);
710   int r;
711
712   NONBLOCKING (r = virDomainAttachDevice (dom, xml));
713   CHECK_ERROR (r == -1, conn, "virDomainAttachDevice");
714
715   CAMLreturn (Val_unit);
716 }
717
718 CAMLprim value
719 ocaml_libvirt_domain_detach_device (value domv, value xmlv)
720 {
721   CAMLparam2 (domv, xmlv);
722   virDomainPtr dom = Domain_val (domv);
723   virConnectPtr conn = Connect_domv (domv);
724   char *xml = String_val (xmlv);
725   int r;
726
727   NONBLOCKING (r = virDomainDetachDevice (dom, xml));
728   CHECK_ERROR (r == -1, conn, "virDomainDetachDevice");
729
730   CAMLreturn (Val_unit);
731 }
732
733 CAMLprim value
734 ocaml_libvirt_domain_migrate_native (value domv, value dconnv, value flagsv, value optdnamev, value opturiv, value optbandwidthv, value unitv)
735 {
736 #ifdef HAVE_VIRDOMAINMIGRATE
737   CAMLparam5 (domv, dconnv, flagsv, optdnamev, opturiv);
738   CAMLxparam2 (optbandwidthv, unitv);
739   CAMLlocal2 (flagv, rv);
740   virDomainPtr dom = Domain_val (domv);
741   virConnectPtr conn = Connect_domv (domv);
742   virConnectPtr dconn = Connect_val (dconnv);
743   int flags = 0;
744   const char *dname = Optstring_val (optdnamev);
745   const char *uri = Optstring_val (opturiv);
746   unsigned long bandwidth;
747   virDomainPtr r;
748
749   /* Iterate over the list of flags. */
750   for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1))
751     {
752       flagv = Field (flagsv, 0);
753       if (flagv == Int_val(0))
754         flags |= VIR_MIGRATE_LIVE;
755     }
756
757   if (optbandwidthv == Val_int (0)) /* None */
758     bandwidth = 0;
759   else                          /* Some bandwidth */
760     bandwidth = Int_val (Field (optbandwidthv, 0));
761
762   WEAK_SYMBOL_CHECK (virDomainMigrate);
763   NONBLOCKING (r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth));
764   CHECK_ERROR (!r, conn, "virDomainMigrate");
765
766   rv = Val_domain (r, dconnv);
767
768   CAMLreturn (rv);
769
770 #else /* virDomainMigrate not supported */
771   not_supported ("virDomainMigrate");
772 #endif
773 }
774
775 CAMLprim value
776 ocaml_libvirt_domain_migrate_bytecode (value *argv, int argn)
777 {
778   return ocaml_libvirt_domain_migrate_native (argv[0], argv[1], argv[2],
779                                               argv[3], argv[4], argv[5],
780                                               argv[6]);
781 }
782
783 CAMLprim value
784 ocaml_libvirt_domain_block_stats (value domv, value pathv)
785 {
786 #if HAVE_VIRDOMAINBLOCKSTATS
787   CAMLparam2 (domv, pathv);
788   CAMLlocal2 (rv,v);
789   virDomainPtr dom = Domain_val (domv);
790   virConnectPtr conn = Connect_domv (domv);
791   char *path = String_val (pathv);
792   struct _virDomainBlockStats stats;
793   int r;
794
795   WEAK_SYMBOL_CHECK (virDomainBlockStats);
796   NONBLOCKING (r = virDomainBlockStats (dom, path, &stats, sizeof stats));
797   CHECK_ERROR (r == -1, conn, "virDomainBlockStats");
798
799   rv = caml_alloc (5, 0);
800   v = caml_copy_int64 (stats.rd_req); Store_field (rv, 0, v);
801   v = caml_copy_int64 (stats.rd_bytes); Store_field (rv, 1, v);
802   v = caml_copy_int64 (stats.wr_req); Store_field (rv, 2, v);
803   v = caml_copy_int64 (stats.wr_bytes); Store_field (rv, 3, v);
804   v = caml_copy_int64 (stats.errs); Store_field (rv, 4, v);
805
806   CAMLreturn (rv);
807 #else
808   not_supported ("virDomainBlockStats");
809 #endif
810 }
811
812 CAMLprim value
813 ocaml_libvirt_domain_interface_stats (value domv, value pathv)
814 {
815 #if HAVE_VIRDOMAININTERFACESTATS
816   CAMLparam2 (domv, pathv);
817   CAMLlocal2 (rv,v);
818   virDomainPtr dom = Domain_val (domv);
819   virConnectPtr conn = Connect_domv (domv);
820   char *path = String_val (pathv);
821   struct _virDomainInterfaceStats stats;
822   int r;
823
824   WEAK_SYMBOL_CHECK (virDomainInterfaceStats);
825   NONBLOCKING (r = virDomainInterfaceStats (dom, path, &stats, sizeof stats));
826   CHECK_ERROR (r == -1, conn, "virDomainInterfaceStats");
827
828   rv = caml_alloc (8, 0);
829   v = caml_copy_int64 (stats.rx_bytes); Store_field (rv, 0, v);
830   v = caml_copy_int64 (stats.rx_packets); Store_field (rv, 1, v);
831   v = caml_copy_int64 (stats.rx_errs); Store_field (rv, 2, v);
832   v = caml_copy_int64 (stats.rx_drop); Store_field (rv, 3, v);
833   v = caml_copy_int64 (stats.tx_bytes); Store_field (rv, 4, v);
834   v = caml_copy_int64 (stats.tx_packets); Store_field (rv, 5, v);
835   v = caml_copy_int64 (stats.tx_errs); Store_field (rv, 6, v);
836   v = caml_copy_int64 (stats.tx_drop); Store_field (rv, 7, v);
837
838   CAMLreturn (rv);
839 #else
840   not_supported ("virDomainInterfaceStats");
841 #endif
842 }
843
844 CAMLprim value
845 ocaml_libvirt_network_lookup_by_uuid (value connv, value uuidv)
846 {
847   CAMLparam2 (connv, uuidv);
848   CAMLlocal1 (rv);
849   virConnectPtr conn = Connect_val (connv);
850   char *uuid = String_val (uuidv);
851   virNetworkPtr r;
852
853   NONBLOCKING (r = virNetworkLookupByUUID (conn, (unsigned char *) uuid));
854   CHECK_ERROR (!r, conn, "virNetworkLookupByUUID");
855
856   rv = Val_network (r, connv);
857   CAMLreturn (rv);
858 }
859
860 CAMLprim value
861 ocaml_libvirt_network_create_xml (value connv, value xmlv)
862 {
863   CAMLparam2 (connv, xmlv);
864   CAMLlocal1 (rv);
865   virConnectPtr conn = Connect_val (connv);
866   char *xml = String_val (xmlv);
867   virNetworkPtr r;
868
869   NONBLOCKING (r = virNetworkCreateXML (conn, xml));
870   CHECK_ERROR (!r, conn, "virNetworkCreateXML");
871
872   rv = Val_network (r, connv);
873   CAMLreturn (rv);
874 }
875
876 CAMLprim value
877 ocaml_libvirt_network_define_xml (value connv, value xmlv)
878 {
879   CAMLparam2 (connv, xmlv);
880   CAMLlocal1 (rv);
881   virConnectPtr conn = Connect_val (connv);
882   char *xml = String_val (xmlv);
883   virNetworkPtr r;
884
885   NONBLOCKING (r = virNetworkDefineXML (conn, xml));
886   CHECK_ERROR (!r, conn, "virNetworkDefineXML");
887
888   rv = Val_network (r, connv);
889   CAMLreturn (rv);
890 }
891
892 CAMLprim value
893 ocaml_libvirt_network_destroy (value netv)
894 {
895   CAMLparam1 (netv);
896   virNetworkPtr net = Network_val (netv);
897   virConnectPtr conn = Connect_netv (netv);
898   int r;
899
900   NONBLOCKING (r = virNetworkDestroy (net));
901   CHECK_ERROR (r == -1, conn, "virNetworkDestroy");
902
903   /* So that we don't double-free in the finalizer: */
904   Network_val (netv) = NULL;
905
906   CAMLreturn (Val_unit);
907 }
908
909 CAMLprim value
910 ocaml_libvirt_network_free (value netv)
911 {
912   CAMLparam1 (netv);
913   virNetworkPtr net = Network_val (netv);
914   virConnectPtr conn = Connect_netv (netv);
915   int r;
916
917   NONBLOCKING (r = virNetworkFree (net));
918   CHECK_ERROR (r == -1, conn, "virNetworkFree");
919
920   /* So that we don't double-free in the finalizer: */
921   Network_val (netv) = NULL;
922
923   CAMLreturn (Val_unit);
924 }
925
926 /*----------------------------------------------------------------------*/
927
928 CAMLprim value
929 ocaml_libvirt_virterror_get_last_error (value unitv)
930 {
931   CAMLparam1 (unitv);
932   CAMLlocal1 (rv);
933   virErrorPtr err = virGetLastError ();
934
935   rv = Val_opt (err, (Val_ptr_t) Val_virterror);
936
937   CAMLreturn (rv);
938 }
939
940 CAMLprim value
941 ocaml_libvirt_virterror_get_last_conn_error (value connv)
942 {
943   CAMLparam1 (connv);
944   CAMLlocal1 (rv);
945   virConnectPtr conn = Connect_val (connv);
946
947   rv = Val_opt (conn, (Val_ptr_t) Val_connect);
948
949   CAMLreturn (rv);
950 }
951
952 CAMLprim value
953 ocaml_libvirt_virterror_reset_last_error (value unitv)
954 {
955   CAMLparam1 (unitv);
956   virResetLastError ();
957   CAMLreturn (Val_unit);
958 }
959
960 CAMLprim value
961 ocaml_libvirt_virterror_reset_last_conn_error (value connv)
962 {
963   CAMLparam1 (connv);
964   virConnectPtr conn = Connect_val (connv);
965   virConnResetLastError (conn);
966   CAMLreturn (Val_unit);
967 }
968
969 /*----------------------------------------------------------------------*/
970
971 /* Initialise the library. */
972 CAMLprim value
973 ocaml_libvirt_init (value unit)
974 {
975   CAMLparam1 (unit);
976   CAMLlocal1 (rv);
977   int r;
978
979   r = virInitialize ();
980   CHECK_ERROR (r == -1, NULL, "virInitialize");
981
982   CAMLreturn (Val_unit);
983 }