From 076cffb5802a01a2908fcc8d0f20b1331e3d4bf5 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 10 Jan 2014 12:12:30 +0000 Subject: [PATCH] sysprep, builder: Add --timezone option to set timezone of guest. You can use it like this: virt-sysprep --timezone Europe/London ... virt-builder --timezone Europe/London ... (cherry picked from commit dd1bfea513658368afd3728e0c5bf8ab6041cd1f) --- builder/Makefile.am | 1 + builder/builder.ml | 12 ++++++- builder/cmdline.ml | 9 ++++- builder/test-virt-builder.sh | 1 + builder/virt-builder.pod | 8 ++++- mllib/Makefile.am | 3 ++ mllib/timezone.ml | 39 +++++++++++++++++++++ mllib/timezone.mli | 22 ++++++++++++ po/POTFILES-ml | 2 ++ sysprep/Makefile.am | 2 ++ sysprep/sysprep_operation_timezone.ml | 66 +++++++++++++++++++++++++++++++++++ 11 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 mllib/timezone.ml create mode 100644 mllib/timezone.mli create mode 100644 sysprep/sysprep_operation_timezone.ml diff --git a/builder/Makefile.am b/builder/Makefile.am index 3f35cc6..fc4c552 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -69,6 +69,7 @@ OBJECTS = \ $(top_builddir)/mllib/urandom.cmx \ $(top_builddir)/mllib/random_seed.cmx \ $(top_builddir)/mllib/hostname.cmx \ + $(top_builddir)/mllib/timezone.cmx \ $(top_builddir)/mllib/firstboot.cmx \ $(top_builddir)/mllib/crypt-c.o \ $(top_builddir)/mllib/crypt.cmx \ diff --git a/builder/builder.ml b/builder/builder.ml index f007b46..90300a3 100644 --- a/builder/builder.ml +++ b/builder/builder.ml @@ -39,7 +39,8 @@ let main () = attach, cache, check_signature, curl, debug, delete, edit, firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, update, upload, writes = + scrub_logfile, size, smp, sources, sync, timezone, update, upload, + writes = parse_cmdline () in (* Timestamped messages in ordinary, non-debug non-quiet mode. *) @@ -619,6 +620,15 @@ let main () = eprintf (f_"%s: warning: hostname could not be set for this type of guest\n%!") prog ); + (* Set the timezone. *) + (match timezone with + | None -> () + | Some timezone -> + msg (f_"Setting the timezone: %s") timezone; + if not (Timezone.set_timezone ~prog g root timezone) then + eprintf (f_"%s: warning: timezone could not be set for this type of guest\n%!") prog + ); + (* Root password. * Note 'None' means that we randomize the root password. *) diff --git a/builder/cmdline.ml b/builder/cmdline.ml index f25280c..813fbd8 100644 --- a/builder/cmdline.ml +++ b/builder/cmdline.ml @@ -169,6 +169,10 @@ let parse_cmdline () = let add_source arg = sources := arg :: !sources in let sync = ref true in + + let timezone = ref None in + let set_timezone s = timezone := Some s in + let update = ref false in let upload = ref [] in @@ -260,6 +264,7 @@ let parse_cmdline () = "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit"; + "--timezone",Arg.String set_timezone, "timezone" ^ " " ^ s_"Set the default timezone"; "--update", Arg.Set update, " " ^ s_"Update core packages"; "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest"; "-v", Arg.Set debug, " " ^ s_"Enable debugging messages"; @@ -321,6 +326,7 @@ read the man page virt-builder(1). let smp = !smp in let sources = List.rev !sources in let sync = !sync in + let timezone = !timezone in let update = !update in let upload = List.rev !upload in let writes = List.rev !writes in @@ -421,4 +427,5 @@ read the man page virt-builder(1). attach, cache, check_signature, curl, debug, delete, edit, firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, update, upload, writes + scrub_logfile, size, smp, sources, sync, timezone, update, upload, + writes diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh index 438f2e9..8d2766a 100755 --- a/builder/test-virt-builder.sh +++ b/builder/test-virt-builder.sh @@ -53,6 +53,7 @@ $VG ./virt-builder phony-fedora \ -v --no-cache --no-check-signature $no_network \ -o $output --size 2G --format $format \ --hostname test.example.com \ + --timezone Europe/London \ --root-password password:123456 \ --mkdir /etc/foo/bar/baz \ --write '/etc/foo/bar/baz/foo:Hello World' \ diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod index f72e284..3558119 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly [--attach ISOFILE] [--root-password SELECTOR] [--hostname HOSTNAME] + [--timezone TIMEZONE] [--update] [--install PKG,[PKG...]] [--mkdir DIR] @@ -583,6 +584,11 @@ Note that you should not point I<--source> to sources that you don't trust (unless the source is signed by someone you do trust). See also the I<--no-network> option. +=item B<--timezone> TIMEZONE + +Set the default timezone of the guest to C. Use a location +string like C + =item B<--update> Do the equivalent of C, C, or whatever @@ -838,7 +844,7 @@ A new random seed is generated for the guest. =item * -The hostname is set (I<--hostname>). +The hostname and timezone are set (I<--hostname>, I<--timezone>). =item * diff --git a/mllib/Makefile.am b/mllib/Makefile.am index 67027d2..5568e02 100644 --- a/mllib/Makefile.am +++ b/mllib/Makefile.am @@ -47,6 +47,8 @@ SOURCES = \ progress.ml \ random_seed.mli \ random_seed.ml \ + timezone.mli \ + timezone.ml \ tty-c.c \ tTY.mli \ tTY.ml \ @@ -77,6 +79,7 @@ OBJECTS = \ urandom.cmx \ random_seed.cmx \ hostname.cmx \ + timezone.cmx \ firstboot.cmx \ tTY.cmx \ fsync.cmx \ diff --git a/mllib/timezone.ml b/mllib/timezone.ml new file mode 100644 index 0000000..8b302d9 --- /dev/null +++ b/mllib/timezone.ml @@ -0,0 +1,39 @@ +(* Set timezone in virt-sysprep and virt-builder. + * Copyright (C) 2014 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 Common_utils + +open Printf + +let set_timezone ~prog (g : Guestfs.guestfs) root timezone = + let typ = g#inspect_get_type root in + + match typ with + (* Every known Linux has /etc/localtime be either a copy of or a + * symlink to a timezone file in /usr/share/zoneinfo. + * Even systemd didn't fuck this up. + *) + | "linux" -> + let target = sprintf "/usr/share/zoneinfo/%s" timezone in + if not (g#exists target) then + error ~prog "timezone '%s' does not exist, use a location like 'Europe/London'" timezone; + g#ln_sf target "/etc/localtime"; + true + + | _ -> + false diff --git a/mllib/timezone.mli b/mllib/timezone.mli new file mode 100644 index 0000000..ad0d4b2 --- /dev/null +++ b/mllib/timezone.mli @@ -0,0 +1,22 @@ +(* Set timezone in virt-sysprep and virt-builder. + * Copyright (C) 2014 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. + *) + +val set_timezone : prog:string -> Guestfs.guestfs -> string -> string -> bool +(** [set_timezone ~prog g root "Europe/London"] sets the default timezone + of the guest. Returns [true] if it was able to set the + timezone or [false] if not. *) diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 8ae6ea9..4c69258 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -21,6 +21,7 @@ mllib/planner.ml mllib/progress.ml mllib/random_seed.ml mllib/tTY.ml +mllib/timezone.ml mllib/uRI.ml mllib/urandom.ml resize/resize.ml @@ -62,6 +63,7 @@ sysprep/sysprep_operation_smolt_uuid.ml sysprep/sysprep_operation_ssh_hostkeys.ml sysprep/sysprep_operation_ssh_userdir.ml sysprep/sysprep_operation_sssd_db_log.ml +sysprep/sysprep_operation_timezone.ml sysprep/sysprep_operation_tmp_files.ml sysprep/sysprep_operation_udev_persistent_net.ml sysprep/sysprep_operation_user_account.ml diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 621d2b6..835d4a6 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -65,6 +65,7 @@ operations = \ ssh_hostkeys \ ssh_userdir \ sssd_db_log \ + timezone \ tmp_files \ udev_persistent_net \ user_account \ @@ -92,6 +93,7 @@ OBJECTS = \ $(top_builddir)/mllib/password.cmx \ $(top_builddir)/mllib/random_seed.cmx \ $(top_builddir)/mllib/hostname.cmx \ + $(top_builddir)/mllib/timezone.cmx \ $(top_builddir)/mllib/firstboot.cmx \ $(top_builddir)/mllib/config.cmx \ sysprep_operation.cmx \ diff --git a/sysprep/sysprep_operation_timezone.ml b/sysprep/sysprep_operation_timezone.ml new file mode 100644 index 0000000..7557f44 --- /dev/null +++ b/sysprep/sysprep_operation_timezone.ml @@ -0,0 +1,66 @@ +(* virt-sysprep + * Copyright (C) 2014 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 Common_utils +open Sysprep_operation +open Common_gettext.Gettext + +module G = Guestfs + +let timezone = ref None + +let timezone_perform (g : Guestfs.guestfs) root = + match !timezone with + | None -> [] + | Some tz -> + if Timezone.set_timezone ~prog g root tz then [ `Created_files ] else [] + +let op = { + defaults with + name = "timezone"; + enabled_by_default = true; + heading = s_"Change the default timezone of the guest"; + + pod_description = Some (s_"\ +This operation changes the default timezone of the guest to the value +given in the I<--timezone> parameter. + +If the I<--timezone> parameter is not given, then the timezone is not +changed. + +This parameter affects the default timezone that users see when they log +in, but they can still change their timezone per-user account."); + + pod_notes = Some (s_"\ +Currently this can only set the timezone on Linux guests."); + + extra_args = [ + let set_timezone str = timezone := Some str in + { extra_argspec = "--timezone", Arg.String set_timezone, s_"timezone" ^ " " ^ s_"New timezone"; + extra_pod_argval = Some "TIMEZONE"; + extra_pod_description = s_"\ +Change the timezone. Use a location string such as C" + } + ]; + + perform_on_filesystems = Some timezone_perform; +} + +let () = register_operation op -- 1.8.4.2