Don't hard-code Storage API errors, in case building with older libvirt.
[virt-top.git] / libvirt / libvirt.mli
index 58198c8..72917ef 100644 (file)
@@ -1,6 +1,6 @@
-(** OCaml bindings for libvirt.
-    (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
-    http://libvirt.org/
+(** OCaml bindings for libvirt. *)
+(* (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
+   http://libvirt.org/
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *)
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *)
 
+(**
+   {2 Introduction and examples}
+
+   This is a set of bindings for writing OCaml programs to
+   manage virtual machines through {{:http://libvirt.org/}libvirt}.
+
+   {3 Using libvirt interactively}
+
+   Using the interactive toplevel:
+
+{v
+$ ocaml -I +libvirt
+        Objective Caml version 3.10.0
+
+# #load "unix.cma";;
+# #load "mllibvirt.cma";;
+# let name = "test:///default";;
+val name : string = "test:///default"
+# let conn = Libvirt.Connect.connect_readonly ~name () ;;
+val conn : Libvirt.ro Libvirt.Connect.t = <abstr>
+# Libvirt.Connect.get_node_info conn;;
+  : Libvirt.Connect.node_info =
+{Libvirt.Connect.model = "i686"; Libvirt.Connect.memory = 3145728L;
+ Libvirt.Connect.cpus = 16; Libvirt.Connect.mhz = 1400;
+ Libvirt.Connect.nodes = 2; Libvirt.Connect.sockets = 2;
+ Libvirt.Connect.cores = 2; Libvirt.Connect.threads = 2}
+v}
+
+   {3 Compiling libvirt programs}
+
+   This command compiles a program to native code:
+
+{v
+ocamlopt -I +libvirt mllibvirt.cmxa list_domains.ml -o list_domains
+v}
+
+   {3 Example: Connect to the hypervisor}
+
+   The main modules are {!Libvirt.Connect}, {!Libvirt.Domain} and
+   {!Libvirt.Network} corresponding respectively to the
+   {{:http://libvirt.org/html/libvirt-libvirt.html}virConnect*, virDomain* and virNetwork* functions from libvirt}.
+   For brevity I usually rename these modules like this:
+
+{v
+module C = Libvirt.Connect
+module D = Libvirt.Domain
+module N = Libvirt.Network
+v}
+
+   To get a connection handle, assuming a Xen hypervisor:
+
+{v
+let name = "xen:///"
+let conn = C.connect_readonly ~name ()
+v}
+
+   {3 Example: List running domains}
+
+{v
+open Printf
+
+let n = C.num_of_domains conn in
+let ids = C.list_domains conn n in
+let domains = Array.map (D.lookup_by_id conn) ids in
+Array.iter (
+  fun dom ->
+    printf "%8d %s\n%!" (D.get_id dom) (D.get_name dom)
+) domains;
+v}
+
+   {3 Example: List inactive domains}
+
+{v
+let n = C.num_of_defined_domains conn in
+let names = C.list_defined_domains conn n in
+Array.iter (
+  fun name ->
+    printf "inactive %s\n%!" name
+) names;
+v}
+
+   {3 Example: Print node info}
+
+{v
+let node_info = C.get_node_info conn in
+printf "model = %s\n" node_info.C.model;
+printf "memory = %Ld K\n" node_info.C.memory;
+printf "cpus = %d\n" node_info.C.cpus;
+printf "mhz = %d\n" node_info.C.mhz;
+printf "nodes = %d\n" node_info.C.nodes;
+printf "sockets = %d\n" node_info.C.sockets;
+printf "cores = %d\n" node_info.C.cores;
+printf "threads = %d\n%!" node_info.C.threads;
+
+let hostname = C.get_hostname conn in
+printf "hostname = %s\n%!" hostname;
+
+let uri = C.get_uri conn in
+printf "uri = %s\n%!" uri
+v}
+
+*)
+
+
+(** {2 Programming issues}
+
+    {3 General safety issues}
+
+    Memory allocation / automatic garbage collection of all libvirt
+    objects should be completely safe (except in the specific
+    virterror case noted below).  If you find any safety issues or if your
+    pure OCaml program ever segfaults, please contact the author.
+
+    You can force a libvirt object to be freed early by calling
+    the [close] function on the object.  This shouldn't affect
+    the safety of garbage collection and should only be used when
+    you want to explicitly free memory.  Note that explicitly
+    closing a connection object does nothing if there are still
+    unclosed domain or network objects referencing it.
+
+    Note that even though you hold open (eg) a domain object, that
+    doesn't mean that the domain (virtual machine) actually exists.
+    The domain could have been shut down or deleted by another user.
+    Thus domain objects can through odd exceptions at any time.
+    This is just the nature of virtualisation.
+
+    Virterror has a specific design error which means that the
+    objects embedded in a virterror exception message are only
+    valid as long as the connection handle is still open.  This
+    is a design flaw in the C code of libvirt and we cannot fix
+    or work around it in the OCaml bindings.
+
+    {3 Backwards and forwards compatibility}
+
+    OCaml-libvirt is backwards and forwards compatible with
+    any libvirt >= 0.2.1.  One consequence of this is that
+    your program can dynamically link to a {i newer} version of
+    libvirt than it was compiled with, and it should still
+    work.
+
+    When we link to an older version of libvirt.so, there may
+    be missing functions.  If ocaml-libvirt was compiled with
+    gcc, then these are turned into OCaml {!Libvirt.Not_supported}
+    exceptions.
+
+    We don't support libvirt < 0.2.1, and never will so don't ask us.
+
+    {3 Threads}
+
+    You can issue multiple concurrent libvirt requests in
+    different threads.  However you must follow this rule:
+    Each thread must have its own separate libvirt connection, {i or}
+    you must implement your own mutex scheme to ensure that no
+    two threads can ever make concurrent calls using the same
+    libvirt connection.
+
+    (Note that multithreaded code is not well tested.  If you find
+    bugs please report them.)
+
+    {3 Initialisation}
+
+    Libvirt requires all callers to call virInitialize before
+    using the library.  This is done automatically for you by
+    these bindings when the program starts up, and we believe
+    that the way this is done is safe.
+
+    {2 Reference}
+*)
+
 type uuid = string
 type uuid = string
-(** This is a "raw" UUID, ie. a packed string of bytes. *)
+    (** This is a "raw" UUID, ie. a packed string of bytes. *)
 
 type xml = string
 
 type xml = string
-(** Type of XML (an uninterpreted string of bytes).  Use PXP, expat,
-    xml-light, etc. if you want to do anything useful with the XML.
-*)
+    (** Type of XML (an uninterpreted string of bytes).  Use PXP, expat,
+       xml-light, etc. if you want to do anything useful with the XML.
+    *)
 
 type filename = string
 
 type filename = string
-(** A filename. *)
+    (** A filename. *)
 
 val get_version : ?driver:string -> unit -> int * int
   (** [get_version ()] returns the library version in the first part
 
 val get_version : ?driver:string -> unit -> int * int
   (** [get_version ()] returns the library version in the first part
@@ -46,12 +215,37 @@ val uuid_length : int
 val uuid_string_length : int
   (** Length of UUID strings. *)
 
 val uuid_string_length : int
   (** Length of UUID strings. *)
 
-(* These phantom types are used to ensure the type-safety of read-only
- * versus read-write connections.  For more information see:
- * http://caml.inria.fr/pub/ml-archives/caml-list/2004/07/80683af867cce6bf8fff273973f70c95.en.html
- *)
 type rw = [`R|`W]
 type ro = [`R]
 type rw = [`R|`W]
 type ro = [`R]
+    (** These
+       {{:http://caml.inria.fr/pub/ml-archives/caml-list/2004/07/80683af867cce6bf8fff273973f70c95.en.html}phantom types}
+       are used to ensure the type-safety of read-only
+       versus read-write connections.
+
+       All connection/domain/etc. objects are marked with
+       a phantom read-write or read-only type, and trying to
+       pass a read-only object into a function which could
+       mutate the object will cause a compile time error.
+
+       Each module provides a function like {!Libvirt.Connect.const}
+       to demote a read-write object into a read-only object.  The
+       opposite operation is, of course, not allowed.
+
+       If you want to handle both read-write and read-only
+       connections at runtime, use a variant similar to this:
+{v
+type conn_t =
+    | No_connection
+    | Read_only of Libvirt.ro Libvirt.Connect.t
+    | Read_write of Libvirt.rw Libvirt.Connect.t
+v}
+       See also the source of [mlvirsh].
+    *)
+
+type ('a, 'b) job_t
+(** Forward definition of {!Job.t} to avoid recursive module dependencies. *)
+
+(** {3 Connections} *)
 
 module Connect :
 sig
 
 module Connect :
 sig
@@ -136,6 +330,15 @@ sig
        Call {!num_of_defined_networks} first to get a value for [max].
     *)
 
        Call {!num_of_defined_networks} first to get a value for [max].
     *)
 
+  val num_of_pools : [>`R] t -> int
+    (** Returns the number of storage pools. *)
+  val list_pools : [>`R] t -> int -> string array
+    (** Return list of storage pools. *)
+  val num_of_defined_pools : [>`R] t -> int
+    (** Returns the number of storage pools. *)
+  val list_defined_pools : [>`R] t -> int -> string array
+    (** Return list of storage pools. *)
+
     (* The name of this function is inconsistent, but the inconsistency
      * is really in libvirt itself.
      *)
     (* The name of this function is inconsistent, but the inconsistency
      * is really in libvirt itself.
      *)
@@ -182,8 +385,9 @@ sig
       *)
 end
   (** Module dealing with connections.  [Connect.t] is the
       *)
 end
   (** Module dealing with connections.  [Connect.t] is the
-      connection object.
-  *)
+      connection object. *)
+
+(** {3 Domains} *)
 
 module Domain :
 sig
 
 module Domain :
 sig
@@ -244,6 +448,8 @@ sig
     (** Create a new guest domain (not necessarily a Linux one)
        from the given XML.
     *)
     (** Create a new guest domain (not necessarily a Linux one)
        from the given XML.
     *)
+  val create_linux_job : [>`W] Connect.t -> xml -> ([`Domain], rw) job_t
+    (** Asynchronous domain creation. *)
   val lookup_by_id : 'a Connect.t -> int -> 'a t
     (** Lookup a domain by ID. *)
   val lookup_by_uuid : 'a Connect.t -> uuid -> 'a t
   val lookup_by_id : 'a Connect.t -> int -> 'a t
     (** Lookup a domain by ID. *)
   val lookup_by_uuid : 'a Connect.t -> uuid -> 'a t
@@ -268,10 +474,16 @@ sig
     (** Resume a domain. *)
   val save : [>`W] t -> filename -> unit
     (** Suspend a domain, then save it to the file. *)
     (** Resume a domain. *)
   val save : [>`W] t -> filename -> unit
     (** Suspend a domain, then save it to the file. *)
+  val save_job : [>`W] t -> filename -> ([`Domain_nocreate], rw) job_t
+    (** Asynchronous domain suspend. *)
   val restore : [>`W] Connect.t -> filename -> unit
     (** Restore a domain from a file. *)
   val restore : [>`W] Connect.t -> filename -> unit
     (** Restore a domain from a file. *)
+  val restore_job : [>`W] Connect.t -> filename -> ([`Domain_nocreate], rw) job_t
+    (** Asynchronous domain restore. *)
   val core_dump : [>`W] t -> filename -> unit
     (** Force a domain to core dump to the named file. *)
   val core_dump : [>`W] t -> filename -> unit
     (** Force a domain to core dump to the named file. *)
+  val core_dump_job : [>`W] t -> filename -> ([`Domain_nocreate], rw) job_t
+    (** Asynchronous core dump. *)
   val shutdown : [>`W] t -> unit
     (** Shutdown a domain. *)
   val reboot : [>`W] t -> unit
   val shutdown : [>`W] t -> unit
     (** Shutdown a domain. *)
   val reboot : [>`W] t -> unit
@@ -313,6 +525,8 @@ sig
     (** Undefine a domain - removes its configuration. *)
   val create : [>`W] t -> unit
     (** Launch a defined (inactive) domain. *)
     (** Undefine a domain - removes its configuration. *)
   val create : [>`W] t -> unit
     (** Launch a defined (inactive) domain. *)
+  val create_job : [>`W] t -> ([`Domain_nocreate], rw) job_t
+    (** Asynchronous launch domain. *)
   val get_autostart : [>`R] t -> bool
     (** Get the autostart flag for a domain. *)
   val set_autostart : [>`W] t -> bool -> unit
   val get_autostart : [>`R] t -> bool
     (** Get the autostart flag for a domain. *)
   val set_autostart : [>`W] t -> bool -> unit
@@ -358,8 +572,9 @@ sig
       *)
 end
   (** Module dealing with domains.  [Domain.t] is the
       *)
 end
   (** Module dealing with domains.  [Domain.t] is the
-      domain object.
-  *)
+      domain object. *)
+
+(** {3 Networks} *)
 
 module Network : 
 sig
 
 module Network : 
 sig
