Connect: add auth/credential handling for connect
[ocaml-libvirt.git] / libvirt / libvirt.ml
1 (* OCaml bindings for libvirt.
2    (C) Copyright 2007-2015 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    with the OCaml linking exception described in ../COPYING.LIB.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 *)
20
21 type uuid = string
22
23 type xml = string
24
25 type filename = string
26
27 external get_version : ?driver:string -> unit -> int * int = "ocaml_libvirt_get_version"
28
29 let uuid_length = 16
30 let uuid_string_length = 36
31
32 (* http://caml.inria.fr/pub/ml-archives/caml-list/2004/07/80683af867cce6bf8fff273973f70c95.en.html *)
33 type rw = [`R|`W]
34 type ro = [`R]
35
36 module Connect =
37 struct
38   type 'rw t
39
40   type node_info = {
41     model : string;
42     memory : int64;
43     cpus : int;
44     mhz : int;
45     nodes : int;
46     sockets : int;
47     cores : int;
48     threads : int;
49   }
50
51   type credential_type =
52     | CredentialUsername
53     | CredentialAuthname
54     | CredentialLanguage
55     | CredentialCnonce
56     | CredentialPassphrase
57     | CredentialEchoprompt
58     | CredentialNoechoprompt
59     | CredentialRealm
60     | CredentialExternal
61
62   type credential = {
63     typ : credential_type;
64     prompt : string;
65     challenge : string option;
66     defresult : string option;
67   }
68
69   type auth = {
70     credtype : credential_type list;
71     cb : (credential list -> string option list);
72   }
73
74   type list_flag =
75     | ListNoState | ListRunning | ListBlocked
76     | ListPaused | ListShutdown | ListShutoff | ListCrashed
77     | ListActive
78     | ListInactive
79     | ListAll
80
81   external connect : ?name:string -> unit -> rw t = "ocaml_libvirt_connect_open"
82   external connect_readonly : ?name:string -> unit -> ro t = "ocaml_libvirt_connect_open_readonly"
83   external connect_auth : ?name:string -> auth -> rw t = "ocaml_libvirt_connect_open_auth"
84   external connect_auth_readonly : ?name:string -> auth -> ro t = "ocaml_libvirt_connect_open_auth_readonly"
85   external close : [>`R] t -> unit = "ocaml_libvirt_connect_close"
86   external get_type : [>`R] t -> string = "ocaml_libvirt_connect_get_type"
87   external get_version : [>`R] t -> int = "ocaml_libvirt_connect_get_version"
88   external get_hostname : [>`R] t -> string = "ocaml_libvirt_connect_get_hostname"
89   external get_uri : [>`R] t -> string = "ocaml_libvirt_connect_get_uri"
90   external get_max_vcpus : [>`R] t -> ?type_:string -> unit -> int = "ocaml_libvirt_connect_get_max_vcpus"
91   external list_domains : [>`R] t -> int -> int array = "ocaml_libvirt_connect_list_domains"
92   external num_of_domains : [>`R] t -> int = "ocaml_libvirt_connect_num_of_domains"
93   external get_capabilities : [>`R] t -> xml = "ocaml_libvirt_connect_get_capabilities"
94   external num_of_defined_domains : [>`R] t -> int = "ocaml_libvirt_connect_num_of_defined_domains"
95   external list_defined_domains : [>`R] t -> int -> string array = "ocaml_libvirt_connect_list_defined_domains"
96   external num_of_networks : [>`R] t -> int = "ocaml_libvirt_connect_num_of_networks"
97   external list_networks : [>`R] t -> int -> string array = "ocaml_libvirt_connect_list_networks"
98   external num_of_defined_networks : [>`R] t -> int = "ocaml_libvirt_connect_num_of_defined_networks"
99   external list_defined_networks : [>`R] t -> int -> string array = "ocaml_libvirt_connect_list_defined_networks"
100   external num_of_pools : [>`R] t -> int = "ocaml_libvirt_connect_num_of_storage_pools"
101   external list_pools : [>`R] t -> int -> string array = "ocaml_libvirt_connect_list_storage_pools"
102   external num_of_defined_pools : [>`R] t -> int = "ocaml_libvirt_connect_num_of_defined_storage_pools"
103   external list_defined_pools : [>`R] t -> int -> string array = "ocaml_libvirt_connect_list_defined_storage_pools"
104
105   external get_node_info : [>`R] t -> node_info = "ocaml_libvirt_connect_get_node_info"
106   external node_get_free_memory : [> `R] t -> int64 = "ocaml_libvirt_connect_node_get_free_memory"
107   external node_get_cells_free_memory : [> `R] t -> int -> int -> int64 array = "ocaml_libvirt_connect_node_get_cells_free_memory"
108
109   (* See VIR_NODEINFO_MAXCPUS macro defined in <libvirt.h>. *)
110   let maxcpus_of_node_info { nodes = nodes; sockets = sockets;
111                              cores = cores; threads = threads } =
112     nodes * sockets * cores * threads
113
114   (* See VIR_CPU_MAPLEN macro defined in <libvirt.h>. *)
115   let cpumaplen nr_cpus =
116     (nr_cpus + 7) / 8
117
118   (* See VIR_USE_CPU, VIR_UNUSE_CPU, VIR_CPU_USABLE macros defined in <libvirt.h>. *)
119   let use_cpu cpumap cpu =
120     Bytes.set cpumap (cpu/8)
121       (Char.chr (Char.code (Bytes.get cpumap (cpu/8)) lor (1 lsl (cpu mod 8))))
122   let unuse_cpu cpumap cpu =
123     Bytes.set cpumap (cpu/8)
124       (Char.chr (Char.code (Bytes.get cpumap (cpu/8)) land (lnot (1 lsl (cpu mod 8)))))
125   let cpu_usable cpumaps maplen vcpu cpu =
126     Char.code (Bytes.get cpumaps (vcpu*maplen + cpu/8)) land (1 lsl (cpu mod 8)) <> 0
127
128   external set_keep_alive : [>`R] t -> int -> int -> unit = "ocaml_libvirt_connect_set_keep_alive"
129
130   external const : [>`R] t -> ro t = "%identity"
131 end
132
133 module Virterror =
134 struct
135   type code =
136     | VIR_ERR_OK
137     | VIR_ERR_INTERNAL_ERROR
138     | VIR_ERR_NO_MEMORY
139     | VIR_ERR_NO_SUPPORT
140     | VIR_ERR_UNKNOWN_HOST
141     | VIR_ERR_NO_CONNECT
142     | VIR_ERR_INVALID_CONN
143     | VIR_ERR_INVALID_DOMAIN
144     | VIR_ERR_INVALID_ARG
145     | VIR_ERR_OPERATION_FAILED
146     | VIR_ERR_GET_FAILED
147     | VIR_ERR_POST_FAILED
148     | VIR_ERR_HTTP_ERROR
149     | VIR_ERR_SEXPR_SERIAL
150     | VIR_ERR_NO_XEN
151     | VIR_ERR_XEN_CALL
152     | VIR_ERR_OS_TYPE
153     | VIR_ERR_NO_KERNEL
154     | VIR_ERR_NO_ROOT
155     | VIR_ERR_NO_SOURCE
156     | VIR_ERR_NO_TARGET
157     | VIR_ERR_NO_NAME
158     | VIR_ERR_NO_OS
159     | VIR_ERR_NO_DEVICE
160     | VIR_ERR_NO_XENSTORE
161     | VIR_ERR_DRIVER_FULL
162     | VIR_ERR_CALL_FAILED
163     | VIR_ERR_XML_ERROR
164     | VIR_ERR_DOM_EXIST
165     | VIR_ERR_OPERATION_DENIED
166     | VIR_ERR_OPEN_FAILED
167     | VIR_ERR_READ_FAILED
168     | VIR_ERR_PARSE_FAILED
169     | VIR_ERR_CONF_SYNTAX
170     | VIR_ERR_WRITE_FAILED
171     | VIR_ERR_XML_DETAIL
172     | VIR_ERR_INVALID_NETWORK
173     | VIR_ERR_NETWORK_EXIST
174     | VIR_ERR_SYSTEM_ERROR
175     | VIR_ERR_RPC
176     | VIR_ERR_GNUTLS_ERROR
177     | VIR_WAR_NO_NETWORK
178     | VIR_ERR_NO_DOMAIN
179     | VIR_ERR_NO_NETWORK
180     | VIR_ERR_INVALID_MAC
181     | VIR_ERR_AUTH_FAILED
182     | VIR_ERR_INVALID_STORAGE_POOL
183     | VIR_ERR_INVALID_STORAGE_VOL
184     | VIR_WAR_NO_STORAGE
185     | VIR_ERR_NO_STORAGE_POOL
186     | VIR_ERR_NO_STORAGE_VOL
187     | VIR_ERR_UNKNOWN of int
188
189   let string_of_code = function
190     | VIR_ERR_OK -> "VIR_ERR_OK"
191     | VIR_ERR_INTERNAL_ERROR -> "VIR_ERR_INTERNAL_ERROR"
192     | VIR_ERR_NO_MEMORY -> "VIR_ERR_NO_MEMORY"
193     | VIR_ERR_NO_SUPPORT -> "VIR_ERR_NO_SUPPORT"
194     | VIR_ERR_UNKNOWN_HOST -> "VIR_ERR_UNKNOWN_HOST"
195     | VIR_ERR_NO_CONNECT -> "VIR_ERR_NO_CONNECT"
196     | VIR_ERR_INVALID_CONN -> "VIR_ERR_INVALID_CONN"
197     | VIR_ERR_INVALID_DOMAIN -> "VIR_ERR_INVALID_DOMAIN"
198     | VIR_ERR_INVALID_ARG -> "VIR_ERR_INVALID_ARG"
199     | VIR_ERR_OPERATION_FAILED -> "VIR_ERR_OPERATION_FAILED"
200     | VIR_ERR_GET_FAILED -> "VIR_ERR_GET_FAILED"
201     | VIR_ERR_POST_FAILED -> "VIR_ERR_POST_FAILED"
202     | VIR_ERR_HTTP_ERROR -> "VIR_ERR_HTTP_ERROR"
203     | VIR_ERR_SEXPR_SERIAL -> "VIR_ERR_SEXPR_SERIAL"
204     | VIR_ERR_NO_XEN -> "VIR_ERR_NO_XEN"
205     | VIR_ERR_XEN_CALL -> "VIR_ERR_XEN_CALL"
206     | VIR_ERR_OS_TYPE -> "VIR_ERR_OS_TYPE"
207     | VIR_ERR_NO_KERNEL -> "VIR_ERR_NO_KERNEL"
208     | VIR_ERR_NO_ROOT -> "VIR_ERR_NO_ROOT"
209     | VIR_ERR_NO_SOURCE -> "VIR_ERR_NO_SOURCE"
210     | VIR_ERR_NO_TARGET -> "VIR_ERR_NO_TARGET"
211     | VIR_ERR_NO_NAME -> "VIR_ERR_NO_NAME"
212     | VIR_ERR_NO_OS -> "VIR_ERR_NO_OS"
213     | VIR_ERR_NO_DEVICE -> "VIR_ERR_NO_DEVICE"
214     | VIR_ERR_NO_XENSTORE -> "VIR_ERR_NO_XENSTORE"
215     | VIR_ERR_DRIVER_FULL -> "VIR_ERR_DRIVER_FULL"
216     | VIR_ERR_CALL_FAILED -> "VIR_ERR_CALL_FAILED"
217     | VIR_ERR_XML_ERROR -> "VIR_ERR_XML_ERROR"
218     | VIR_ERR_DOM_EXIST -> "VIR_ERR_DOM_EXIST"
219     | VIR_ERR_OPERATION_DENIED -> "VIR_ERR_OPERATION_DENIED"
220     | VIR_ERR_OPEN_FAILED -> "VIR_ERR_OPEN_FAILED"
221     | VIR_ERR_READ_FAILED -> "VIR_ERR_READ_FAILED"
222     | VIR_ERR_PARSE_FAILED -> "VIR_ERR_PARSE_FAILED"
223     | VIR_ERR_CONF_SYNTAX -> "VIR_ERR_CONF_SYNTAX"
224     | VIR_ERR_WRITE_FAILED -> "VIR_ERR_WRITE_FAILED"
225     | VIR_ERR_XML_DETAIL -> "VIR_ERR_XML_DETAIL"
226     | VIR_ERR_INVALID_NETWORK -> "VIR_ERR_INVALID_NETWORK"
227     | VIR_ERR_NETWORK_EXIST -> "VIR_ERR_NETWORK_EXIST"
228     | VIR_ERR_SYSTEM_ERROR -> "VIR_ERR_SYSTEM_ERROR"
229     | VIR_ERR_RPC -> "VIR_ERR_RPC"
230     | VIR_ERR_GNUTLS_ERROR -> "VIR_ERR_GNUTLS_ERROR"
231     | VIR_WAR_NO_NETWORK -> "VIR_WAR_NO_NETWORK"
232     | VIR_ERR_NO_DOMAIN -> "VIR_ERR_NO_DOMAIN"
233     | VIR_ERR_NO_NETWORK -> "VIR_ERR_NO_NETWORK"
234     | VIR_ERR_INVALID_MAC -> "VIR_ERR_INVALID_MAC"
235     | VIR_ERR_AUTH_FAILED -> "VIR_ERR_AUTH_FAILED"
236     | VIR_ERR_INVALID_STORAGE_POOL -> "VIR_ERR_INVALID_STORAGE_POOL"
237     | VIR_ERR_INVALID_STORAGE_VOL -> "VIR_ERR_INVALID_STORAGE_VOL"
238     | VIR_WAR_NO_STORAGE -> "VIR_WAR_NO_STORAGE"
239     | VIR_ERR_NO_STORAGE_POOL -> "VIR_ERR_NO_STORAGE_POOL"
240     | VIR_ERR_NO_STORAGE_VOL -> "VIR_ERR_NO_STORAGE_VOL"
241     | VIR_ERR_UNKNOWN i -> "VIR_ERR_" ^ string_of_int i
242
243   type domain =
244     | VIR_FROM_NONE
245     | VIR_FROM_XEN
246     | VIR_FROM_XEND
247     | VIR_FROM_XENSTORE
248     | VIR_FROM_SEXPR
249     | VIR_FROM_XML
250     | VIR_FROM_DOM
251     | VIR_FROM_RPC
252     | VIR_FROM_PROXY
253     | VIR_FROM_CONF
254     | VIR_FROM_QEMU
255     | VIR_FROM_NET
256     | VIR_FROM_TEST
257     | VIR_FROM_REMOTE
258     | VIR_FROM_OPENVZ
259     | VIR_FROM_XENXM
260     | VIR_FROM_STATS_LINUX
261     | VIR_FROM_STORAGE
262     | VIR_FROM_UNKNOWN of int
263
264   let string_of_domain = function
265     | VIR_FROM_NONE -> "VIR_FROM_NONE"
266     | VIR_FROM_XEN -> "VIR_FROM_XEN"
267     | VIR_FROM_XEND -> "VIR_FROM_XEND"
268     | VIR_FROM_XENSTORE -> "VIR_FROM_XENSTORE"
269     | VIR_FROM_SEXPR -> "VIR_FROM_SEXPR"
270     | VIR_FROM_XML -> "VIR_FROM_XML"
271     | VIR_FROM_DOM -> "VIR_FROM_DOM"
272     | VIR_FROM_RPC -> "VIR_FROM_RPC"
273     | VIR_FROM_PROXY -> "VIR_FROM_PROXY"
274     | VIR_FROM_CONF -> "VIR_FROM_CONF"
275     | VIR_FROM_QEMU -> "VIR_FROM_QEMU"
276     | VIR_FROM_NET -> "VIR_FROM_NET"
277     | VIR_FROM_TEST -> "VIR_FROM_TEST"
278     | VIR_FROM_REMOTE -> "VIR_FROM_REMOTE"
279     | VIR_FROM_OPENVZ -> "VIR_FROM_OPENVZ"
280     | VIR_FROM_XENXM -> "VIR_FROM_XENXM"
281     | VIR_FROM_STATS_LINUX -> "VIR_FROM_STATS_LINUX"
282     | VIR_FROM_STORAGE -> "VIR_FROM_STORAGE"
283     | VIR_FROM_UNKNOWN i -> "VIR_FROM_" ^ string_of_int i
284
285   type level =
286     | VIR_ERR_NONE
287     | VIR_ERR_WARNING
288     | VIR_ERR_ERROR
289     | VIR_ERR_UNKNOWN_LEVEL of int
290
291   let string_of_level = function
292     | VIR_ERR_NONE -> "VIR_ERR_NONE"
293     | VIR_ERR_WARNING -> "VIR_ERR_WARNING"
294     | VIR_ERR_ERROR -> "VIR_ERR_ERROR"
295     | VIR_ERR_UNKNOWN_LEVEL i -> "VIR_ERR_LEVEL_" ^ string_of_int i
296
297   type t = {
298     code : code;
299     domain : domain;
300     message : string option;
301     level : level;
302     str1 : string option;
303     str2 : string option;
304     str3 : string option;
305     int1 : int32;
306     int2 : int32;
307   }
308
309   let to_string { code = code; domain = domain; message = message } =
310     let buf = Buffer.create 128 in
311     Buffer.add_string buf "libvirt: ";
312     Buffer.add_string buf (string_of_code code);
313     Buffer.add_string buf ": ";
314     Buffer.add_string buf (string_of_domain domain);
315     Buffer.add_string buf ": ";
316     (match message with Some msg -> Buffer.add_string buf msg | None -> ());
317     Buffer.contents buf
318
319   external get_last_error : unit -> t option = "ocaml_libvirt_virterror_get_last_error"
320   external get_last_conn_error : [>`R] Connect.t -> t option = "ocaml_libvirt_virterror_get_last_conn_error"
321   external reset_last_error : unit -> unit = "ocaml_libvirt_virterror_reset_last_error"
322   external reset_last_conn_error : [>`R] Connect.t -> unit = "ocaml_libvirt_virterror_reset_last_conn_error"
323
324   let no_error () =
325     { code = VIR_ERR_OK; domain = VIR_FROM_NONE;
326       message = None; level = VIR_ERR_NONE;
327       str1 = None; str2 = None; str3 = None;
328       int1 = 0_l; int2 = 0_l }
329 end
330
331 exception Virterror of Virterror.t
332 exception Not_supported of string
333
334 let rec map_ignore_errors f = function
335   | [] -> []
336   | x :: xs ->
337       try f x :: map_ignore_errors f xs
338       with Virterror _ -> map_ignore_errors f xs
339
340 module Domain =
341 struct
342   type 'rw t
343
344   type state =
345     | InfoNoState | InfoRunning | InfoBlocked | InfoPaused
346     | InfoShutdown | InfoShutoff | InfoCrashed
347
348   type info = {
349     state : state;
350     max_mem : int64;
351     memory : int64;
352     nr_virt_cpu : int;
353     cpu_time : int64;
354   }
355
356   type vcpu_state = VcpuOffline | VcpuRunning | VcpuBlocked
357
358   type vcpu_info = {
359     number : int;
360     vcpu_state : vcpu_state;
361     vcpu_time : int64;
362     cpu : int;
363   }
364
365   type domain_create_flag =
366   | START_PAUSED
367   | START_AUTODESTROY
368   | START_BYPASS_CACHE
369   | START_FORCE_BOOT
370   | START_VALIDATE
371   let rec int_of_domain_create_flags = function
372     | [] -> 0
373     | START_PAUSED :: flags ->       1 lor int_of_domain_create_flags flags
374     | START_AUTODESTROY :: flags ->  2 lor int_of_domain_create_flags flags
375     | START_BYPASS_CACHE :: flags -> 4 lor int_of_domain_create_flags flags
376     | START_FORCE_BOOT :: flags ->   8 lor int_of_domain_create_flags flags
377     | START_VALIDATE :: flags ->    16 lor int_of_domain_create_flags flags
378
379   type sched_param = string * sched_param_value
380   and sched_param_value =
381     | SchedFieldInt32 of int32 | SchedFieldUInt32 of int32
382     | SchedFieldInt64 of int64 | SchedFieldUInt64 of int64
383     | SchedFieldFloat of float | SchedFieldBool of bool
384
385   type typed_param = string * typed_param_value
386   and typed_param_value =
387     | TypedFieldInt32 of int32 | TypedFieldUInt32 of int32
388     | TypedFieldInt64 of int64 | TypedFieldUInt64 of int64
389     | TypedFieldFloat of float | TypedFieldBool of bool
390     | TypedFieldString of string
391
392   type migrate_flag = Live
393
394   type memory_flag = Virtual
395
396   type list_flag =
397     | ListActive
398     | ListInactive
399     | ListAll
400
401   type block_stats = {
402     rd_req : int64;
403     rd_bytes : int64;
404     wr_req : int64;
405     wr_bytes : int64;
406     errs : int64;
407   }
408
409   type interface_stats = {
410     rx_bytes : int64;
411     rx_packets : int64;
412     rx_errs : int64;
413     rx_drop : int64;
414     tx_bytes : int64;
415     tx_packets : int64;
416     tx_errs : int64;
417     tx_drop : int64;
418   }
419
420   type get_all_domain_stats_flag =
421     | GetAllDomainsStatsActive
422     | GetAllDomainsStatsInactive
423     | GetAllDomainsStatsOther
424     | GetAllDomainsStatsPaused
425     | GetAllDomainsStatsPersistent
426     | GetAllDomainsStatsRunning
427     | GetAllDomainsStatsShutoff
428     | GetAllDomainsStatsTransient
429     | GetAllDomainsStatsBacking
430     | GetAllDomainsStatsEnforceStats
431
432   type stats_type =
433     | StatsState | StatsCpuTotal | StatsBalloon | StatsVcpu
434     | StatsInterface | StatsBlock | StatsPerf
435
436   type domain_stats_record = {
437     dom_uuid : uuid;
438     params : typed_param array;
439   }
440
441   (* The maximum size for Domain.memory_peek and Domain.block_peek
442    * supported by libvirt.  This may change with different versions
443    * of libvirt in the future, hence it's a function.
444    *)
445   let max_peek _ = 65536
446
447   external create_linux : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_domain_create_linux"
448   external _create_xml : [>`W] Connect.t -> xml -> int -> rw t = "ocaml_libvirt_domain_create_xml"
449   let create_xml conn xml flags =
450     _create_xml conn xml (int_of_domain_create_flags flags)
451   external lookup_by_id : 'a Connect.t -> int -> 'a t = "ocaml_libvirt_domain_lookup_by_id"
452   external lookup_by_uuid : 'a Connect.t -> uuid -> 'a t = "ocaml_libvirt_domain_lookup_by_uuid"
453   external lookup_by_uuid_string : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_domain_lookup_by_uuid_string"
454   external lookup_by_name : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_domain_lookup_by_name"
455   external destroy : [>`W] t -> unit = "ocaml_libvirt_domain_destroy"
456   external free : [>`R] t -> unit = "ocaml_libvirt_domain_free"
457   external suspend : [>`W] t -> unit = "ocaml_libvirt_domain_suspend"
458   external resume : [>`W] t -> unit = "ocaml_libvirt_domain_resume"
459   external save : [>`W] t -> filename -> unit = "ocaml_libvirt_domain_save"
460   external restore : [>`W] Connect.t -> filename -> unit = "ocaml_libvirt_domain_restore"
461   external core_dump : [>`W] t -> filename -> unit = "ocaml_libvirt_domain_core_dump"
462   external shutdown : [>`W] t -> unit = "ocaml_libvirt_domain_shutdown"
463   external reboot : [>`W] t -> unit = "ocaml_libvirt_domain_reboot"
464   external get_name : [>`R] t -> string = "ocaml_libvirt_domain_get_name"
465   external get_uuid : [>`R] t -> uuid = "ocaml_libvirt_domain_get_uuid"
466   external get_uuid_string : [>`R] t -> string = "ocaml_libvirt_domain_get_uuid_string"
467   external get_id : [>`R] t -> int = "ocaml_libvirt_domain_get_id"
468   external get_os_type : [>`R] t -> string = "ocaml_libvirt_domain_get_os_type"
469   external get_max_memory : [>`R] t -> int64 = "ocaml_libvirt_domain_get_max_memory"
470   external set_max_memory : [>`W] t -> int64 -> unit = "ocaml_libvirt_domain_set_max_memory"
471   external set_memory : [>`W] t -> int64 -> unit = "ocaml_libvirt_domain_set_memory"
472   external get_info : [>`R] t -> info = "ocaml_libvirt_domain_get_info"
473   external get_xml_desc : [>`R] t -> xml = "ocaml_libvirt_domain_get_xml_desc"
474   external get_scheduler_type : [>`R] t -> string * int = "ocaml_libvirt_domain_get_scheduler_type"
475   external get_scheduler_parameters : [>`R] t -> int -> sched_param array = "ocaml_libvirt_domain_get_scheduler_parameters"
476   external set_scheduler_parameters : [>`W] t -> sched_param array -> unit = "ocaml_libvirt_domain_set_scheduler_parameters"
477   external define_xml : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_domain_define_xml"
478   external undefine : [>`W] t -> unit = "ocaml_libvirt_domain_undefine"
479   external create : [>`W] t -> unit = "ocaml_libvirt_domain_create"
480   external get_autostart : [>`R] t -> bool = "ocaml_libvirt_domain_get_autostart"
481   external set_autostart : [>`W] t -> bool -> unit = "ocaml_libvirt_domain_set_autostart"
482   external set_vcpus : [>`W] t -> int -> unit = "ocaml_libvirt_domain_set_vcpus"
483   external pin_vcpu : [>`W] t -> int -> string -> unit = "ocaml_libvirt_domain_pin_vcpu"
484   external get_vcpus : [>`R] t -> int -> int -> int * vcpu_info array * string = "ocaml_libvirt_domain_get_vcpus"
485   external get_cpu_stats : [>`R] t -> typed_param list array = "ocaml_libvirt_domain_get_cpu_stats"
486   external get_max_vcpus : [>`R] t -> int = "ocaml_libvirt_domain_get_max_vcpus"
487   external attach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_attach_device"
488   external detach_device : [>`W] t -> xml -> unit = "ocaml_libvirt_domain_detach_device"
489   external migrate : [>`W] t -> [>`W] Connect.t -> migrate_flag list -> ?dname:string -> ?uri:string -> ?bandwidth:int -> unit -> rw t = "ocaml_libvirt_domain_migrate_bytecode" "ocaml_libvirt_domain_migrate_native"
490   external block_stats : [>`R] t -> string -> block_stats = "ocaml_libvirt_domain_block_stats"
491   external interface_stats : [>`R] t -> string -> interface_stats = "ocaml_libvirt_domain_interface_stats"
492   external block_peek : [>`W] t -> string -> int64 -> int -> string -> int -> unit = "ocaml_libvirt_domain_block_peek_bytecode" "ocaml_libvirt_domain_block_peek_native"
493   external memory_peek : [>`W] t -> memory_flag list -> int64 -> int -> string -> int -> unit = "ocaml_libvirt_domain_memory_peek_bytecode" "ocaml_libvirt_domain_memory_peek_native"
494
495   external get_all_domain_stats : [>`R] Connect.t -> stats_type list -> get_all_domain_stats_flag list -> domain_stats_record array = "ocaml_libvirt_domain_get_all_domain_stats"
496
497   external const : [>`R] t -> ro t = "%identity"
498
499   let get_domains conn flags =
500     (* Old/slow/inefficient method. *)
501     let get_active, get_inactive =
502       if List.mem ListAll flags then
503         (true, true)
504       else
505         (List.mem ListActive flags, List.mem ListInactive flags) in
506     let active_doms =
507       if get_active then (
508         let n = Connect.num_of_domains conn in
509         let ids = Connect.list_domains conn n in
510         let ids = Array.to_list ids in
511         map_ignore_errors (lookup_by_id conn) ids
512       ) else [] in
513
514     let inactive_doms =
515       if get_inactive then (
516         let n = Connect.num_of_defined_domains conn in
517         let names = Connect.list_defined_domains conn n in
518         let names = Array.to_list names in
519         map_ignore_errors (lookup_by_name conn) names
520       ) else [] in
521
522     active_doms @ inactive_doms
523
524   let get_domains_and_infos conn flags =
525     (* Old/slow/inefficient method. *)
526     let get_active, get_inactive =
527       if List.mem ListAll flags then
528         (true, true)
529       else (List.mem ListActive flags, List.mem ListInactive flags) in
530     let active_doms =
531       if get_active then (
532         let n = Connect.num_of_domains conn in
533         let ids = Connect.list_domains conn n in
534         let ids = Array.to_list ids in
535         map_ignore_errors (lookup_by_id conn) ids
536       ) else [] in
537
538     let inactive_doms =
539       if get_inactive then (
540         let n = Connect.num_of_defined_domains conn in
541         let names = Connect.list_defined_domains conn n in
542         let names = Array.to_list names in
543         map_ignore_errors (lookup_by_name conn) names
544       ) else [] in
545
546     let doms = active_doms @ inactive_doms in
547
548     map_ignore_errors (fun dom -> (dom, get_info dom)) doms
549 end
550
551 module Event =
552 struct
553
554   module Defined = struct
555     type t = [
556       | `Added
557       | `Updated
558       | `Unknown of int
559     ]
560
561     let to_string = function
562       | `Added -> "Added"
563       | `Updated -> "Updated"
564       | `Unknown x -> Printf.sprintf "Unknown Defined.detail: %d" x
565
566     let make = function
567       | 0 -> `Added
568       | 1 -> `Updated
569       | x -> `Unknown x (* newer libvirt *)
570   end
571
572   module Undefined = struct
573     type t = [
574       | `Removed
575       | `Unknown of int
576     ]
577
578     let to_string = function
579       | `Removed -> "UndefinedRemoved"
580       | `Unknown x -> Printf.sprintf "Unknown Undefined.detail: %d" x
581
582     let make = function
583       | 0 -> `Removed
584       | x -> `Unknown x (* newer libvirt *)
585   end
586
587   module Started = struct
588     type t = [
589       | `Booted
590       | `Migrated
591       | `Restored
592       | `FromSnapshot
593       | `Wakeup
594       | `Unknown of int
595     ]
596
597     let to_string = function
598       | `Booted -> "Booted"
599       | `Migrated -> "Migrated"
600       | `Restored -> "Restored"
601       | `FromSnapshot -> "FromSnapshot"
602       | `Wakeup -> "Wakeup"
603       | `Unknown x -> Printf.sprintf "Unknown Started.detail: %d" x
604  
605     let make = function
606       | 0 -> `Booted
607       | 1 -> `Migrated
608       | 2 -> `Restored
609       | 3 -> `FromSnapshot
610       | 4 -> `Wakeup
611       | x -> `Unknown x (* newer libvirt *)
612   end
613
614   module Suspended = struct
615     type t = [
616       | `Paused
617       | `Migrated
618       | `IOError
619       | `Watchdog
620       | `Restored
621       | `FromSnapshot
622       | `APIError
623       | `Unknown of int (* newer libvirt *)
624     ]
625
626     let to_string = function
627       | `Paused -> "Paused"
628       | `Migrated -> "Migrated"
629       | `IOError -> "IOError"
630       | `Watchdog -> "Watchdog"
631       | `Restored -> "Restored"
632       | `FromSnapshot -> "FromSnapshot"
633       | `APIError -> "APIError"
634       | `Unknown x -> Printf.sprintf "Unknown Suspended.detail: %d" x
635
636      let make = function
637       | 0 -> `Paused
638       | 1 -> `Migrated
639       | 2 -> `IOError
640       | 3 -> `Watchdog
641       | 4 -> `Restored
642       | 5 -> `FromSnapshot
643       | 6 -> `APIError
644       | x -> `Unknown x (* newer libvirt *)
645   end
646
647   module Resumed = struct
648     type t = [
649       | `Unpaused
650       | `Migrated
651       | `FromSnapshot
652       | `Unknown of int (* newer libvirt *)
653     ]
654
655     let to_string = function
656       | `Unpaused -> "Unpaused"
657       | `Migrated -> "Migrated"
658       | `FromSnapshot -> "FromSnapshot"
659       | `Unknown x -> Printf.sprintf "Unknown Resumed.detail: %d" x
660
661     let make = function
662       | 0 -> `Unpaused
663       | 1 -> `Migrated
664       | 2 -> `FromSnapshot
665       | x -> `Unknown x (* newer libvirt *)
666   end
667
668   module Stopped = struct
669     type t = [
670       | `Shutdown
671       | `Destroyed
672       | `Crashed
673       | `Migrated
674       | `Saved
675       | `Failed
676       | `FromSnapshot
677       | `Unknown of int
678     ]
679     let to_string = function
680       | `Shutdown -> "Shutdown"
681       | `Destroyed -> "Destroyed"
682       | `Crashed -> "Crashed"
683       | `Migrated -> "Migrated"
684       | `Saved -> "Saved"
685       | `Failed -> "Failed"
686       | `FromSnapshot -> "FromSnapshot"
687       | `Unknown x -> Printf.sprintf "Unknown Stopped.detail: %d" x
688
689     let make = function
690       | 0 -> `Shutdown
691       | 1 -> `Destroyed
692       | 2 -> `Crashed
693       | 3 -> `Migrated
694       | 4 -> `Saved
695       | 5 -> `Failed
696       | 6 -> `FromSnapshot
697       | x -> `Unknown x (* newer libvirt *)
698   end
699
700   module PM_suspended = struct
701     type t = [
702       | `Memory
703       | `Disk
704       | `Unknown of int (* newer libvirt *)
705     ]
706
707     let to_string = function
708       | `Memory -> "Memory"
709       | `Disk -> "Disk"
710       | `Unknown x -> Printf.sprintf "Unknown PM_suspended.detail: %d" x
711
712     let make = function
713       | 0 -> `Memory
714       | 1 -> `Disk
715       | x -> `Unknown x (* newer libvirt *)
716   end
717
718   let string_option x = match x with
719     | None -> "None"
720     | Some x' -> "Some " ^ x'
721
722   module Lifecycle = struct
723     type t = [
724       | `Defined of Defined.t
725       | `Undefined of Undefined.t
726       | `Started of Started.t
727       | `Suspended of Suspended.t
728       | `Resumed of Resumed.t
729       | `Stopped of Stopped.t
730       | `Shutdown (* no detail defined yet *)
731       | `PMSuspended of PM_suspended.t
732       | `Unknown of int (* newer libvirt *)
733     ]
734
735     let to_string = function
736       | `Defined x -> "Defined " ^ (Defined.to_string x)
737       | `Undefined x -> "Undefined " ^ (Undefined.to_string x)
738       | `Started x -> "Started " ^ (Started.to_string x)
739       | `Suspended x -> "Suspended " ^ (Suspended.to_string x)
740       | `Resumed x -> "Resumed " ^ (Resumed.to_string x)
741       | `Stopped x -> "Stopped " ^ (Stopped.to_string x)
742       | `Shutdown -> "Shutdown"
743       | `PMSuspended x -> "PMSuspended " ^ (PM_suspended.to_string x)
744       | `Unknown x -> Printf.sprintf "Unknown Lifecycle event: %d" x
745
746     let make (ty, detail) = match ty with
747       | 0 -> `Defined (Defined.make detail)
748       | 1 -> `Undefined (Undefined.make detail)
749       | 2 -> `Started (Started.make detail)
750       | 3 -> `Suspended (Suspended.make detail)
751       | 4 -> `Resumed (Resumed.make detail)
752       | 5 -> `Stopped (Stopped.make detail)
753       | 6 -> `Shutdown
754       | 7 -> `PMSuspended (PM_suspended.make detail)
755       | x -> `Unknown x
756   end
757
758   module Reboot = struct
759     type t = unit
760
761     let to_string _ = "()"
762
763     let make () = ()
764   end
765
766   module Rtc_change = struct
767     type t = int64
768
769     let to_string = Int64.to_string
770
771     let make x = x
772   end
773
774   module Watchdog = struct
775     type t = [
776       | `None
777       | `Pause
778       | `Reset
779       | `Poweroff
780       | `Shutdown
781       | `Debug
782       | `Unknown of int
783     ]
784
785     let to_string = function
786       | `None -> "None"
787       | `Pause -> "Pause"
788       | `Reset -> "Reset"
789       | `Poweroff -> "Poweroff"
790       | `Shutdown -> "Shutdown"
791       | `Debug -> "Debug"
792       | `Unknown x -> Printf.sprintf "Unknown watchdog_action: %d" x
793
794     let make = function
795       | 0 -> `None
796       | 1 -> `Pause
797       | 2 -> `Reset
798       | 3 -> `Poweroff
799       | 4 -> `Shutdown
800       | 5 -> `Debug
801       | x -> `Unknown x (* newer libvirt *)
802   end
803
804   module Io_error = struct
805     type action = [
806       | `None
807       | `Pause
808       | `Report
809       | `Unknown of int (* newer libvirt *)
810     ]
811
812     let string_of_action = function
813       | `None -> "None"
814       | `Pause -> "Pause"
815       | `Report -> "Report"
816       | `Unknown x -> Printf.sprintf "Unknown Io_error.action: %d" x
817
818     let action_of_int = function
819       | 0 -> `None
820       | 1 -> `Pause
821       | 2 -> `Report
822       | x -> `Unknown x
823
824     type t = {
825       src_path: string option;
826       dev_alias: string option;
827       action: action;
828       reason: string option;
829     }
830
831     let to_string t = Printf.sprintf
832         "{ Io_error.src_path = %s; dev_alias = %s; action = %s; reason = %s }"
833         (string_option t.src_path)
834         (string_option t.dev_alias)
835         (string_of_action t.action)
836         (string_option t.reason)
837
838     let make (src_path, dev_alias, action, reason) = {
839         src_path = src_path;
840         dev_alias = dev_alias;
841         action = action_of_int action;
842         reason = reason;
843     }
844
845     let make_noreason (src_path, dev_alias, action) =
846       make (src_path, dev_alias, action, None)
847   end
848
849   module Graphics_address = struct
850     type family = [
851       | `Ipv4
852       | `Ipv6
853       | `Unix
854       | `Unknown of int (* newer libvirt *)
855     ]
856
857     let string_of_family = function
858       | `Ipv4 -> "IPv4"
859       | `Ipv6 -> "IPv6"
860       | `Unix -> "UNIX"
861       | `Unknown x -> Printf.sprintf "Unknown Graphics_address.family: %d" x
862
863     let family_of_int = function
864       (* no zero *)
865       | 1 -> `Ipv4
866       | 2 -> `Ipv6
867       | 3 -> `Unix
868       | x -> `Unknown x
869
870     type t = {
871       family: family;         (** Address family *)
872       node: string option;    (** Address of node (eg IP address, or UNIX path *)
873       service: string option; (** Service name/number (eg TCP port, or NULL) *)
874     }
875
876     let to_string t = Printf.sprintf
877       "{ family = %s; node = %s; service = %s }"
878         (string_of_family t.family)
879         (string_option t.node)
880         (string_option t.service)
881
882     let make (family, node, service) = {
883       family = family_of_int family;
884       node = node;
885       service = service;
886     }
887   end
888
889   module Graphics_subject = struct
890     type identity = {
891       ty: string option;
892       name: string option;
893     }
894
895     let string_of_identity t = Printf.sprintf
896       "{ ty = %s; name = %s }"
897       (string_option t.ty)
898       (string_option t.name)
899
900     type t = identity list
901
902     let to_string ts =
903       "[ " ^ (String.concat "; " (List.map string_of_identity ts)) ^ " ]"
904
905     let make xs =
906       List.map (fun (ty, name) -> { ty = ty; name = name })
907         (Array.to_list xs)
908   end
909
910   module Graphics = struct
911     type phase = [
912       | `Connect
913       | `Initialize
914       | `Disconnect
915       | `Unknown of int (** newer libvirt *)
916     ]
917
918     let string_of_phase = function
919       | `Connect -> "Connect"
920       | `Initialize -> "Initialize"
921       | `Disconnect -> "Disconnect"
922       | `Unknown x -> Printf.sprintf "Unknown Graphics.phase: %d" x
923
924     let phase_of_int = function
925       | 0 -> `Connect
926       | 1 -> `Initialize
927       | 2 -> `Disconnect
928       | x -> `Unknown x
929
930     type t = {
931       phase: phase;                (** the phase of the connection *)
932       local: Graphics_address.t;   (** the local server address *)
933       remote: Graphics_address.t;  (** the remote client address *)
934       auth_scheme: string option;  (** the authentication scheme activated *)
935       subject: Graphics_subject.t; (** the authenticated subject (user) *)
936     }
937
938     let to_string t =
939       let phase = Printf.sprintf "phase = %s"
940         (string_of_phase t.phase) in
941       let local = Printf.sprintf "local = %s"
942         (Graphics_address.to_string t.local) in
943       let remote = Printf.sprintf "remote = %s"
944         (Graphics_address.to_string t.remote) in
945       let auth_scheme = Printf.sprintf "auth_scheme = %s"
946         (string_option t.auth_scheme) in
947       let subject = Printf.sprintf "subject = %s"
948         (Graphics_subject.to_string t.subject) in
949       "{ " ^ (String.concat "; " [ phase; local; remote; auth_scheme; subject ]) ^ " }"
950
951     let make (phase, local, remote, auth_scheme, subject) = {
952       phase = phase_of_int phase;
953       local = Graphics_address.make local;
954       remote = Graphics_address.make remote;
955       auth_scheme = auth_scheme;
956       subject = Graphics_subject.make subject;
957     }
958   end
959
960   module Control_error = struct
961     type t = unit
962
963     let to_string () = "()"
964
965     let make () = ()
966   end
967
968   module Block_job = struct
969     type ty = [
970       | `KnownUnknown (* explicitly named UNKNOWN in the spec *)
971       | `Pull
972       | `Copy
973       | `Commit
974       | `Unknown of int (* newer libvirt *)
975     ]
976
977     let string_of_ty = function
978       | `KnownUnknown -> "KnownUnknown"
979       | `Pull -> "Pull"
980       | `Copy -> "Copy"
981       | `Commit -> "Commit"
982       | `Unknown x -> Printf.sprintf "Unknown Block_job.ty: %d" x
983
984     let ty_of_int = function
985       | 0 -> `KnownUnknown
986       | 1 -> `Pull
987       | 2 -> `Copy
988       | 3 -> `Commit
989       | x -> `Unknown x (* newer libvirt *)
990
991     type status = [
992       | `Completed
993       | `Failed
994       | `Cancelled
995       | `Ready
996       | `Unknown of int
997     ]
998
999     let string_of_status = function
1000       | `Completed -> "Completed"
1001       | `Failed -> "Failed"
1002       | `Cancelled -> "Cancelled"
1003       | `Ready -> "Ready"
1004       | `Unknown x -> Printf.sprintf "Unknown Block_job.status: %d" x
1005
1006     let status_of_int = function
1007       | 0 -> `Completed
1008       | 1 -> `Failed
1009       | 2 -> `Cancelled
1010       | 3 -> `Ready
1011       | x -> `Unknown x
1012
1013     type t = {
1014       disk: string option;
1015       ty: ty;
1016       status: status;
1017     }
1018
1019     let to_string t = Printf.sprintf "{ disk = %s; ty = %s; status = %s }"
1020       (string_option t.disk)
1021       (string_of_ty t.ty)
1022       (string_of_status t.status)
1023
1024     let make (disk, ty, status) = {
1025       disk = disk;
1026       ty = ty_of_int ty;
1027       status = status_of_int ty;
1028     }
1029   end
1030
1031   module Disk_change = struct
1032     type reason = [
1033       | `MissingOnStart
1034       | `Unknown of int
1035     ]
1036
1037     let string_of_reason = function
1038       | `MissingOnStart -> "MissingOnStart"
1039       | `Unknown x -> Printf.sprintf "Unknown Disk_change.reason: %d" x
1040
1041     let reason_of_int = function
1042       | 0 -> `MissingOnStart
1043       | x -> `Unknown x
1044
1045     type t = {
1046       old_src_path: string option;
1047       new_src_path: string option;
1048       dev_alias: string option;
1049       reason: reason;
1050     }
1051
1052     let to_string t =
1053       let o = Printf.sprintf "old_src_path = %s" (string_option t.old_src_path) in
1054       let n = Printf.sprintf "new_src_path = %s" (string_option t.new_src_path) in
1055       let d = Printf.sprintf "dev_alias = %s" (string_option t.dev_alias) in
1056       let r = string_of_reason t.reason in
1057       "{ " ^ (String.concat "; " [ o; n; d; r ]) ^ " }"
1058
1059     let make (o, n, d, r) = {
1060       old_src_path = o;
1061       new_src_path = n;
1062       dev_alias = d;
1063       reason = reason_of_int r;
1064     }
1065   end
1066
1067   module Tray_change = struct
1068     type reason = [
1069       | `Open
1070       | `Close
1071       | `Unknown of int
1072     ]
1073
1074     let string_of_reason = function
1075       | `Open -> "Open"
1076       | `Close -> "Close"
1077       | `Unknown x -> Printf.sprintf "Unknown Tray_change.reason: %d" x
1078
1079     let reason_of_int = function
1080       | 0 -> `Open
1081       | 1 -> `Close
1082       | x -> `Unknown x
1083
1084     type t = {
1085       dev_alias: string option;
1086       reason: reason;
1087     }
1088
1089     let to_string t = Printf.sprintf
1090       "{ dev_alias = %s; reason = %s }"
1091         (string_option t.dev_alias)
1092         (string_of_reason t.reason)
1093
1094     let make (dev_alias, reason) = {
1095       dev_alias = dev_alias;
1096       reason = reason_of_int reason;
1097     }
1098   end
1099
1100   module PM_wakeup = struct
1101     type reason = [
1102       | `Unknown of int
1103     ]
1104
1105     type t = reason
1106
1107     let to_string = function
1108       | `Unknown x -> Printf.sprintf "Unknown PM_wakeup.reason: %d" x
1109
1110     let make x = `Unknown x
1111   end
1112
1113   module PM_suspend = struct
1114     type reason = [
1115       | `Unknown of int
1116     ]
1117
1118     type t = reason
1119
1120     let to_string = function
1121       | `Unknown x -> Printf.sprintf "Unknown PM_suspend.reason: %d" x
1122
1123     let make x = `Unknown x
1124   end
1125
1126   module Balloon_change = struct
1127     type t = int64
1128
1129     let to_string = Int64.to_string
1130     let make x = x
1131   end
1132
1133   module PM_suspend_disk = struct
1134     type reason = [
1135       | `Unknown of int
1136     ]
1137
1138     type t = reason
1139
1140     let to_string = function
1141       | `Unknown x -> Printf.sprintf "Unknown PM_suspend_disk.reason: %d" x
1142
1143     let make x = `Unknown x
1144   end
1145
1146   type callback =
1147     | Lifecycle     of ([`R] Domain.t -> Lifecycle.t -> unit)
1148     | Reboot        of ([`R] Domain.t -> Reboot.t -> unit)
1149     | RtcChange     of ([`R] Domain.t -> Rtc_change.t -> unit)
1150     | Watchdog      of ([`R] Domain.t -> Watchdog.t -> unit)
1151     | IOError       of ([`R] Domain.t -> Io_error.t -> unit)
1152     | Graphics      of ([`R] Domain.t -> Graphics.t -> unit)
1153     | IOErrorReason of ([`R] Domain.t -> Io_error.t -> unit)
1154     | ControlError  of ([`R] Domain.t -> Control_error.t -> unit)
1155     | BlockJob      of ([`R] Domain.t -> Block_job.t -> unit)
1156     | DiskChange    of ([`R] Domain.t -> Disk_change.t -> unit)
1157     | TrayChange    of ([`R] Domain.t -> Tray_change.t -> unit)
1158     | PMWakeUp      of ([`R] Domain.t -> PM_wakeup.t -> unit)
1159     | PMSuspend     of ([`R] Domain.t -> PM_suspend.t -> unit)
1160     | BalloonChange of ([`R] Domain.t -> Balloon_change.t -> unit)
1161     | PMSuspendDisk of ([`R] Domain.t -> PM_suspend_disk.t -> unit)
1162
1163   type callback_id = int64
1164
1165   let fresh_callback_id =
1166     let next = ref 0L in
1167     fun () ->
1168       let result = !next in
1169       next := Int64.succ !next;
1170       result
1171
1172   let make_table value_name =
1173     let table = Hashtbl.create 16 in
1174     let callback callback_id generic x =
1175       if Hashtbl.mem table callback_id
1176       then Hashtbl.find table callback_id generic x in
1177     let _ = Callback.register value_name callback in
1178     table
1179
1180   let u_table = make_table "Libvirt.u_callback"
1181   let i_table = make_table "Libvirt.i_callback"
1182   let i64_table = make_table "Libvirt.i64_callback"
1183   let i_i_table = make_table "Libvirt.i_i_callback"
1184   let s_i_table = make_table "Libvirt.s_i_callback"
1185   let s_i_i_table = make_table "Libvirt.s_i_i_callback"
1186   let s_s_i_table = make_table "Libvirt.s_s_i_callback"
1187   let s_s_i_s_table = make_table "Libvirt.s_s_i_s_callback"
1188   let s_s_s_i_table = make_table "Libvirt.s_s_s_i_callback"
1189   let i_ga_ga_s_gs_table = make_table "Libvirt.i_ga_ga_s_gs_callback"
1190
1191   external register_default_impl : unit -> unit = "ocaml_libvirt_event_register_default_impl"
1192
1193   external run_default_impl : unit -> unit = "ocaml_libvirt_event_run_default_impl"
1194
1195   external register_any' : 'a Connect.t -> 'a Domain.t option -> callback -> callback_id -> int = "ocaml_libvirt_connect_domain_event_register_any"
1196
1197   external deregister_any' : 'a Connect.t -> int -> unit = "ocaml_libvirt_connect_domain_event_deregister_any"
1198
1199   let our_id_to_libvirt_id = Hashtbl.create 16
1200
1201   let register_any conn ?dom callback =
1202     let id = fresh_callback_id () in
1203     begin match callback with
1204     | Lifecycle f ->
1205         Hashtbl.add i_i_table id (fun dom x ->
1206             f dom (Lifecycle.make x)
1207         )
1208     | Reboot f ->
1209         Hashtbl.add u_table id (fun dom x ->
1210             f dom (Reboot.make x)
1211         )
1212     | RtcChange f ->
1213         Hashtbl.add i64_table id (fun dom x ->
1214             f dom (Rtc_change.make x)
1215         )
1216     | Watchdog f ->
1217         Hashtbl.add i_table id (fun dom x ->
1218             f dom (Watchdog.make x)
1219         ) 
1220     | IOError f ->
1221         Hashtbl.add s_s_i_table id (fun dom x ->
1222             f dom (Io_error.make_noreason x)
1223         )
1224     | Graphics f ->
1225         Hashtbl.add i_ga_ga_s_gs_table id (fun dom x ->
1226             f dom (Graphics.make x)
1227         )
1228     | IOErrorReason f ->
1229         Hashtbl.add s_s_i_s_table id (fun dom x ->
1230             f dom (Io_error.make x)
1231         )
1232     | ControlError f ->
1233         Hashtbl.add u_table id (fun dom x ->
1234             f dom (Control_error.make x)
1235         )
1236     | BlockJob f ->
1237         Hashtbl.add s_i_i_table id (fun dom x ->
1238             f dom (Block_job.make x)
1239         )
1240     | DiskChange f ->
1241         Hashtbl.add s_s_s_i_table id (fun dom x ->
1242             f dom (Disk_change.make x)
1243         )
1244     | TrayChange f ->
1245         Hashtbl.add s_i_table id (fun dom x ->
1246             f dom (Tray_change.make x)
1247         )
1248     | PMWakeUp f ->
1249         Hashtbl.add i_table id (fun dom x ->
1250             f dom (PM_wakeup.make x)
1251         )
1252     | PMSuspend f ->
1253         Hashtbl.add i_table id (fun dom x ->
1254             f dom (PM_suspend.make x)
1255         )
1256     | BalloonChange f ->
1257         Hashtbl.add i64_table id (fun dom x ->
1258             f dom (Balloon_change.make x)
1259         )
1260     | PMSuspendDisk f ->
1261         Hashtbl.add i_table id (fun dom x ->
1262             f dom (PM_suspend_disk.make x)
1263         )
1264     end;
1265     let libvirt_id = register_any' conn dom callback id in
1266     Hashtbl.replace our_id_to_libvirt_id id libvirt_id;
1267     id
1268
1269   let deregister_any conn id =
1270     if Hashtbl.mem our_id_to_libvirt_id id then begin
1271       let libvirt_id = Hashtbl.find our_id_to_libvirt_id id in
1272       deregister_any' conn libvirt_id
1273     end;
1274     Hashtbl.remove our_id_to_libvirt_id id;
1275     Hashtbl.remove u_table id;
1276     Hashtbl.remove i_table id;
1277     Hashtbl.remove i64_table id;
1278     Hashtbl.remove i_i_table id;
1279     Hashtbl.remove s_i_table id;
1280     Hashtbl.remove s_i_i_table id;
1281     Hashtbl.remove s_s_i_table id;
1282     Hashtbl.remove s_s_i_s_table id;
1283     Hashtbl.remove s_s_s_i_table id;
1284     Hashtbl.remove i_ga_ga_s_gs_table id
1285
1286   let timeout_table = Hashtbl.create 16
1287   let _ =
1288     let callback x =
1289       if Hashtbl.mem timeout_table x
1290       then Hashtbl.find timeout_table x () in
1291   Callback.register "Libvirt.timeout_callback" callback
1292
1293   type timer_id = int64
1294
1295   external add_timeout' : 'a Connect.t -> int -> int64 -> int = "ocaml_libvirt_event_add_timeout"
1296
1297   external remove_timeout' : 'a Connect.t -> int -> unit = "ocaml_libvirt_event_remove_timeout"
1298
1299   let our_id_to_timer_id = Hashtbl.create 16
1300   let add_timeout conn ms fn =
1301     let id = fresh_callback_id () in
1302     Hashtbl.add timeout_table id fn;
1303     let timer_id = add_timeout' conn ms id in
1304     Hashtbl.add our_id_to_timer_id id timer_id;
1305     id
1306
1307   let remove_timeout conn id =
1308     if Hashtbl.mem our_id_to_timer_id id then begin
1309       let timer_id = Hashtbl.find our_id_to_timer_id id in
1310       remove_timeout' conn timer_id
1311     end;
1312     Hashtbl.remove our_id_to_timer_id id;
1313     Hashtbl.remove timeout_table id
1314 end
1315
1316 module Network =
1317 struct
1318   type 'rw t
1319
1320   external lookup_by_name : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_network_lookup_by_name"
1321   external lookup_by_uuid : 'a Connect.t -> uuid -> 'a t = "ocaml_libvirt_network_lookup_by_uuid"
1322   external lookup_by_uuid_string : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_network_lookup_by_uuid_string"
1323   external create_xml : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_network_create_xml"
1324   external define_xml : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_network_define_xml"
1325   external undefine : [>`W] t -> unit = "ocaml_libvirt_network_undefine"
1326   external create : [>`W] t -> unit = "ocaml_libvirt_network_create"
1327   external destroy : [>`W] t -> unit = "ocaml_libvirt_network_destroy"
1328   external free : [>`R] t -> unit = "ocaml_libvirt_network_free"
1329   external get_name : [>`R] t -> string = "ocaml_libvirt_network_get_name"
1330   external get_uuid : [>`R] t -> uuid = "ocaml_libvirt_network_get_uuid"
1331   external get_uuid_string : [>`R] t -> string = "ocaml_libvirt_network_get_uuid_string"
1332   external get_xml_desc : [>`R] t -> xml = "ocaml_libvirt_network_get_xml_desc"
1333   external get_bridge_name : [>`R] t -> string = "ocaml_libvirt_network_get_bridge_name"
1334   external get_autostart : [>`R] t -> bool = "ocaml_libvirt_network_get_autostart"
1335   external set_autostart : [>`W] t -> bool -> unit = "ocaml_libvirt_network_set_autostart"
1336
1337   external const : [>`R] t -> ro t = "%identity"
1338 end
1339
1340 module Pool =
1341 struct
1342   type 'rw t
1343   type pool_state = Inactive | Building | Running | Degraded
1344   type pool_build_flags = New | Repair | Resize
1345   type pool_delete_flags = Normal | Zeroed
1346   type pool_info = {
1347     state : pool_state;
1348     capacity : int64;
1349     allocation : int64;
1350     available : int64;
1351   }
1352
1353   external lookup_by_name : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_storage_pool_lookup_by_name"
1354   external lookup_by_uuid : 'a Connect.t -> uuid -> 'a t = "ocaml_libvirt_storage_pool_lookup_by_uuid"
1355   external lookup_by_uuid_string : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_storage_pool_lookup_by_uuid_string"
1356   external create_xml : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_storage_pool_create_xml"
1357   external define_xml : [>`W] Connect.t -> xml -> rw t = "ocaml_libvirt_storage_pool_define_xml"
1358   external build : [>`W] t -> pool_build_flags -> unit = "ocaml_libvirt_storage_pool_build"
1359   external undefine : [>`W] t -> unit = "ocaml_libvirt_storage_pool_undefine"
1360   external create : [>`W] t -> unit = "ocaml_libvirt_storage_pool_create"
1361   external destroy : [>`W] t -> unit = "ocaml_libvirt_storage_pool_destroy"
1362   external delete : [>`W] t -> unit = "ocaml_libvirt_storage_pool_delete"
1363   external free : [>`R] t -> unit = "ocaml_libvirt_storage_pool_free"
1364   external refresh : [`R] t -> unit = "ocaml_libvirt_storage_pool_refresh"
1365   external get_name : [`R] t -> string = "ocaml_libvirt_storage_pool_get_name"
1366   external get_uuid : [`R] t -> uuid = "ocaml_libvirt_storage_pool_get_uuid"
1367   external get_uuid_string : [`R] t -> string = "ocaml_libvirt_storage_pool_get_uuid_string"
1368   external get_info : [`R] t -> pool_info = "ocaml_libvirt_storage_pool_get_info"
1369   external get_xml_desc : [`R] t -> xml = "ocaml_libvirt_storage_pool_get_xml_desc"
1370   external get_autostart : [`R] t -> bool = "ocaml_libvirt_storage_pool_get_autostart"
1371   external set_autostart : [>`W] t -> bool -> unit = "ocaml_libvirt_storage_pool_set_autostart"
1372   external num_of_volumes : [`R] t -> int = "ocaml_libvirt_storage_pool_num_of_volumes"
1373   external list_volumes : [`R] t -> int -> string array = "ocaml_libvirt_storage_pool_list_volumes"
1374   external const : [>`R] t -> ro t = "%identity"
1375 end
1376
1377 module Volume =
1378 struct
1379   type 'rw t
1380   type vol_type = File | Block
1381   type vol_delete_flags = Normal | Zeroed
1382   type vol_info = {
1383     typ : vol_type;
1384     capacity : int64;
1385     allocation : int64;
1386   }
1387
1388   external lookup_by_name : 'a Pool.t -> string -> 'a t = "ocaml_libvirt_storage_vol_lookup_by_name"
1389   external lookup_by_key : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_storage_vol_lookup_by_key"
1390   external lookup_by_path : 'a Connect.t -> string -> 'a t = "ocaml_libvirt_storage_vol_lookup_by_path"
1391   external pool_of_volume : 'a t -> 'a Pool.t = "ocaml_libvirt_storage_pool_lookup_by_volume"
1392   external get_name : [`R] t -> string = "ocaml_libvirt_storage_vol_get_name"
1393   external get_key : [`R] t -> string = "ocaml_libvirt_storage_vol_get_key"
1394   external get_path : [`R] t -> string = "ocaml_libvirt_storage_vol_get_path"
1395   external get_info : [`R] t -> vol_info = "ocaml_libvirt_storage_vol_get_info"
1396   external get_xml_desc : [`R] t -> xml = "ocaml_libvirt_storage_vol_get_xml_desc"
1397   external create_xml : [>`W] Pool.t -> xml -> unit = "ocaml_libvirt_storage_vol_create_xml"
1398   external delete : [>`W] t -> vol_delete_flags -> unit = "ocaml_libvirt_storage_vol_delete"
1399   external free : [>`R] t -> unit = "ocaml_libvirt_storage_vol_free"
1400   external const : [>`R] t -> ro t = "%identity"
1401 end
1402
1403 (* Initialization. *)
1404 external c_init : unit -> unit = "ocaml_libvirt_init"
1405 let () =
1406   Callback.register_exception
1407     "ocaml_libvirt_virterror" (Virterror (Virterror.no_error ()));
1408   Callback.register_exception
1409     "ocaml_libvirt_not_supported" (Not_supported "");
1410   c_init ()