Skip to content

Commit

Permalink
Merge pull request #99 from yast/readonly-timezone-casp
Browse files Browse the repository at this point in the history
Set timezone as read-only
  • Loading branch information
imobachgs committed Dec 13, 2016
2 parents b8509e2 + b9f5f6b commit e72f58c
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 8 deletions.
13 changes: 13 additions & 0 deletions package/yast2-country.changes
@@ -1,3 +1,16 @@
-------------------------------------------------------------------
Tue Dec 13 09:03:47 UTC 2016 - igonzalezsosa@suse.com

- Improve code/documentation regarding FATE#321754
- 3.1.33

-------------------------------------------------------------------
Fri Dec 9 10:09:53 UTC 2016 - igonzalezsosa@suse.com

- Add support to set the timezone as read-only in the product's
control file (FATE#321754)
- 3.1.32

-------------------------------------------------------------------
Wed Nov 23 13:41:41 CET 2016 - schubi@suse.de

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-country.spec
Expand Up @@ -17,7 +17,7 @@


Name: yast2-country
Version: 3.1.31
Version: 3.1.33
Release: 0

BuildRoot: %{_tmppath}/%{name}-%{version}-build
Expand Down
8 changes: 8 additions & 0 deletions timezone/src/clients/inst_timezone.rb
Expand Up @@ -23,6 +23,8 @@
# $Id$
module Yast
class InstTimezoneClient < Client
include Yast::Logger

def main
Yast.import "UI"
Yast.import "GetInstArgs"
Expand All @@ -35,6 +37,12 @@ def main
@args = GetInstArgs.argmap
@args["first_run"] = "yes" unless @args["first_run"] == "no"

if Timezone.readonly
# Do not run if timezone is readonly
log.info "Timezone is read-only for this product so the inst_timezone client is skipped"
return :auto
end

if Stage.initial &&
Ops.greater_than(
Builtins.size(Storage.GetWinPrimPartitions(Storage.GetTargetMap)),
Expand Down
53 changes: 46 additions & 7 deletions timezone/src/modules/Timezone.rb
Expand Up @@ -29,6 +29,8 @@

module Yast
class TimezoneClass < Module
include Yast::Logger

def main
textdomain "country"

Expand Down Expand Up @@ -163,6 +165,10 @@ def main

# remember if /sbin/hwclock --hctosys was called, it can be done only once (bnc#584484)
@systz_called = false

# timezone is read-only
@readonly = nil

Timezone()
end

Expand Down Expand Up @@ -245,20 +251,25 @@ def get_zonemap
# @return the number of the region that contains the timezone
#
def Set(zone, really)
zmap = get_zonemap
# Do not update the timezone if it's forced and it was already set
if (Mode.installation || Mode.update) && readonly && !@timezone.empty?
log.info "Timezone is read-only and cannot be changed during installation"
else
# Set the new timezone internally
@timezone = zone
end

# Set the new timezone internally
@timezone = zone
zmap = get_zonemap

sel = 0
while Ops.less_than(sel, Builtins.size(zmap)) &&
!Builtins.haskey(Ops.get_map(zmap, [sel, "entries"], {}), zone)
!Builtins.haskey(Ops.get_map(zmap, [sel, "entries"], {}), @timezone)
sel = Ops.add(sel, 1)
end

@name = Ops.add(
Ops.add(Ops.get_string(zmap, [sel, "name"], ""), " / "),
Ops.get_string(zmap, [sel, "entries", zone], zone)
Ops.get_string(zmap, [sel, "entries", @timezone], @timezone)
)

# Adjust system to the new timezone.
Expand Down Expand Up @@ -431,9 +442,14 @@ def Timezone
@hwclock = "-u"
if Stage.initial && !Mode.live_installation
# language --> timezone database, e.g. "de_DE" : "Europe/Berlin"
lang2tz = get_lang2tz
new_timezone =
if readonly
product_default_timezone
else
lang2tz = get_lang2tz
Ops.get(lang2tz, Language.language, "")
end

new_timezone = Ops.get(lang2tz, Language.language, "")
Builtins.y2milestone("Timezone new_timezone %1", new_timezone)

Set(new_timezone, true) if new_timezone != ""
Expand Down Expand Up @@ -984,6 +1000,29 @@ def Summary
HTML.List(ret)
end

# Determines whether timezone is read-only for the current product
#
# @return [Boolean] true if it's read-only; false otherwise.
def readonly
return @readonly unless @readonly.nil?
@readonly = ProductFeatures.GetBooleanFeature("globals", "readonly_timezone")
end

# Product's default timezone when it's not defined in the control file.
FALLBACK_PRODUCT_DEFAULT_TIMEZONE = "UTC"

# Determines the default timezone for the current product
#
# If not timezone is set, FALLBACK_PRODUCT_DEFAULT_TIMEZONE will be used.
# More information can be found on FATE#321754 and
# https://github.com/yast/yast-installation/blob/master/doc/control-file.md#installation-and-product-variables
#
# @return [String] timezone
def product_default_timezone
product_timezone = ProductFeatures.GetStringFeature("globals", "timezone")
product_timezone.empty? ? FALLBACK_PRODUCT_DEFAULT_TIMEZONE : product_timezone
end

publish :variable => :timezone, :type => "string"
publish :variable => :hwclock, :type => "string"
publish :variable => :default_timezone, :type => "string"
Expand Down
118 changes: 118 additions & 0 deletions timezone/test/Timezone_test.rb
Expand Up @@ -3,8 +3,23 @@
require_relative "test_helper"

Yast.import "Timezone"
Yast.import "ProductFeatures"

describe Yast::Timezone do
let(:readonly_timezone) { false }
let(:default_timezone) { "" }
let(:initial) { false }

before do
allow(Yast::ProductFeatures).to receive(:GetBooleanFeature)
.with("globals", "readonly_timezone").and_return(readonly_timezone)
allow(Yast::ProductFeatures).to receive(:GetStringFeature)
.with("globals", "timezone").and_return(default_timezone)
allow(Yast::Stage).to receive(:initial).and_return(initial)
Yast::Timezone.main
end

subject { Yast::Timezone }

describe "#ProposeLocaltime" do
subject { Yast::Timezone.ProposeLocaltime }
Expand Down Expand Up @@ -44,4 +59,107 @@
end

end

describe "#timezone" do
context "when timezone is read-only during installation" do
let(:readonly_timezone) { true }
let(:initial) { true }

it "returns 'UTC'" do
expect(subject.timezone).to eq("UTC")
end

context "and default timezone is set" do
let(:default_timezone) { "Atlantic/Canary" }

it "returns the default timezone" do
expect(subject.timezone).to eq("Atlantic/Canary")
end
end
end
end

describe "#Set" do
before do
allow(Yast::Misc).to receive(:SysconfigRead).with(Yast::Path.new(".sysconfig.clock.TIMEZONE"))
.and_return("Europe/Berlin")
allow(Yast::Misc).to receive(:SysconfigRead).and_call_original
allow(Yast::FileUtils).to receive(:IsLink).with("/etc/localtime").and_return(false)
end

it "returns the region number" do
expect(subject.Set("Atlantic/Canary", false)).to eq(3)
end

it "modifies the timezone" do
subject.Set("Atlantic/Canary", false)
expect(subject.timezone).to eq("Atlantic/Canary")
end

context "when timezone is read-only during installation" do
let(:readonly_timezone) { true }
let(:installation) { true }
let(:initial) { true }

before do
allow(Yast::Mode).to receive(:installation).and_return(true)
end

it "returns the region number" do
expect(subject.Set("Atlantic/Canary", false)).to eq(10) # UTC
end

it "does not modify the timezone" do
subject.Set("Atlantic/Canary", false)
expect(subject.timezone).to eq("UTC")
end
end

context "when timezone is read-only in a running system" do
let(:readonly_timezone) { true }

it "returns the region number" do
expect(subject.Set("Atlantic/Canary", false)).to eq(3) # Atlantic
end

it "modifies the timezone" do
subject.Set("Atlantic/Canary", false)
expect(subject.timezone).to eq("Atlantic/Canary")
end
end
end

describe "#readonly" do
context "when timezone is read-only" do
let(:readonly_timezone) { true }

it "returns true" do
expect(subject.readonly).to eq(true)
end
end

context "when timezone is not read-only" do
let(:readonly_timezone) { false }

it "returns false" do
expect(subject.readonly).to eq(false)
end
end
end

describe "#product_default_timezone" do
let(:default_timezone) { "Atlantic/Canary" }

it "returns the globals/timezone feature" do
expect(subject.product_default_timezone).to eq(default_timezone)
end

context "when globals/timezone is not set" do
let(:default_timezone) { "" }

it "returns 'UTC'" do
expect(subject.product_default_timezone).to eq("UTC")
end
end
end
end

0 comments on commit e72f58c

Please sign in to comment.