[Libguestfs] [PATCH 4/4] v2v: -o qemu: Reimplement qemu command line using common/qemuopts.

Richard W.M. Jones rjones at redhat.com
Thu Apr 27 15:03:27 UTC 2017


---
 v2v/Makefile.am                        |   8 +-
 v2v/output_qemu.ml                     |  88 +++++++-------
 v2v/qemu_command.ml                    | 101 ---------------
 v2v/qemuopts-c.c                       | 216 +++++++++++++++++++++++++++++++++
 v2v/qemuopts.ml                        |  35 ++++++
 v2v/{qemu_command.mli => qemuopts.mli} |  24 ++--
 6 files changed, 318 insertions(+), 154 deletions(-)
 delete mode 100644 v2v/qemu_command.ml
 create mode 100644 v2v/qemuopts-c.c
 create mode 100644 v2v/qemuopts.ml
 rename v2v/{qemu_command.mli => qemuopts.mli} (75%)

diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 8df8ca0..5b6618a 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -57,7 +57,7 @@ SOURCES_MLI = \
 	parse_ovf_from_ova.mli \
 	parse_libvirt_xml.mli \
 	parse_vmx.mli \
-	qemu_command.mli \
+	qemuopts.mli \
 	target_bus_assignment.mli \
 	types.mli \
 	uefi.mli \
@@ -85,7 +85,7 @@ SOURCES_ML = \
 	parse_vmx.ml \
 	parse_libvirt_xml.ml \
 	create_libvirt_xml.ml \
-	qemu_command.ml \
+	qemuopts.ml \
 	input_libvirtxml.ml \
 	input_libvirt_other.ml \
 	input_libvirt_vcenter_https.ml \
@@ -111,6 +111,7 @@ SOURCES_ML = \
 
 SOURCES_C = \
 	libvirt_utils-c.c \
+	qemuopts-c.c \
 	utils-c.c
 
 if HAVE_OCAML
@@ -122,6 +123,7 @@ virt_v2v_CPPFLAGS = \
 	-I. \
 	-I$(top_builddir) \
 	-I$(shell $(OCAMLC) -where) \
+	-I$(top_srcdir)/common/qemuopts \
 	-I$(top_srcdir)/common/utils \
 	-I$(top_srcdir)/lib
 virt_v2v_CFLAGS = \
@@ -140,6 +142,7 @@ XOBJECTS = $(BOBJECTS:.cmo=.cmx)
 OCAMLPACKAGES = \
 	-package str,unix \
 	-I $(top_builddir)/common/utils/.libs \
+	-I $(top_builddir)/common/qemuopts/.libs \
 	-I $(top_builddir)/lib/.libs \
 	-I $(top_builddir)/gnulib/lib/.libs \
 	-I $(top_builddir)/ocaml \
@@ -151,6 +154,7 @@ endif
 
 OCAMLCLIBS = \
 	-lutils \
+	-lqemuopts \
 	$(LIBVIRT_LIBS) \
 	$(LIBXML2_LIBS) \
 	$(LIBINTL) \
diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml
index 7721f0b..031279c 100644
--- a/v2v/output_qemu.ml
+++ b/v2v/output_qemu.ml
@@ -69,29 +69,31 @@ object
     let machine_q35 = secure_boot_required in
     let smm = secure_boot_required in
 
-    (* Construct the command line.  Note that the [Qemu_command]
+    (* Construct the command line.  Note that the [Qemuopts]
      * module deals with shell and qemu comma quoting.
      *)
-    let cmd = Qemu_command.create ~arch:guestcaps.gcaps_arch () in
-    let flag = Qemu_command.flag cmd
-    and arg = Qemu_command.arg cmd
-    and arg_noquote = Qemu_command.arg_noquote cmd
-    and commas = Qemu_command.commas cmd in
+    let cmd = Qemuopts.create () in
+    Qemuopts.set_binary_by_arch cmd (Some guestcaps.gcaps_arch);
+
+    let flag = Qemuopts.flag cmd
+    and arg = Qemuopts.arg cmd
+    and arg_noquote = Qemuopts.arg_noquote cmd
+    and arg_list = Qemuopts.arg_list cmd in
 
     flag "-no-user-config"; flag "-nodefaults";
     arg "-name" source.s_name;
-    commas "-machine" (if machine_q35 then ["q35"] else [] @
-                       if smm then ["smm=on"] else [] @
-                       ["accel=kvm:tcg"]);
+    arg_list "-machine" (if machine_q35 then ["q35"] else [] @
+                         if smm then ["smm=on"] else [] @
+                         ["accel=kvm:tcg"]);
 
     (match uefi_firmware with
      | None -> ()
      | Some { Uefi.code = code } ->
         if secure_boot_required then
-          commas "-global"
-                 ["driver=cfi.pflash01"; "property=secure"; "value=on"];
-        commas "-drive"
-               ["if=pflash"; "format=raw"; "file=" ^ code; "readonly"];
+          arg_list "-global"
+                   ["driver=cfi.pflash01"; "property=secure"; "value=on"];
+        arg_list "-drive"
+                 ["if=pflash"; "format=raw"; "file=" ^ code; "readonly"];
         arg_noquote "-drive" "if=pflash,format=raw,file=\"$uefi_vars\"";
     );
 
@@ -113,7 +115,7 @@ object
                              (match source.s_cpu_threads with
                               | None -> 1
                               | Some v -> v));
