From 40b67f85ef72db318162bf850694b5be733741b3 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 15 Jan 2024 14:07:05 +0800 Subject: [PATCH 01/20] Refactor watchdog test case - one prerequisite: Set watchdog config variable before starting the tests --- providers/base/bin/watchdog_config_test.py | 21 +- providers/base/units/watchdog/jobs.pxu | 214 +++++++++++++++++--- providers/base/units/watchdog/test-plan.pxu | 14 +- 3 files changed, 218 insertions(+), 31 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index 67973c4e85..e975e55321 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -17,12 +17,29 @@ # You should have received a copy of the GNU General Public License # along with Checkbox. If not, see . +''' +Watchdog implementation on both classic and core image no longer rely +on watchdogd service since 20.04, with this change watchdog/systemd-config +tests only systemd configuration on 20.04 and later series while keeping +the original test for prior releases +''' + import subprocess +import argparse +import sys from checkbox_support.snap_utils.system import on_ubuntucore from checkbox_support.snap_utils.system import get_series +def watchdog_argparse(): + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--check_time', action='store_true') + parser.add_argument('-s', '--check_service', action='store_true') + + return parser.parse_args() + + def get_systemd_wdt_usec(): """ Return value of systemd-watchdog RuntimeWatchdogUSec @@ -91,8 +108,8 @@ def main(): print("systemd watchdog disabled") print("watchdog.service active") - raise SystemExit(not watchdog_config_ready) + return not watchdog_config_ready if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index dea139f14d..bcbec7efe3 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -1,44 +1,208 @@ -id: watchdog/detect +id: watchdog/check-timeout category_id: com.canonical.plainbox::power-management -_summary: Detect the presence of a Hardware Watchdog +_summary: Check the timeout of Hardware Watchdog +_description: + Check the value of RuntimeWatchdogUSec shouldn't be 0 in OEM image. + It means the systemd watchdog is disabled if the value is 0. flags: simple imports: from com.canonical.plainbox import manifest -requires: manifest.has_hardware_watchdog == 'True' -command: udev_resource.py -f WATCHDOG +requires: + manifest.has_hardware_watchdog == 'True' + image_source_and_type.source == 'oem' +command: watchdog_config_test.py --check_time + -id: watchdog/systemd-config -_summary: Check if the hardware watchdog is properly configured -template-engine: jinja2 -command: watchdog_config_test.py +id: watchdog/check-service category_id: com.canonical.plainbox::power-management +_summary: Check the watchdog.service is enabled or not +_description: + Check the watchdog.service is enabled or not. + Watchdog implementation on both classic and core image no longer rely + on watchdogd service since 20.04. flags: simple imports: from com.canonical.plainbox import manifest -requires: manifest.has_hardware_watchdog == 'True' +requires: + manifest.has_hardware_watchdog == 'True' +command: watchdog_config_test.py --check_service -id: watchdog/trigger-system-reset-auto -depends: watchdog/systemd-config -_summary: Test that the watchdog module can trigger a system reset + +id: watchdog/probe-module +category_id: com.canonical.plainbox::power-management +_summary: Probe the suitable module for watchdog +_description: + Probe the suitable module of watchdog based on the environment variable 'WATCHDOG_TYPE' in config file. + This job only be execute on the Stock Classic image because the module isn't probed automatically. +user: root +flags: simple +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_hardware_watchdog == 'True' + image_source_and_type.source == 'stock' + image_source_and_type.type == 'classic' +environ: WATCHDOG_TYPE +command: + if [[ ! -n "$WATCHDOG_TYPE" ]]; then + >&2 echo "WATCHDOG_TYPE is not available" + exit 1 + fi + echo "Trying to probe '$WATCHDOG_TYPE' module" + modprobe $WATCHDOG_TYPE + if [[ "$?" -ne 0 ]]; then + >&2 echo "Unable to probe the '$WATCHDOG_TYPE' module" + exit 1 + fi + lsmod | grep -q -i $WATCHDOG_TYPE + if [[ "$?" -ne 0 ]]; then + >&2 echo "Unable to find the '$WATCHDOG_TYPE' module after probing it" + exit 1 + fi + + +id: watchdog/detect +category_id: com.canonical.plainbox::power-management +_summary: Detect presence of a Hardware Watchdog +_description: + Detect the watchdog is under the /sys/class/watchdog/ path and no other type of watchdog +flags: simple +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_hardware_watchdog == 'True' +environ: WATCHDOG_TYPE WATCHDOG_IDENTITY +command: + source=$(checkbox-support-image_checker -s| awk -F ": " '{print $2}') + if [[ $source == "oem" ]]; then + udev_resource.py -f WATCHDOG + elif [[ $source == "stock" ]]; then + if [ -z "$WATCHDOG_TYPE" ] || [ -z "$WATCHDOG_IDENTITY" ]; then + >&2 echo "Please define the WATCHDOG_TYPE and WATCHDOG_IDENTITY in advance" + exit 1 + fi + WATCHDOGDS=$(find /sys/class/watchdog/watchdog*[0-9]) + EXIT=$? + for w in $WATCHDOGDS; do + identity=$(cat "$w"/identity) + echo "Identity of $w: $identity" + if [[ "$identity" != "$WATCHDOG_IDENTITY" ]]; then + >&2 echo "Find an unmatched watchdog" + EXIT=1 + fi + done + exit $EXIT + else + >&2 echo "Unrecognized image source: $source" + exit 1 + fi + + +id: watchdog/set-timeout +category_id: com.canonical.plainbox::power-management +_summary: Configure the timeout for Hardware Watchdog +_description: + Configure the value of RuntimeWatchdogSec +flags: simple +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_hardware_watchdog == 'True' + image_source_and_type.source == 'stock' +depends: + watchdog/check-service + watchdog/detect +user: root command: - sync - sleep 5 - echo 1 > /proc/sys/kernel/sysrq - echo 0 > /proc/sys/kernel/panic - echo c > /proc/sysrq-trigger -flags: preserve-locale noreturn autorestart + DEFAULT_WATCHDOG="^#RuntimeWatchdogSec" + search_pattern="#RuntimeWatchdogSec=[0-9]*s*" + for i in {0..1} + do + result=`grep $DEFAULT_WATCHDOG /etc/systemd/system.conf` + if [[ -n "$result" && $i -eq 0 ]]; then + echo "Modifying the watchdog timeout" + sed -i "s/$search_pattern/RuntimeWatchdogSec=35/g" /etc/systemd/system.conf + elif [[ $i -eq 1 ]]; then + if [[ -n "$result" ]]; then + >&2 echo "Failed to set watchdog timeout"; RET=1 + else + echo "Watchdog timeout has been configured, reloading configuration" + systemctl daemon-reexec; RET=$? + if [[ $RET -ne 0 ]]; then + >&2 echo "Failed to reloading configuration" + fi + fi + else + echo "Watchdog timeout is already set" + break + fi + done + exit $RET + + +id: watchdog/revert-timeout +category_id: com.canonical.plainbox::power-management +_summary: Restore the timeout for Hardware Watchdog +_description: + Restore the value of RuntimeWatchdogSec +flags: simple +imports: from com.canonical.plainbox import manifest +requires: + manifest.has_hardware_watchdog == 'True' + image_source_and_type.source == 'stock' +depends: + watchdog/set-timeout user: root +command: + SET_WATCHDOG="RuntimeWatchdogSec=35" + for i in {0..1} + do + result=`grep $SET_WATCHDOG /etc/systemd/system.conf` + if [[ "$result" == "$SET_WATCHDOG" && $i -eq 0 ]]; then + echo "Modifying the watchdog timeout" + sed -i "s/$SET_WATCHDOG/#RuntimeWatchdogSec=0/g" /etc/systemd/system.conf + elif [[ $i -eq 1 ]]; then + if [[ "$result" == "$SET_WATCHDOG" ]]; then + >&2 echo "Failed to revert watchdog timeout"; RET=1 + else + echo "Watchdog timeout has been configured, reloading configuration" + systemctl daemon-reexec; RET=$? + if [[ $RET -ne 0 ]]; then + >&2 echo "Failed to reloading configuration" + fi + fi + else + timeout_value=`grep RuntimeWatchdogSec /etc/systemd/system.conf | awk -F '=' {'print $2'}` + echo "The watchdog timeout is $timeout_value now, not the value we set in previouse job" + echo "No need to revert watchdog timeout" + break + fi + done + exit $RET + + +id: watchdog/trigger-system-reset-auto plugin: shell category_id: com.canonical.plainbox::power-management +_summary: Test that the watchdog module can trigger a system reset +user: root +flags: noreturn autorestart estimated_duration: 60 -_purpose: Ensure that the watchdog module can successfully initiate a system reset. +depends: + watchdog/check-service + watchdog/detect +command: + sync + sleep 5 + echo 1 > /proc/sys/kernel/sysrq + echo 0 > /proc/sys/kernel/panic + echo c > /proc/sysrq-trigger + id: watchdog/post-trigger-system-reset-auto -after: watchdog/trigger-system-reset-auto +plugin: shell category_id: com.canonical.plainbox::power-management _summary: Post watchdog reset service check -_purpose: Check there are no failed services after the watchdog triggered -unit: job -plugin: shell -command: failed_service_check.sh +_description: Check there are no failed services after the watchdog triggered estimated_duration: 1.0 imports: from com.canonical.plainbox import manifest -requires: manifest.has_hardware_watchdog == 'True' +requires: + manifest.has_hardware_watchdog == 'True' +depends: + watchdog/trigger-system-reset-auto +command: failed_service_check.sh diff --git a/providers/base/units/watchdog/test-plan.pxu b/providers/base/units/watchdog/test-plan.pxu index dd2ecb1404..70e2c7c416 100644 --- a/providers/base/units/watchdog/test-plan.pxu +++ b/providers/base/units/watchdog/test-plan.pxu @@ -1,7 +1,7 @@ id: watchdog-full unit: test plan _name: Watchdog tests -_description: Watchdog tests for Ubuntu Core devices +_description: Watchdog tests include: nested_part: watchdog-manual @@ -10,15 +10,21 @@ nested_part: id: watchdog-manual unit: test plan _name: Manual watchdog tests -_description: Manual watchdog tests for Ubuntu Core devices +_description: Manual watchdog tests include: id: watchdog-automated unit: test plan _name: Automated watchdog tests -_description: Automated watchdog tests for Ubuntu Core devices +_description: Automated watchdog tests include: + watchdog/check-timeout + watchdog/check-service + watchdog/probe-module watchdog/detect - watchdog/systemd-config + watchdog/set-timeout watchdog/trigger-system-reset-auto watchdog/post-trigger-system-reset-auto + watchdog/revert-timeout +bootstrap_include: + image_source_and_type From 8b30f3891edb7229475be1e6163a75bbbff5ea73 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 1 Apr 2024 10:24:54 +0800 Subject: [PATCH 02/20] Add unittest for watchdog_config_test.py --- .../base/tests/test_watchdog_config_test.py | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 providers/base/tests/test_watchdog_config_test.py diff --git a/providers/base/tests/test_watchdog_config_test.py b/providers/base/tests/test_watchdog_config_test.py new file mode 100644 index 0000000000..d8a35ea139 --- /dev/null +++ b/providers/base/tests/test_watchdog_config_test.py @@ -0,0 +1,165 @@ +import unittest +import argparse +from unittest.mock import patch, Mock, MagicMock +from watchdog_config_test import ( + watchdog_argparse, + get_systemd_wdt_usec, + watchdog_service_check, + main, +) + + +class TestWatchdogConfigTest(unittest.TestCase): + + @patch( + "argparse.ArgumentParser.parse_args", + return_value=argparse.Namespace(check_time=True, check_service=False), + ) + def test_check_time_argument(self, mock_parse_args): + result = watchdog_argparse() + self.assertTrue(result.check_time) + self.assertFalse(result.check_service) + + @patch( + "argparse.ArgumentParser.parse_args", + return_value=argparse.Namespace(check_time=False, check_service=True), + ) + def test_check_service_argument(self, mock_parse_args): + result = watchdog_argparse() + self.assertFalse(result.check_time) + self.assertTrue(result.check_service) + + @patch("watchdog_config_test.subprocess.check_output") + def test_get_systemd_wdt_usec_success(self, mock_check_output): + # Mock subprocess.check_output to return a mock result + mock_check_output.return_value = "RuntimeWatchdogUSec=1000000\n" + + # Call the function under test + result = get_systemd_wdt_usec() + + # Assert that subprocess.check_output was called + # with the correct arguments + mock_check_output.assert_called_once_with( + ["systemctl", "show", "-p", "RuntimeWatchdogUSec"], + universal_newlines=True, + ) + + # Assert that the correct value was returned + self.assertEqual(result, "1000000") + + @patch("watchdog_config_test.subprocess.check_output") + def test_get_systemd_wdt_usec_exception(self, mock_check_output): + # Mock subprocess.check_output to raise an exception + mock_check_output.side_effect = Exception("Something went wrong") + + # Call the function under test + with self.assertRaises(SystemExit): + get_systemd_wdt_usec() + + @patch("watchdog_config_test.subprocess.check_output") + def test_get_systemd_wdt_usec_no_result(self, mock_check_output): + # Mock subprocess.check_output to return an empty result + mock_check_output.return_value = "" + + # Call the function under test + with self.assertRaises(SystemExit): + get_systemd_wdt_usec() + + @patch("watchdog_config_test.subprocess.run") + def test_watchdog_service_check_active(self, mock_subprocess_run): + # Mock subprocess.run to return a process with returncode 0 (active) + mock_process = Mock(returncode=0) + mock_subprocess_run.return_value = mock_process + + # Call the function under test + result = watchdog_service_check() + + # Assert that subprocess.run was called with the correct arguments + mock_subprocess_run.assert_called_once_with( + ["systemctl", "is-active", "watchdog.service", "--quiet"] + ) + + # Assert that the correct value was returned + self.assertTrue(result) + + @patch("watchdog_config_test.subprocess.run") + def test_watchdog_service_check_inactive(self, mock_subprocess_run): + # Mock subprocess.run to return a process with returncode 1 (inactive) + mock_process = Mock(returncode=1) + mock_subprocess_run.return_value = mock_process + + # Call the function under test + result = watchdog_service_check() + + # Assert that subprocess.run was called with the correct arguments + mock_subprocess_run.assert_called_once_with( + ["systemctl", "is-active", "watchdog.service", "--quiet"] + ) + + # Assert that the correct value was returned + self.assertFalse(result) + + @patch("watchdog_config_test.subprocess.run") + def test_watchdog_service_check_exception(self, mock_subprocess_run): + # Mock subprocess.run to raise an exception + mock_subprocess_run.side_effect = Exception("Something went wrong") + + # Call the function under test + with self.assertRaises(SystemExit): + watchdog_service_check() + + @patch('watchdog_config_test.watchdog_argparse') + @patch('watchdog_config_test.get_series') + @patch('watchdog_config_test.get_systemd_wdt_usec') + @patch('watchdog_config_test.on_ubuntucore') + @patch('watchdog_config_test.watchdog_service_check') + def test_main_check_time(self, mock_watchdog_service_check, mock_on_ubuntucore, mock_get_systemd_wdt_usec, mock_get_series, mock_watchdog_argparse): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = False + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "20.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = "1000000" + + # Call the function under test + with patch('builtins.print') as mock_print: + main() + + # Assert that the expected messages are printed + mock_print.assert_any_call("systemd watchdog enabled, reset timeout: 1000000") + + @patch('watchdog_config_test.watchdog_argparse') + @patch('watchdog_config_test.get_series') + @patch('watchdog_config_test.get_systemd_wdt_usec') + @patch('watchdog_config_test.on_ubuntucore') + @patch('watchdog_config_test.watchdog_service_check') + def test_main_check_service(self, mock_watchdog_service_check, mock_on_ubuntucore, mock_get_systemd_wdt_usec, mock_get_series, mock_watchdog_argparse): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = False + mock_args.check_service = True + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "20.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock watchdog_service_check + mock_watchdog_service_check.return_value = False + + # Call the function under test + with patch('builtins.print') as mock_print: + main() + + # Assert that the expected messages are printed + mock_print.assert_any_call("watchdog.service is not active") From 6df0108ef429b8ed770c1b737d377b9a01365db8 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 1 Apr 2024 11:09:28 +0800 Subject: [PATCH 03/20] Fix shell check --- providers/base/units/watchdog/jobs.pxu | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index bcbec7efe3..0ef1bd8f9c 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -41,18 +41,16 @@ requires: image_source_and_type.type == 'classic' environ: WATCHDOG_TYPE command: - if [[ ! -n "$WATCHDOG_TYPE" ]]; then + if [[ -z "$WATCHDOG_TYPE" ]]; then >&2 echo "WATCHDOG_TYPE is not available" exit 1 fi echo "Trying to probe '$WATCHDOG_TYPE' module" - modprobe $WATCHDOG_TYPE - if [[ "$?" -ne 0 ]]; then + if ! modprobe "$WATCHDOG_TYPE"; then >&2 echo "Unable to probe the '$WATCHDOG_TYPE' module" exit 1 fi - lsmod | grep -q -i $WATCHDOG_TYPE - if [[ "$?" -ne 0 ]]; then + if ! lsmod | grep -q -i "$WATCHDOG_TYPE"; then >&2 echo "Unable to find the '$WATCHDOG_TYPE' module after probing it" exit 1 fi @@ -113,7 +111,7 @@ command: search_pattern="#RuntimeWatchdogSec=[0-9]*s*" for i in {0..1} do - result=`grep $DEFAULT_WATCHDOG /etc/systemd/system.conf` + result=$(grep $DEFAULT_WATCHDOG /etc/systemd/system.conf) if [[ -n "$result" && $i -eq 0 ]]; then echo "Modifying the watchdog timeout" sed -i "s/$search_pattern/RuntimeWatchdogSec=35/g" /etc/systemd/system.conf @@ -132,7 +130,7 @@ command: break fi done - exit $RET + exit "$RET" id: watchdog/revert-timeout @@ -152,7 +150,7 @@ command: SET_WATCHDOG="RuntimeWatchdogSec=35" for i in {0..1} do - result=`grep $SET_WATCHDOG /etc/systemd/system.conf` + result=$(grep $SET_WATCHDOG /etc/systemd/system.conf) if [[ "$result" == "$SET_WATCHDOG" && $i -eq 0 ]]; then echo "Modifying the watchdog timeout" sed -i "s/$SET_WATCHDOG/#RuntimeWatchdogSec=0/g" /etc/systemd/system.conf @@ -167,13 +165,13 @@ command: fi fi else - timeout_value=`grep RuntimeWatchdogSec /etc/systemd/system.conf | awk -F '=' {'print $2'}` + timeout_value=$(grep RuntimeWatchdogSec /etc/systemd/system.conf | awk -F '=' '{print $2}') echo "The watchdog timeout is $timeout_value now, not the value we set in previouse job" echo "No need to revert watchdog timeout" break fi done - exit $RET + exit "$RET" id: watchdog/trigger-system-reset-auto From b0962069256680ec3639d05af1b262275992f0d0 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 1 Apr 2024 11:40:19 +0800 Subject: [PATCH 04/20] Increase unittest coverage --- .../base/tests/test_watchdog_config_test.py | 334 +++++++++++++++++- 1 file changed, 317 insertions(+), 17 deletions(-) diff --git a/providers/base/tests/test_watchdog_config_test.py b/providers/base/tests/test_watchdog_config_test.py index d8a35ea139..f9d6ddacea 100644 --- a/providers/base/tests/test_watchdog_config_test.py +++ b/providers/base/tests/test_watchdog_config_test.py @@ -108,12 +108,133 @@ def test_watchdog_service_check_exception(self, mock_subprocess_run): with self.assertRaises(SystemExit): watchdog_service_check() - @patch('watchdog_config_test.watchdog_argparse') - @patch('watchdog_config_test.get_series') - @patch('watchdog_config_test.get_systemd_wdt_usec') - @patch('watchdog_config_test.on_ubuntucore') - @patch('watchdog_config_test.watchdog_service_check') - def test_main_check_time(self, mock_watchdog_service_check, mock_on_ubuntucore, mock_get_systemd_wdt_usec, mock_get_series, mock_watchdog_argparse): + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_and_service( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = True + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "20.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = "1000000" + + # Mock watchdog_service_check + mock_watchdog_service_check.return_value = False + + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected messages are printed + mock_print.assert_any_call( + "systemd watchdog enabled, reset timeout: 1000000" + ) + mock_print.assert_any_call("watchdog.service is not active") + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_ubuntucore( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = False + mock_watchdog_argparse.return_value = mock_args + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = 1000000 + + # Mock get_series + mock_get_series.return_value = "18.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = True + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected messages are printed + mock_print.assert_any_call( + "systemd watchdog enabled, reset timeout: 1000000" + ) + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_not_active( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = False + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "20.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = "0" + + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected message is printed + mock_print.assert_any_call( + "systemd watchdog should be enabled but reset timeout: 0" + ) + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_and_systemd_wdt_configured( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): # Mock arguments mock_args = MagicMock() mock_args.check_time = True @@ -130,18 +251,94 @@ def test_main_check_time(self, mock_watchdog_service_check, mock_on_ubuntucore, mock_get_systemd_wdt_usec.return_value = "1000000" # Call the function under test - with patch('builtins.print') as mock_print: + with patch("builtins.print") as mock_print: + main() + # Assert that the expected messages are printed + mock_print.assert_any_call( + "systemd watchdog enabled, reset timeout: 1000000" + ) + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_and_watchdog_config_ready( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = False + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "18.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = "0" + + # Call the function under test + with patch("builtins.print") as mock_print: main() + # Assert that the expected messages are printed + mock_print.assert_any_call("systemd watchdog disabled") + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.get_systemd_wdt_usec") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_time_is_systemd_wdt_configured( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_systemd_wdt_usec, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = True + mock_args.check_service = False + mock_watchdog_argparse.return_value = mock_args + # Mock get_series + mock_get_series.return_value = "18.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock get_systemd_wdt_usec + mock_get_systemd_wdt_usec.return_value = "1000000" + + # Call the function under test + with patch("builtins.print") as mock_print: + main() # Assert that the expected messages are printed - mock_print.assert_any_call("systemd watchdog enabled, reset timeout: 1000000") - - @patch('watchdog_config_test.watchdog_argparse') - @patch('watchdog_config_test.get_series') - @patch('watchdog_config_test.get_systemd_wdt_usec') - @patch('watchdog_config_test.on_ubuntucore') - @patch('watchdog_config_test.watchdog_service_check') - def test_main_check_service(self, mock_watchdog_service_check, mock_on_ubuntucore, mock_get_systemd_wdt_usec, mock_get_series, mock_watchdog_argparse): + mock_print.assert_any_call( + "systemd watchdog should not be enabled but reset timeout: 1000000" + ) + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_service_ubuntucore_not_active( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_series, + mock_watchdog_argparse, + ): # Mock arguments mock_args = MagicMock() mock_args.check_time = False @@ -158,8 +355,111 @@ def test_main_check_service(self, mock_watchdog_service_check, mock_on_ubuntucor mock_watchdog_service_check.return_value = False # Call the function under test - with patch('builtins.print') as mock_print: + with patch("builtins.print") as mock_print: main() - # Assert that the expected messages are printed + # Assert that the expected message is printed mock_print.assert_any_call("watchdog.service is not active") + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_service_ubuntucore_is_wdt_service_configured( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = False + mock_args.check_service = True + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "20.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock watchdog_service_check + mock_watchdog_service_check.return_value = True + + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected message is printed + mock_print.assert_any_call( + "found unexpected active watchdog.service unit" + ) + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_service_active( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = False + mock_args.check_service = True + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "18.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock watchdog_service_check + mock_watchdog_service_check.return_value = True + + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected message is printed + mock_print.assert_any_call("watchdog.service is active") + + @patch("watchdog_config_test.watchdog_argparse") + @patch("watchdog_config_test.get_series") + @patch("watchdog_config_test.on_ubuntucore") + @patch("watchdog_config_test.watchdog_service_check") + def test_main_check_service_is_wdt_service_configured( + self, + mock_watchdog_service_check, + mock_on_ubuntucore, + mock_get_series, + mock_watchdog_argparse, + ): + # Mock arguments + mock_args = MagicMock() + mock_args.check_time = False + mock_args.check_service = True + mock_watchdog_argparse.return_value = mock_args + + # Mock get_series + mock_get_series.return_value = "18.04" + + # Mock on_ubuntucore + mock_on_ubuntucore.return_value = False + + # Mock watchdog_service_check + mock_watchdog_service_check.return_value = False + + # Call the function under test + with patch("builtins.print") as mock_print: + main() + + # Assert that the expected message is printed + mock_print.assert_any_call( + "watchdog.service unit does not report as active" + ) From 3130eaa322693ca56812e8ba10453d1248c30b00 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Wed, 17 Apr 2024 16:09:53 +0800 Subject: [PATCH 05/20] Fix black --- providers/base/bin/watchdog_config_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index e975e55321..bc72326444 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -17,12 +17,12 @@ # You should have received a copy of the GNU General Public License # along with Checkbox. If not, see . -''' +""" Watchdog implementation on both classic and core image no longer rely on watchdogd service since 20.04, with this change watchdog/systemd-config tests only systemd configuration on 20.04 and later series while keeping the original test for prior releases -''' +""" import subprocess import argparse @@ -34,8 +34,8 @@ def watchdog_argparse(): parser = argparse.ArgumentParser() - parser.add_argument('-t', '--check_time', action='store_true') - parser.add_argument('-s', '--check_service', action='store_true') + parser.add_argument("-t", "--check_time", action="store_true") + parser.add_argument("-s", "--check_service", action="store_true") return parser.parse_args() From d3a1ee17ff99c207db83281ddc3a9429f5ee4a42 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Wed, 17 Apr 2024 16:23:21 +0800 Subject: [PATCH 06/20] Fix watchdog_config_test.py --- providers/base/bin/watchdog_config_test.py | 82 ++++++++++++---------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index bc72326444..63c7419854 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -26,7 +26,6 @@ import subprocess import argparse -import sys from checkbox_support.snap_utils.system import on_ubuntucore from checkbox_support.snap_utils.system import get_series @@ -71,45 +70,56 @@ def watchdog_service_check(): def main(): - runtime_watchdog_usec = get_systemd_wdt_usec() - systemd_wdt_configured = runtime_watchdog_usec != "0" - wdt_service_configured = watchdog_service_check() + args = watchdog_argparse() + ubuntu_version = int(get_series().split(".")[0]) watchdog_config_ready = True - if (ubuntu_version >= 20) or (on_ubuntucore()): - if not systemd_wdt_configured: - print( - "systemd watchdog should be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if wdt_service_configured: - print("found unexpected active watchdog.service unit") - watchdog_config_ready = False - if watchdog_config_ready: - print( - "systemd watchdog enabled, reset timeout: {}".format( - runtime_watchdog_usec + if args.check_time: + runtime_watchdog_usec = get_systemd_wdt_usec() + is_systemd_wdt_configured = runtime_watchdog_usec != "0" + + if (ubuntu_version >= 20) or (on_ubuntucore()): + if not is_systemd_wdt_configured: + print( + "systemd watchdog should be enabled but reset timeout: " + "{}".format(runtime_watchdog_usec) ) - ) - print("watchdog.service is not active") - else: - if systemd_wdt_configured: - print( - "systemd watchdog should not be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if not wdt_service_configured: - print("watchdog.service unit does not report as active") - watchdog_config_ready = False - if watchdog_config_ready: - print("systemd watchdog disabled") - print("watchdog.service active") - - return not watchdog_config_ready + watchdog_config_ready = False + if watchdog_config_ready: + print( + "systemd watchdog enabled, reset timeout: {}".format( + runtime_watchdog_usec + ) + ) + else: + if is_systemd_wdt_configured: + print( + "systemd watchdog should not be enabled but reset timeout: " + "{}".format(runtime_watchdog_usec) + ) + watchdog_config_ready = False + if watchdog_config_ready: + print("systemd watchdog disabled") + + if args.check_service: + is_wdt_service_configured = watchdog_service_check() + + if (ubuntu_version >= 20) or (on_ubuntucore()): + if is_wdt_service_configured: + print("found unexpected active watchdog.service unit") + watchdog_config_ready = False + if watchdog_config_ready: + print("watchdog.service is not active") + else: + if not is_wdt_service_configured: + print("watchdog.service unit does not report as active") + watchdog_config_ready = False + if watchdog_config_ready: + print("watchdog.service active") + + raise SystemExit(not watchdog_config_ready) if __name__ == "__main__": - sys.exit(main()) + main() From 3c51c3a63be3d5c62a47ea8928a153b64ce4af06 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Wed, 17 Apr 2024 16:48:05 +0800 Subject: [PATCH 07/20] Fix blake8 --- providers/base/bin/watchdog_config_test.py | 4 +- providers/base/tests/watchdog_config_test.py | 126 +++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100755 providers/base/tests/watchdog_config_test.py diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index 63c7419854..b78b3bca28 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -95,8 +95,8 @@ def main(): else: if is_systemd_wdt_configured: print( - "systemd watchdog should not be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) + "systemd watchdog should not be enabled but " + "reset timeout: {}".format(runtime_watchdog_usec) ) watchdog_config_ready = False if watchdog_config_ready: diff --git a/providers/base/tests/watchdog_config_test.py b/providers/base/tests/watchdog_config_test.py new file mode 100755 index 0000000000..66c6ac246e --- /dev/null +++ b/providers/base/tests/watchdog_config_test.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# Copyright 2021 Canonical Ltd. +# All rights reserved. +# +# Written by: +# Vic Liu +# +# Checkbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# Checkbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Checkbox. If not, see . + +""" +Watchdog implementation on both classic and core image no longer rely +on watchdogd service since 20.04, with this change watchdog/systemd-config +tests only systemd configuration on 20.04 and later series while keeping +the original test for prior releases +""" + +import subprocess +import argparse + +from checkbox_support.snap_utils.system import on_ubuntucore +from checkbox_support.snap_utils.system import get_series +from yaml import parse + + +def watchdog_argparse(): + parser = argparse.ArgumentParser() + parser.add_argument("-t", "--check_time", action="store_true") + parser.add_argument("-s", "--check_service", action="store_true") + + return parser.parse_args() + + +def get_systemd_wdt_usec(): + """ + Return value of systemd-watchdog RuntimeWatchdogUSec + """ + cmd = ["systemctl", "show", "-p", "RuntimeWatchdogUSec"] + try: + result = subprocess.check_output(cmd, universal_newlines=True) + except Exception as err: + raise SystemExit("Error: {}".format(err)) + + if result: + runtime_watchdog_usec = result.split("=")[1].strip() + return runtime_watchdog_usec + else: + raise SystemExit( + "Unexpected failure occurred when executing: {}".format(cmd) + ) + + +def watchdog_service_check(): + """ + Check if the watchdog service is configured correctly + """ + cmd = ["systemctl", "is-active", "watchdog.service", "--quiet"] + try: + return not subprocess.run(cmd).returncode + except Exception as err: + raise SystemExit("Error: {}".format(err)) + + +def main(): + args = watchdog_argparse() + + ubuntu_version = int(get_series().split(".")[0]) + watchdog_config_ready = True + + if args.check_time: + runtime_watchdog_usec = get_systemd_wdt_usec() + is_systemd_wdt_configured = runtime_watchdog_usec != "0" + + if (ubuntu_version >= 20) or (on_ubuntucore()): + if not is_systemd_wdt_configured: + print( + "systemd watchdog should be enabled but reset timeout: " + "{}".format(runtime_watchdog_usec) + ) + watchdog_config_ready = False + if watchdog_config_ready: + print( + "systemd watchdog enabled, reset timeout: {}".format( + runtime_watchdog_usec + ) + ) + else: + if is_systemd_wdt_configured: + print( + "systemd watchdog should not be enabled but reset timeout: " + "{}".format(runtime_watchdog_usec) + ) + watchdog_config_ready = False + if watchdog_config_ready: + print("systemd watchdog disabled") + + if args.check_service: + is_wdt_service_configured = watchdog_service_check() + + if (ubuntu_version >= 20) or (on_ubuntucore()): + if is_wdt_service_configured: + print("found unexpected active watchdog.service unit") + watchdog_config_ready = False + if watchdog_config_ready: + print("watchdog.service is not active") + else: + if not is_wdt_service_configured: + print("watchdog.service unit does not report as active") + watchdog_config_ready = False + if watchdog_config_ready: + print("watchdog.service active") + + raise SystemExit(not watchdog_config_ready) + + +if __name__ == "__main__": + main() From 89777842b95c9140b76f8fb923c9330e85f1f8d1 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Wed, 17 Apr 2024 17:50:59 +0800 Subject: [PATCH 08/20] Fix unittest and watchdog --- providers/base/bin/watchdog_config_test.py | 4 ++-- providers/base/tests/watchdog_config_test.py | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index b78b3bca28..6e7fad8e3d 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -116,9 +116,9 @@ def main(): print("watchdog.service unit does not report as active") watchdog_config_ready = False if watchdog_config_ready: - print("watchdog.service active") + print("watchdog.service is active") - raise SystemExit(not watchdog_config_ready) + return not watchdog_config_ready if __name__ == "__main__": diff --git a/providers/base/tests/watchdog_config_test.py b/providers/base/tests/watchdog_config_test.py index 66c6ac246e..6e7fad8e3d 100755 --- a/providers/base/tests/watchdog_config_test.py +++ b/providers/base/tests/watchdog_config_test.py @@ -29,7 +29,6 @@ from checkbox_support.snap_utils.system import on_ubuntucore from checkbox_support.snap_utils.system import get_series -from yaml import parse def watchdog_argparse(): @@ -96,8 +95,8 @@ def main(): else: if is_systemd_wdt_configured: print( - "systemd watchdog should not be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) + "systemd watchdog should not be enabled but " + "reset timeout: {}".format(runtime_watchdog_usec) ) watchdog_config_ready = False if watchdog_config_ready: @@ -117,9 +116,9 @@ def main(): print("watchdog.service unit does not report as active") watchdog_config_ready = False if watchdog_config_ready: - print("watchdog.service active") + print("watchdog.service is active") - raise SystemExit(not watchdog_config_ready) + return not watchdog_config_ready if __name__ == "__main__": From 6bcc64d8874a73dcffa523983c9633ad192c5dbf Mon Sep 17 00:00:00 2001 From: liaou3 Date: Fri, 19 Apr 2024 10:19:44 +0800 Subject: [PATCH 09/20] Remove watchdog in tests --- providers/base/tests/watchdog_config_test.py | 125 ------------------- 1 file changed, 125 deletions(-) delete mode 100755 providers/base/tests/watchdog_config_test.py diff --git a/providers/base/tests/watchdog_config_test.py b/providers/base/tests/watchdog_config_test.py deleted file mode 100755 index 6e7fad8e3d..0000000000 --- a/providers/base/tests/watchdog_config_test.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 Canonical Ltd. -# All rights reserved. -# -# Written by: -# Vic Liu -# -# Checkbox is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, -# as published by the Free Software Foundation. -# -# Checkbox is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Checkbox. If not, see . - -""" -Watchdog implementation on both classic and core image no longer rely -on watchdogd service since 20.04, with this change watchdog/systemd-config -tests only systemd configuration on 20.04 and later series while keeping -the original test for prior releases -""" - -import subprocess -import argparse - -from checkbox_support.snap_utils.system import on_ubuntucore -from checkbox_support.snap_utils.system import get_series - - -def watchdog_argparse(): - parser = argparse.ArgumentParser() - parser.add_argument("-t", "--check_time", action="store_true") - parser.add_argument("-s", "--check_service", action="store_true") - - return parser.parse_args() - - -def get_systemd_wdt_usec(): - """ - Return value of systemd-watchdog RuntimeWatchdogUSec - """ - cmd = ["systemctl", "show", "-p", "RuntimeWatchdogUSec"] - try: - result = subprocess.check_output(cmd, universal_newlines=True) - except Exception as err: - raise SystemExit("Error: {}".format(err)) - - if result: - runtime_watchdog_usec = result.split("=")[1].strip() - return runtime_watchdog_usec - else: - raise SystemExit( - "Unexpected failure occurred when executing: {}".format(cmd) - ) - - -def watchdog_service_check(): - """ - Check if the watchdog service is configured correctly - """ - cmd = ["systemctl", "is-active", "watchdog.service", "--quiet"] - try: - return not subprocess.run(cmd).returncode - except Exception as err: - raise SystemExit("Error: {}".format(err)) - - -def main(): - args = watchdog_argparse() - - ubuntu_version = int(get_series().split(".")[0]) - watchdog_config_ready = True - - if args.check_time: - runtime_watchdog_usec = get_systemd_wdt_usec() - is_systemd_wdt_configured = runtime_watchdog_usec != "0" - - if (ubuntu_version >= 20) or (on_ubuntucore()): - if not is_systemd_wdt_configured: - print( - "systemd watchdog should be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if watchdog_config_ready: - print( - "systemd watchdog enabled, reset timeout: {}".format( - runtime_watchdog_usec - ) - ) - else: - if is_systemd_wdt_configured: - print( - "systemd watchdog should not be enabled but " - "reset timeout: {}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if watchdog_config_ready: - print("systemd watchdog disabled") - - if args.check_service: - is_wdt_service_configured = watchdog_service_check() - - if (ubuntu_version >= 20) or (on_ubuntucore()): - if is_wdt_service_configured: - print("found unexpected active watchdog.service unit") - watchdog_config_ready = False - if watchdog_config_ready: - print("watchdog.service is not active") - else: - if not is_wdt_service_configured: - print("watchdog.service unit does not report as active") - watchdog_config_ready = False - if watchdog_config_ready: - print("watchdog.service is active") - - return not watchdog_config_ready - - -if __name__ == "__main__": - main() From 23563518ddbc40d253c83aeb77a5615a9629c236 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 6 May 2024 16:52:40 +0800 Subject: [PATCH 10/20] Fix the suggestions from @Hook25 --- providers/base/bin/watchdog_config_test.py | 340 +++++++++++++++++---- providers/base/units/watchdog/jobs.pxu | 79 +---- 2 files changed, 293 insertions(+), 126 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index 6e7fad8e3d..20d939af66 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -26,20 +26,69 @@ import subprocess import argparse +import shlex +import os +import re from checkbox_support.snap_utils.system import on_ubuntucore from checkbox_support.snap_utils.system import get_series +from checkbox_support.scripts.image_checker import get_source -def watchdog_argparse(): - parser = argparse.ArgumentParser() - parser.add_argument("-t", "--check_time", action="store_true") - parser.add_argument("-s", "--check_service", action="store_true") +def watchdog_argparse() -> argparse.Namespace: + """ + Parse command line arguments and return the parsed arguments. + + This function parses the command line arguments and returns the parsed + arguments. The arguments are parsed using the `argparse` module. The + function takes no parameters. + Returns: + argparse.Namespace: The parsed command line arguments. + """ + parser = argparse.ArgumentParser( + prog="Watchdog Testing Tool", + description="This is a tool to help you perform the watchdog testing", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "-t", + "--check_time", + action="store_true", + help="Check if watchdog service timeout is configured correctly", + ) + group.add_argument( + "-s", + "--check-service", + action="store_true", + help="Check if watchdog service is running", + ) + group.add_argument( + "-d", + "--detect", + action="store_true", + help="Check if there is watchdog under the /sys/class/watchdog/ " + "and no other type of watchdog is detected", + ) + group.add_argument( + "--set-timeout", + nargs='?', + const=35, + type=int, + help="Set the timeout for watchdog service", + ) + group.add_argument( + "--revert-timeout", + nargs='?', + const=35, + type=int, + help="Revert the timeout for watchdog service", + ) return parser.parse_args() -def get_systemd_wdt_usec(): +def get_systemd_wdt_usec() -> str: """ Return value of systemd-watchdog RuntimeWatchdogUSec """ @@ -58,7 +107,7 @@ def get_systemd_wdt_usec(): ) -def watchdog_service_check(): +def watchdog_service_check() -> bool: """ Check if the watchdog service is configured correctly """ @@ -69,56 +118,243 @@ def watchdog_service_check(): raise SystemExit("Error: {}".format(err)) -def main(): - args = watchdog_argparse() +def check_timeout() -> bool: + ubuntu_version: int = int(get_series().split(".")[0]) + runtime_watchdog_usec: str = get_systemd_wdt_usec() + is_systemd_wdt_configured: bool = runtime_watchdog_usec != "0" + + if ubuntu_version >= 20 or on_ubuntucore(): + if not is_systemd_wdt_configured: + raise SystemExit( + "systemd watchdog should be enabled but reset timeout: " + "{}".format(runtime_watchdog_usec) + ) + print( + "systemd watchdog enabled, reset timeout: {}".format( + runtime_watchdog_usec + ) + ) + else: + if is_systemd_wdt_configured: + raise SystemExit( + "systemd watchdog should not be enabled but " + "reset timeout: {}".format(runtime_watchdog_usec) + ) + print("systemd watchdog disabled") + +def check_service() -> bool: ubuntu_version = int(get_series().split(".")[0]) - watchdog_config_ready = True + is_wdt_service_configured = watchdog_service_check() - if args.check_time: - runtime_watchdog_usec = get_systemd_wdt_usec() - is_systemd_wdt_configured = runtime_watchdog_usec != "0" - - if (ubuntu_version >= 20) or (on_ubuntucore()): - if not is_systemd_wdt_configured: - print( - "systemd watchdog should be enabled but reset timeout: " - "{}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if watchdog_config_ready: - print( - "systemd watchdog enabled, reset timeout: {}".format( - runtime_watchdog_usec + if ubuntu_version >= 20 or on_ubuntucore(): + if is_wdt_service_configured: + raise SystemExit("Found unexpected active watchdog.service unit") + print("watchdog.service is not active") + else: + if not is_wdt_service_configured: + raise SystemExit("watchdog.service unit does not report as active") + print("watchdog.service is active") + + +def detect() -> None: + """ + Detects watchdog under /sys/class/watchdog/ and no other type of watchdog. + + This function executes the watchdog detection process based on the image + source. For OEM images, it runs the `udev_resource.py` script with the + argument "-f WATCHDOG". For stock images, it checks if the environment + variables "WATCHDOG_TYPE" and "WATCHDOG_IDENTITY" are set. It then iterates + over the watchdog devices under "/sys/class/watchdog/", verifies their + identities, and raises an exception if an unmatched watchdog is found. + + Raises: + SystemExit: When the image source is not recognized or when the + environment variables "WATCHDOG_TYPE" or "WATCHDOG_IDENTITY" are not + set for stock images. + """ + # Get the image source + source = get_source() + + # Handle OEM image source + if source == "oem": + cmd = "udev_resource.py -f WATCHDOG" + result = subprocess.run( + shlex.split(cmd), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + timeout=10, + text=True, + ) + if result.returncode: + raise SystemExit("[ERROR] {}".format(result.stderr.strip())) + print(result.stdout.strip()) + + # Handle stock image source + elif source == "stock": + # Check if environment variables are set + if "WATCHDOG_TYPE" not in os.environ or \ + "WATCHDOG_IDENTITY" not in os.environ: + raise SystemExit( + "WATCHDOG_TYPE or WATCHDOG_IDENTITY not set!\n" + "Please define the WATCHDOG_TYPE and WATCHDOG_IDENTITY " + "in advance!" + ) + + # Iterate over watchdog devices + watchdogs = os.listdir("/sys/class/watchdog") + for watchdog in watchdogs: + if not watchdog.startswith("watchdog"): + continue + + # Get the identity of the watchdog + path = "/sys/class/watchdog/{}/identity".format(watchdog) + with open(path, "r") as f: + identity = f.readline().strip() + print("Identity of {}: {}".format(path, identity)) + + # Check if the identity matches the expected identity + if identity != os.environ["WATCHDOG_IDENTITY"]: + raise SystemExit( + "Found an unmatched watchdog!\n" + "Expected: {}\n" + "Found: {}".format( + os.environ["WATCHDOG_IDENTITY"], identity + ) ) - ) - else: - if is_systemd_wdt_configured: - print( - "systemd watchdog should not be enabled but " - "reset timeout: {}".format(runtime_watchdog_usec) - ) - watchdog_config_ready = False - if watchdog_config_ready: - print("systemd watchdog disabled") - - if args.check_service: - is_wdt_service_configured = watchdog_service_check() - - if (ubuntu_version >= 20) or (on_ubuntucore()): - if is_wdt_service_configured: - print("found unexpected active watchdog.service unit") - watchdog_config_ready = False - if watchdog_config_ready: - print("watchdog.service is not active") - else: - if not is_wdt_service_configured: - print("watchdog.service unit does not report as active") - watchdog_config_ready = False - if watchdog_config_ready: - print("watchdog.service is active") - - return not watchdog_config_ready + + # Handle unrecognized image source + else: + raise SystemExit("Unrecognized image source: {}".format(source)) + + +def set_timeout(timeout: int = 35) -> None: + """ + Sets the watchdog timeout in /etc/systemd/system.conf + and reloads configuration. + + Args: + timeout (int): Timeout value in seconds. Default is 35. + + Raises: + SystemExit: If there is an error in reloading the configuration. + """ + # Pattern to match the line containing the current watchdog timeout + pattern = r"#RuntimeWatchdogSec=.*" + + # Read the contents of /etc/systemd/system.conf + with open("/etc/systemd/system.conf", "r") as f: + text = f.read() + + # Check if the timeout is already set + if not re.search(pattern, text): + print("Watchdog timeout is already set") + return + + # Substitute the current timeout with the new one + text = re.sub( + pattern, "RuntimeWatchdogSec={}".format(timeout), + text, + flags=re.MULTILINE + ) + + print("Configuring Watchdog timeout...") + # Write the updated configuration to /etc/systemd/system.conf + with open("/etc/systemd/system.conf", "w") as f: + f.write(text) + + print("Reloading configuration...") + # Reload the configuration + cmd = "systemctl daemon-reexec" + res = subprocess.run( + shlex.split(cmd), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + # Raise an error if there was an error in reloading the configuration + if res.returncode: + raise SystemExit( + "[ERROR] {}".format(res.stderr.strip()) + ) + + # Print the new timeout value + print("Watchdog timeout is now set to {}".format(timeout)) + + +def revert_timeout(timeout: int = 35) -> None: + """ + Revert the watchdog timeout to 0 in /etc/systemd/system.conf + and reload the configuration. + + Args: + timeout (int): The timeout value to revert to. Default is 35. + + Raises: + SystemExit: If the timeout pattern is not found in the + configuration file or if there is an error in reloading the + configuration. + """ + # Pattern to match the line containing the current watchdog timeout + pattern = "RuntimeWatchdogSec={}".format(timeout) + + # Read the contents of /etc/systemd/system.conf + with open("/etc/systemd/system.conf", "r") as f: + text = f.read() + + # Check if the timeout is already set + if not re.search(pattern, text): + raise SystemExit( + "Could not find Watchdog timeout equal to " + "{} in /etc/systemd/system.conf".format(timeout)) + + # Substitute the current timeout with 0 + text = re.sub( + pattern, + "#RuntimeWatchdogSec=0", + text, + flags=re.MULTILINE, + ) + + print("Configuring Watchdog timeout...") + # Write the updated configuration to /etc/systemd/system.conf + with open("/etc/systemd/system.conf", "w") as f: + f.write(text) + + print("Reloading configuration...") + # Reload the configuration + cmd = "systemctl daemon-reexec" + res = subprocess.run( + shlex.split(cmd), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + + # Raise an error if there was an error in reloading the configuration + if res.returncode: + raise SystemExit( + "[ERROR] {}".format(res.stderr.strip()) + ) + + # Print the new timeout value + print("Watchdog timeout is now set to 0 and disabled") + + +def main(): + args = watchdog_argparse() + if args.check_time: + check_timeout() + elif args.check_service: + check_service() + elif args.detect: + detect() + elif args.set_timeout: + set_timeout(args.set_timeout) + elif args.revert_timeout: + revert_timeout(args.revert_timeout) + else: + raise SystemExit("Unexpected arguments") if __name__ == "__main__": diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index 0ef1bd8f9c..73e31aa122 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -9,7 +9,7 @@ imports: from com.canonical.plainbox import manifest requires: manifest.has_hardware_watchdog == 'True' image_source_and_type.source == 'oem' -command: watchdog_config_test.py --check_time +command: watchdog_config_test.py --check-time id: watchdog/check-service @@ -23,7 +23,7 @@ flags: simple imports: from com.canonical.plainbox import manifest requires: manifest.has_hardware_watchdog == 'True' -command: watchdog_config_test.py --check_service +command: watchdog_config_test.py --check-service id: watchdog/probe-module @@ -67,29 +67,7 @@ requires: manifest.has_hardware_watchdog == 'True' environ: WATCHDOG_TYPE WATCHDOG_IDENTITY command: - source=$(checkbox-support-image_checker -s| awk -F ": " '{print $2}') - if [[ $source == "oem" ]]; then - udev_resource.py -f WATCHDOG - elif [[ $source == "stock" ]]; then - if [ -z "$WATCHDOG_TYPE" ] || [ -z "$WATCHDOG_IDENTITY" ]; then - >&2 echo "Please define the WATCHDOG_TYPE and WATCHDOG_IDENTITY in advance" - exit 1 - fi - WATCHDOGDS=$(find /sys/class/watchdog/watchdog*[0-9]) - EXIT=$? - for w in $WATCHDOGDS; do - identity=$(cat "$w"/identity) - echo "Identity of $w: $identity" - if [[ "$identity" != "$WATCHDOG_IDENTITY" ]]; then - >&2 echo "Find an unmatched watchdog" - EXIT=1 - fi - done - exit $EXIT - else - >&2 echo "Unrecognized image source: $source" - exit 1 - fi + watchdog_config_test.py --detect id: watchdog/set-timeout @@ -107,30 +85,7 @@ depends: watchdog/detect user: root command: - DEFAULT_WATCHDOG="^#RuntimeWatchdogSec" - search_pattern="#RuntimeWatchdogSec=[0-9]*s*" - for i in {0..1} - do - result=$(grep $DEFAULT_WATCHDOG /etc/systemd/system.conf) - if [[ -n "$result" && $i -eq 0 ]]; then - echo "Modifying the watchdog timeout" - sed -i "s/$search_pattern/RuntimeWatchdogSec=35/g" /etc/systemd/system.conf - elif [[ $i -eq 1 ]]; then - if [[ -n "$result" ]]; then - >&2 echo "Failed to set watchdog timeout"; RET=1 - else - echo "Watchdog timeout has been configured, reloading configuration" - systemctl daemon-reexec; RET=$? - if [[ $RET -ne 0 ]]; then - >&2 echo "Failed to reloading configuration" - fi - fi - else - echo "Watchdog timeout is already set" - break - fi - done - exit "$RET" + watchdog_config_test.py --set-timeout ${WATCHDOG_TIMEOUT:-35} id: watchdog/revert-timeout @@ -147,31 +102,7 @@ depends: watchdog/set-timeout user: root command: - SET_WATCHDOG="RuntimeWatchdogSec=35" - for i in {0..1} - do - result=$(grep $SET_WATCHDOG /etc/systemd/system.conf) - if [[ "$result" == "$SET_WATCHDOG" && $i -eq 0 ]]; then - echo "Modifying the watchdog timeout" - sed -i "s/$SET_WATCHDOG/#RuntimeWatchdogSec=0/g" /etc/systemd/system.conf - elif [[ $i -eq 1 ]]; then - if [[ "$result" == "$SET_WATCHDOG" ]]; then - >&2 echo "Failed to revert watchdog timeout"; RET=1 - else - echo "Watchdog timeout has been configured, reloading configuration" - systemctl daemon-reexec; RET=$? - if [[ $RET -ne 0 ]]; then - >&2 echo "Failed to reloading configuration" - fi - fi - else - timeout_value=$(grep RuntimeWatchdogSec /etc/systemd/system.conf | awk -F '=' '{print $2}') - echo "The watchdog timeout is $timeout_value now, not the value we set in previouse job" - echo "No need to revert watchdog timeout" - break - fi - done - exit "$RET" + watchdog_config_test.py --revert-timeout ${WATCHDOG_TIMEOUT:-35} id: watchdog/trigger-system-reset-auto From b1b17c23ff4e3011d842f9da758b9538d2f02dc2 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 6 May 2024 16:55:16 +0800 Subject: [PATCH 11/20] Fix black --- providers/base/bin/watchdog_config_test.py | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index 20d939af66..db36079bb8 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -73,14 +73,14 @@ def watchdog_argparse() -> argparse.Namespace: ) group.add_argument( "--set-timeout", - nargs='?', + nargs="?", const=35, type=int, help="Set the timeout for watchdog service", ) group.add_argument( "--revert-timeout", - nargs='?', + nargs="?", const=35, type=int, help="Revert the timeout for watchdog service", @@ -193,8 +193,10 @@ def detect() -> None: # Handle stock image source elif source == "stock": # Check if environment variables are set - if "WATCHDOG_TYPE" not in os.environ or \ - "WATCHDOG_IDENTITY" not in os.environ: + if ( + "WATCHDOG_TYPE" not in os.environ + or "WATCHDOG_IDENTITY" not in os.environ + ): raise SystemExit( "WATCHDOG_TYPE or WATCHDOG_IDENTITY not set!\n" "Please define the WATCHDOG_TYPE and WATCHDOG_IDENTITY " @@ -253,9 +255,10 @@ def set_timeout(timeout: int = 35) -> None: # Substitute the current timeout with the new one text = re.sub( - pattern, "RuntimeWatchdogSec={}".format(timeout), + pattern, + "RuntimeWatchdogSec={}".format(timeout), text, - flags=re.MULTILINE + flags=re.MULTILINE, ) print("Configuring Watchdog timeout...") @@ -274,9 +277,7 @@ def set_timeout(timeout: int = 35) -> None: ) # Raise an error if there was an error in reloading the configuration if res.returncode: - raise SystemExit( - "[ERROR] {}".format(res.stderr.strip()) - ) + raise SystemExit("[ERROR] {}".format(res.stderr.strip())) # Print the new timeout value print("Watchdog timeout is now set to {}".format(timeout)) @@ -306,7 +307,8 @@ def revert_timeout(timeout: int = 35) -> None: if not re.search(pattern, text): raise SystemExit( "Could not find Watchdog timeout equal to " - "{} in /etc/systemd/system.conf".format(timeout)) + "{} in /etc/systemd/system.conf".format(timeout) + ) # Substitute the current timeout with 0 text = re.sub( @@ -333,9 +335,7 @@ def revert_timeout(timeout: int = 35) -> None: # Raise an error if there was an error in reloading the configuration if res.returncode: - raise SystemExit( - "[ERROR] {}".format(res.stderr.strip()) - ) + raise SystemExit("[ERROR] {}".format(res.stderr.strip())) # Print the new timeout value print("Watchdog timeout is now set to 0 and disabled") From b0c8721e036cdb92b20cb051269857afdb25e38d Mon Sep 17 00:00:00 2001 From: LiaoU3 <58060146+LiaoU3@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:17:58 +0800 Subject: [PATCH 12/20] Update providers/base/bin/watchdog_config_test.py Co-authored-by: Massimiliano --- providers/base/bin/watchdog_config_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index db36079bb8..fe0d7ae3d4 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -242,7 +242,7 @@ def set_timeout(timeout: int = 35) -> None: SystemExit: If there is an error in reloading the configuration. """ # Pattern to match the line containing the current watchdog timeout - pattern = r"#RuntimeWatchdogSec=.*" + pattern = r".?RuntimeWatchdogSec=.*" # Read the contents of /etc/systemd/system.conf with open("/etc/systemd/system.conf", "r") as f: From 1dbc969cdb0e8c313717805b6dae6f055063d64e Mon Sep 17 00:00:00 2001 From: LiaoU3 <58060146+LiaoU3@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:20:00 +0800 Subject: [PATCH 13/20] Update providers/base/units/watchdog/jobs.pxu Co-authored-by: Massimiliano --- providers/base/units/watchdog/jobs.pxu | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index 73e31aa122..b177814091 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -16,9 +16,8 @@ id: watchdog/check-service category_id: com.canonical.plainbox::power-management _summary: Check the watchdog.service is enabled or not _description: - Check the watchdog.service is enabled or not. - Watchdog implementation on both classic and core image no longer rely - on watchdogd service since 20.04. + Check the state of the watchdog.service. It must be disabled/missing + on both classic and core images since 20.04. Else it must be enabled. flags: simple imports: from com.canonical.plainbox import manifest requires: From a48651b301acb05158fda7dbee60e617cb9f0b71 Mon Sep 17 00:00:00 2001 From: LiaoU3 <58060146+LiaoU3@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:20:11 +0800 Subject: [PATCH 14/20] Update providers/base/units/watchdog/jobs.pxu Co-authored-by: Massimiliano --- providers/base/units/watchdog/jobs.pxu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index b177814091..efd1ac1e9f 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -2,8 +2,8 @@ id: watchdog/check-timeout category_id: com.canonical.plainbox::power-management _summary: Check the timeout of Hardware Watchdog _description: - Check the value of RuntimeWatchdogUSec shouldn't be 0 in OEM image. - It means the systemd watchdog is disabled if the value is 0. + Check the value of RuntimeWatchdogUSec that shouldn't be 0 or unset + in OEM images because that means that the watchdog is disabled. flags: simple imports: from com.canonical.plainbox import manifest requires: From 9fb6b0d5f87c5f1ee37eaeb4937c7c56f748d4f6 Mon Sep 17 00:00:00 2001 From: LiaoU3 <58060146+LiaoU3@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:20:23 +0800 Subject: [PATCH 15/20] Update providers/base/units/watchdog/jobs.pxu Co-authored-by: Massimiliano --- providers/base/units/watchdog/jobs.pxu | 1 + 1 file changed, 1 insertion(+) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index efd1ac1e9f..ef979a25ec 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -99,6 +99,7 @@ requires: image_source_and_type.source == 'stock' depends: watchdog/set-timeout +environ: WATCHDOG_TIMEOUT user: root command: watchdog_config_test.py --revert-timeout ${WATCHDOG_TIMEOUT:-35} From 385a2f92df8c43184acf42472399ee23c5f8e2da Mon Sep 17 00:00:00 2001 From: LiaoU3 <58060146+LiaoU3@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:20:32 +0800 Subject: [PATCH 16/20] Update providers/base/units/watchdog/jobs.pxu Co-authored-by: Massimiliano --- providers/base/units/watchdog/jobs.pxu | 1 + 1 file changed, 1 insertion(+) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index ef979a25ec..18395fc26f 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -83,6 +83,7 @@ depends: watchdog/check-service watchdog/detect user: root +environ: WATCHDOG_TIMEOUT command: watchdog_config_test.py --set-timeout ${WATCHDOG_TIMEOUT:-35} From 335a01d3a98ce656d1310411c6b604178b2718b8 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 3 Jun 2024 15:06:50 +0800 Subject: [PATCH 17/20] Simplify the description for watchdog/probe-module --- providers/base/units/watchdog/jobs.pxu | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/providers/base/units/watchdog/jobs.pxu b/providers/base/units/watchdog/jobs.pxu index 18395fc26f..e526d22cd8 100644 --- a/providers/base/units/watchdog/jobs.pxu +++ b/providers/base/units/watchdog/jobs.pxu @@ -29,8 +29,9 @@ id: watchdog/probe-module category_id: com.canonical.plainbox::power-management _summary: Probe the suitable module for watchdog _description: - Probe the suitable module of watchdog based on the environment variable 'WATCHDOG_TYPE' in config file. - This job only be execute on the Stock Classic image because the module isn't probed automatically. + Probe the module 'WATCHDOG_TYPE'. + This job can only be execute on the Stock Classic image, + because the watchdog module is not probed automatically. user: root flags: simple imports: from com.canonical.plainbox import manifest From 42678ef92267464927536af2d47df619674366c0 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Mon, 3 Jun 2024 15:09:28 +0800 Subject: [PATCH 18/20] SystemExit when the watchdog timeout is already set --- providers/base/bin/watchdog_config_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index fe0d7ae3d4..a79e0b6813 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -250,8 +250,7 @@ def set_timeout(timeout: int = 35) -> None: # Check if the timeout is already set if not re.search(pattern, text): - print("Watchdog timeout is already set") - return + raise SystemExit("Watchdog timeout is already set") # Substitute the current timeout with the new one text = re.sub( From fdced8ecb0b975bf1025f5e7944792e0795c110f Mon Sep 17 00:00:00 2001 From: liaou3 Date: Fri, 7 Jun 2024 10:15:20 +0800 Subject: [PATCH 19/20] Fix suggestions from hook25 --- providers/base/bin/watchdog_config_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index a79e0b6813..8ace07517e 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -202,6 +202,7 @@ def detect() -> None: "Please define the WATCHDOG_TYPE and WATCHDOG_IDENTITY " "in advance!" ) + input_identities = os.environ["WATCHDOG_IDENTITY"].split(",") # Iterate over watchdog devices watchdogs = os.listdir("/sys/class/watchdog") @@ -214,9 +215,12 @@ def detect() -> None: with open(path, "r") as f: identity = f.readline().strip() print("Identity of {}: {}".format(path, identity)) - + try: + # check that the identity was expected + input_identities.remove(identity) + print("Identity of {}: {}".format(path, identity)) # Check if the identity matches the expected identity - if identity != os.environ["WATCHDOG_IDENTITY"]: + except KeyError: raise SystemExit( "Found an unmatched watchdog!\n" "Expected: {}\n" From 10601ec687e50e3120898aee85edd5703ff6b3d1 Mon Sep 17 00:00:00 2001 From: liaou3 Date: Fri, 7 Jun 2024 15:40:47 +0800 Subject: [PATCH 20/20] Add check when there are still watchdogs unmatched at the end of detection --- providers/base/bin/watchdog_config_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/providers/base/bin/watchdog_config_test.py b/providers/base/bin/watchdog_config_test.py index 8ace07517e..8795fd0038 100755 --- a/providers/base/bin/watchdog_config_test.py +++ b/providers/base/bin/watchdog_config_test.py @@ -214,7 +214,6 @@ def detect() -> None: path = "/sys/class/watchdog/{}/identity".format(watchdog) with open(path, "r") as f: identity = f.readline().strip() - print("Identity of {}: {}".format(path, identity)) try: # check that the identity was expected input_identities.remove(identity) @@ -228,6 +227,13 @@ def detect() -> None: os.environ["WATCHDOG_IDENTITY"], identity ) ) + # Check if there are any remain watchdogs + if input_identities: + raise SystemExit( + "There are still unmatched watchdogs!\n{}".format( + input_identities + ) + ) # Handle unrecognized image source else: