diff --git a/ipatests/pytest_plugins/integration/__init__.py b/ipatests/pytest_plugins/integration/__init__.py index d126b413a..20e60e919 100644 --- a/ipatests/pytest_plugins/integration/__init__.py +++ b/ipatests/pytest_plugins/integration/__init__.py @@ -72,6 +72,36 @@ def collect_test_logs(node, logs_dict, test_config): ) +def collect_systemd_journal(node, hosts, test_config): + """Collect systemd journal from remote hosts + + :param node: The pytest collection node (request.node) + :param hosts: List of hosts from which to collect journal + :param test_config: Pytest configuration + """ + name = _get_logname_from_node(node) + logfile_dir = test_config.getoption('logfile_dir') + + for host in hosts: + log.info("Collecting journal from: %s", host.hostname) + + topdirname = os.path.join(logfile_dir, name, host.hostname) + if not os.path.exists(topdirname): + os.makedirs(topdirname) + + # Get journal content + cmd = host.run_command( + ['journalctl', '--since', host.config.log_journal_since], + log_stdout=False, raiseonerr=False) + if cmd.returncode: + log.error('An error occurred while collecting journal') + continue + + # Write journal to file + with open(os.path.join(topdirname, "journal"), 'w') as f: + f.write(cmd.stdout_text) + + def collect_logs(name, logs_dict, logfile_dir=None, beakerlib_plugin=None): """Collect logs from remote hosts @@ -158,7 +188,9 @@ def integration_logs(class_integration_logs, request): """Provides access to test integration logs, and collects after each test """ yield class_integration_logs + hosts = class_integration_logs.keys() collect_test_logs(request.node, class_integration_logs, request.config) + collect_systemd_journal(request.node, hosts, request.config) @yield_fixture(scope='class') diff --git a/ipatests/pytest_plugins/integration/config.py b/ipatests/pytest_plugins/integration/config.py index 3d026e340..c5cd162a2 100644 --- a/ipatests/pytest_plugins/integration/config.py +++ b/ipatests/pytest_plugins/integration/config.py @@ -41,6 +41,7 @@ class Config(pytest_multihost.config.Config): 'ad_admin_password', 'dns_forwarder', 'domain_level', + 'log_journal_since', } def __init__(self, **kwargs): @@ -62,6 +63,7 @@ class Config(pytest_multihost.config.Config): # 8.8.8.8 is probably the best-known public DNS self.dns_forwarder = kwargs.get('dns_forwarder') or '8.8.8.8' self.debug = False + self.log_journal_since = kwargs.get('log_journal_since') or '-1h' if self.domain_level is None: self.domain_level = MAX_DOMAIN_LEVEL diff --git a/ipatests/pytest_plugins/integration/env_config.py b/ipatests/pytest_plugins/integration/env_config.py index bd8c8d2a9..d140aa9df 100644 --- a/ipatests/pytest_plugins/integration/env_config.py +++ b/ipatests/pytest_plugins/integration/env_config.py @@ -63,6 +63,8 @@ _setting_infos = ( _SettingInfo('ipv6', 'IPv6SETUP', False), _SettingInfo('debug', 'IPADEBUG', False), _SettingInfo('domain_level', 'DOMAINLVL', MAX_DOMAIN_LEVEL), + + _SettingInfo('log_journal_since', 'LOG_JOURNAL_SINCE', '-1h'), ) diff --git a/ipatests/test_integration/test_testconfig.py b/ipatests/test_integration/test_testconfig.py index c66be8c33..b495f368e 100644 --- a/ipatests/test_integration/test_testconfig.py +++ b/ipatests/test_integration/test_testconfig.py @@ -41,7 +41,8 @@ DEFAULT_OUTPUT_DICT = { "dirman_password": "Secret123", "ntp_server": "ntp.clock.test", "admin_password": "Secret123", - "domain_level": MAX_DOMAIN_LEVEL + "domain_level": MAX_DOMAIN_LEVEL, + "log_journal_since": "-1h", } DEFAULT_OUTPUT_ENV = { @@ -60,6 +61,7 @@ DEFAULT_OUTPUT_ENV = { "IPv6SETUP": "", "IPADEBUG": "", "DOMAINLVL": str(MAX_DOMAIN_LEVEL), + "LOG_JOURNAL_SINCE": "-1h", } DEFAULT_INPUT_ENV = {