From 3339c19a50f9abbb0ffb5457e2fc4c3cfb5c4721 Mon Sep 17 00:00:00 2001 From: Mark D Horn Date: Mon, 22 Oct 2018 16:23:22 -0700 Subject: [PATCH] Set the time zone on target system Signed-off-by: Mark D Horn --- clr-installer/main.go | 5 +++ controller/controller.go | 31 ++++++++++++++++++ model/model.go | 9 +++++ timezone/timezone.go | 71 ++++++++++++++++++++++++++++++++++++++-- tui/timezone.go | 2 +- 5 files changed, 114 insertions(+), 4 deletions(-) diff --git a/clr-installer/main.go b/clr-installer/main.go index 0d40e4b..e5c29dd 100644 --- a/clr-installer/main.go +++ b/clr-installer/main.go @@ -26,6 +26,7 @@ import ( "github.com/clearlinux/clr-installer/model" "github.com/clearlinux/clr-installer/swupd" "github.com/clearlinux/clr-installer/telemetry" + "github.com/clearlinux/clr-installer/timezone" "github.com/clearlinux/clr-installer/tui" ) @@ -204,6 +205,10 @@ func main() { } } + if md.Timezone != nil && !timezone.IsValidTimezone(md.Timezone) { + fatal(fmt.Errorf("Invalid Time Zone '%s'", md.Timezone.Code)) + } + installReboot := false go func() { diff --git a/controller/controller.go b/controller/controller.go index 981d52c..914632e 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -28,6 +28,7 @@ import ( "github.com/clearlinux/clr-installer/storage" "github.com/clearlinux/clr-installer/swupd" "github.com/clearlinux/clr-installer/telemetry" + "github.com/clearlinux/clr-installer/timezone" cuser "github.com/clearlinux/clr-installer/user" "github.com/clearlinux/clr-installer/utils" ) @@ -247,6 +248,10 @@ func Install(rootDir string, model *model.SystemInstall, options args.Args) erro model.AddBundle(telemetry.RequiredBundle) } + if model.Timezone.Code != timezone.DefaultTimezone { + model.AddBundle(timezone.RequiredBundle) + } + if model.KernelArguments != nil && len(model.KernelArguments.Add) > 0 { cmdlineDir := filepath.Join(rootDir, "etc", "kernel") cmdlineFile := filepath.Join(cmdlineDir, "cmdline") @@ -280,6 +285,11 @@ func Install(rootDir string, model *model.SystemInstall, options args.Args) erro return err } + if err = configureTimezone(rootDir, model); err != nil { + // Just log the error, not setting the timezone is not reason to fail the install + log.Error("Error setting timezone: %v", err) + } + if err = cuser.Apply(rootDir, model.Users); err != nil { return err } @@ -479,6 +489,27 @@ func configureNetwork(model *model.SystemInstall) (progress.Progress, error) { return nil, nil } +// configureTimezone applies the model/configured Timezone to the target +func configureTimezone(rootDir string, model *model.SystemInstall) error { + if model.Timezone.Code == timezone.DefaultTimezone { + log.Debug("Skipping setting timezone " + model.Timezone.Code) + return nil + } + + msg := "Setting Timezone to " + model.Timezone.Code + prg := progress.NewLoop(msg) + log.Info(msg) + + err := timezone.SetTargetTimezone(rootDir, model.Timezone.Code) + if err != nil { + prg.Failure() + return err + } + prg.Success() + + return nil +} + // saveInstallResults saves the results of the installation process // onto the target media func saveInstallResults(rootDir string, md *model.SystemInstall) error { diff --git a/model/model.go b/model/model.go index 56d5562..27167f8 100644 --- a/model/model.go +++ b/model/model.go @@ -182,6 +182,10 @@ func (si *SystemInstall) Validate() error { } } + if si.Timezone == nil { + return errors.ValidationErrorf("Timezone not set") + } + if si.Keyboard == nil { return errors.ValidationErrorf("Keyboard not set") } @@ -250,6 +254,11 @@ func LoadFile(path string, options args.Args) (*SystemInstall, error) { } } + // Set default Timezone if not defined + if result.Timezone == nil { + result.Timezone = &timezone.TimeZone{Code: timezone.DefaultTimezone} + } + tmp := map[string]*StorageAlias{} for _, bds := range result.StorageAlias { diff --git a/timezone/timezone.go b/timezone/timezone.go index 9b037f3..e7c2150 100644 --- a/timezone/timezone.go +++ b/timezone/timezone.go @@ -6,9 +6,13 @@ package timezone import ( "bytes" + "fmt" + "path/filepath" "strings" "github.com/clearlinux/clr-installer/cmd" + "github.com/clearlinux/clr-installer/errors" + "github.com/clearlinux/clr-installer/utils" ) // TimeZone represents the system time zone @@ -17,6 +21,18 @@ type TimeZone struct { userDefined bool } +const ( + // DefaultTimezone is the default timezone string + // This is what is set in os-core + DefaultTimezone = "UTC" + + // RequiredBundle the bundle needed to set timezone other than the default + RequiredBundle = "tzdata" +) + +// validTimezones stores the list of all valid, known timezones +var validTimezones []*TimeZone + // IsUserDefined returns true if the configuration was interactively // defined by the user func (tz *TimeZone) IsUserDefined() bool { @@ -52,7 +68,10 @@ func (tz *TimeZone) Equals(comp *TimeZone) bool { // Load uses timedatectl to load the currently available timezones func Load() ([]*TimeZone, error) { - result := []*TimeZone{} + if validTimezones != nil { + return validTimezones, nil + } + validTimezones = []*TimeZone{} w := bytes.NewBuffer(nil) err := cmd.Run(w, "timedatectl", "list-timezones") @@ -70,8 +89,54 @@ func Load() ([]*TimeZone, error) { Code: curr, } - result = append(result, tz) + validTimezones = append(validTimezones, tz) } - return result, nil + return validTimezones, nil +} + +// IsValidTimezone verifies if the given keyboard is valid +func IsValidTimezone(t *TimeZone) bool { + var result = false + + tzs, err := Load() + if err != nil { + return result + } + + for _, curr := range tzs { + if curr.Equals(t) { + result = true + } + } + + return result +} + +// SetTargetTimezone uses creates a symlink to set the timezone on the target +func SetTargetTimezone(rootDir string, timezone string) error { + + tzFile := filepath.Join("/usr/share/zoneinfo", timezone) + targetTzFile := filepath.Join(rootDir, tzFile) + + if ok, err := utils.FileExists(targetTzFile); err != nil || !ok { + return fmt.Errorf("Target timezone file missing") + } + + args := []string{ + "chroot", + rootDir, + "ln", + "-s", + "-r", + tzFile, + "/etc/localtime", + } + + err := cmd.RunAndLog(args...) + if err != nil { + return errors.Wrap(err) + } + + return nil } diff --git a/tui/timezone.go b/tui/timezone.go index c9d2598..997a748 100644 --- a/tui/timezone.go +++ b/tui/timezone.go @@ -102,7 +102,7 @@ func newTimezonePage(tui *Tui) (Page, error) { page.tzListBox.SelectItem(defTimezone) page.activated = page.confirmBtn } else { - page.tzListBox.AddItem("No time zone data found: Defaulting to 'UTC'") + page.tzListBox.AddItem("No time zone data found: Defaulting to '" + timezone.DefaultTimezone + "'") page.activated = page.cancelBtn page.confirmBtn.SetEnabled(false) }