-
Notifications
You must be signed in to change notification settings - Fork 601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: propagate host timezone to guest #1931
Conversation
@lobshunter Thanks for the PR. Can you try out setting timezone via cloud-init (via pkg/cidata/) This way it will set for all distro supporting cloud-init. Also will be set early in boot |
We can add If you change the timezone via |
1488564
to
ca37cf0
Compare
Hi, I updated the cloud-init version in the second commit. PTAL which one do you prefer.
It's
I am confused by this actually. Alpine doesn't have cloud-init installed, but it did run the new added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not happy that this PR cannot support timezones with fractional-hours offsets from GMT. E.g. India is GMT+5:30, and there are plenty more.
I wonder if there isn't a way to get an exact match to the host timezone?
Please also address linter errors! |
macOS sets $ readlink /etc/localtime | sed 's#.*zoneinfo/##'
America/Vancouver |
I think this is not what @balajiv113 meant. timezone: US/Eastern You would not need the Please ignore my earlier review and use the proper
It uses |
Yes, will do.
Me neither, but I couldn't find a proper way after digging for half an hour. This is the simplest one I got.
I did try, but the problem is Lima currently supports multiple host platforms (Linux/MacOS/Windows(that's WSL2 IIUC)). Especially for Windows, I didn't find a portable way to get the host timezone. Using Golang's built-in function would be the most portable one, but it doesn't provide the I noticed location timezone can be retrieved in |
Yeah, it is almost impossible to map Windows time zones to IANA (tzdata) time zone names. There is a Python app that seems to implement it. However, I think WSL2 already sets this up by itself, so we may not need this. Well, I saw it set up correctly in Ubuntu, but not in Alpine. I wonder if this would work in Alpine if the tzdata package was installed, but my Windows machine is in a data centre in a different country and seems to have network issues connecting to the Alpine package CDN right now. I don't have time to research this further right now, but if Windows doesn't need to be solved, then the solution might turn out to be simple. |
I gave it one more try, and it did indeed work. After / # cat /etc/timezone
America/Los_Angeles
/ # ls -l /etc/localtime
lrwxrwxrwx 1 root 0 39 Oct 20 22:19 /etc/localtime -> /usr/share/zoneinfo/America/Los_Angeles Which means we don't need to propagate the host timezone to the guest on WSL2. |
fe1705f
to
b5dc0bc
Compare
logrus.Debugf("cannot get timezone from /etc/timezone: %s", err) | ||
|
||
// 3. try to get timezone from /etc/localtime soft link | ||
// base on the assumption that <zoneinfo_basedir>/zone.tab file exists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't found any official documents about zoneinfo data file hierarchy, just assume zone.tab
file exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know either. Right now it seems like a safe assumption, but there are 2 comments in the file that might want us to look for safer alternatives:
# tzdb timezone descriptions (deprecated version)
[...]
# This file is intended as a backward-compatibility aid for older programs.
Maybe we should look for a directory named Antarctica
(or a file named Etc/UTC
) instead?
@lobshunter I see you updated this PR, but it is still marked as a draft. Not sure if you are still working on it or not. When you think it is ready for another review, please move it out of draft mode and re-request a review! |
Signed-off-by: pengyu <lobshunter86@gmail.com>
b5dc0bc
to
d86ad17
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly feel that we don't want to look at TZ
here, plus some additional comments.
tzEnv := os.Getenv("TZ") | ||
if tzEnv != "" && | ||
// skip if TZ is in "std offset dst offset, rule" format | ||
!strings.Contains(tzEnv, " ") { | ||
return tzEnv | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think trying to parse TZ
is futile; there are just too many different possible formats, and different C runtime libraries implement them differently.
Neither of them show any spaces in the "std offset dst offset" format, and I believe spaces are not even allowed optionally.
Furthermore, cloud-init
only allows settings corresponding to zoneinfo entries:
timezone: (string) The timezone to use as represented in /usr/share/zoneinfo
If we want to support importing the TZ
environment variable, then I think it should be optional, and added to /etc/environment
. There is some precedent for doing this (we have logic for proxy settings), but this should be a separate issue, if we decide to do this at all. For this PR I think you should concentrate on synchronizing the /etc/localtime
and /etc/timezone
settings, and nothing else.
logrus.Debugf("cannot get timezone from /etc/timezone: %s", err) | ||
|
||
// 3. try to get timezone from /etc/localtime soft link | ||
// base on the assumption that <zoneinfo_basedir>/zone.tab file exists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know either. Right now it seems like a safe assumption, but there are 2 comments in the file that might want us to look for safer alternatives:
# tzdb timezone descriptions (deprecated version)
[...]
# This file is intended as a backward-compatibility aid for older programs.
Maybe we should look for a directory named Antarctica
(or a file named Etc/UTC
) instead?
tz := strings.TrimPrefix(tzFilePath, baseDir+"/") | ||
_, err = time.LoadLocation(tz) | ||
if err == nil { | ||
return tz | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the check if time.LoadLocation
succeeds is useful. It is the setting that has been configured, so if the datafile somehow got corrupted or deleted, it is not our problem. The interesting question would be if the data file exists inside the VM, and we can't answer that anyways.
If we kept the check, then I would still argue that we need to return ""
in the failure case, and not to keep looking in higher levels of the directory tree; that seems to be wrong either way.
tz := strings.TrimPrefix(tzFilePath, baseDir+"/") | |
_, err = time.LoadLocation(tz) | |
if err == nil { | |
return tz | |
} | |
return strings.TrimPrefix(tzFilePath, baseDir+"/") |
logrus.Debugf("cannot get host timezone from /etc/localtime: %s", err) | ||
|
||
logrus.Warnf("cannot get host timezone") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have only one log message, not 2 at different levels. Since we no longer have the err
value, we should drop the first one.
@lobshunter Could you check comments from @jandubois ? |
@@ -136,6 +137,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort | |||
VMType: *y.VMType, | |||
VSockPort: vsockPort, | |||
Plain: *y.Plain, | |||
Timezone: getHostTimezone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Timezone shouldn't be set when *y.Plain
is true
Thanks for reviewing and sorry for late response. I've been too occupied to work on this PR. All review comments make sense but I won't be able to update and test the code in the short future. It should be better to close this PR :-). |
@@ -370,6 +372,54 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort | |||
return iso9660util.Write(filepath.Join(instDir, filenames.CIDataISO), "cidata", layout) | |||
} | |||
|
|||
// getHostTimezone tries to get host timezone from env or specific files | |||
func getHostTimezone() string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably we could just use https://pkg.go.dev/time#Time.Zone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Tried but it didn't work; time.Now().Zone()
returns "JST" but it is missing in /usr/share/zoneinfo/
)
This PR closes #1921, propagates host timezone to guest VM.
This doesn't work for template://alpine for it doesn't have pre-installed tzdata. And this PR doesn't use timedatectl because some distros might not be using systemd.