From ad43dde9c87a6c3d58c626d2fa42dd68c2e15e01 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 31 Mar 2012 21:41:10 +0100 Subject: sysprep: Implement 'script' operation for running general scripts against the guest. --- sysprep/Makefile.am | 2 + sysprep/sysprep_operation_script.ml | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 sysprep/sysprep_operation_script.ml diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 034252e0..d2303a68 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -42,6 +42,7 @@ SOURCES += \ sysprep_operation_net_hwaddr.ml \ sysprep_operation_random_seed.ml \ sysprep_operation_rhn_systemid.ml \ + sysprep_operation_script.ml \ sysprep_operation_smolt_uuid.ml \ sysprep_operation_ssh_hostkeys.ml \ sysprep_operation_udev_persistent_net.ml \ @@ -62,6 +63,7 @@ OBJECTS = \ sysprep_operation_net_hwaddr.cmx \ sysprep_operation_random_seed.cmx \ sysprep_operation_rhn_systemid.cmx \ + sysprep_operation_script.cmx \ sysprep_operation_smolt_uuid.cmx \ sysprep_operation_ssh_hostkeys.cmx \ sysprep_operation_udev_persistent_net.cmx \ diff --git a/sysprep/sysprep_operation_script.ml b/sysprep/sysprep_operation_script.ml new file mode 100644 index 00000000..14a00ebf --- /dev/null +++ b/sysprep/sysprep_operation_script.ml @@ -0,0 +1,140 @@ +(* virt-sysprep + * Copyright (C) 2012 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. + *) + +open Printf +open Unix + +open Utils +open Sysprep_operation + +module G = Guestfs + +let scriptdir = ref None +let set_scriptdir dir = + if !scriptdir <> None then ( + eprintf "virt-sysprep: --scriptdir cannot be used more than once\n"; + exit 1 + ); + scriptdir := Some dir + +let scripts = ref [] +let add_script script = + (* Sanity check that the script is executable. *) + let statbuf = stat script in + if statbuf.st_perm land 0o555 = 0 then ( + eprintf "virt-sysprep: script: %s: script is not executable\n" script; + exit 1 + ); + scripts := script :: !scripts + +let rec script_perform (g : Guestfs.guestfs) root = + let scripts = List.rev !scripts in + if scripts <> [] then ( + (* Create a temporary directory? *) + let scriptdir, cleanup = + match !scriptdir with + | Some dir -> dir, false + | None -> + let tmpdir = Filename.temp_dir_name in + let tmpdir = tmpdir // string_random8 () in + mkdir tmpdir 0o755; + tmpdir, true in + + (* Mount the directory locally. *) + g#mount_local scriptdir; + + (* Run the script(s)/program(s). *) + run_scripts scriptdir scripts; + + (* Run FUSE. *) + g#mount_local_run (); + + (* Remote temporary directory / mountpoint. *) + if cleanup then rmdir scriptdir + ); + [] + +(* Run the scripts in the background and make sure they call + * fusermount afterwards. + *) +and run_scripts mp scripts = + let sh = "/bin/bash" in + let cmd = + sprintf "\ +set -e +sysprep_unmount () +{ + cd / + count=10 + while ! fusermount -u %s && [ $count -gt 0 ]; do + sleep 1 + ((count--)) + done +} +trap sysprep_unmount INT TERM QUIT EXIT ERR\n" (Filename.quote mp) ^ + String.concat "\n" scripts in + let args = [| sh; "-c"; cmd |] in + + let pid = fork () in + if pid = 0 then ( (* child *) + chdir mp; + execv sh args + ) + +let script_op = { + name = "script"; + pod_description = "\ +The C