Fix timezone lookup

Unfortunately strftime does not always return a timezone that matches up
with what is available via zoneinfo on the file system. So instead of
using that, this patch creates a function to use timedatectl on the host
itself to determine what the current timezone is configured to.

Change-Id: I0d64cb0a534b48f1aa747655f7b7d997c74d77bc
Closes-Bug: #1820081
This commit is contained in:
Alex Schultz 2019-03-14 10:25:40 -06:00
parent 1a09cf7c78
commit 93bff99379
4 changed files with 45 additions and 2 deletions

View File

@ -1406,6 +1406,31 @@ class TestConfigParser(TestCase):
'does-not-exist', 'foo', 'bar')
class TestGetLocalTimezone(TestCase):
@mock.patch('tripleoclient.utils.run_command')
def test_get_local_timezone(self, run_mock):
run_mock.return_value = "" \
" Local time: Thu 2019-03-14 12:05:49 EDT\n" \
" Universal time: Thu 2019-03-14 16:05:49 UTC\n" \
" RTC time: Thu 2019-03-14 16:15:50\n" \
" Time zone: America/New_York (EDT, -0400)\n" \
"System clock synchronized: yes\n" \
" NTP service: active\n"\
" RTC in local TZ: no\n"
self.assertEqual('America/New_York', utils.get_local_timezone())
@mock.patch('tripleoclient.utils.run_command')
def test_get_local_timezone_bad_timedatectl(self, run_mock):
run_mock.return_value = "meh"
self.assertEqual('UTC', utils.get_local_timezone())
@mock.patch('tripleoclient.utils.run_command')
def test_get_local_timezone_bad_timezone_line(self, run_mock):
run_mock.return_value = "" \
" Time zone: "
self.assertEqual('UTC', utils.get_local_timezone())
class TestAnsibleSymlink(TestCase):
@mock.patch('tripleoclient.utils.run_command')
@mock.patch('os.path.exists', side_effect=[False, True])

View File

@ -43,6 +43,8 @@ class TestUndercloudInstall(TestPluginV1):
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
self.conf.config(container_images_file='/home/stack/foo.yaml')
self.conf.set_default('output_dir', '/home/stack')
# setting this so we don't have to mock get_local_timezone everywhere
self.conf.set_default('undercloud_timezone', 'UTC')
# don't actually load config from ~/undercloud.conf
self.mock_config_load = self.useFixture(
fixtures.MockPatch('tripleoclient.utils.load_config'))
@ -550,6 +552,8 @@ class TestUndercloudUpgrade(TestPluginV1):
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
self.conf.config(container_images_file='/home/stack/foo.yaml')
self.conf.set_default('output_dir', '/home/stack')
# setting this so we don't have to mock get_local_timezone everywhere
self.conf.set_default('undercloud_timezone', 'UTC')
# don't actually load config from ~/undercloud.conf
self.mock_config_load = self.useFixture(
fixtures.MockPatch('tripleoclient.utils.load_config'))

View File

@ -1589,6 +1589,21 @@ def get_validations_yaml(validations_data):
indent=2)
def get_local_timezone():
info = run_command(['timedatectl'], name='timedatectl')
timezoneline = [tz for tz in info.split('\n') if 'Time zone:' in tz]
if not timezoneline:
LOG.warning('Unable to determine timezone, using UTC')
return 'UTC'
# The line returned is "[whitespace]Time zone: [timezone] ([tz], [offset])"
try:
timezone = timezoneline[0].strip().split(' ')[2]
except Exception:
LOG.error('Unable to parse timezone from timedatectl, using UTC')
timezone = 'UTC'
return timezone
def ansible_symlink():
# https://bugs.launchpad.net/tripleo/+bug/1812837
python_version = sys.version_info[0]

View File

@ -33,7 +33,6 @@ from jinja2 import meta
from osc_lib.i18n import _
from oslo_config import cfg
from time import strftime
from tripleo_common.image import kolla_builder
from tripleoclient.config.undercloud import load_global_config
@ -404,7 +403,7 @@ def prepare_undercloud_deploy(upgrade=False, no_validations=False,
if CONF.get('undercloud_timezone', None):
env_data['TimeZone'] = CONF['undercloud_timezone']
else:
env_data['TimeZone'] = strftime("%Z")
env_data['TimeZone'] = utils.get_local_timezone()
if CONF.get('enable_validations', False):
env_data['UndercloudConfigFilePath'] = constants.UNDERCLOUD_CONF_PATH