@@ -376,12 +591,16 @@ sig
     (** Lookup a network by UUID string. *)
   val create_xml : [>`W] Connect.t -> xml -> rw t
     (** Create a network. *)
     (** Lookup a network by UUID string. *)
   val create_xml : [>`W] Connect.t -> xml -> rw t
     (** Create a network. *)
+  val create_xml_job : [>`W] Connect.t -> xml -> ([`Network], rw) job_t
+    (** Asynchronous create network. *)
   val define_xml : [>`W] Connect.t -> xml -> rw t
     (** Define but don't activate a network. *)
   val undefine : [>`W] t -> unit
     (** Undefine configuration of a network. *)
   val create : [>`W] t -> unit
     (** Start up a defined (inactive) network. *)
   val define_xml : [>`W] Connect.t -> xml -> rw t
     (** Define but don't activate a network. *)
   val undefine : [>`W] t -> unit
     (** Undefine configuration of a network. *)
   val create : [>`W] t -> unit
     (** Start up a defined (inactive) network. *)
+  val create_job : [>`W] t -> ([`Network_nocreate], rw) job_t
+    (** Asynchronous start network. *)
   val destroy : [>`W] t -> unit
     (** Destroy a network. *)
   val free : [>`R] t -> unit
   val destroy : [>`W] t -> unit
     (** Destroy a network. *)
   val free : [>`R] t -> unit
