Pino Toscano
2020-May-04 13:22 UTC
[Libguestfs] [common PATCH] mltools: add run_in_guest_command helper
Add an helper function to run a command in the guest, checking for the
host/guest compatibility. This is mostly extracted from the internal
do_run helper currently in the Customize_run module of virt-customize.
---
mltools/tools_utils.ml | 50 +++++++++++++++++++++++++++++++++++++++++
mltools/tools_utils.mli | 10 +++++++++
2 files changed, 60 insertions(+)
diff --git a/mltools/tools_utils.ml b/mltools/tools_utils.ml
index 1271802..d54ec58 100644
--- a/mltools/tools_utils.ml
+++ b/mltools/tools_utils.ml
@@ -679,3 +679,53 @@ let with_timeout op timeout ?(sleep = 2) fn loop ()
in
loop ()
+
+let run_in_guest_command g root ?logfile ?incompatible_fn cmd + (* Is the
host_cpu compatible with the guest arch? ie. Can we
+ * run commands in this guest?
+ *)
+ let guest_arch = g#inspect_get_arch root in
+ let guest_arch_compatible = guest_arch_compatible guest_arch in
+ if not guest_arch_compatible then (
+ match incompatible_fn with
+ | None -> ()
+ | Some fn -> fn ()
+ )
+ else (
+ (* Add a prologue to the scripts:
+ * - Pass environment variables through from the host.
+ * - Optionally send stdout and stderr to a log file so we capture
+ * all output in error messages.
+ * - Use setarch when running x86_64 host + i686 guest.
+ *)
+ let env_vars + List.filter_map (
+ fun name ->
+ try Some (sprintf "export %s=%s" name (quote (Sys.getenv
name)))
+ with Not_found -> None
+ ) [ "http_proxy"; "https_proxy";
"ftp_proxy"; "no_proxy" ] in
+ let env_vars = String.concat "\n" env_vars ^ "\n" in
+
+ let cmd + match Guestfs_config.host_cpu, guest_arch with
+ | "x86_64",
("i386"|"i486"|"i586"|"i686") ->
+ sprintf "setarch i686 <<\"__EOCMD\"
+%s
+__EOCMD
+" cmd
+ | _ -> cmd in
+
+ let logfile_redirect + match logfile with
+ | None -> ""
+ | Some logfile -> sprintf "exec >>%s 2>&1"
(quote logfile) in
+
+ let cmd = sprintf "\
+%s
+%s
+%s
+" (logfile_redirect) env_vars cmd in
+
+ debug "running command:\n%s" cmd;
+ ignore (g#sh cmd)
+ )
diff --git a/mltools/tools_utils.mli b/mltools/tools_utils.mli
index ab70f58..102abff 100644
--- a/mltools/tools_utils.mli
+++ b/mltools/tools_utils.mli
@@ -212,3 +212,13 @@ val with_timeout : string -> int -> ?sleep:int ->
(unit -> 'a option) -> 'a
calls {!error} and the program exits. The error message will
contain the diagnostic string [op] to identify the operation
which timed out. *)
+
+val run_in_guest_command : Guestfs.guestfs -> string -> ?logfile:string
-> ?incompatible_fn:(unit -> unit) -> string -> unit
+(** [run_in_guest_command g root ?incompatible_archs_fn cmd]
+ runs a command in the guest, which is already mounted for the
+ specified [root]. The command is run directly in case the
+ architecture of the host and the guest are compatible, optionally
+ calling [?incompatible_fn] in case they are not.
+
+ [?logfile] is an optional file in the guest to where redirect
+ stdout and stderr of the command. *)
--
2.25.4
Richard W.M. Jones
2020-May-04 15:25 UTC
Re: [Libguestfs] [common PATCH] mltools: add run_in_guest_command helper
On Mon, May 04, 2020 at 03:22:37PM +0200, Pino Toscano wrote:> Add an helper function to run a command in the guest, checking for the > host/guest compatibility. This is mostly extracted from the internal > do_run helper currently in the Customize_run module of virt-customize. > --- > mltools/tools_utils.ml | 50 +++++++++++++++++++++++++++++++++++++++++ > mltools/tools_utils.mli | 10 +++++++++ > 2 files changed, 60 insertions(+) > > diff --git a/mltools/tools_utils.ml b/mltools/tools_utils.ml > index 1271802..d54ec58 100644 > --- a/mltools/tools_utils.ml > +++ b/mltools/tools_utils.ml > @@ -679,3 +679,53 @@ let with_timeout op timeout ?(sleep = 2) fn > loop () > in > loop () > + > +let run_in_guest_command g root ?logfile ?incompatible_fn cmd > + (* Is the host_cpu compatible with the guest arch? ie. Can we > + * run commands in this guest? > + *) > + let guest_arch = g#inspect_get_arch root in > + let guest_arch_compatible = guest_arch_compatible guest_arch in > + if not guest_arch_compatible then ( > + match incompatible_fn with > + | None -> () > + | Some fn -> fn () > + ) > + else ( > + (* Add a prologue to the scripts: > + * - Pass environment variables through from the host. > + * - Optionally send stdout and stderr to a log file so we capture > + * all output in error messages. > + * - Use setarch when running x86_64 host + i686 guest. > + *) > + let env_vars > + List.filter_map ( > + fun name -> > + try Some (sprintf "export %s=%s" name (quote (Sys.getenv name))) > + with Not_found -> None > + ) [ "http_proxy"; "https_proxy"; "ftp_proxy"; "no_proxy" ] in > + let env_vars = String.concat "\n" env_vars ^ "\n" in > + > + let cmd > + match Guestfs_config.host_cpu, guest_arch with > + | "x86_64", ("i386"|"i486"|"i586"|"i686") -> > + sprintf "setarch i686 <<\"__EOCMD\" > +%s > +__EOCMD > +" cmd > + | _ -> cmd in > + > + let logfile_redirect > + match logfile with > + | None -> "" > + | Some logfile -> sprintf "exec >>%s 2>&1" (quote logfile) in > + > + let cmd = sprintf "\ > +%s > +%s > +%s > +" (logfile_redirect) env_vars cmd in > + > + debug "running command:\n%s" cmd; > + ignore (g#sh cmd) > + ) > diff --git a/mltools/tools_utils.mli b/mltools/tools_utils.mli > index ab70f58..102abff 100644 > --- a/mltools/tools_utils.mli > +++ b/mltools/tools_utils.mli > @@ -212,3 +212,13 @@ val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a > calls {!error} and the program exits. The error message will > contain the diagnostic string [op] to identify the operation > which timed out. *) > + > +val run_in_guest_command : Guestfs.guestfs -> string -> ?logfile:string -> ?incompatible_fn:(unit -> unit) -> string -> unit > +(** [run_in_guest_command g root ?incompatible_archs_fn cmd] > + runs a command in the guest, which is already mounted for the > + specified [root]. The command is run directly in case the > + architecture of the host and the guest are compatible, optionally > + calling [?incompatible_fn] in case they are not. > + > + [?logfile] is an optional file in the guest to where redirect > + stdout and stderr of the command. *)Pretty much a straightforward copy of the virt-sysprep function. ACK. Thanks, Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
Apparently Analagous Threads
- [PATCH 0/4] sysprep: add FreeIPA offline unenrollment (RHBZ#1789592)
- [PATCH] customize: fix running commands on the same architecture
- [PATCH] customize: Use setarch when running commands on i686 guest (RHBZ#1256405).
- [PATCH v2] customize: Use setarch when running commands on i686 guest
- Possible bug in RTERM (PR#14043)