-        commas "-smp" !a
+        arg_list "-smp" !a
       )
       else
         arg "-smp" (string_of_int source.s_vcpu);
@@ -123,17 +125,17 @@ object
     | BusSlotEmpty -> ()
 
     | BusSlotTarget t ->
-       commas "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
-                        "if=" ^ if_name; "index=" ^ string_of_int i;
-                        "media=disk"]
+       arg_list "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
+                          "if=" ^ if_name; "index=" ^ string_of_int i;
+                          "media=disk"]
 
     | BusSlotRemovable { s_removable_type = CDROM } ->
-       commas "-drive" ["format=raw"; "if=" ^ if_name;
-                        "index=" ^ string_of_int i; "media=cdrom"]
+       arg_list "-drive" ["format=raw"; "if=" ^ if_name;
+                          "index=" ^ string_of_int i; "media=cdrom"]
 
     | BusSlotRemovable { s_removable_type = Floppy } ->
-       commas "-drive" ["format=raw"; "if=" ^ if_name;
-                        "index=" ^ string_of_int i; "media=floppy"]
+       arg_list "-drive" ["format=raw"; "if=" ^ if_name;
+                          "index=" ^ string_of_int i; "media=floppy"]
     in
     Array.iteri (make_disk "virtio") target_buses.target_virtio_blk_bus;
     Array.iteri (make_disk "ide") target_buses.target_ide_bus;
@@ -142,17 +144,17 @@ object
     | BusSlotEmpty -> ()
 
     | BusSlotTarget t ->
-       commas "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
-                        "if=scsi"; "bus=0"; "unit=" ^ string_of_int i;
-                        "media=disk"]
+       arg_list "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
+                          "if=scsi"; "bus=0"; "unit=" ^ string_of_int i;
+                          "media=disk"]
 
     | BusSlotRemovable { s_removable_type = CDROM } ->
-       commas "-drive" ["format=raw"; "if=scsi"; "bus=0";
-                        "unit=" ^ string_of_int i; "media=cdrom"]
+       arg_list "-drive" ["format=raw"; "if=scsi"; "bus=0";
+                          "unit=" ^ string_of_int i; "media=cdrom"]
 
     | BusSlotRemovable { s_removable_type = Floppy } ->
-       commas "-drive" ["format=raw"; "if=scsi"; "bus=0";
-                        "unit=" ^ string_of_int i; "media=floppy"]
+       arg_list "-drive" ["format=raw"; "if=scsi"; "bus=0";
+                          "unit=" ^ string_of_int i; "media=floppy"]
     in
     Array.iteri make_scsi target_buses.target_scsi_bus;
 
@@ -167,12 +169,12 @@ object
       | RTL8139 -> "rtl8139" in
     iteri (
       fun i nic ->
-        commas "-netdev" ["user"; "id=net" ^ string_of_int i];
-        commas "-device" [net_bus;
-                          sprintf "netdev=net%d%s" i
-                                  (match nic.s_mac with
-                                   | None -> ""
-                                   | Some mac -> "mac=" ^ mac)]
+        arg_list "-netdev" ["user"; "id=net" ^ string_of_int i];
+        arg_list "-device" [net_bus;
+                            sprintf "netdev=net%d%s" i
+                                    (match nic.s_mac with
+                                     | None -> ""
+                                     | Some mac -> "mac=" ^ mac)]
     ) source.s_nics;
 
     (* Add a display. *)
@@ -185,11 +187,11 @@ object
       | VNC ->
          arg "-display" "vnc=:0"
       | Spice ->
