1 (* OCaml bindings for libvirt.
2 (C) Copyright 2007-2015 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,
9 with the OCaml linking exception described in ../COPYING.LIB.
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.
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
25 type filename = string
27 external get_version : ?driver:string -> unit -> int * int = "ocaml_libvirt_get_version"
30 let uuid_string_length = 36
32 (* http://caml.inria.fr/pub/ml-archives/caml-list/2004/07/80683af867cce6bf8fff273973f70c95.en.html *)
51 type credential_type =
56 | CredentialPassphrase
57 | CredentialEchoprompt
58 | CredentialNoechoprompt
63 typ : credential_type;
65 challenge : string option;
66 defresult : string option;
70 credtype : credential_type list;
71 cb : (credential list -> string option list);
75 | ListNoState | ListRunning | ListBlocked
76 | ListPaused | ListShutdown | ListShutoff | ListCrashed
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"
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"
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
114 (* See VIR_CPU_MAPLEN macro defined in <libvirt.h>. *)
115 let cpumaplen nr_cpus =
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
128 external set_keep_alive : [>`R] t -> int -> int -> unit = "ocaml_libvirt_connect_set_keep_alive"
130 external const : [>`R] t -> ro t = "%identity"
137 | VIR_ERR_INTERNAL_ERROR
140 | VIR_ERR_UNKNOWN_HOST
142 | VIR_ERR_INVALID_CONN
143 | VIR_ERR_INVALID_DOMAIN
144 | VIR_ERR_INVALID_ARG
145 | VIR_ERR_OPERATION_FAILED
147 | VIR_ERR_POST_FAILED
149 | VIR_ERR_SEXPR_SERIAL
160 | VIR_ERR_NO_XENSTORE
161 | VIR_ERR_DRIVER_FULL
162 | VIR_ERR_CALL_FAILED
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
172 | VIR_ERR_INVALID_NETWORK
173 | VIR_ERR_NETWORK_EXIST
174 | VIR_ERR_SYSTEM_ERROR
176 | VIR_ERR_GNUTLS_ERROR
180 | VIR_ERR_INVALID_MAC
181 | VIR_ERR_AUTH_FAILED
182 | VIR_ERR_INVALID_STORAGE_POOL
183 | VIR_ERR_INVALID_STORAGE_VOL
185 | VIR_ERR_NO_STORAGE_POOL
186 | VIR_ERR_NO_STORAGE_VOL
187 | VIR_ERR_UNKNOWN of int
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
260 | VIR_FROM_STATS_LINUX
262 | VIR_FROM_UNKNOWN of int
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
289 | VIR_ERR_UNKNOWN_LEVEL of int
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
300 message : string option;
302 str1 : string option;
303 str2 : string option;
304 str3 : string option;
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 -> ());
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"
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 }
331 exception Virterror of Virterror.t
332 exception Not_supported of string
334 let rec map_ignore_errors f = function
337 try f x :: map_ignore_errors f xs
338 with Virterror _ -> map_ignore_errors f xs
345 | InfoNoState | InfoRunning | InfoBlocked | InfoPaused
346 | InfoShutdown | InfoShutoff | InfoCrashed
356 type vcpu_state = VcpuOffline | VcpuRunning | VcpuBlocked
360 vcpu_state : vcpu_state;
365 type domain_create_flag =
371 let rec int_of_domain_create_flags = function
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
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
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
392 type migrate_flag = Live
394 type memory_flag = Virtual
409 type interface_stats = {
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
433 | StatsState | StatsCpuTotal | StatsBalloon | StatsVcpu
434 | StatsInterface | StatsBlock | StatsPerf
436 type domain_stats_record = {
438 params : typed_param array;
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.
445 let max_peek _ = 65536
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"
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"
497 external const : [>`R] t -> ro t = "%identity"
499 let get_domains conn flags =
500 (* Old/slow/inefficient method. *)
501 let get_active, get_inactive =
502 if List.mem ListAll flags then
505 (List.mem ListActive flags, List.mem ListInactive flags) in
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
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
522 active_doms @ inactive_doms
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
529 else (List.mem ListActive flags, List.mem ListInactive flags) in
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
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
546 let doms = active_doms @ inactive_doms in
548 map_ignore_errors (fun dom -> (dom, get_info dom)) doms
554 module Defined = struct
561 let to_string = function
563 | `Updated -> "Updated"
564 | `Unknown x -> Printf.sprintf "Unknown Defined.detail: %d" x
569 | x -> `Unknown x (* newer libvirt *)
572 module Undefined = struct
578 let to_string = function
579 | `Removed -> "UndefinedRemoved"
580 | `Unknown x -> Printf.sprintf "Unknown Undefined.detail: %d" x
584 | x -> `Unknown x (* newer libvirt *)
587 module Started = struct
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
611 | x -> `Unknown x (* newer libvirt *)
614 module Suspended = struct
623 | `Unknown of int (* newer libvirt *)
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
644 | x -> `Unknown x (* newer libvirt *)
647 module Resumed = struct
652 | `Unknown of int (* newer libvirt *)
655 let to_string = function
656 | `Unpaused -> "Unpaused"
657 | `Migrated -> "Migrated"
658 | `FromSnapshot -> "FromSnapshot"
659 | `Unknown x -> Printf.sprintf "Unknown Resumed.detail: %d" x
665 | x -> `Unknown x (* newer libvirt *)
668 module Stopped = struct
679 let to_string = function
680 | `Shutdown -> "Shutdown"
681 | `Destroyed -> "Destroyed"
682 | `Crashed -> "Crashed"
683 | `Migrated -> "Migrated"
685 | `Failed -> "Failed"
686 | `FromSnapshot -> "FromSnapshot"
687 | `Unknown x -> Printf.sprintf "Unknown Stopped.detail: %d" x
697 | x -> `Unknown x (* newer libvirt *)
700 module PM_suspended = struct
704 | `Unknown of int (* newer libvirt *)
707 let to_string = function
708 | `Memory -> "Memory"
710 | `Unknown x -> Printf.sprintf "Unknown PM_suspended.detail: %d" x
715 | x -> `Unknown x (* newer libvirt *)
718 let string_option x = match x with
720 | Some x' -> "Some " ^ x'
722 module Lifecycle = struct
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 *)
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
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)
754 | 7 -> `PMSuspended (PM_suspended.make detail)
758 module Reboot = struct
761 let to_string _ = "()"
766 module Rtc_change = struct
769 let to_string = Int64.to_string
774 module Watchdog = struct
785 let to_string = function
789 | `Poweroff -> "Poweroff"
790 | `Shutdown -> "Shutdown"
792 | `Unknown x -> Printf.sprintf "Unknown watchdog_action: %d" x
801 | x -> `Unknown x (* newer libvirt *)
804 module Io_error = struct
809 | `Unknown of int (* newer libvirt *)
812 let string_of_action = function
815 | `Report -> "Report"
816 | `Unknown x -> Printf.sprintf "Unknown Io_error.action: %d" x
818 let action_of_int = function
825 src_path: string option;
826 dev_alias: string option;
828 reason: string option;
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)
838 let make (src_path, dev_alias, action, reason) = {
840 dev_alias = dev_alias;
841 action = action_of_int action;
845 let make_noreason (src_path, dev_alias, action) =
846 make (src_path, dev_alias, action, None)
849 module Graphics_address = struct
854 | `Unknown of int (* newer libvirt *)
857 let string_of_family = function
861 | `Unknown x -> Printf.sprintf "Unknown Graphics_address.family: %d" x
863 let family_of_int = function
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) *)
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)
882 let make (family, node, service) = {
883 family = family_of_int family;
889 module Graphics_subject = struct
895 let string_of_identity t = Printf.sprintf
896 "{ ty = %s; name = %s }"
898 (string_option t.name)
900 type t = identity list
903 "[ " ^ (String.concat "; " (List.map string_of_identity ts)) ^ " ]"
906 List.map (fun (ty, name) -> { ty = ty; name = name })
910 module Graphics = struct
915 | `Unknown of int (** newer libvirt *)
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
924 let phase_of_int = function
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) *)
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 ]) ^ " }"
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;
960 module Control_error = struct
963 let to_string () = "()"
968 module Block_job = struct
970 | `KnownUnknown (* explicitly named UNKNOWN in the spec *)
974 | `Unknown of int (* newer libvirt *)
977 let string_of_ty = function
978 | `KnownUnknown -> "KnownUnknown"
981 | `Commit -> "Commit"
982 | `Unknown x -> Printf.sprintf "Unknown Block_job.ty: %d" x
984 let ty_of_int = function
989 | x -> `Unknown x (* newer libvirt *)
999 let string_of_status = function
1000 | `Completed -> "Completed"
1001 | `Failed -> "Failed"
1002 | `Cancelled -> "Cancelled"
1004 | `Unknown x -> Printf.sprintf "Unknown Block_job.status: %d" x
1006 let status_of_int = function
1014 disk: string option;
1019 let to_string t = Printf.sprintf "{ disk = %s; ty = %s; status = %s }"
1020 (string_option t.disk)
1022 (string_of_status t.status)
1024 let make (disk, ty, status) = {
1027 status = status_of_int ty;
1031 module Disk_change = struct
1037 let string_of_reason = function
1038 | `MissingOnStart -> "MissingOnStart"
1039 | `Unknown x -> Printf.sprintf "Unknown Disk_change.reason: %d" x
1041 let reason_of_int = function
1042 | 0 -> `MissingOnStart
1046 old_src_path: string option;
1047 new_src_path: string option;
1048 dev_alias: string option;
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 ]) ^ " }"
1059 let make (o, n, d, r) = {
1063 reason = reason_of_int r;
1067 module Tray_change = struct
1074 let string_of_reason = function
1077 | `Unknown x -> Printf.sprintf "Unknown Tray_change.reason: %d" x
1079 let reason_of_int = function
1085 dev_alias: string option;
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)
1094 let make (dev_alias, reason) = {
1095 dev_alias = dev_alias;
1096 reason = reason_of_int reason;
1100 module PM_wakeup = struct
1107 let to_string = function
1108 | `Unknown x -> Printf.sprintf "Unknown PM_wakeup.reason: %d" x
1110 let make x = `Unknown x
1113 module PM_suspend = struct
1120 let to_string = function
1121 | `Unknown x -> Printf.sprintf "Unknown PM_suspend.reason: %d" x
1123 let make x = `Unknown x
1126 module Balloon_change = struct
1129 let to_string = Int64.to_string
1133 module PM_suspend_disk = struct
1140 let to_string = function
1141 | `Unknown x -> Printf.sprintf "Unknown PM_suspend_disk.reason: %d" x
1143 let make x = `Unknown x
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)
1163 type callback_id = int64
1165 let fresh_callback_id =
1166 let next = ref 0L in
1168 let result = !next in
1169 next := Int64.succ !next;
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
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"
1191 external register_default_impl : unit -> unit = "ocaml_libvirt_event_register_default_impl"
1193 external run_default_impl : unit -> unit = "ocaml_libvirt_event_run_default_impl"
1195 external register_any' : 'a Connect.t -> 'a Domain.t option -> callback -> callback_id -> int = "ocaml_libvirt_connect_domain_event_register_any"
1197 external deregister_any' : 'a Connect.t -> int -> unit = "ocaml_libvirt_connect_domain_event_deregister_any"
1199 let our_id_to_libvirt_id = Hashtbl.create 16
1201 let register_any conn ?dom callback =
1202 let id = fresh_callback_id () in
1203 begin match callback with
1205 Hashtbl.add i_i_table id (fun dom x ->
1206 f dom (Lifecycle.make x)
1209 Hashtbl.add u_table id (fun dom x ->
1210 f dom (Reboot.make x)
1213 Hashtbl.add i64_table id (fun dom x ->
1214 f dom (Rtc_change.make x)
1217 Hashtbl.add i_table id (fun dom x ->
1218 f dom (Watchdog.make x)
1221 Hashtbl.add s_s_i_table id (fun dom x ->
1222 f dom (Io_error.make_noreason x)
1225 Hashtbl.add i_ga_ga_s_gs_table id (fun dom x ->
1226 f dom (Graphics.make x)
1228 | IOErrorReason f ->
1229 Hashtbl.add s_s_i_s_table id (fun dom x ->
1230 f dom (Io_error.make x)
1233 Hashtbl.add u_table id (fun dom x ->
1234 f dom (Control_error.make x)
1237 Hashtbl.add s_i_i_table id (fun dom x ->
1238 f dom (Block_job.make x)
1241 Hashtbl.add s_s_s_i_table id (fun dom x ->
1242 f dom (Disk_change.make x)
1245 Hashtbl.add s_i_table id (fun dom x ->
1246 f dom (Tray_change.make x)
1249 Hashtbl.add i_table id (fun dom x ->
1250 f dom (PM_wakeup.make x)
1253 Hashtbl.add i_table id (fun dom x ->
1254 f dom (PM_suspend.make x)
1256 | BalloonChange f ->
1257 Hashtbl.add i64_table id (fun dom x ->
1258 f dom (Balloon_change.make x)
1260 | PMSuspendDisk f ->
1261 Hashtbl.add i_table id (fun dom x ->
1262 f dom (PM_suspend_disk.make x)
1265 let libvirt_id = register_any' conn dom callback id in
1266 Hashtbl.replace our_id_to_libvirt_id id libvirt_id;
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
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
1286 let timeout_table = Hashtbl.create 16
1289 if Hashtbl.mem timeout_table x
1290 then Hashtbl.find timeout_table x () in
1291 Callback.register "Libvirt.timeout_callback" callback
1293 type timer_id = int64
1295 external add_timeout' : 'a Connect.t -> int -> int64 -> int = "ocaml_libvirt_event_add_timeout"
1297 external remove_timeout' : 'a Connect.t -> int -> unit = "ocaml_libvirt_event_remove_timeout"
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;
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
1312 Hashtbl.remove our_id_to_timer_id id;
1313 Hashtbl.remove timeout_table id
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"
1337 external const : [>`R] t -> ro t = "%identity"
1343 type pool_state = Inactive | Building | Running | Degraded
1344 type pool_build_flags = New | Repair | Resize
1345 type pool_delete_flags = Normal | Zeroed
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"
1380 type vol_type = File | Block
1381 type vol_delete_flags = Normal | Zeroed
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"
1403 (* Initialization. *)
1404 external c_init : unit -> unit = "ocaml_libvirt_init"
1406 Callback.register_exception
1407 "ocaml_libvirt_virterror" (Virterror (Virterror.no_error ()));
1408 Callback.register_exception
1409 "ocaml_libvirt_not_supported" (Not_supported "");