From b4e446c21e299af0441ec44db7a86334980b77c2 Mon Sep 17 00:00:00 2001 From: Angelo Naselli Date: Mon, 16 Mar 2015 19:20:40 +0100 Subject: Moved the tree accordingly --- lib/ManaTools/Shared/TimeZone.pm | 799 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 799 insertions(+) create mode 100644 lib/ManaTools/Shared/TimeZone.pm (limited to 'lib/ManaTools/Shared/TimeZone.pm') diff --git a/lib/ManaTools/Shared/TimeZone.pm b/lib/ManaTools/Shared/TimeZone.pm new file mode 100644 index 0000000..efb49a2 --- /dev/null +++ b/lib/ManaTools/Shared/TimeZone.pm @@ -0,0 +1,799 @@ +# vim: set et ts=4 sw=4: +package ManaTools::Shared::TimeZone; + +#============================================================= -*-perl-*- + +=head1 NAME + +ManaTools::Shared::TimeZone - module to manage TimeZone settings + +=head1 SYNOPSIS + + my $tz = ManaTools::Shared::TimeZone->new(); + + +=head1 DESCRIPTION + +This module allows to manage time zone settings. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command: + +perldoc ManaTools::Shared::TimeZone + + +=head1 AUTHOR + +Angelo Naselli + +=head1 COPYRIGHT and LICENSE + +Copyright (C) 2014-2015, Angelo Naselli. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2, as +published by the Free Software Foundation. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +=head1 METHODS + +=cut + + +use diagnostics; +use strict; + +use Moose; + +use DateTime::TimeZone; +use Net::DBus; + +use ManaTools::Shared::Locales; +use ManaTools::Shared::Services; + +use MDK::Common::File qw(cat_ output_p substInFile); +use MDK::Common::Func qw(find if_); + + +#============================================================= + +=head2 new - optional parameters + +=head3 timezone_prefix + + optional parameter to set the system timezone directory, + default value is /usr/share/zoneinfo + +=cut + +#============================================================= + +has 'timezone_prefix' => ( + is => 'rw', + isa => 'Str', + default => "/usr/share/zoneinfo", +); + + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_configuration_file + + optional parameter to set the ntp server configuration file, + default value is /etc/[chrony|ntp].conf + +=cut + +#============================================================= + +has 'ntp_configuration_file' => ( + is => 'rw', + isa => 'Str', + builder => '_ntp_configuration_file_init', +); + +sub _ntp_configuration_file_init { + my $self = shift; + + if (-f "/etc/chrony.conf") { + return "/etc/chrony.conf"; + } + return "/etc/ntp.conf"; +} + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_conf_dir + + optional parameter to set ntp configuration directory, + default value is /etc/ntp + +=cut + +#============================================================= + +has 'ntp_conf_dir' => ( + is => 'rw', + isa => 'Str', + lazy => 1, + default => "/etc/ntp", +); + +#============================================================= + +=head2 new - optional parameters + +=head3 ntp_program + + optional parameter to set the ntp program that runs into the + system, default value is [chrony|ntp] + +=cut + +#============================================================= +has 'ntp_program' => ( + is => 'rw', + isa => 'Str', + builder => '_ntp_program_init', +); + +sub _ntp_program_init { + my $self = shift; + + if (-f "/etc/chrony.conf") { + return "chrony"; + } + return "ntp"; +} + +#============================================================= + +=head2 new - optional parameters + +=head3 installer_or_livecd + + To inform the back-end that is working during installer or + livecd. Useful if Time zone setting and using fix_system + to use the real time clock (see setLocalRTC and + writeConfiguration). + +=cut + +#============================================================= +has 'installer_or_livecd' => ( + is => 'rw', + isa => 'Bool', + default => 0, +); + +#=== globals === + +has 'sh_services' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_SharedServicesInitialize' +); + +sub _SharedServicesInitialize { + my $self = shift(); + + $self->sh_services(ManaTools::Shared::Services->new() ); +} + + +has 'dbus_timedate1_service' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusTimeDateInitialize' +); + +sub _dbusTimeDateInitialize { + my $self = shift(); + + my $bus = Net::DBus->system; + $self->dbus_timedate1_service($bus->get_service("org.freedesktop.timedate1")); +} + + +has 'dbus_timedate1_object' => ( + is => 'rw', + init_arg => undef, + lazy => 1, + builder => '_dbusObjectInitialize' +); + +sub _dbusObjectInitialize { + my $self = shift(); + + $self->dbus_timedate1_object($self->dbus_timedate1_service->get_object("/org/freedesktop/timedate1")); +} + + +has 'servername_config_suffix' => ( + is => 'ro', + isa => 'Str', + lazy => 1, + builder => '_servername_config_suffix_init', +); + +sub _servername_config_suffix_init { + my $self = shift; + + return " iburst" if ($self->ntp_program eq "chrony"); + + return ""; +} + +has 'loc' => ( + is => 'rw', + lazy => 1, + init_arg => undef, + builder => '_localeInitialize' +); + +sub _localeInitialize { + my $self = shift; + + # TODO fix domain binding for translation + $self->loc(ManaTools::Shared::Locales->new(domain_name => 'libDrakX') ); + # TODO if we want to give the opportunity to test locally add dir_name => 'path' +} + + +has 'ntp_servers' => ( + traits => ['Hash'], + is => 'rw', + isa => 'HashRef', + lazy => 1, + handles => { + get_ntp_server => 'get', + ntp_server_pairs => 'kv', + }, + init_arg => undef, + builder => '_buildNTPServers' +); + +sub _buildNTPServers { + my $self = shift; + + my %ntpServersHash; + $ntpServersHash{"-"} = { + $self->loc->N_("Global") => "pool.ntp.org", + }; + $ntpServersHash{Global} = { + $self->loc->N_("Africa") => "africa.pool.ntp.org", + $self->loc->N_("Asia") => "asia.pool.ntp.org", + $self->loc->N_("Europe") => "europe.pool.ntp.org", + $self->loc->N_("North America") => "north-america.pool.ntp.org", + $self->loc->N_("Oceania") => "oceania.pool.ntp.org", + $self->loc->N_("South America") => "south-america.pool.ntp.org", + }; + $ntpServersHash{Africa} = { + $self->loc->N_("South Africa") => "za.pool.ntp.org", + $self->loc->N_("Tanzania") => "tz.pool.ntp.org", + }; + $ntpServersHash{Asia} = { + $self->loc->N_("Bangladesh") => "bd.pool.ntp.org", + $self->loc->N_("China") => "cn.pool.ntp.org", + $self->loc->N_("Hong Kong") => "hk.pool.ntp.org", + $self->loc->N_("India") => "in.pool.ntp.org", + $self->loc->N_("Indonesia") => "id.pool.ntp.org", + $self->loc->N_("Iran") => "ir.pool.ntp.org", + $self->loc->N_("Israel") => "il.pool.ntp.org", + $self->loc->N_("Japan") => "jp.pool.ntp.org", + $self->loc->N_("Korea") => "kr.pool.ntp.org", + $self->loc->N_("Malaysia") => "my.pool.ntp.org", + $self->loc->N_("Philippines") => "ph.pool.ntp.org", + $self->loc->N_("Singapore") => "sg.pool.ntp.org", + $self->loc->N_("Taiwan") => "tw.pool.ntp.org", + $self->loc->N_("Thailand") => "th.pool.ntp.org", + $self->loc->N_("Turkey") => "tr.pool.ntp.org", + $self->loc->N_("United Arab Emirates") => "ae.pool.ntp.org", + }; + $ntpServersHash{Europe} = { + $self->loc->N_("Austria") => "at.pool.ntp.org", + $self->loc->N_("Belarus") => "by.pool.ntp.org", + $self->loc->N_("Belgium") => "be.pool.ntp.org", + $self->loc->N_("Bulgaria") => "bg.pool.ntp.org", + $self->loc->N_("Czech Republic") => "cz.pool.ntp.org", + $self->loc->N_("Denmark") => "dk.pool.ntp.org", + $self->loc->N_("Estonia") => "ee.pool.ntp.org", + $self->loc->N_("Finland") => "fi.pool.ntp.org", + $self->loc->N_("France") => "fr.pool.ntp.org", + $self->loc->N_("Germany") => "de.pool.ntp.org", + $self->loc->N_("Greece") => "gr.pool.ntp.org", + $self->loc->N_("Hungary") => "hu.pool.ntp.org", + $self->loc->N_("Ireland") => "ie.pool.ntp.org", + $self->loc->N_("Italy") => "it.pool.ntp.org", + $self->loc->N_("Lithuania") => "lt.pool.ntp.org", + $self->loc->N_("Luxembourg") => "lu.pool.ntp.org", + $self->loc->N_("Netherlands") => "nl.pool.ntp.org", + $self->loc->N_("Norway") => "no.pool.ntp.org", + $self->loc->N_("Poland") => "pl.pool.ntp.org", + $self->loc->N_("Portugal") => "pt.pool.ntp.org", + $self->loc->N_("Romania") => "ro.pool.ntp.org", + $self->loc->N_("Russian Federation") => "ru.pool.ntp.org", + $self->loc->N_("Slovakia") => "sk.pool.ntp.org", + $self->loc->N_("Slovenia") => "si.pool.ntp.org", + $self->loc->N_("Spain") => "es.pool.ntp.org", + $self->loc->N_("Sweden") => "se.pool.ntp.org", + $self->loc->N_("Switzerland") => "ch.pool.ntp.org", + $self->loc->N_("Ukraine") => "ua.pool.ntp.org", + $self->loc->N_("United Kingdom") => "uk.pool.ntp.org", + $self->loc->N_("Yugoslavia") => "yu.pool.ntp.org", + }; + $ntpServersHash{"North America"} = { + $self->loc->N_("Canada") => "ca.pool.ntp.org", + $self->loc->N_("Guatemala") => "gt.pool.ntp.org", + $self->loc->N_("Mexico") => "mx.pool.ntp.org", + $self->loc->N_("United States") => "us.pool.ntp.org", + }; + $ntpServersHash{Oceania} = { + $self->loc->N_("Australia") => "au.pool.ntp.org", + $self->loc->N_("New Zealand") => "nz.pool.ntp.org", + }; + $ntpServersHash{"South America"} = { + $self->loc->N_("Argentina") => "ar.pool.ntp.org", + $self->loc->N_("Brazil") => "br.pool.ntp.org", + $self->loc->N_("Chile") => "cl.pool.ntp.org", + }; + + return \%ntpServersHash; +} + + +#============================================================= + +=head2 get_timezone_prefix + +=head3 OUTPUT + +timezone_prefix: directory in which time zone files are + +=head3 DESCRIPTION + +Return the timezone directory (defualt: /usr/share/zoneinfo) + +=cut + +#============================================================= +sub get_timezone_prefix { + my $self = shift; + + return $self->timezone_prefix; +} + +#============================================================= + +=head2 getTimeZones + +=head3 INPUT + + $from_system: if present and its value is not 0 checks into timezone_prefix + directory and gets the list from there + +=head3 OUTPUT + + @l: ARRAY containing sorted time zones + +=head3 DESCRIPTION + + This method returns the available timezones + +=cut + +#============================================================= +sub getTimeZones { + my ($self, $from_system) = @_; + + if ($from_system and $from_system != 0) { + require MDK::Common::DataStructure; + require MDK::Common::Various; + my $tz_prefix = $self->get_timezone_prefix(); + open(my $F, "cd $tz_prefix && find [A-Z]* -noleaf -type f |"); + my @l = MDK::Common::DataStructure::difference2([ MDK::Common::Various::chomp_(<$F>) ], [ 'ROC', 'PRC' ]); + close $F or die "cannot list the available zoneinfos"; + return sort @l; + } + + return DateTime::TimeZone->all_names; +} + +#============================================================= + +=head2 setTimeZone + +=head3 INPUT + + $new_time_zone: New time zone to be set + +=head3 DESCRIPTION + + This method get the new time zone to set and performs + the setting + +=cut + +#============================================================= +sub setTimeZone { + my ($self, $new_time_zone) = @_; + + die "Time zone value required" if !defined($new_time_zone); + + my $object = $self->dbus_timedate1_object; + $object->SetTimezone($new_time_zone, 1); +} + +#============================================================= + +=head2 getTimeZone + +=head3 OUTPUT + + $timezone: current time zone + +=head3 DESCRIPTION + + This method returns the current timezone setting + +=cut + +#============================================================= +sub getTimeZone { + my ($self) = @_; + + my $object = $self->dbus_timedate1_object; + + return $object->Get("org.freedesktop.timedate1", 'Timezone') || ""; +} + + +#============================================================= + +=head2 setLocalRTC + +=head3 INPUT + + $enable: bool value enable/disable real time clock as + localtime + $fix_system: bool read or not the real time clock + +=head3 DESCRIPTION + + This method enables/disables the real time clock as + localtime (e.g. disable means set the rtc to UTC). + NOTE from dbus: + Use SetLocalRTC() to control whether the RTC is in + local time or UTC. It is strongly recommended to maintain + the RTC in UTC. Some OSes (Windows) however maintain the + RTC in local time which might make it necessary to enable + this feature. However, this creates various problems as + daylight changes might be missed. If fix_system is passed + "true" the time from the RTC is read again and the system + clock adjusted according to the new setting. + If fix_system is passed "false" the system time is written + to the RTC taking the new setting into account. + Use fix_system=true in installers and livecds where the + RTC is probably more reliable than the system time. + Use fix_system=false in configuration UIs that are run during + normal operation and where the system clock is probably more + reliable than the RTC. + +=cut + +#============================================================= +sub setLocalRTC { + my ($self, $enable, $fix_system) = @_; + + die "Localtime enable/disable value required" if !defined($enable); + + $fix_system = 0 if !defined($fix_system); + my $object = $self->dbus_timedate1_object; + $object->SetLocalRTC($enable, $fix_system, 1) ; +} + +#============================================================= + +=head2 getLocalRTC + +=head3 OUTPUT + + $localRTC: 1 if RTC is localtime 0 for UTC + +=head3 DESCRIPTION + + This method returns the RTC localtime setting + +=cut + +#============================================================= +sub getLocalRTC { + my $self = shift; + + my $object = $self->dbus_timedate1_object; + + return $object->Get("org.freedesktop.timedate1", 'LocalRTC') ? 1 : 0; +} + + +#============================================================= + +=head2 setTime + +=head3 INPUT + + $sec_since_epoch: Time in seconds since 1/1/1970 + +=head3 DESCRIPTION + + This method set the system time and sets the RTC also + +=cut + +#============================================================= +sub setTime { + my ($self, $sec_since_epoch) = @_; + + die "second since epoch required" if !defined($sec_since_epoch); + + my $object = $self->dbus_timedate1_object; + my $usec = $sec_since_epoch* 1000000; + + $object->SetTime($usec, 0, 1); +} + +#============================================================= + +=head2 readConfiguration + +=head3 OUTPUT + + hash reference containing: + UTC => HW clock is set as UTC + ZONE => Time Zone set + +=head3 DESCRIPTION + + This method returns the time zone system settings as hash + reference + +=cut + +#============================================================= +sub readConfiguration { + my $self = shift; + + my $prefs = {}; + $prefs->{'ZONE'} = $self->getTimeZone(); + $prefs->{'UTC'} = $self->getLocalRTC() ? 0 : 1; + + return $prefs; +} + + +#============================================================= + +=head2 writeConfiguration + +=head3 INPUT + + $info: hash containing: + UTC => HW clock is set as UTC + ZONE => Time Zone + +=head3 DESCRIPTION + + This method sets the passed Time Zone configuration. + If installer_or_livecd attribute is set fix_system is + passed to setLocalRTC + +=cut + +#============================================================= +sub writeConfiguration { + my ($self, $info) = @_; + + die "UTC field required" if !defined($info->{UTC}); + die "ZONE field required" if !defined($info->{ZONE}); + + my $localRTC = $info->{UTC} ? 0 : 1; + $self->setLocalRTC( + $localRTC, + $self->installer_or_livecd + ); + + $self->setTimeZone( + $info->{ZONE} + ); +} + + +#left for back compatibility +sub _get_ntp_server_tree { + my ($self, $zone) = @_; + $zone = "-" if ! $zone; + my $ns = $self->get_ntp_server($zone); + return if !$ns; + + map { + $ns->{$_} => ( + $self->get_ntp_server($_) ? + $zone ? + $self->loc->N($_) . "|" . $self->loc->N("All servers") : + $self->loc->N("All servers") : + $self->loc->N($zone) . "|" . $self->loc->N($_) + ), + $self->_get_ntp_server_tree($_) + } keys %{$ns}; +} + +#============================================================= + +=head2 ntpServers + +=head3 OUTPUT + + HASHREF containing ntp_server => zone info + +=head3 DESCRIPTION + + This method returns an hash ref containing pairs ntp-server, zone + +=cut + +#============================================================= +sub ntpServers { + my ($self) = @_; + # FIXME: missing parameter: + +{$self->_get_ntp_server_tree()}; +} + + +#============================================================= + +=head2 ntpCurrentServer + +=head3 INPUT + +Input_Parameter: in_par_description + +=head3 DESCRIPTION + +Returns the current ntp server address read from configuration file + +=cut + +#============================================================= + +sub ntpCurrentServer { + my $self = shift; + + MDK::Common::Func::find { $_ ne '127.127.1.0' } map { MDK::Common::Func::if_(/^\s*server\s+(\S*)/, $1) } MDK::Common::File::cat_($self->ntp_configuration_file); +} + +#============================================================= + +=head2 isNTPRunning + +=head3 DESCRIPTION + + This method just returns if the given ntp server is running + +=cut + +#============================================================= +sub isNTPRunning { + my $self = shift; + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + return $self->sh_services->is_service_running($ntpd); +} + +#============================================================= + +=head2 setNTPServer + +=head3 INPUT + +$server: server address to be configured + +=head3 DESCRIPTION + +This method writes into NTP configuration file new server address +settings + +=cut + +#============================================================= +sub setNTPServer { + my ($self, $server) = @_; + + my $f = $self->ntp_configuration_file; + -f $f or return; + return if (!$server); + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + ManaTools::Shared::disable_x_screensaver(); + if ($self->isNTPRunning()) { + $self->sh_services->stopService($ntpd); + } + + my $pool_match = qr/\.pool\.ntp\.org$/; + my @servers = $server =~ $pool_match ? (map { "$_.$server" } 0 .. 2) : $server; + + my $added = 0; + my $servername_config_suffix = $self->servername_config_suffix ? $self->servername_config_suffix : " "; + MDK::Common::File::substInFile { + if (/^#?\s*server\s+(\S*)/ && $1 ne '127.127.1.0') { + $_ = $added ? $_ =~ $pool_match ? undef : "#server $1\n" : join('', map { "server $_$servername_config_suffix\n" } @servers); + $added = 1; + } + } $f; + if ($self->ntp_program eq "ntp") { + my $ntp_prefix = $self->ntp_conf_dir; + MDK::Common::File::output_p("$ntp_prefix/step-tickers", join('', map { "$_\n" } @servers)); + } + + # enable but do not start the service + $self->sh_services->set_status($ntpd, 1, 1); + if ($ntpd eq "chronyd") { + $self->sh_services->startService($ntpd); + $ENV{PATH} = "/usr/bin:/usr/sbin"; + # Wait up to 30s for sync + system('/usr/bin/chronyc', 'waitsync', '30', '0.1'); + } else { + $ENV{PATH} = "/usr/bin:/usr/sbin"; + system('/usr/sbin/ntpdate', $server); + $self->sh_services->startService($ntpd); + } + + ManaTools::Shared::enable_x_screensaver(); +} + +#============================================================= + +=head2 disableAndStopNTP + +=head3 DESCRIPTION + + Disable and stop the ntp server + +=cut + +#============================================================= +sub disableAndStopNTP { + my $self = shift; + + # TODO is that valid for any ntp program? adding ntp_service_name parameter + my $ntpd = $self->ntp_program . 'd'; + + # also stop the service without dont_apply parameter + $self->sh_services->set_status($ntpd, 0); +} + +no Moose; +__PACKAGE__->meta->make_immutable; + + +1; + + -- cgit v1.2.1