Skip to content

Commit a4668de

Browse files
committed
Set guest timezone from host setting
Allow explicit override via lima.yaml. Signed-off-by: Jan Dubois <[email protected]>
1 parent 04e3886 commit a4668de

File tree

7 files changed

+53
-5
lines changed

7 files changed

+53
-5
lines changed

examples/default.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ rosetta:
259259
# 🟢 Builtin default: false
260260
binfmt: null
261261

262+
# Specify the timezone name (as used by the zoneinfo database). Specify the empty string
263+
# to not set a timezone in the instance.
264+
# 🟢 Builtin default: use name from /etc/timezone or deduce from symlink target of /etc/localtime
265+
timezone: null
266+
262267
firmware:
263268
# Use legacy BIOS instead of UEFI. Ignored for aarch64.
264269
# 🟢 Builtin default: false

pkg/cidata/cidata.TEMPLATE.d/user-data

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ mounts:
1414
{{- end }}
1515
{{- end }}
1616

17+
{{- if .TimeZone }}
18+
timezone: {{.TimeZone}}
19+
{{- end }}
20+
1721
users:
1822
- name: "{{.User}}"
1923
uid: "{{.UID}}"

pkg/cidata/cidata.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort
136136
VMType: *y.VMType,
137137
VSockPort: vsockPort,
138138
Plain: *y.Plain,
139+
TimeZone: *y.TimeZone,
139140
}
140141

141142
firstUsernetIndex := limayaml.FirstUsernetIndex(y)

pkg/cidata/template.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type TemplateArgs struct {
8282
VMType string
8383
VSockPort int
8484
Plain bool
85+
TimeZone string
8586
}
8687

8788
func ValidateTemplateArgs(args TemplateArgs) error {

pkg/limayaml/defaults.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ import (
99
"path/filepath"
1010
"runtime"
1111
"strconv"
12+
"strings"
1213
"text/template"
1314

1415
"github.com/docker/go-units"
15-
"github.com/lima-vm/lima/pkg/networks"
16-
"github.com/lima-vm/lima/pkg/ptr"
1716
"github.com/pbnjay/memory"
17+
"github.com/sirupsen/logrus"
18+
"golang.org/x/sys/cpu"
1819

1920
"github.com/lima-vm/lima/pkg/guestagent/api"
21+
"github.com/lima-vm/lima/pkg/networks"
2022
"github.com/lima-vm/lima/pkg/osutil"
23+
"github.com/lima-vm/lima/pkg/ptr"
2124
"github.com/lima-vm/lima/pkg/store/dirnames"
2225
"github.com/lima-vm/lima/pkg/store/filenames"
23-
"github.com/sirupsen/logrus"
24-
25-
"golang.org/x/sys/cpu"
2626
)
2727

2828
const (
@@ -83,6 +83,26 @@ func MACAddress(uniqueID string) string {
8383
return hw.String()
8484
}
8585

86+
func hostTimeZone() string {
87+
// WSL2 will automatically set the timezone
88+
if runtime.GOOS != "windows" {
89+
tz, err := os.ReadFile("/etc/timezone")
90+
if err == nil {
91+
return strings.TrimSpace(string(tz))
92+
}
93+
zoneinfoFile, err := filepath.EvalSymlinks("/etc/localtime")
94+
if err == nil {
95+
for baseDir := filepath.Dir(zoneinfoFile); baseDir != "/"; baseDir = filepath.Dir(baseDir) {
96+
if _, err = os.Stat(filepath.Join(baseDir, "Etc/UTC")); err == nil {
97+
return strings.TrimPrefix(zoneinfoFile, baseDir+"/")
98+
}
99+
}
100+
logrus.Warnf("could not locate zoneinfo directory from %q", zoneinfoFile)
101+
}
102+
}
103+
return ""
104+
}
105+
86106
func defaultCPUs() int {
87107
const x = 4
88108
if hostCPUs := runtime.NumCPU(); hostCPUs < x {
@@ -325,6 +345,16 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
325345
}
326346
}
327347

348+
if y.TimeZone == nil {
349+
y.TimeZone = d.TimeZone
350+
}
351+
if o.TimeZone != nil {
352+
y.TimeZone = o.TimeZone
353+
}
354+
if y.TimeZone == nil {
355+
y.TimeZone = ptr.Of(hostTimeZone())
356+
}
357+
328358
if y.SSH.LocalPort == nil {
329359
y.SSH.LocalPort = d.SSH.LocalPort
330360
}
@@ -731,6 +761,7 @@ func fixUpForPlainMode(y *LimaYAML) {
731761
y.Containerd.User = ptr.Of(false)
732762
y.Rosetta.BinFmt = ptr.Of(false)
733763
y.Rosetta.Enabled = ptr.Of(false)
764+
y.TimeZone = ptr.Of("")
734765
}
735766

736767
func executeGuestTemplate(format string) (bytes.Buffer, error) {

pkg/limayaml/defaults_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func TestFillDefault(t *testing.T) {
8585
ForwardX11: ptr.Of(false),
8686
ForwardX11Trusted: ptr.Of(false),
8787
},
88+
TimeZone: ptr.Of(hostTimeZone()),
8889
Firmware: Firmware{
8990
LegacyBIOS: ptr.Of(false),
9091
},
@@ -181,6 +182,7 @@ func TestFillDefault(t *testing.T) {
181182
"-----BEGIN CERTIFICATE-----\nYOUR-ORGS-TRUSTED-CA-CERT\n-----END CERTIFICATE-----\n",
182183
},
183184
},
185+
TimeZone: ptr.Of("Antarctica"),
184186
Firmware: Firmware{
185187
LegacyBIOS: ptr.Of(false),
186188
Images: []FileWithVMType{
@@ -273,6 +275,7 @@ func TestFillDefault(t *testing.T) {
273275
},
274276
}
275277

278+
expect.TimeZone = y.TimeZone
276279
expect.Firmware = y.Firmware
277280

278281
expect.Rosetta = Rosetta{
@@ -320,6 +323,7 @@ func TestFillDefault(t *testing.T) {
320323
ForwardX11: ptr.Of(false),
321324
ForwardX11Trusted: ptr.Of(false),
322325
},
326+
TimeZone: ptr.Of("Zulu"),
323327
Firmware: Firmware{
324328
LegacyBIOS: ptr.Of(true),
325329
Images: []FileWithVMType{
@@ -512,6 +516,7 @@ func TestFillDefault(t *testing.T) {
512516
ForwardX11: ptr.Of(false),
513517
ForwardX11Trusted: ptr.Of(false),
514518
},
519+
TimeZone: ptr.Of("Universal"),
515520
Firmware: Firmware{
516521
LegacyBIOS: ptr.Of(true),
517522
},

pkg/limayaml/limayaml.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type LimaYAML struct {
3939
CACertificates CACertificates `yaml:"caCerts,omitempty" json:"caCerts,omitempty"`
4040
Rosetta Rosetta `yaml:"rosetta,omitempty" json:"rosetta,omitempty"`
4141
Plain *bool `yaml:"plain,omitempty" json:"plain,omitempty"`
42+
TimeZone *string `yaml:"timezone,omitempty" json:"timezone,omitempty"`
4243
}
4344

4445
type (

0 commit comments

Comments
 (0)