You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
10 KiB
264 lines
10 KiB
10 months ago
|
import os
|
||
|
from functools import partial
|
||
|
|
||
|
import pytest
|
||
|
|
||
|
from leapp.libraries.common import systemd
|
||
|
from leapp.libraries.common.testutils import logger_mocked
|
||
|
from leapp.libraries.stdlib import api
|
||
|
from leapp.models import SystemdServiceFile, SystemdServicePreset
|
||
|
|
||
|
CURR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
|
|
||
|
|
||
|
def test_get_service_files(monkeypatch):
|
||
|
def run_mocked(cmd, *args, **kwargs):
|
||
|
if cmd == ['systemctl', 'list-unit-files'] + systemd._SYSTEMCTL_CMD_OPTIONS:
|
||
|
return {'stdout': [
|
||
|
'auditd.service enabled',
|
||
|
'crond.service enabled ',
|
||
|
'dbus.service static ',
|
||
|
'dnf-makecache.service static ',
|
||
|
'firewalld.service enabled ',
|
||
|
'getty@.service enabled ',
|
||
|
'gssproxy.service disabled',
|
||
|
'kdump.service enabled ',
|
||
|
'mdmon@.service static ',
|
||
|
'nfs.service disabled',
|
||
|
'polkit.service static ',
|
||
|
'rescue.service static ',
|
||
|
'rngd.service enabled ',
|
||
|
'rsyncd.service disabled',
|
||
|
'rsyncd@.service static ',
|
||
|
'smartd.service enabled ',
|
||
|
'sshd.service enabled ',
|
||
|
'sshd@.service static ',
|
||
|
'wpa_supplicant.service disabled'
|
||
|
]}
|
||
|
raise ValueError('Attempted to call unexpected command: {}'.format(cmd))
|
||
|
|
||
|
monkeypatch.setattr(systemd, 'run', run_mocked)
|
||
|
service_files = systemd.get_service_files()
|
||
|
|
||
|
expected = [
|
||
|
SystemdServiceFile(name='auditd.service', state='enabled'),
|
||
|
SystemdServiceFile(name='crond.service', state='enabled'),
|
||
|
SystemdServiceFile(name='dbus.service', state='static'),
|
||
|
SystemdServiceFile(name='dnf-makecache.service', state='static'),
|
||
|
SystemdServiceFile(name='firewalld.service', state='enabled'),
|
||
|
SystemdServiceFile(name='getty@.service', state='enabled'),
|
||
|
SystemdServiceFile(name='gssproxy.service', state='disabled'),
|
||
|
SystemdServiceFile(name='kdump.service', state='enabled'),
|
||
|
SystemdServiceFile(name='mdmon@.service', state='static'),
|
||
|
SystemdServiceFile(name='nfs.service', state='disabled'),
|
||
|
SystemdServiceFile(name='polkit.service', state='static'),
|
||
|
SystemdServiceFile(name='rescue.service', state='static'),
|
||
|
SystemdServiceFile(name='rngd.service', state='enabled'),
|
||
|
SystemdServiceFile(name='rsyncd.service', state='disabled'),
|
||
|
SystemdServiceFile(name='rsyncd@.service', state='static'),
|
||
|
SystemdServiceFile(name='smartd.service', state='enabled'),
|
||
|
SystemdServiceFile(name='sshd.service', state='enabled'),
|
||
|
SystemdServiceFile(name='sshd@.service', state='static'),
|
||
|
SystemdServiceFile(name='wpa_supplicant.service', state='disabled')
|
||
|
]
|
||
|
|
||
|
assert service_files == expected
|
||
|
|
||
|
|
||
|
def test_preset_files_overrides():
|
||
|
etc_files = [
|
||
|
'/etc/systemd/system-preset/00-abc.preset',
|
||
|
'/etc/systemd/system-preset/preset_without_prio.preset'
|
||
|
]
|
||
|
usr_files = [
|
||
|
'/usr/lib/systemd/system-preset/00-abc.preset',
|
||
|
'/usr/lib/systemd/system-preset/99-xyz.preset',
|
||
|
'/usr/lib/systemd/system-preset/preset_without_prio.preset'
|
||
|
]
|
||
|
|
||
|
expected = [
|
||
|
'/usr/lib/systemd/system-preset/99-xyz.preset',
|
||
|
'/etc/systemd/system-preset/00-abc.preset',
|
||
|
'/etc/systemd/system-preset/preset_without_prio.preset'
|
||
|
]
|
||
|
|
||
|
presets = systemd._join_presets_resolving_overrides(etc_files, usr_files)
|
||
|
assert sorted(presets) == sorted(expected)
|
||
|
|
||
|
|
||
|
def test_preset_files_block_override(monkeypatch):
|
||
|
etc_files = [
|
||
|
'/etc/systemd/system-preset/00-abc.preset'
|
||
|
]
|
||
|
usr_files = [
|
||
|
'/usr/lib/systemd/system-preset/00-abc.preset',
|
||
|
'/usr/lib/systemd/system-preset/99-xyz.preset'
|
||
|
]
|
||
|
|
||
|
expected = [
|
||
|
'/usr/lib/systemd/system-preset/99-xyz.preset',
|
||
|
]
|
||
|
|
||
|
def islink_mocked(path):
|
||
|
return path == '/etc/systemd/system-preset/00-abc.preset'
|
||
|
|
||
|
def readlink_mocked(path):
|
||
|
if path == '/etc/systemd/system-preset/00-abc.preset':
|
||
|
return '/dev/null'
|
||
|
raise OSError
|
||
|
|
||
|
monkeypatch.setattr(os.path, 'islink', islink_mocked)
|
||
|
monkeypatch.setattr(os, 'readlink', readlink_mocked)
|
||
|
|
||
|
presets = systemd._join_presets_resolving_overrides(etc_files, usr_files)
|
||
|
assert sorted(presets) == sorted(expected)
|
||
|
|
||
|
|
||
|
TEST_SYSTEMD_LOAD_PATH = [os.path.join(CURR_DIR, 'test_systemd_files/')]
|
||
|
|
||
|
TESTING_PRESET_FILES = [
|
||
|
os.path.join(CURR_DIR, '00-test.preset'),
|
||
|
os.path.join(CURR_DIR, '01-test.preset')
|
||
|
]
|
||
|
|
||
|
TESTING_PRESET_WITH_INVALID_ENTRIES = os.path.join(CURR_DIR, '05-invalid.preset')
|
||
|
|
||
|
_PARSE_PRESET_ENTRIES_TEST_DEFINITION = (
|
||
|
('enable example.service', {'example.service': 'enable'}),
|
||
|
('disable abc.service', {'abc.service': 'disable'}),
|
||
|
('enable template@.service', {'template@.service': 'enable'}),
|
||
|
('disable template2@.service', {'template2@.service': 'disable'}),
|
||
|
('disable template@.service instance1 instance2', {
|
||
|
'template@instance1.service': 'disable',
|
||
|
'template@instance2.service': 'disable'
|
||
|
}),
|
||
|
('enable globbed*.service', {'globbed-one.service': 'enable', 'globbed-two.service': 'enable'}),
|
||
|
('enable example.*', {'example.service': 'enable', 'example.socket': 'enable'}),
|
||
|
('disable *', {
|
||
|
'example.service': 'disable',
|
||
|
'abc.service': 'disable',
|
||
|
'template@.service': 'disable',
|
||
|
'template2@.service': 'disable',
|
||
|
'globbed-one.service': 'disable',
|
||
|
'globbed-two.service': 'disable',
|
||
|
'example.socket': 'disable',
|
||
|
'extra.service': 'disable'
|
||
|
})
|
||
|
)
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize('entry,expected', _PARSE_PRESET_ENTRIES_TEST_DEFINITION)
|
||
|
def test_parse_preset_entry(monkeypatch, entry, expected):
|
||
|
presets = {}
|
||
|
systemd._parse_preset_entry(entry, presets, TEST_SYSTEMD_LOAD_PATH)
|
||
|
assert presets == expected
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
'entry',
|
||
|
[
|
||
|
('hello.service'),
|
||
|
('mask hello.service'),
|
||
|
('enable'),
|
||
|
]
|
||
|
)
|
||
|
def test_parse_preset_entry_invalid(monkeypatch, entry):
|
||
|
presets = {}
|
||
|
with pytest.raises(ValueError, match=r'^Invalid preset file entry: '):
|
||
|
systemd._parse_preset_entry(entry, presets, TEST_SYSTEMD_LOAD_PATH)
|
||
|
|
||
|
|
||
|
def test_parse_preset_files(monkeypatch):
|
||
|
|
||
|
expected = {
|
||
|
'example.service': 'enable',
|
||
|
'example.socket': 'disable',
|
||
|
'abc.service': 'disable',
|
||
|
'template@.service': 'disable',
|
||
|
'template@instance1.service': 'enable',
|
||
|
'template@instance2.service': 'enable',
|
||
|
'globbed-one.service': 'enable',
|
||
|
'globbed-two.service': 'enable',
|
||
|
'extra.service': 'disable',
|
||
|
'template2@.service': 'disable'
|
||
|
}
|
||
|
|
||
|
presets = systemd._parse_preset_files(TESTING_PRESET_FILES, TEST_SYSTEMD_LOAD_PATH, False)
|
||
|
assert presets == expected
|
||
|
|
||
|
|
||
|
def test_parse_preset_files_invalid():
|
||
|
with pytest.raises(ValueError):
|
||
|
systemd._parse_preset_files(
|
||
|
[TESTING_PRESET_WITH_INVALID_ENTRIES], TEST_SYSTEMD_LOAD_PATH, ignore_invalid_entries=False
|
||
|
)
|
||
|
|
||
|
|
||
|
def test_parse_preset_files_ignore_invalid(monkeypatch):
|
||
|
monkeypatch.setattr(api, 'current_logger', logger_mocked())
|
||
|
|
||
|
invalid_preset_files = [TESTING_PRESET_WITH_INVALID_ENTRIES]
|
||
|
presets = systemd._parse_preset_files(
|
||
|
invalid_preset_files, TEST_SYSTEMD_LOAD_PATH, ignore_invalid_entries=True
|
||
|
)
|
||
|
|
||
|
for entry in ('enable', 'hello.service', 'mask hello.service'):
|
||
|
msg = 'Invalid preset file {}: Invalid preset file entry: "{}"'.format(invalid_preset_files[0], entry)
|
||
|
assert msg in api.current_logger.warnmsg
|
||
|
|
||
|
assert presets == {'example.service': 'disable'}
|
||
|
|
||
|
|
||
|
def parse_preset_files_mocked():
|
||
|
mocked = partial(systemd._parse_preset_files, load_path=TEST_SYSTEMD_LOAD_PATH)
|
||
|
|
||
|
def impl(preset_files, load_path, ignore_invalid_entries):
|
||
|
return mocked(preset_files, ignore_invalid_entries=ignore_invalid_entries)
|
||
|
return impl
|
||
|
|
||
|
|
||
|
def test_get_service_preset_files(monkeypatch):
|
||
|
|
||
|
def get_system_preset_files_mocked():
|
||
|
return TESTING_PRESET_FILES
|
||
|
|
||
|
monkeypatch.setattr(systemd, '_get_system_preset_files', get_system_preset_files_mocked)
|
||
|
monkeypatch.setattr(systemd, '_parse_preset_files', parse_preset_files_mocked())
|
||
|
|
||
|
service_files = [
|
||
|
SystemdServiceFile(name='abc.service', state='transient'),
|
||
|
SystemdServiceFile(name='example.service', state='static'),
|
||
|
SystemdServiceFile(name='example.socket', state='masked'),
|
||
|
SystemdServiceFile(name='extra.service', state='disabled'),
|
||
|
SystemdServiceFile(name='template2@.service', state='enabled'),
|
||
|
SystemdServiceFile(name='template@.service', state='enabled'),
|
||
|
]
|
||
|
|
||
|
expected = [
|
||
|
# dont expect example.service since it's static
|
||
|
# dont expect abc.service since it's transient
|
||
|
SystemdServicePreset(service='template@.service', state='disable'),
|
||
|
SystemdServicePreset(service='template@instance1.service', state='enable'),
|
||
|
SystemdServicePreset(service='template@instance2.service', state='enable'),
|
||
|
SystemdServicePreset(service='globbed-one.service', state='enable'),
|
||
|
SystemdServicePreset(service='globbed-two.service', state='enable'),
|
||
|
SystemdServicePreset(service='extra.service', state='disable'),
|
||
|
SystemdServicePreset(service='template2@.service', state='disable')
|
||
|
]
|
||
|
|
||
|
presets = systemd.get_system_service_preset_files(service_files, False)
|
||
|
assert sorted(presets, key=lambda e: e.service) == sorted(expected, key=lambda e: e.service)
|
||
|
|
||
|
|
||
|
def test_get_service_preset_files_invalid(monkeypatch):
|
||
|
|
||
|
def get_system_preset_files_mocked():
|
||
|
return [TESTING_PRESET_WITH_INVALID_ENTRIES]
|
||
|
|
||
|
monkeypatch.setattr(systemd, '_get_system_preset_files', get_system_preset_files_mocked)
|
||
|
monkeypatch.setattr(systemd, '_parse_preset_files', parse_preset_files_mocked())
|
||
|
|
||
|
with pytest.raises(ValueError):
|
||
|
# doesn't matter what service_files are
|
||
|
systemd.get_system_service_preset_files([], ignore_invalid_entries=False)
|