Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Add a new cloud-config plugin for setting the timezone
cloud-config supports a new plugin, called 'set-timezone', which can be used to change the timezone on the underlying instance. The patch adds a new method in the osutils abstraction, called `set_timezone`, which should be implemented by each separated OS. The abstraction calls into cloudbaseinit.utils.windows.timezone, another layer of abstraction over two API methods, SetTimeZoneInformation for Windows 2003 and older and SetDynamicTimeZoneInformation, for newer versions of Windows, which also handles Daylight Saving Time. The plugin supports standard IANA timezone names, which are then translated to the Windows-specific timezone names, using tzlocal library. Change-Id: I18674e1ae078fc69f3fb938065ba01a4de5464a1
- Loading branch information
1 parent
0073c7b
commit b10917f
Showing
11 changed files
with
717 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
cloudbaseinit/plugins/common/userdataplugins/cloudconfigplugins/set_timezone.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Copyright 2015 Cloudbase Solutions Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
from cloudbaseinit.openstack.common import log as logging | ||
from cloudbaseinit.osutils import factory | ||
from cloudbaseinit.plugins.common.userdataplugins.cloudconfigplugins import ( | ||
base | ||
) | ||
|
||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class SetTimezonePlugin(base.BaseCloudConfigPlugin): | ||
"""Change the timezone for the underlying platform. | ||
This uses IANA timezone names (which are mapped to the Windows | ||
time zone names, as seen in the following link: | ||
https://technet.microsoft.com/en-us/library/cc749073%28v=ws.10%29.aspx). | ||
For instance, to change the timezone to 'America/Montevideo', use | ||
this syntax:: | ||
set_timezone: America/Montevideo | ||
""" | ||
|
||
def process(self, data): | ||
LOG.info("Changing timezone to %r", data) | ||
osutils = factory.get_os_utils() | ||
osutils.set_timezone(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
cloudbaseinit/tests/plugins/common/userdataplugins/cloudconfigplugins/test_set_timezone.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Copyright 2015 Cloudbase Solutions Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
import unittest | ||
|
||
try: | ||
import unittest.mock as mock | ||
except ImportError: | ||
import mock | ||
|
||
from cloudbaseinit.plugins.common.userdataplugins import cloudconfig | ||
from cloudbaseinit.plugins.common.userdataplugins.cloudconfigplugins import ( | ||
set_timezone | ||
) | ||
from cloudbaseinit.tests import testutils | ||
|
||
|
||
class TestSetTimezone(unittest.TestCase): | ||
|
||
@mock.patch('cloudbaseinit.plugins.common.userdataplugins.' | ||
'cloudconfigplugins.set_timezone.factory') | ||
def test_process(self, mock_osutils_factory): | ||
with testutils.LogSnatcher('cloudbaseinit.plugins.common.' | ||
'userdataplugins.cloudconfigplugins.' | ||
'set_timezone') as snatcher: | ||
set_timezone.SetTimezonePlugin().process(mock.sentinel.timezone) | ||
|
||
expected_logging = [ | ||
'Changing timezone to %r' % mock.sentinel.timezone | ||
] | ||
mock_osutils_factory.get_os_utils.assert_called_once_with() | ||
mock_osutils = mock_osutils_factory.get_os_utils.return_value | ||
mock_osutils.set_timezone.assert_called_once_with( | ||
mock.sentinel.timezone) | ||
self.assertEqual(expected_logging, snatcher.output) | ||
|
||
@mock.patch('cloudbaseinit.plugins.common.userdataplugins.' | ||
'cloudconfigplugins.set_timezone.SetTimezonePlugin.process') | ||
def test_timezone_dispatch(self, mock_process_plugin): | ||
plugin = cloudconfig.CloudConfigPlugin() | ||
plugin.process_non_multipart("set_timezone: America Standard Time") | ||
|
||
mock_process_plugin.assert_called_once_with("America Standard Time") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Copyright 2015 Cloudbase Solutions Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
import importlib | ||
import unittest | ||
|
||
try: | ||
import unittest.mock as mock | ||
except ImportError: | ||
import mock | ||
|
||
|
||
class TestPrivilege(unittest.TestCase): | ||
|
||
def setUp(self): | ||
self._win32process_mock = mock.MagicMock() | ||
self._win32security_mock = mock.MagicMock() | ||
self._module_patcher = mock.patch.dict( | ||
'sys.modules', | ||
{'win32process': self._win32process_mock, | ||
'win32security': self._win32security_mock}) | ||
|
||
self._module_patcher.start() | ||
self.privilege_module = importlib.import_module( | ||
"cloudbaseinit.utils.windows.privilege") | ||
|
||
def tearDown(self): | ||
self._module_patcher.stop() | ||
|
||
def test_privilege_context_manager(self): | ||
fake_process = mock.MagicMock() | ||
fake_token = True | ||
LUID = 'fakeid' | ||
self._win32process_mock.GetCurrentProcess.return_value = fake_process | ||
self._win32security_mock.OpenProcessToken.return_value = fake_token | ||
self._win32security_mock.LookupPrivilegeValue.return_value = LUID | ||
privilege_enabled = [(LUID, | ||
self._win32security_mock.SE_PRIVILEGE_ENABLED)] | ||
privilege_removed = [(LUID, | ||
self._win32security_mock.SE_PRIVILEGE_REMOVED)] | ||
with self.privilege_module.acquire_privilege(mock.sentinel.privilege): | ||
|
||
self._win32security_mock.AdjustTokenPrivileges.assert_called_with( | ||
fake_token, False, privilege_enabled) | ||
|
||
self._win32security_mock.OpenProcessToken.assert_called_with( | ||
fake_process, | ||
self._win32security_mock.TOKEN_ADJUST_PRIVILEGES | | ||
self._win32security_mock.TOKEN_QUERY) | ||
|
||
self._win32security_mock.AdjustTokenPrivileges.assert_called_with( | ||
fake_token, False, privilege_removed) |
Oops, something went wrong.