[pve-devel] [PATCH v2 container 2/5] fix #1423: add timezone config option

Oguz Bektas o.bektas at proxmox.com
Wed Jun 17 15:32:30 CEST 2020


optionally enabled.

adds the 'timezone' option to config, which takes a valid timezone (i.e.
Europe/Vienna) to set in the container.

if nothing is selected, then it will show as 'container managed' in
GUI, and nothing will be done.

if set to 'host', the /etc/localtime symlink from the host node will be
cached and set in the container rootfs.

Signed-off-by: Oguz Bektas <o.bektas at proxmox.com>
---

v1->v2:
* s/zone1970/zone/
* use 'pve-ct-timezone' format instead of 'timezone' format directly
* avoid IO if target is already set to correct zone
* create a tmpfile to rename after symlinking, instead of symlinking
/etc/localtime directly

 src/PVE/LXC/Config.pm     | 14 ++++++++++++++
 src/PVE/LXC/Setup.pm      | 13 +++++++++++++
 src/PVE/LXC/Setup/Base.pm | 33 ++++++++++++++++++++++++++++++---
 3 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 8d1854a..29f2cd9 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -444,6 +444,11 @@ my $confdesc = {
 	type => 'string', format => 'address-list',
 	description => "Sets DNS server IP address for a container. Create will automatically use the setting from the host if you neither set searchdomain nor nameserver.",
     },
+    timezone => {
+	optional => 1,
+	type => 'string', format => 'pve-ct-timezone',
+	description => "Time zone to use in the container. If option isn't set, then nothing will be done. Can be set to 'host' to match the host time zone, or an arbitrary time zone option from /usr/share/zoneinfo/zone.tab",
+    },
     rootfs => get_standard_option('pve-ct-rootfs'),
     parent => {
 	optional => 1,
@@ -706,6 +711,15 @@ for (my $i = 0; $i < $MAX_LXC_NETWORKS; $i++) {
     };
 }
 
+PVE::JSONSchema::register_format('pve-ct-timezone', \&verify_ct_timezone);
+sub verify_ct_timezone {
+    my ($timezone, $noerr) = @_;
+
+    return if $timezone eq 'host'; # using host settings
+
+    PVE::JSONSchema::pve_verify_timezone($timezone);
+}
+
 PVE::JSONSchema::register_format('pve-lxc-mp-string', \&verify_lxc_mp_string);
 sub verify_lxc_mp_string {
     my ($mp, $noerr) = @_;
diff --git a/src/PVE/LXC/Setup.pm b/src/PVE/LXC/Setup.pm
index c738e64..0e07796 100644
--- a/src/PVE/LXC/Setup.pm
+++ b/src/PVE/LXC/Setup.pm
@@ -5,6 +5,8 @@ use warnings;
 use POSIX;
 use PVE::Tools;
 
+use Cwd 'abs_path';
+
 use PVE::LXC::Setup::Debian;
 use PVE::LXC::Setup::Ubuntu;
 use PVE::LXC::Setup::CentOS;
@@ -103,6 +105,7 @@ sub new {
 
     # Cache some host files we need access to:
     $plugin->{host_resolv_conf} = PVE::INotify::read_file('resolvconf');
+    $plugin->{host_localtime} = abs_path('/etc/localtime');
 
     # pass on user namespace information:
     my ($id_map, $rootuid, $rootgid) = PVE::LXC::parse_id_maps($conf);
@@ -205,6 +208,16 @@ sub set_dns {
     $self->protected_call($code);
 }
 
+sub set_timezone {
+    my ($self) = @_;
+
+    return if !$self->{plugin}; # unmanaged
+    my $code = sub {
+	$self->{plugin}->set_timezone($self->{conf});
+    };
+    $self->protected_call($code);
+}
+
 sub setup_init {
     my ($self) = @_;
 
diff --git a/src/PVE/LXC/Setup/Base.pm b/src/PVE/LXC/Setup/Base.pm
index 93dace7..d73335b 100644
--- a/src/PVE/LXC/Setup/Base.pm
+++ b/src/PVE/LXC/Setup/Base.pm
@@ -3,6 +3,7 @@ package PVE::LXC::Setup::Base;
 use strict;
 use warnings;
 
+use Cwd 'abs_path';
 use File::stat;
 use Digest::SHA;
 use IO::File;
@@ -451,6 +452,30 @@ my $randomize_crontab = sub {
    }
 };
 
+sub set_timezone {
+    my ($self, $conf) = @_;
+
+    my $zoneinfo = $conf->{timezone};
+
+    return if !defined($zoneinfo);
+
+    my $tz_path = "/usr/share/zoneinfo/$zoneinfo";
+
+    if ($zoneinfo eq 'host') {
+	$tz_path = $self->{host_localtime};
+    }
+
+    return if abs_path('/etc/localtime') eq $tz_path;
+
+    if ($self->ct_file_exists($tz_path)) {
+	my $tmpfile = "localtime.$$.new.tmpfile";
+	$self->ct_symlink($tz_path, $tmpfile);
+	$self->ct_rename($tmpfile, "/etc/localtime");
+    } else {
+	warn "container does not have $tz_path, timezone can not be modified\n";
+    }
+}
+
 sub pre_start_hook {
     my ($self, $conf) = @_;
 
@@ -458,6 +483,7 @@ sub pre_start_hook {
     $self->setup_network($conf);
     $self->set_hostname($conf);
     $self->set_dns($conf);
+    $self->set_timezone($conf);
 
     # fixme: what else ?
 }
@@ -466,16 +492,17 @@ sub post_create_hook {
     my ($self, $conf, $root_password, $ssh_keys) = @_;
 
     $self->template_fixup($conf);
-    
+
     &$randomize_crontab($self, $conf);
-    
+
     $self->set_user_password($conf, 'root', $root_password);
     $self->set_user_authorized_ssh_keys($conf, 'root', $ssh_keys) if $ssh_keys;
     $self->setup_init($conf);
     $self->setup_network($conf);
     $self->set_hostname($conf);
     $self->set_dns($conf);
-    
+    $self->set_timezone($conf);
+
     # fixme: what else ?
 }
 
-- 
2.20.1




More information about the pve-devel mailing list