2016-06-14 20:47:17 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
2017-07-25 01:47:15 +00:00
|
|
|
# Import Python libs
|
2018-01-24 20:47:14 +00:00
|
|
|
from __future__ import absolute_import, unicode_literals, print_function
|
2016-06-15 19:34:54 +00:00
|
|
|
import datetime
|
2017-02-12 21:47:11 +00:00
|
|
|
import logging
|
2016-06-14 20:47:17 +00:00
|
|
|
import os
|
2017-02-12 21:47:11 +00:00
|
|
|
import signal
|
2017-01-27 22:07:50 +00:00
|
|
|
import subprocess
|
2018-01-31 21:08:06 +00:00
|
|
|
import textwrap
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
# Import Salt Testing libs
|
2017-04-03 16:04:09 +00:00
|
|
|
from tests.support.case import ModuleCase
|
2017-02-27 13:58:07 +00:00
|
|
|
from tests.support.unit import skipIf
|
2017-04-04 17:57:27 +00:00
|
|
|
from tests.support.helpers import destructiveTest, skip_if_not_root
|
2016-06-14 20:47:17 +00:00
|
|
|
|
Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
2017-07-25 01:47:15 +00:00
|
|
|
# Import Salt libs
|
2017-07-18 16:31:01 +00:00
|
|
|
import salt.utils.files
|
Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
2017-07-25 01:47:15 +00:00
|
|
|
import salt.utils.path
|
|
|
|
import salt.utils.platform
|
2016-08-18 14:03:26 +00:00
|
|
|
import salt.states.file
|
2017-02-27 15:59:04 +00:00
|
|
|
from salt.ext.six.moves import range
|
2018-01-24 20:47:14 +00:00
|
|
|
from salt.ext import six
|
2016-06-14 20:47:17 +00:00
|
|
|
|
2017-02-12 21:47:11 +00:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2016-06-30 15:46:35 +00:00
|
|
|
|
Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
2017-07-25 01:47:15 +00:00
|
|
|
@skipIf(not salt.utils.platform.is_linux(), 'These tests can only be run on linux')
|
2017-04-03 16:04:09 +00:00
|
|
|
class SystemModuleTest(ModuleCase):
|
2016-06-14 20:47:17 +00:00
|
|
|
'''
|
|
|
|
Validate the date/time functions in the system module
|
|
|
|
'''
|
|
|
|
fmt_str = "%Y-%m-%d %H:%M:%S"
|
|
|
|
|
2016-06-21 19:24:49 +00:00
|
|
|
def __init__(self, arg):
|
|
|
|
super(self.__class__, self).__init__(arg)
|
|
|
|
self._orig_time = None
|
2016-08-18 14:03:26 +00:00
|
|
|
self._machine_info = True
|
2016-06-21 19:24:49 +00:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
super(SystemModuleTest, self).setUp()
|
|
|
|
os_grain = self.run_function('grains.item', ['kernel'])
|
2016-06-30 15:46:35 +00:00
|
|
|
if os_grain['kernel'] not in 'Linux':
|
2016-06-21 19:24:49 +00:00
|
|
|
self.skipTest(
|
|
|
|
'Test not applicable to \'{kernel}\' kernel'.format(
|
|
|
|
**os_grain
|
|
|
|
)
|
|
|
|
)
|
2016-08-31 15:16:39 +00:00
|
|
|
if self.run_function('service.available', ['systemd-timesyncd']):
|
|
|
|
self.run_function('service.stop', ['systemd-timesyncd'])
|
2016-06-21 19:24:49 +00:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
if self._orig_time is not None:
|
|
|
|
self._restore_time()
|
|
|
|
self._orig_time = None
|
2016-08-18 14:03:26 +00:00
|
|
|
if self._machine_info is not True:
|
|
|
|
self._restore_machine_info()
|
|
|
|
self._machine_info = True
|
2016-08-31 15:16:39 +00:00
|
|
|
if self.run_function('service.available', ['systemd-timesyncd']):
|
|
|
|
self.run_function('service.start', ['systemd-timesyncd'])
|
2016-06-21 19:24:49 +00:00
|
|
|
|
2016-06-14 20:47:17 +00:00
|
|
|
def _save_time(self):
|
2016-06-21 19:24:49 +00:00
|
|
|
self._orig_time = datetime.datetime.utcnow()
|
2016-06-14 20:47:17 +00:00
|
|
|
|
2016-06-21 19:24:49 +00:00
|
|
|
def _set_time(self, new_time, offset=None):
|
2016-06-14 20:47:17 +00:00
|
|
|
t = new_time.timetuple()[:6]
|
2016-06-21 19:24:49 +00:00
|
|
|
t += (offset,)
|
|
|
|
return self.run_function('system.set_system_date_time', t)
|
|
|
|
|
|
|
|
def _restore_time(self):
|
|
|
|
result = self._set_time(self._orig_time, "+0000")
|
|
|
|
self.assertTrue(result, msg="Unable to restore time properly")
|
|
|
|
|
2017-01-27 22:07:50 +00:00
|
|
|
def _same_times(self, t1, t2, seconds_diff=30):
|
2016-06-21 19:24:49 +00:00
|
|
|
'''
|
|
|
|
Helper function to check if two datetime objects
|
|
|
|
are close enough to the same time.
|
|
|
|
'''
|
2016-06-14 20:47:17 +00:00
|
|
|
return abs(t1 - t2) < datetime.timedelta(seconds=seconds_diff)
|
|
|
|
|
2017-01-27 22:07:50 +00:00
|
|
|
def _hwclock_has_compare(self):
|
|
|
|
'''
|
|
|
|
Some builds of hwclock don't include the `--compare` function
|
|
|
|
needed to test hw/sw clock synchronization. Returns false on
|
|
|
|
systems where it's not present so that we can skip the
|
|
|
|
comparison portion of the test.
|
|
|
|
'''
|
|
|
|
res = self.run_function('cmd.run_all', cmd='hwclock -h')
|
|
|
|
return res['retcode'] == 0 and res['stdout'].find('--compare') > 0
|
|
|
|
|
|
|
|
def _test_hwclock_sync(self):
|
|
|
|
'''
|
|
|
|
Check that hw and sw clocks are sync'd.
|
|
|
|
'''
|
2017-02-10 17:15:25 +00:00
|
|
|
if not self.run_function('system.has_settable_hwclock'):
|
2017-01-27 22:07:50 +00:00
|
|
|
return None
|
|
|
|
if not self._hwclock_has_compare():
|
|
|
|
return None
|
|
|
|
|
2017-02-12 21:47:11 +00:00
|
|
|
class CompareTimeout(BaseException):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _alrm_handler(sig, frame):
|
|
|
|
log.warning('hwclock --compare failed to produce output after 3 seconds')
|
|
|
|
raise CompareTimeout
|
|
|
|
|
|
|
|
for _ in range(2):
|
|
|
|
try:
|
|
|
|
orig_handler = signal.signal(signal.SIGALRM, _alrm_handler)
|
|
|
|
signal.alarm(3)
|
|
|
|
rpipeFd, wpipeFd = os.pipe()
|
|
|
|
log.debug('Comparing hwclock to sys clock')
|
|
|
|
with os.fdopen(rpipeFd, "r") as rpipe:
|
|
|
|
with os.fdopen(wpipeFd, "w") as wpipe:
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(os.devnull, "r") as nulFd:
|
2017-02-12 21:47:11 +00:00
|
|
|
p = subprocess.Popen(args=['hwclock', '--compare'],
|
|
|
|
stdin=nulFd, stdout=wpipeFd, stderr=subprocess.PIPE)
|
|
|
|
p.communicate()
|
|
|
|
|
|
|
|
# read header
|
|
|
|
rpipe.readline()
|
|
|
|
|
|
|
|
# read first time comparison
|
|
|
|
timeCompStr = rpipe.readline()
|
|
|
|
|
|
|
|
# stop
|
|
|
|
p.terminate()
|
|
|
|
|
|
|
|
timeComp = timeCompStr.split()
|
|
|
|
hwTime = float(timeComp[0])
|
|
|
|
swTime = float(timeComp[1])
|
|
|
|
diff = abs(hwTime - swTime)
|
|
|
|
|
|
|
|
self.assertTrue(diff <= 2.0,
|
2018-01-24 20:47:14 +00:00
|
|
|
msg=("hwclock difference too big: " + six.text_type(timeCompStr)))
|
2017-02-12 21:47:11 +00:00
|
|
|
break
|
|
|
|
except CompareTimeout:
|
|
|
|
p.terminate()
|
|
|
|
finally:
|
|
|
|
signal.alarm(0)
|
|
|
|
signal.signal(signal.SIGALRM, orig_handler)
|
|
|
|
else:
|
|
|
|
log.error('Failed to check hwclock sync')
|
2017-01-27 22:07:50 +00:00
|
|
|
|
2016-08-18 14:03:26 +00:00
|
|
|
def _save_machine_info(self):
|
|
|
|
if os.path.isfile('/etc/machine-info'):
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen('/etc/machine-info', 'r') as mach_info:
|
2016-08-18 14:03:26 +00:00
|
|
|
self._machine_info = mach_info.read()
|
|
|
|
else:
|
|
|
|
self._machine_info = False
|
|
|
|
|
|
|
|
def _restore_machine_info(self):
|
|
|
|
if self._machine_info is not False:
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen('/etc/machine-info', 'w') as mach_info:
|
2016-08-18 14:03:26 +00:00
|
|
|
mach_info.write(self._machine_info)
|
|
|
|
else:
|
|
|
|
self.run_function('file.remove', ['/etc/machine-info'])
|
|
|
|
|
2016-06-14 20:47:17 +00:00
|
|
|
def test_get_system_date_time(self):
|
|
|
|
'''
|
|
|
|
Test we are able to get the correct time
|
|
|
|
'''
|
|
|
|
t1 = datetime.datetime.now()
|
|
|
|
res = self.run_function('system.get_system_date_time')
|
|
|
|
t2 = datetime.datetime.strptime(res, self.fmt_str)
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-20 17:05:05 +00:00
|
|
|
.format(t1, t2))
|
2017-01-27 22:07:50 +00:00
|
|
|
self.assertTrue(self._same_times(t1, t2, seconds_diff=2), msg=msg)
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
def test_get_system_date_time_utc(self):
|
|
|
|
'''
|
|
|
|
Test we are able to get the correct time with utc
|
|
|
|
'''
|
|
|
|
t1 = datetime.datetime.utcnow()
|
2016-06-21 19:24:49 +00:00
|
|
|
res = self.run_function('system.get_system_date_time',
|
|
|
|
utc_offset="+0000")
|
2016-06-14 20:47:17 +00:00
|
|
|
t2 = datetime.datetime.strptime(res, self.fmt_str)
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-20 17:05:05 +00:00
|
|
|
.format(t1, t2))
|
2017-01-27 22:07:50 +00:00
|
|
|
self.assertTrue(self._same_times(t1, t2, seconds_diff=2), msg=msg)
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-14 20:47:17 +00:00
|
|
|
def test_set_system_date_time(self):
|
|
|
|
'''
|
|
|
|
Test changing the system clock. We are only able to set it up to a
|
|
|
|
resolution of a second so this test may appear to run in negative time.
|
|
|
|
'''
|
|
|
|
self._save_time()
|
2017-02-12 21:47:11 +00:00
|
|
|
cmp_time = datetime.datetime.now() - datetime.timedelta(days=7)
|
2016-06-21 19:24:49 +00:00
|
|
|
result = self._set_time(cmp_time)
|
2016-06-14 20:47:17 +00:00
|
|
|
time_now = datetime.datetime.now()
|
2017-02-12 21:47:11 +00:00
|
|
|
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-21 19:24:49 +00:00
|
|
|
.format(time_now, cmp_time))
|
|
|
|
self.assertTrue(result and self._same_times(time_now, cmp_time),
|
|
|
|
msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-14 20:47:17 +00:00
|
|
|
def test_set_system_date_time_utc(self):
|
|
|
|
'''
|
|
|
|
Test changing the system clock. We are only able to set it up to a
|
|
|
|
resolution of a second so this test may appear to run in negative time.
|
|
|
|
'''
|
|
|
|
self._save_time()
|
2017-02-12 21:47:11 +00:00
|
|
|
cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7)
|
2016-06-21 19:24:49 +00:00
|
|
|
result = self._set_time(cmp_time, offset="+0000")
|
2016-06-14 20:47:17 +00:00
|
|
|
time_now = datetime.datetime.utcnow()
|
2017-02-12 21:47:11 +00:00
|
|
|
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-21 19:24:49 +00:00
|
|
|
.format(time_now, cmp_time))
|
|
|
|
self.assertTrue(result)
|
|
|
|
self.assertTrue(self._same_times(time_now, cmp_time), msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-21 19:24:49 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-21 19:24:49 +00:00
|
|
|
def test_set_system_date_time_utcoffset_east(self):
|
|
|
|
'''
|
|
|
|
Test changing the system clock. We are only able to set it up to a
|
|
|
|
resolution of a second so this test may appear to run in negative time.
|
|
|
|
'''
|
|
|
|
self._save_time()
|
2017-02-12 21:47:11 +00:00
|
|
|
cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7)
|
|
|
|
# 25200 seconds = 7 hours
|
|
|
|
time_to_set = cmp_time - datetime.timedelta(seconds=25200)
|
|
|
|
result = self._set_time(time_to_set, offset='-0700')
|
2016-06-21 19:24:49 +00:00
|
|
|
time_now = datetime.datetime.utcnow()
|
2017-02-12 21:47:11 +00:00
|
|
|
|
2016-06-21 19:24:49 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
|
|
|
.format(time_now, cmp_time))
|
|
|
|
self.assertTrue(result)
|
|
|
|
self.assertTrue(self._same_times(time_now, cmp_time), msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-21 19:24:49 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-21 19:24:49 +00:00
|
|
|
def test_set_system_date_time_utcoffset_west(self):
|
|
|
|
'''
|
|
|
|
Test changing the system clock. We are only able to set it up to a
|
|
|
|
resolution of a second so this test may appear to run in negative time.
|
|
|
|
'''
|
|
|
|
self._save_time()
|
2017-02-12 21:47:11 +00:00
|
|
|
cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7)
|
|
|
|
# 7200 seconds = 2 hours
|
|
|
|
time_to_set = cmp_time + datetime.timedelta(seconds=7200)
|
|
|
|
result = self._set_time(time_to_set, offset='+0200')
|
2016-06-21 19:24:49 +00:00
|
|
|
time_now = datetime.datetime.utcnow()
|
2017-02-12 21:47:11 +00:00
|
|
|
|
2016-06-21 19:24:49 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
|
|
|
.format(time_now, cmp_time))
|
|
|
|
self.assertTrue(result)
|
|
|
|
self.assertTrue(self._same_times(time_now, cmp_time), msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-14 20:47:17 +00:00
|
|
|
def test_set_system_time(self):
|
|
|
|
'''
|
|
|
|
Test setting the system time without adjusting the date.
|
|
|
|
'''
|
2016-06-21 19:24:49 +00:00
|
|
|
cmp_time = datetime.datetime.now().replace(hour=10, minute=5, second=0)
|
2016-06-14 20:47:17 +00:00
|
|
|
self._save_time()
|
|
|
|
|
2016-06-21 19:24:49 +00:00
|
|
|
result = self.run_function('system.set_system_time', ["10:05:00"])
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
time_now = datetime.datetime.now()
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-21 19:24:49 +00:00
|
|
|
.format(time_now, cmp_time))
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
self.assertTrue(result)
|
2016-06-21 19:24:49 +00:00
|
|
|
self.assertTrue(self._same_times(time_now, cmp_time), msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-06-14 20:47:17 +00:00
|
|
|
def test_set_system_date(self):
|
|
|
|
'''
|
|
|
|
Test setting the system date without adjusting the time.
|
|
|
|
'''
|
2017-02-12 21:47:11 +00:00
|
|
|
cmp_time = datetime.datetime.now() - datetime.timedelta(days=7)
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
self._save_time()
|
2017-02-12 21:47:11 +00:00
|
|
|
result = self.run_function(
|
|
|
|
'system.set_system_date',
|
|
|
|
[cmp_time.strftime('%Y-%m-%d')]
|
|
|
|
)
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
time_now = datetime.datetime.now()
|
2016-06-15 19:34:54 +00:00
|
|
|
msg = ("Difference in times is too large. Now: {0} Fake: {1}"
|
2016-06-21 19:24:49 +00:00
|
|
|
.format(time_now, cmp_time))
|
2016-06-14 20:47:17 +00:00
|
|
|
|
|
|
|
self.assertTrue(result)
|
2016-06-21 19:24:49 +00:00
|
|
|
self.assertTrue(self._same_times(time_now, cmp_time), msg=msg)
|
2017-01-27 22:07:50 +00:00
|
|
|
self._test_hwclock_sync()
|
2016-06-14 20:47:17 +00:00
|
|
|
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-08-18 14:03:26 +00:00
|
|
|
def test_get_computer_desc(self):
|
|
|
|
'''
|
|
|
|
Test getting the system hostname
|
|
|
|
'''
|
|
|
|
res = self.run_function('system.get_computer_desc')
|
|
|
|
|
Use explicit unicode strings + break up salt.utils
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
2017-07-25 01:47:15 +00:00
|
|
|
hostname_cmd = salt.utils.path.which('hostnamectl')
|
2016-08-18 14:03:26 +00:00
|
|
|
if hostname_cmd:
|
|
|
|
desc = self.run_function('cmd.run', ["hostnamectl status --pretty"])
|
|
|
|
self.assertEqual(res, desc)
|
|
|
|
else:
|
|
|
|
if not os.path.isfile('/etc/machine-info'):
|
|
|
|
self.assertFalse(res)
|
|
|
|
else:
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen('/etc/machine-info', 'r') as mach_info:
|
2016-08-18 14:03:26 +00:00
|
|
|
data = mach_info.read()
|
|
|
|
self.assertIn(res, data.decode('string_escape'))
|
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2016-08-18 14:03:26 +00:00
|
|
|
def test_set_computer_desc(self):
|
|
|
|
'''
|
2018-01-31 21:08:06 +00:00
|
|
|
Test setting the computer description
|
2016-08-18 14:03:26 +00:00
|
|
|
'''
|
|
|
|
self._save_machine_info()
|
|
|
|
desc = "test"
|
|
|
|
ret = self.run_function('system.set_computer_desc', [desc])
|
|
|
|
computer_desc = self.run_function('system.get_computer_desc')
|
|
|
|
|
|
|
|
self.assertTrue(ret)
|
2016-08-22 11:54:03 +00:00
|
|
|
self.assertIn(desc, computer_desc)
|
2016-08-18 14:03:26 +00:00
|
|
|
|
2018-01-31 21:08:06 +00:00
|
|
|
@destructiveTest
|
|
|
|
@skip_if_not_root
|
|
|
|
def test_set_computer_desc_multiline(self):
|
|
|
|
'''
|
|
|
|
Test setting the computer description with a multiline string with tabs
|
|
|
|
and double-quotes.
|
|
|
|
'''
|
|
|
|
self._save_machine_info()
|
|
|
|
desc = textwrap.dedent('''\
|
|
|
|
'First Line
|
|
|
|
\tSecond Line: 'single-quoted string'
|
|
|
|
\t\tThird Line: "double-quoted string with unicode: питон"''')
|
|
|
|
ret = self.run_function('system.set_computer_desc', [desc])
|
|
|
|
# self.run_function returns the serialized return, we need to convert
|
|
|
|
# back to unicode to compare to desc. in the assertIn below.
|
|
|
|
computer_desc = salt.utils.stringutils.to_unicode(
|
|
|
|
self.run_function('system.get_computer_desc')
|
|
|
|
)
|
|
|
|
|
|
|
|
self.assertTrue(ret)
|
|
|
|
self.assertIn(desc, computer_desc)
|
|
|
|
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2017-01-27 22:07:50 +00:00
|
|
|
def test_has_hwclock(self):
|
|
|
|
'''
|
|
|
|
Verify platform has a settable hardware clock, if possible.
|
|
|
|
'''
|
|
|
|
if self.run_function('grains.get', ['os_family']) == 'NILinuxRT':
|
|
|
|
self.assertTrue(self.run_function('system._has_settable_hwclock'))
|
|
|
|
self.assertTrue(self._hwclock_has_compare())
|
2018-04-24 18:37:14 +00:00
|
|
|
|
|
|
|
|
2018-04-27 17:44:44 +00:00
|
|
|
@skipIf(not salt.utils.platform.is_windows(), 'These tests can only be run on windows')
|
2018-04-24 18:37:14 +00:00
|
|
|
class WinSystemModuleTest(ModuleCase):
|
|
|
|
'''
|
|
|
|
Validate the date/time functions in the win_system module
|
|
|
|
'''
|
|
|
|
def test_get_computer_name(self):
|
|
|
|
'''
|
|
|
|
Test getting the computer name
|
|
|
|
'''
|
|
|
|
ret = self.run_function('system.get_computer_name')
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(ret, str))
|
|
|
|
import socket
|
|
|
|
name = socket.gethostname()
|
|
|
|
self.assertEqual(name, ret)
|
|
|
|
|
2018-04-24 18:44:15 +00:00
|
|
|
@destructiveTest
|
2018-04-24 18:37:14 +00:00
|
|
|
def test_set_computer_desc(self):
|
|
|
|
'''
|
|
|
|
Test setting the computer description
|
|
|
|
'''
|
|
|
|
desc = 'test description'
|
|
|
|
set_desc = self.run_function('system.set_computer_desc', [desc])
|
|
|
|
self.assertTrue(set_desc)
|
|
|
|
|
|
|
|
get_desc = self.run_function('system.get_computer_desc')
|
|
|
|
self.assertEqual(set_desc['Computer Description'], get_desc)
|
|
|
|
|
|
|
|
def test_get_system_time(self):
|
|
|
|
'''
|
|
|
|
Test getting the system time
|
|
|
|
'''
|
|
|
|
ret = self.run_function('system.get_system_time')
|
|
|
|
now = datetime.datetime.now()
|
|
|
|
self.assertEqual(now.strftime("%I:%M"), ret.rsplit(':', 1)[0])
|
|
|
|
|
2018-04-24 18:44:15 +00:00
|
|
|
@destructiveTest
|
2018-04-24 18:37:14 +00:00
|
|
|
def test_set_system_time(self):
|
|
|
|
'''
|
|
|
|
Test setting the system time
|
|
|
|
'''
|
|
|
|
test_time = '10:55'
|
|
|
|
set_time = self.run_function('system.set_system_time', [test_time + ' AM'])
|
|
|
|
get_time = self.run_function('system.get_system_time').rsplit(':', 1)[0]
|
|
|
|
self.assertEqual(get_time, test_time)
|
|
|
|
|
|
|
|
def test_get_system_date(self):
|
|
|
|
'''
|
|
|
|
Test getting system date
|
|
|
|
'''
|
|
|
|
ret = self.run_function('system.get_system_date')
|
|
|
|
date = datetime.datetime.now().date().strftime("%m/%d/%Y")
|
|
|
|
self.assertEqual(date, ret)
|
|
|
|
|
2018-04-24 18:44:15 +00:00
|
|
|
@destructiveTest
|
2018-04-24 18:37:14 +00:00
|
|
|
def test_set_system_date(self):
|
|
|
|
'''
|
|
|
|
Test setting system date
|
|
|
|
'''
|
|
|
|
self.assertTrue(self.run_function('system.set_system_date', ['3/25/2018']))
|