-         commas "-spice" [sprintf "port=%d"
-                                  (match display.s_port with
-                                   | None -> 5900
-                                   | Some p -> p);
-                          "addr=127.0.0.1"]
+         arg_list "-spice" [sprintf "port=%d"
+                                    (match display.s_port with
+                                     | None -> 5900
+                                     | Some p -> p);
+                            "addr=127.0.0.1"]
       );
       arg "-vga"
           (match guestcaps.gcaps_video with Cirrus -> "cirrus" | QXL -> "qxl")
@@ -215,15 +217,15 @@ object
 
     (* Add the miscellaneous KVM devices. *)
     if guestcaps.gcaps_virtio_rng then (
-      commas "-object" ["rng-random"; "filename=/dev/urandom"; "id=rng0"];
-      commas "-device" ["virtio-rng-pci"; "rng=rng0"];
+      arg_list "-object" ["rng-random"; "filename=/dev/urandom"; "id=rng0"];
+      arg_list "-device" ["virtio-rng-pci"; "rng=rng0"];
     );
     if guestcaps.gcaps_virtio_balloon then
       arg "-balloon" "virtio"
     else
       arg "-balloon" "none";
     if guestcaps.gcaps_isa_pvpanic then
-      commas "-device" ["pvpanic"; "ioport=0x505"];
+      arg_list "-device" ["pvpanic"; "ioport=0x505"];
 
     (* Add a serial console to Linux guests. *)
     if inspect.i_type = "linux" then
@@ -244,7 +246,7 @@ object
         fpf "\n"
     );
 
-    Qemu_command.to_chan cmd chan;
+    Qemuopts.to_chan cmd chan;
     close_out chan;
 
     Unix.chmod file 0o755;
diff --git a/v2v/qemu_command.ml b/v2v/qemu_command.ml
deleted file mode 100644
index ccdda8a..0000000
--- a/v2v/qemu_command.ml
+++ /dev/null
@@ -1,101 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-2017 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-(** Generate a qemu command line, dealing with quoting. *)
-
-open Printf
-
-open Common_utils
-
-type t = {
-  cmd : string;
-  mutable args : arg list; (* list constructed in reverse order *)
-}
-and arg =
-  | Flag of string
-  | Arg of string * string * bool
-  | Commas of string * string list
-
-let create ?(arch = "x86_64") () =
-  { cmd = "qemu-system-" ^ arch; args = [] }
-
-let flag t k =
-  assert (String.is_prefix k "-");
-  t.args <- Flag k :: t.args
-
-let arg t k v =
-  assert (String.is_prefix k "-");
-  t.args <- Arg (k, v, true) :: t.args
-
-let arg_noquote t k v =
-  assert (String.is_prefix k "-");
-  t.args <- Arg (k, v, false) :: t.args
-
-let commas t k vs =
-  assert (String.is_prefix k "-");
-  List.iter (fun v -> assert (v <> "")) vs;
-  t.args <- Commas (k, vs) :: t.args
-
-let nl = " \\\n\t"
-
-(* If the value contains only simple characters then it doesn't
- * need quoting.  This keeps the output as similar as possible
- * to the old code.
- *)
-let do_quoting str =
-  let len = String.length str in
-  let ret = ref false in
-  for i = 0 to len-1 do
-    let c = String.unsafe_get str i in
-    if not (Char.isalnum c) &&
-         c <> '.' && c <> '-' && c <> '_' &&
-         c <> '=' && c <> ',' && c <> ':' && c <> '/'
-    then
-      ret := true
-  done;
-  !ret
-
-let print_quoted_param chan k v =
-  if not (do_quoting v) then
-    fprintf chan "%s%s %s" nl k v
-  else
-    fprintf chan "%s%s %s" nl k (quote v)
-
-let to_chan t chan =
-  fprintf chan "%s" t.cmd;
-  List.iter (
-    function
-    | Flag k ->
-       fprintf chan "%s%s" nl k
-    | Arg (k, v, true) ->
-       print_quoted_param chan k v
-    | Arg (k, v, false) ->
-       fprintf chan "%s%s %s" nl k v
-    | Commas (k, vs) ->
-       let vs = List.map (fun s -> String.replace s "," ",,") vs in
-       let v = String.concat "," vs in
-       print_quoted_param chan k v
-  ) (List.rev t.args);
-  fprintf chan "\n"
-
-let to_script t filename =
-  let chan = open_out filename in
-  fprintf chan "#!/bin/sh -\n";
-  to_chan t chan;
-  close_out chan;
-  Unix.chmod filename 0o755
diff --git a/v2v/qemuopts-c.c b/v2v/qemuopts-c.c
new file mode 100644
index 0000000..cfdb5f6
--- /dev/null
+++ b/v2v/qemuopts-c.c
@@ -0,0 +1,216 @@
+/* virt-v2v
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <caml/alloc.h>
+#include <caml/custom.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#ifdef HAVE_CAML_UNIXSUPPORT_H
+#include <caml/unixsupport.h>
+#else
+#define Nothing ((value) 0)
+extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
+#endif
+
+#include "qemuopts.h"
+
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+
+#define Qopts_val(v) (*((struct qemuopts **)Data_custom_val(v)))
+
+static void
+qopts_finalize (value qoptsv)
+{
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qopts)
+    qemuopts_free (qopts);
+}
+
+static struct custom_operations qemuopts_custom_operations = {
+  (char *) "qemuopts_custom_operations",
+  qopts_finalize,
+  custom_compare_default,
+  custom_hash_default,
+  custom_serialize_default,
+  custom_deserialize_default
+};
+
+value
+guestfs_int_qemuopts_create (value unitv)
+{
+  CAMLparam1 (unitv);
+  CAMLlocal1 (qoptsv);
+  struct qemuopts *qopts;
+
+  qopts = qemuopts_create ();
+  if (qopts == NULL)
+    unix_error (errno, (char *) "qemuopts_create", Nothing);
+
+  qoptsv = caml_alloc_custom (&qemuopts_custom_operations,
+                              sizeof (struct qemuopts *), 0, 1);
+  Qopts_val (qoptsv) = qopts;
+
+  CAMLreturn (qoptsv);
+}
+
+value
+guestfs_int_qemuopts_set_binary (value qoptsv, value strv)
+{
+  CAMLparam2 (qoptsv, strv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_set_binary (qopts, String_val (strv)) == -1)
+    unix_error (errno, (char *) "qemuopts_set_binary", strv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_set_binary_by_arch (value qoptsv, value ostrv)
+{
+  CAMLparam2 (qoptsv, ostrv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+  int r;
+
+  if (ostrv != Val_int (0))
+    r = qemuopts_set_binary_by_arch (qopts, NULL);
+  else
+    r = qemuopts_set_binary_by_arch (qopts, String_val (Field (ostrv, 0)));
+
+  if (r == -1)
+    unix_error (errno, (char *) "qemuopts_set_binary_by_arch", Nothing);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_flag (value qoptsv, value flagv)
+{
+  CAMLparam2 (qoptsv, flagv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_add_flag (qopts, String_val (flagv)) == -1)
+    unix_error (errno, (char *) "qemuopts_add_flag", flagv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_arg (value qoptsv, value flagv, value valv)
+{
+  CAMLparam3 (qoptsv, flagv, valv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_add_arg (qopts, String_val (flagv), String_val (valv)) == -1)
+    unix_error (errno, (char *) "qemuopts_add_arg", flagv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_arg_noquote (value qoptsv, value flagv, value valv)
+{
+  CAMLparam3 (qoptsv, flagv, valv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_add_arg_noquote (qopts,
+                                String_val (flagv), String_val (valv)) == -1)
+    unix_error (errno, (char *) "qemuopts_add_arg_noquote", flagv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_arg_list (value qoptsv, value flagv, value valuesv)
+{
+  CAMLparam3 (qoptsv, flagv, valuesv);
+  CAMLlocal1 (hd);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_start_arg_list (qopts, String_val (flagv)) == -1)
+    unix_error (errno, (char *) "qemuopts_start_arg_list", flagv);
+
+  while (valuesv != Val_emptylist) {
+    hd = Field (valuesv, 0);
+    if (qemuopts_append_arg_list (qopts, String_val (hd)) == -1)
+      unix_error (errno, (char *) "qemuopts_append_arg_list", flagv);
+    valuesv = Field (valuesv, 1);
+  }
+
+  if (qemuopts_end_arg_list (qopts) == -1)
+    unix_error (errno, (char *) "qemuopts_end_arg_list", flagv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_to_script (value qoptsv, value strv)
+{
+  CAMLparam2 (qoptsv, strv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+
+  if (qemuopts_to_script (qopts, String_val (strv)) == -1)
+    unix_error (errno, (char *) "qemuopts_to_script", strv);
+
+  CAMLreturn (Val_unit);
+}
+
+value
+guestfs_int_qemuopts_to_chan (value qoptsv, value fdv)
+{
+  CAMLparam2 (qoptsv, fdv);
+  struct qemuopts *qopts = Qopts_val (qoptsv);
+  /* Note that Unix.file_descr is really just an int. */
+  int fd = Int_val (fdv);
+  int fd2;
+  FILE *fp;
+  int saved_errno;
+
+  /* Dup the file descriptor so we don't lose it in fclose. */
+  fd2 = dup (fd);
+  if (fd2 == -1)
+    unix_error (errno, (char *) "qemuopts_to_channel: dup", Nothing);
+
+  fp = fdopen (fd2, "w");
+  if (fp == NULL) {
+    saved_errno = errno;
+    close (fd2);
+    unix_error (saved_errno, (char *) "qemuopts_to_channel: fdopen", Nothing);
+  }
+
+  if (qemuopts_to_channel (qopts, fp) == -1) {
+    saved_errno = errno;
+    fclose (fp);
+    unix_error (saved_errno, (char *) "qemuopts_to_channel", Nothing);
+  }
+
+  if (fclose (fp) == EOF)
+    unix_error (errno, (char *) "qemuopts_to_channel: fclose", Nothing);
+
+  CAMLreturn (Val_unit);
+}
diff --git a/v2v/qemuopts.ml b/v2v/qemuopts.ml
new file mode 100644
index 0000000..752e4d6
--- /dev/null
+++ b/v2v/qemuopts.ml
@@ -0,0 +1,35 @@
+(* virt-v2v
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+type t
+
+external create : unit -> t = "guestfs_int_qemuopts_create"
+external set_binary : t -> string -> unit = "guestfs_int_qemuopts_set_binary"
+external set_binary_by_arch : t -> string option -> unit = "guestfs_int_qemuopts_set_binary_by_arch"
+external flag : t -> string -> unit = "guestfs_int_qemuopts_flag"
+external arg : t -> string -> string -> unit = "guestfs_int_qemuopts_arg"
+external arg_noquote : t -> string -> string -> unit = "guestfs_int_qemuopts_arg_noquote"
+external arg_list : t -> string -> string list -> unit = "guestfs_int_qemuopts_arg_list"
+external to_script : t -> string -> unit = "guestfs_int_qemuopts_to_script"
+
+external _to_chan : t -> Unix.file_descr -> unit = "guestfs_int_qemuopts_to_chan"
+
+let to_chan t chan =
+  flush chan;
+  let fd = Unix.descr_of_out_channel chan in
+  _to_chan t fd
diff --git a/v2v/qemu_command.mli b/v2v/qemuopts.mli
similarity index 75%
rename from v2v/qemu_command.mli
rename to v2v/qemuopts.mli
index d993bd2..695acab 100644
--- a/v2v/qemu_command.mli
+++ b/v2v/qemuopts.mli
@@ -16,14 +16,22 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(** Generate a qemu command line, dealing with quoting. *)
+(** OCaml bindings for the [common/qemuopts] library. *)
 
 type t
 
-val create : ?arch:string -> unit -> t
-(** Create an empty qemu command.  If the optional [?arch] parameter
-    is supplied then the command will be [qemu-system-<arch>],
-    otherwise it will be [qemu-system-x86_64]. *)
+val create : unit -> t
+(** Create an empty qemu command line.
+
+    In case of error, all these functions raise [Unix_error]. *)
+
+val set_binary : t -> string -> unit
+(** Set the qemu binary name. *)
+
+val set_binary_by_arch : t -> string option -> unit
+(** Set the qemu binary to [qemu-system-<arch>].  If [arch] is [None],
+    then this picks the right KVM binary for the current host
+    architecture. *)
 
 val flag : t -> string -> unit
 (** [flag t "-foo"] adds a parameter to the command line with no argument. *)
@@ -34,13 +42,13 @@ val arg : t -> string -> string -> unit
     The value will shell-quoted if required, so you do not need to quote
     the string.  However if the value is a comma-separated list
     (eg. [-drive file=foo,if=ide]) then do {b not} use this function, call
-    {!commas} instead. *)
+    {!arg_list} instead. *)
 
 val arg_noquote : t -> string -> string -> unit
 (** Like {!arg} except no quoting is done on the value. *)
 
-val commas : t -> string -> string list -> unit
-(** [commas t "-drive" ["file=foo"; "if=ide"]] adds a comma-separated
+val arg_list : t -> string -> string list -> unit
+(** [arg_list t "-drive" ["file=foo"; "if=ide"]] adds a comma-separated
     list of parameters to the command line [-drive file=foo,if=ide].
 
     This does both qemu comma-quoting and shell-quoting as required. *)
-- 
2.9.3




More information about the Libguestfs mailing list