@@ -413,8 +632,192 @@ sig
       *)
 end
   (** Module dealing with networks.  [Network.t] is the
       *)
 end
   (** Module dealing with networks.  [Network.t] is the
-      network object.
-  *)
+      network object. *)
+
+(** {3 Storage pools} *)
+
+module Pool :
+sig
+  type 'rw t
+    (** Storage pool handle. *)
+
+  type pool_state = Inactive | Active
+    (** State of the storage pool. *)
+
+  type pool_info = {
+    state : pool_state;                        (** Inactive | Active *)
+    capacity : int64;                  (** Logical size in bytes. *)
+    allocation : int64;                        (** Currently allocated in bytes. *)
+  }
+
+  val lookup_by_name : 'a Connect.t -> string -> 'a t
+  val lookup_by_uuid : 'a Connect.t -> uuid -> 'a t
+  val lookup_by_uuid_string : 'a Connect.t -> string -> 'a t
+    (** Look up a storage pool by name, UUID or UUID string. *)
+
+  val create_xml : [>`W] Connect.t -> xml -> rw t
+    (** Create a storage pool. *)
+  val define_xml : [>`W] Connect.t -> xml -> rw t
+    (** Define but don't activate a storage pool. *)
+  val undefine : [>`W] t -> unit
+    (** Undefine configuration of a storage pool. *)
+  val create : [>`W] t -> unit
+    (** Start up a defined (inactive) storage pool. *)
+  val destroy : [>`W] t -> unit
+    (** Destroy a storage pool. *)
+  val shutdown : [>`W] t -> unit
+    (** Shutdown a storage pool. *)
+  val free : [>`R] t -> unit
+    (** Free a storage pool object in memory.
+
+       The storage pool object is automatically freed if it is garbage
+       collected.  This function just forces it to be freed right
+       away.
+    *)
+  val refresh : [`R] t -> unit
+    (** Refresh the list of volumes in the storage pool. *)
+
+  val get_name : [`R] t -> string
+    (** Name of the pool. *)
+  val get_uuid : [`R] t -> uuid
+    (** Get the UUID (as a packed byte array). *)
+  val get_uuid_string : [`R] t -> string
+    (** Get the UUID (as a printable string). *)
+  val get_info : [`R] t -> pool_info
+    (** Get information about the pool. *)
+  val get_xml_desc : [`R] t -> xml
+    (** Get the XML description. *)
+  val get_autostart : [`R] t -> bool
+    (** Get the autostart flag for the storage pool. *)
+  val set_autostart : [`W] t -> bool -> unit
+    (** Set the autostart flag for the storage pool. *)
+
+  external const : [>`R] t -> ro t = "%identity"
+    (** [const conn] turns a read/write storage pool into a read-only
+       pool.  Note that the opposite operation is impossible.
+      *)
+end
+  (** Module dealing with storage pools. *)
+
+(** {3 Storage volumes} *)
+
+module Volume :
+sig
+  type 'rw t
+    (** Storage volume handle. *)
+
+  type vol_type = File | Block | Virtual
+    (** Type of a storage volume. *)
+
+  type vol_info = {
+    typ : vol_type;                    (** Type of storage volume. *)
+    capacity : int64;                  (** Logical size in bytes. *)
+    allocation : int64;                        (** Currently allocated in bytes. *)
+  }
+
+  val lookup_by_name : 'a Pool.t -> string -> 'a t
+  val lookup_by_key : 'a Pool.t -> string -> 'a t
+  val lookup_by_path : 'a Pool.t -> string -> 'a t
+    (** Look up a storage volume by name, key or path volume. *)
+
+  val pool_of_volume : 'a t -> 'a Pool.t
+    (** Get the storage pool containing this volume. *)
+
+  val get_name : [`R] t -> string
+    (** Name of the volume. *)
+  val get_key : [`R] t -> string
+    (** Key of the volume. *)
+  val get_path : [`R] t -> string
+    (** Path of the volume. *)
+  val get_info : [`R] t -> vol_info
+    (** Get information about the storage volume. *)
+  val get_xml_desc : [`R] t -> xml
+    (** Get the XML description. *)
+
+  val create_xml : [`W] Pool.t -> xml -> unit
+    (** Create a storage volume. *)
+  val destroy : [`W] t -> unit
+    (** Destroy a storage volume. *)
+  val free : [>`R] t -> unit
+    (** Free a storage volume object in memory.
+
+       The storage volume object is automatically freed if it is garbage
+       collected.  This function just forces it to be freed right
+       away.
+    *)
+
+  external const : [>`R] t -> ro t = "%identity"
+    (** [const conn] turns a read/write storage volume into a read-only
+       volume.  Note that the opposite operation is impossible.
+      *)
+end
+  (** Module dealing with storage volumes. *)
+
+(** {3 Jobs and asynchronous processing} *)
+
+module Job :
+sig
+  type ('jobclass, 'rw) t = ('jobclass, 'rw) job_t
+    (** A background asynchronous job.
+
+        Jobs represent a pending operation such as domain creation.
+       The possible types for a job are:
+
+{v
+(`Domain, `W) Job.t            Job creating a new domain
+(`Domain_nocreate, `W) Job.t   Job acting on an existing domain
+(`Network, `W) Job.t           Job creating a new network
+(`Network_nocreate, `W) Job.t  Job acting on an existing network
+v}
+      *)
+
+  type job_type = Bounded | Unbounded
+    (** A Bounded job is one where we can estimate time to completion. *)
+
+  type job_state = Running | Complete | Failed | Cancelled
+    (** State of the job. *)
+
+  type job_info = {
+    typ : job_type;                    (** Job type (Bounded, Unbounded) *)
+    state : job_state;                 (** Job state (Running, etc.) *)
+    running_time : int;                        (** Actual running time (seconds) *)
+    (** The following fields are only available in Bounded jobs: *)
+    remaining_time : int;              (** Estimated time left (seconds) *)
+    percent_complete : int             (** Estimated percent complete *)
+  }
+
+  val get_info : ('a,'b) t -> job_info
+    (** Get information and status about the job. *)
+
+  val get_domain : ([`Domain], 'a) t -> 'a Domain.t
+    (** Get the completed domain from a job.
+
+        You should only call it on a job in state Complete. *)
+
+  val get_network : ([`Network], 'a) t -> 'a Network.t
+    (** Get the completed network from a job.
+
+        You should only call it on a job in state Complete. *)
+
+  val cancel : ('a,'b) t -> unit
+    (** Cancel a job. *)
+
+  val free : ('a, [>`R]) t -> unit
+    (** Free a job object in memory.
+
+       The job object is automatically freed if it is garbage
+       collected.  This function just forces it to be freed right
+       away.
+    *)
+
+  external const : ('a, [>`R]) t -> ('a, ro) t = "%identity"
+    (** [const conn] turns a read/write job into a read-only
+       job.  Note that the opposite operation is impossible.
+      *)
+end
+  (** Module dealing with asynchronous jobs. *)
+
+(** {3 Error handling and exceptions} *)
 
 module Virterror :
 sig
 
 module Virterror :
 sig
@@ -464,7 +867,14 @@ sig
     | VIR_ERR_NO_DOMAIN
     | VIR_ERR_NO_NETWORK
     | VIR_ERR_INVALID_MAC
     | VIR_ERR_NO_DOMAIN
     | VIR_ERR_NO_NETWORK
     | VIR_ERR_INVALID_MAC
-       (* ^^ NB: If you add a variant you MUST edit libvirt_c.c:MAX_VIR_* *)
+    | VIR_ERR_AUTH_FAILED
+    | VIR_ERR_INVALID_STORAGE_POOL
+    | VIR_ERR_INVALID_STORAGE_VOL
+    | VIR_WAR_NO_STORAGE
+    | VIR_ERR_NO_STORAGE_POOL
+    | VIR_ERR_NO_STORAGE_VOL
+       (* ^^ NB: If you add a variant you MUST edit
+          libvirt_c_epilogue.c:MAX_VIR_* *)
     | VIR_ERR_UNKNOWN of int
        (** See [<libvirt/virterror.h>] for meaning of these codes. *)
 
     | VIR_ERR_UNKNOWN of int
        (** See [<libvirt/virterror.h>] for meaning of these codes. *)
 
@@ -488,7 +898,9 @@ sig
     | VIR_FROM_OPENVZ
     | VIR_FROM_XENXM
     | VIR_FROM_STATS_LINUX
     | VIR_FROM_OPENVZ
     | VIR_FROM_XENXM
     | VIR_FROM_STATS_LINUX
-       (* ^^ NB: If you add a variant you MUST edit libvirt_c.c: MAX_VIR_* *)
+    | VIR_FROM_STORAGE
+       (* ^^ NB: If you add a variant you MUST edit
+          libvirt_c_epilogue.c: MAX_VIR_* *)
     | VIR_FROM_UNKNOWN of int
        (** Subsystem / driver which produced the error. *)
 
     | VIR_FROM_UNKNOWN of int
        (** Subsystem / driver which produced the error. *)
 
@@ -560,6 +972,6 @@ exception Not_supported of string
     not supported at either compile or run time.  This applies to
     any libvirt function added after version 0.2.1.
 
     not supported at either compile or run time.  This applies to
     any libvirt function added after version 0.2.1.
 
-    See also [http://libvirt.org/hvsupport.html]
+    See also {{:http://libvirt.org/hvsupport.html}http://libvirt.org/hvsupport.html}
 *)
 
 *)