Use signals to loosely couple modules.
[guestfs-browser.git] / slave.mli
index 1e310bc..c1fdb04 100644 (file)
--- a/slave.mli
+++ b/slave.mli
 (** The public interface to the slave thread.
     Please see HACKING file. *)
 
 (** The public interface to the slave thread.
     Please see HACKING file. *)
 
-(** {2 Commands and callbacks} *)
+(** {2 Commands and callbacks}
+
+    Commands for libvirt and libguestfs are executed in a separate slave
+    thread.  This file describes the interface with that thread that the
+    rest of the program sees.
+
+    Commands are intentionally as high level as possible.  Often a
+    single command may perform many libvirt and libguestfs operations
+    before returing a result.  This is to make use of the slave thread
+    as simple as possible.
+
+    Commands are executed in a "continuation-passing style" (CPS),
+    which means that you call a function to issue the command, passing
+    in a callback ("continuation").  The function returns immediately.
+    The callback may be called some time later once the issued command
+    completes successfully.  Several commands can be queued up for
+    execution.  Commands are executed and callbacks are performed in
+    sequence.
+
+    The callback returns the result of the command.  The callback does
+    not get invoked if there was an error, or if the command was
+    cancelled before it runs (see {!discard_command_queue}).  For some
+    commands the callback can be called multiple times (see
+    documentation below).
+*)
 
 type 'a callback = 'a -> unit
   (** A callback function in the main thread which is called when the
 
 type 'a callback = 'a -> unit
   (** A callback function in the main thread which is called when the
-      command finishes (successfully).
+      command finishes successfully.
 
       This can also return some data (the ['a] parameter).  A command
       that returns a list of strings might have callback type [string
       list callback], and a command that returns nothing would have
       callback type [unit callback].
 
 
       This can also return some data (the ['a] parameter).  A command
       that returns a list of strings might have callback type [string
       list callback], and a command that returns nothing would have
       callback type [unit callback].
 
-      Note that errors are not returned this way.  Errors result
-      in the command queue being discarded and the failure_hook
-      function being called. *)
+      Note that errors are not returned this way.  Each function can
+      optionally supply an extra callback to handle errors, or if
+      not supplied then it defaults to the failure hook set by
+      {!set_failure_hook}. *)
 
 val no_callback : 'a callback
   (** The main thread uses this as a callback if it doesn't care about
       the return value from a command. *)
 
 
 val no_callback : 'a callback
   (** The main thread uses this as a callback if it doesn't care about
       the return value from a command. *)
 
-val connect : string option -> unit callback -> unit
-  (** [connect uri cb] sends the [Connect] message to the slave
-      thread.
+val checksum_file : ?fail:exn callback -> Slave_types.source -> string -> string -> string callback -> unit
+  (** [checksum_file src pathname csumtype cb] calculates the checksum
+      of the file [pathname].  [csumtype] is one of the types
+      supported by libguestfs. *)
 
 
-      This causes the slave thread to disconnect from libvirt and
-      connect to the libvirt [uri].  If this succeeds, [cb] is called
-      in the main thread.
+val connect : ?fail:exn callback -> string option -> Slave_types.domain list callback -> unit
+  (** [connect uri cb] causes the slave thread to disconnect from
+      libvirt and connect to the libvirt [uri].  If this succeeds,
+      then the list of all domains fetched from libvirt and [cb] is
+      called in the main thread.
 
       Although you can connect to remote hosts, libguestfs won't
       usually be able to see the drives on those hosts, so it normally
 
       Although you can connect to remote hosts, libguestfs won't
       usually be able to see the drives on those hosts, so it normally
-      doesn't make sense to use remote URIs. *)
-
-type domain = {
-  dom_id : int;
-  dom_name : string;
-  dom_state : Libvirt.Domain.state;
-}
-    (** List of domains as returned in the [Get_domains] message callback.
-
-        Note that [dom_state] is the state of the domain and should
-        control whether we are allowed to write to the domain's
-        filesystem (disallowed if [dom_state] is not [InfoShutoff]). *)
-
-val get_domains : domain list callback -> unit
-  (** [get_domains cb] sends the [Get_domains] message to the
-      slave thread.
-
-      This causes the slave thread to retrieve the list of domains
-      from libvirt (active and inactive ones).  If this succeeds,
-      [cb] is called in the main thread with the list of
-      domains.  See also the {!domain} type. *)
-
-type rw_flag = RO | RW
-    (** This flag is passed to open callbacks to indicate whether
-        we could open the disks read-only ([RO]) or read-write ([RW]). *)
-
-val open_domain : string -> rw_flag callback -> unit
-  (** [open_domain name cb] sends the [Open_domain] message to the
-      slave thread.
-
-      This causes the slave thread to retrieve the list of
-      block devices for the libvirt domain [name], create a
-      libguestfs handle, add those block devices, and launch
-      the handle.  If this is successful, then [cb] is called
-      in the main thread.
-
-      If the domain is live then the disks are opened read only,
-      else they are opened read write if write_flag is true.
-      The [rw_flag] is passed into the callback accordingly.
+      doesn't make sense to use remote URIs.
+
+      If [fail] is passed, then failures cause this callback to
+      be called.  If not, the global failure hook is called. *)
+
+val disk_usage : ?fail:exn callback -> Slave_types.source -> string -> int64 callback -> unit
+  (** [disk_usage src pathname cb] calculates the disk usage of
+      directory [pathname] and calls the callback with the answer
+      (size of {b kilobytes}). *)
+
+val download_dir_tarball : ?fail:exn callback -> Slave_types.source -> string -> Slave_types.download_dir_tarball_format -> string -> unit callback -> unit
+  (** [download_dir_tarball_format src pathname format localfile cb]
+      downloads directory [pathname] to the named local file (a
+      tarball), and then calls the callback function.
+
+      [format] controls the download format, which is one of
+      uncompressed tar, gzip-compressed tar, or xz-compressed tar. *)
+
+val download_dir_find0 : ?fail:exn callback -> Slave_types.source -> string -> string -> unit callback -> unit
+  (** [download_dir_find0 src pathname localfile cb] downloads the
+      list of filenames of directory [pathname] to the named local
+      file (a ASCII NUL-separated text file), and then calls the
+      callback function. *)
+
+val download_file : ?fail:exn callback -> Slave_types.source -> string -> string -> unit callback -> unit
+  (** [download_file src pathname localfile cb] downloads [pathname]
+      to the named local file, and then calls the callback function. *)
+
+val download_file_if_not_exist : ?fail:exn callback -> Slave_types.source -> string -> string -> unit callback -> unit
+  (** Like {!download_file} except that if [localfile] already exists
+      then the download is skipped.  You can use this to implement
+      caching of remote files. *)
+
+val file_information : ?fail:exn callback -> Slave_types.source -> string -> string callback -> unit
+  (** [file_information src pathname cb] calculates the file
+      information of the file [pathname]. *)
+
+val list_applications : ?fail:exn callback -> Slave_types.inspection_os -> Guestfs.application array callback -> unit
+  (** [list_applications os cb] lists the applications in the
+      guest using libguestfs inspection. *)
+
+val open_domain : ?fail:exn callback -> string -> Slave_types.inspection_data callback -> unit
+  (** [open_domain name cb] retrieves the list of block devices for
+      the libvirt domain [name], creates a libguestfs handle, adds
+      those block devices, launches the handle, and performs
+      inspection.
+
+      If this is successful, then [cb] is called in the main thread
+      with the list of filesystems and the results of inspection.
 
       The slave thread must be connected to libvirt (see {!connect})
 
       The slave thread must be connected to libvirt (see {!connect})
-      else this command will fail. *)
-
-val open_images : string list -> rw_flag callback -> unit
-  (** [open_images images cb] is like {!open_domain} except
-      that it opens local disk image(s) directly. *)
-
-type volume = {
-  vol_device : string;
-  vol_type : string;
-  vol_label : string;
-  vol_uuid : string;
-  vol_statvfs : Guestfs.statvfs;
-}
-    (** The volume structure which is passed to the {!get_volumes} callback. *)
-
-val get_volumes : volume callback -> unit
-  (** [get_volumes cb] sends the [Get_volumes] message to the
-      slave thread.
-
-      This causes the slave thread to examine all partitions, LVs
-      etc within the current disk image, and for each that contains
-      a mountable filesystem, [cb] is called.  (Note [cb] can be
-      called multiple times). *)
-
-type direntry = {
-  dent_name : string;          (** Basename in directory. *)
-  dent_stat : Guestfs.stat;    (** stat(2) for this entry. *)
-  dent_link : string;          (** (for symlinks only) readlink(2). *)
-}
-
-val read_directory : string -> string -> direntry list callback -> unit
-  (** [read_directory dev dir cb] sends the [Read_directory] message
-      to the slave thread.
-
-      This causes the slave thread to read the contents of the
-      directory [dir] from volume [dev], and call [cb] with the
-      complete result.  If [dir] is not a directory then this
-      is an error.
-
-      Note that [.] and [..] entries are not included in the result,
-      and the list is sorted on the [filename] field. *)
-
-val disk_usage : string -> string -> int64 callback -> unit
-  (** [disk_usage dev dir cb] sends the [Disk_usage] message to the
-      slave thread.
-
-      This causes the slave thread to estimate the disk usage of the
-      directory (or file) [dir] from volume [dev], and call [cb] with
-      the result (size in {b kilobytes}). *)
-
-type export_t =
-  | Export_tar                      (** uncompressed tar archive *)
-  | Export_tgz                      (** gzip compressed tar archive *)
-  | Export_checksums of string      (** checksums using algorithm *)
-  | Export_list                     (** list of file names, \0-separated *)
-      (** Export format used by {!export_dir_to}. *)
-
-val export_dir_to : export_t -> string -> string -> string -> unit callback -> unit
-  (** [export_dir_to t dev dir file cb] sends the [Export_dir_to] message
-      to the slave thread.
-
-      This causes the slave thread to export the directory [dir] on
-      device [dev] to the host file called [file].  The precise
-      operation (ie. what is exported) is controlled by the type
-      [export_t].  When the export has been completed, the callback
-      [cb] is called in the main thread.
-
-      Libguestfs doesn't offer any way to view progress of this
-      operation, which could potentially take a long time. *)
+      else this command will fail.
+
+      If [fail] is passed, then failures cause this callback to
+      be called.  If not, the global failure hook is called. *)
+
+val open_images : ?fail:exn callback -> (string * string option) list -> Slave_types.inspection_data callback -> unit
+  (** [open_images images cb] is like {!open_domain} except that it
+      opens local disk image(s) directly.  [images] is a list of
+      [(filename, format)] pairs.
+
+      If [fail] is passed, then failures cause this callback to
+      be called.  If not, the global failure hook is called. *)
+
+val read_directory : ?fail:exn callback -> Slave_types.source -> string -> Slave_types.direntry list callback -> unit
+  (** [read_directory src dir cb] reads the contents of the directory
+      [dir] from source [src], and calls the callback function [cb]
+      with the resulting list of directory entries, if successful.
+
+      The source may be either a filesystem (if [src] is [Volume
+      dev]), or a fully mounted up operating system (if [src] is [OS ...]).
+      In the second case all the mountpoints of the operating system
+      are mounted up so that the path may span mountpoints in the
+      natural way.
+
+      If [fail] is passed, then failures cause this callback to
+      be called.  If not, the global failure hook is called. *)
+
+val run_command : ?fail:exn callback -> string -> unit callback -> unit
+  (** [run_command cmd] runs an external command [cmd].  This is
+      useful for possibly long-running commands as it keeps the
+      display interactive.  Be careful to quote arguments in the
+      command properly (see {!Filename.quote}).  The external command
+      must eventually terminate and must not wait for user input. *)
 
 val discard_command_queue : unit -> unit
   (** [discard_command_queue ()] discards any commands on the command
 
 val discard_command_queue : unit -> unit
   (** [discard_command_queue ()] discards any commands on the command
-      queue.  The currently running command is not (and can not be)
-      stopped. *)
+      queue.
+
+      The currently running command cannot be discarded (because of
+      the design of libguestfs).  Instead the callback is discarded,
+      so from the point of view of the main thread, the effect is
+      similar. *)
 
 val exit_thread : unit -> unit
   (** [exit_thread ()] causes the slave thread to exit, and returns
 
 val exit_thread : unit -> unit
   (** [exit_thread ()] causes the slave thread to exit, and returns
@@ -171,8 +177,8 @@ val exit_thread : unit -> unit
 (** {2 Hooks}
 
     Hooks are like callbacks, except they hook into special events
 (** {2 Hooks}
 
     Hooks are like callbacks, except they hook into special events
-    that happen in the slave threads, rather than just being a
-    response to commands.
+    that happen in the slave thread, rather than just being a response
+    to commands.
 
     The other difference is that hooks are global variables.  You can
     only set one hook of each type.
 
     The other difference is that hooks are global variables.  You can
     only set one hook of each type.
@@ -181,7 +187,9 @@ val exit_thread : unit -> unit
     and display those in the main thread.
 
     {!set_busy_hook} and {!set_idle_hook} are used to implement a
     and display those in the main thread.
 
     {!set_busy_hook} and {!set_idle_hook} are used to implement a
-    "throbber". *)
+    "throbber".
+
+    {!set_progress_hook} is used to implement a progress bar. *)
 
 val set_failure_hook : exn callback -> unit
   (** Set the function in the main thread which is called if there is
 
 val set_failure_hook : exn callback -> unit
   (** Set the function in the main thread which is called if there is
@@ -196,3 +204,14 @@ val set_idle_hook : unit callback -> unit
   (** Set the function in the main thread which is called whenever
       the slave thread stops working on a command {i and} has no
       more commands left in the queue to work on. *)
   (** Set the function in the main thread which is called whenever
       the slave thread stops working on a command {i and} has no
       more commands left in the queue to work on. *)
+
+val set_status_hook : string callback -> unit
+  (** Set the function in the main thread which is called to
+      update the status bar.  The slave thread updates the
+      status bar when an operation starts or stops, keeping the
+      user informed of what is happening. *)
+
+val set_progress_hook : (int64 * int64) callback -> unit
+  (** Set the function in the main thread which is called whenever
+      the slave thread receives a progress notification message
+      from libguestfs. *)