The firstboot infrastructure used to give the firstboot scripts some
cryptic names which were impossible to relate to the actions they were
supposed to take.
This patch reworks the scheme such that the caller registering a
firstboot script has to provide a descriptive name for the action. That
name, with non-alphanumeric characters replaced with dashes, prefixed by
the serial number, is then used as the name of the script, e.g.
0004-install-gcc
or
0002-msiexec--i-foo-msi.bat
OTOH the numbering becomes internal to the API, i.e. the scripts are
numbered and executed in the order they are registered.
This greatly facilitates debugging and troubleshooting in case when
there are multiple firstboot scripts.
Signed-off-by: Roman Kagan <rkagan(a)parallels.com>
---
customize/customize_run.ml | 19 +++++++------------
customize/firstboot.ml | 17 ++++++++++-------
customize/firstboot.mli | 13 ++++++++-----
v2v/convert_windows.ml | 2 +-
4 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 5cc6a6e..980df7e 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -143,9 +143,6 @@ exec >>%s 2>&1
if not (Random_seed.set_random_seed g root) then
warning (f_"random seed could not be set for this type of guest");
- (* Used for numbering firstboot commands. *)
- let i = ref 0 in
-
(* Store the passwords and set them all at the end. *)
let passwords = Hashtbl.create 13 in
let set_password user pw =
@@ -191,22 +188,20 @@ exec >>%s 2>&1
Perl_edit.edit_file ~verbose g#ocaml_handle path expr
| `FirstbootCommand cmd ->
- incr i;
- msg (f_"Installing firstboot command: [%d] %s") !i cmd;
- Firstboot.add_firstboot_script g root !i cmd
+ msg (f_"Installing firstboot command: %s") cmd;
+ Firstboot.add_firstboot_script g root cmd cmd
| `FirstbootPackages pkgs ->
- incr i;
- msg (f_"Installing firstboot packages: [%d] %s") !i
+ msg (f_"Installing firstboot packages: %s")
(String.concat " " pkgs);
let cmd = guest_install_command pkgs in
- Firstboot.add_firstboot_script g root !i cmd
+ let name = String.concat " " ("install" :: pkgs) in
+ Firstboot.add_firstboot_script g root name cmd
| `FirstbootScript script ->
- incr i;
- msg (f_"Installing firstboot script: [%d] %s") !i script;
+ msg (f_"Installing firstboot script: %s") script;
let cmd = read_whole_file script in
- Firstboot.add_firstboot_script g root !i cmd
+ Firstboot.add_firstboot_script g root script cmd
| `Hostname hostname ->
msg (f_"Setting the hostname: %s") hostname;
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index f529462..b12d616 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -27,6 +27,9 @@ open Regedit
let unix2dos s =
String.concat "\r\n" (Str.split_delim (Str.regexp_string "\n") s)
+let sanitize_name n =
+ Str.global_replace (Str.regexp "[^A-Za-z0-9_]") "-" n
+
(* For Linux guests. *)
module Linux = struct
let firstboot_dir = "/usr/lib/virt-sysprep"
@@ -289,23 +292,23 @@ rhsrvany.exe -s firstboot uninstall
end
-let add_firstboot_script (g : Guestfs.guestfs) root i content =
+let script_count = ref 0
+
+let add_firstboot_script (g : Guestfs.guestfs) root name content =
let typ = g#inspect_get_type root in
let distro = g#inspect_get_distro root in
+ incr script_count;
+ let filename = sprintf "%04d-%s" !script_count (sanitize_name name) in
match typ, distro with
| "linux", _ ->
Linux.install_service g distro;
- let t = Int64.of_float (Unix.time ()) in
- let r = string_random8 () in
- let filename = sprintf "%s/scripts/%04d-%Ld-%s" Linux.firstboot_dir i t r
in
+ let filename = Linux.firstboot_dir // "scripts" // filename in
g#write filename content;
g#chmod 0o755 filename
| "windows", _ ->
let firstboot_dir = Windows.install_service g root in
- let t = Int64.of_float (Unix.time ()) in
- let r = string_random8 () in
- let filename = sprintf "%s/scripts/%04d-%Ld-%s.bat" firstboot_dir i t r in
+ let filename = firstboot_dir // "scripts" // filename ^ ".bat"
in
g#write filename (unix2dos content)
| _ ->
diff --git a/customize/firstboot.mli b/customize/firstboot.mli
index 5f2fae5..d7556e7 100644
--- a/customize/firstboot.mli
+++ b/customize/firstboot.mli
@@ -16,13 +16,16 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
-val add_firstboot_script : Guestfs.guestfs -> string -> int -> string ->
unit
- (** [add_firstboot_script g root idx content] adds a firstboot
- script called [shortname] containing [content].
+val add_firstboot_script : Guestfs.guestfs -> string -> string -> string ->
unit
+ (** [add_firstboot_script g root name content] adds a firstboot
+ script called [name] containing [content].
- NB. [content] is the contents of the script, {b not} a filename.
+ [content] is the contents of the script, {b not} a filename.
- The scripts run in index ([idx]) order.
+ The actual name of the script on the guest filesystem is made of [name]
+ with all characters but alphanumeric replaced with dashes.
+
+ The scripts are run in the order they are registered.
For Linux guests using SELinux you should make sure the
filesystem is relabelled after calling this. *)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 4e60e31..a3c7152 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -148,7 +148,7 @@ let convert ~verbose ~keep_serial_console (g : G.guestfs) inspect
source =
(* Write the completed script to the guest. *)
let firstboot_script = Buffer.contents fb in
- Firstboot.add_firstboot_script g inspect.i_root 1 firstboot_script
+ Firstboot.add_firstboot_script g inspect.i_root "firstboot"
firstboot_script
and configure_rhev_apt fb =
(* Configure RHEV-APT (the RHEV guest agent). However if it doesn't
--
2.1.0