mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #36755 from terminalmage/issue36671
systemd.py: check retcode for service availability in systemd >= 231
This commit is contained in:
commit
6b782c15e1
2 changed files with 83 additions and 12 deletions
|
@ -75,7 +75,23 @@ def _check_available(name):
|
|||
'''
|
||||
Returns boolean telling whether or not the named service is available
|
||||
'''
|
||||
out = _systemctl_status(name).lower()
|
||||
_status = _systemctl_status(name)
|
||||
sd_version = salt.utils.systemd.version(__context__)
|
||||
if sd_version is not None and sd_version >= 231:
|
||||
# systemd 231 changed the output of "systemctl status" for unknown
|
||||
# services, and also made it return an exit status of 4. If we are on
|
||||
# a new enough version, check the retcode, otherwise fall back to
|
||||
# parsing the "systemctl status" output.
|
||||
# See: https://github.com/systemd/systemd/pull/3385
|
||||
# Also: https://github.com/systemd/systemd/commit/3dced37
|
||||
return 0 <= _status['retcode'] < 4
|
||||
|
||||
out = _status['stdout'].lower()
|
||||
if 'could not be found' in out:
|
||||
# Catch cases where the systemd version is < 231 but the return code
|
||||
# and output changes have been backported (e.g. RHEL 7.3).
|
||||
return False
|
||||
|
||||
for line in salt.utils.itertools.split(out, '\n'):
|
||||
match = re.match(r'\s+loaded:\s+(\S+)', line)
|
||||
if match:
|
||||
|
@ -287,9 +303,10 @@ def _systemctl_status(name):
|
|||
contextkey = 'systemd._systemctl_status.%s' % name
|
||||
if contextkey in __context__:
|
||||
return __context__[contextkey]
|
||||
__context__[contextkey] = __salt__['cmd.run'](
|
||||
__context__[contextkey] = __salt__['cmd.run_all'](
|
||||
_systemctl_cmd('status', name),
|
||||
python_shell=False,
|
||||
redirect_stderr=True,
|
||||
ignore_retcode=True
|
||||
)
|
||||
return __context__[contextkey]
|
||||
|
@ -323,7 +340,7 @@ def _unit_file_changed(name):
|
|||
Returns True if systemctl reports that the unit file has changed, otherwise
|
||||
returns False.
|
||||
'''
|
||||
return "'systemctl daemon-reload'" in _systemctl_status(name).lower()
|
||||
return "'systemctl daemon-reload'" in _systemctl_status(name)['stdout'].lower()
|
||||
|
||||
|
||||
def systemctl_reload():
|
||||
|
|
|
@ -29,15 +29,35 @@ systemd.__salt__ = {}
|
|||
systemd.__context__ = {}
|
||||
|
||||
_SYSTEMCTL_STATUS = {
|
||||
'sshd.service': '''\
|
||||
'sshd.service': {
|
||||
'stdout': '''\
|
||||
* sshd.service - OpenSSH Daemon
|
||||
Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: disabled)
|
||||
Active: inactive (dead)''',
|
||||
'stderr': '',
|
||||
'retcode': 3,
|
||||
'pid': 12345,
|
||||
},
|
||||
|
||||
'foo.service': '''\
|
||||
'foo.service': {
|
||||
'stdout': '''\
|
||||
* foo.service
|
||||
Loaded: not-found (Reason: No such file or directory)
|
||||
Active: inactive (dead)'''
|
||||
Active: inactive (dead)''',
|
||||
'stderr': '',
|
||||
'retcode': 3,
|
||||
'pid': 12345,
|
||||
},
|
||||
}
|
||||
|
||||
# This reflects systemd >= 231 behavior
|
||||
_SYSTEMCTL_STATUS_GTE_231 = {
|
||||
'bar.service': {
|
||||
'stdout': 'Unit bar.service could not be found.',
|
||||
'stderr': '',
|
||||
'retcode': 4,
|
||||
'pid': 12345,
|
||||
},
|
||||
}
|
||||
|
||||
_LIST_UNIT_FILES = '''\
|
||||
|
@ -170,18 +190,52 @@ class SystemdTestCase(TestCase):
|
|||
Test to check that the given service is available
|
||||
'''
|
||||
mock = MagicMock(side_effect=lambda x: _SYSTEMCTL_STATUS[x])
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertTrue(systemd.available('sshd.service'))
|
||||
self.assertFalse(systemd.available('foo.service'))
|
||||
|
||||
# systemd < 231
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 230}):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertTrue(systemd.available('sshd.service'))
|
||||
self.assertFalse(systemd.available('foo.service'))
|
||||
|
||||
# systemd >= 231
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 231}):
|
||||
with patch.dict(_SYSTEMCTL_STATUS, _SYSTEMCTL_STATUS_GTE_231):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertTrue(systemd.available('sshd.service'))
|
||||
self.assertFalse(systemd.available('bar.service'))
|
||||
|
||||
# systemd < 231 with retcode/output changes backported (e.g. RHEL 7.3)
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 219}):
|
||||
with patch.dict(_SYSTEMCTL_STATUS, _SYSTEMCTL_STATUS_GTE_231):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertTrue(systemd.available('sshd.service'))
|
||||
self.assertFalse(systemd.available('bar.service'))
|
||||
|
||||
def test_missing(self):
|
||||
'''
|
||||
Test to the inverse of service.available.
|
||||
'''
|
||||
mock = MagicMock(side_effect=lambda x: _SYSTEMCTL_STATUS[x])
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertFalse(systemd.missing('sshd.service'))
|
||||
self.assertTrue(systemd.missing('foo.service'))
|
||||
|
||||
# systemd < 231
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 230}):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertFalse(systemd.missing('sshd.service'))
|
||||
self.assertTrue(systemd.missing('foo.service'))
|
||||
|
||||
# systemd >= 231
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 231}):
|
||||
with patch.dict(_SYSTEMCTL_STATUS, _SYSTEMCTL_STATUS_GTE_231):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertFalse(systemd.missing('sshd.service'))
|
||||
self.assertTrue(systemd.missing('bar.service'))
|
||||
|
||||
# systemd < 231 with retcode/output changes backported (e.g. RHEL 7.3)
|
||||
with patch.dict(systemd.__context__, {'salt.utils.systemd.version': 219}):
|
||||
with patch.dict(_SYSTEMCTL_STATUS, _SYSTEMCTL_STATUS_GTE_231):
|
||||
with patch.object(systemd, '_systemctl_status', mock):
|
||||
self.assertFalse(systemd.missing('sshd.service'))
|
||||
self.assertTrue(systemd.missing('bar.service'))
|
||||
|
||||
def test_show(self):
|
||||
'''
|
||||
|
|
Loading…
Add table
Reference in a new issue