From 20dc04e5e2b23f888ff79a3873d35fd4c170c8d8 Mon Sep 17 00:00:00 2001 From: Annie Lezil Date: Mon, 19 Dec 2016 11:09:52 -0800 Subject: [PATCH] Reboot and Poweroff fails with coreos IPA image The CoreOS IPA images do not support poweroff/reboot due to running in a chroot. For this case, we fall back to forcing poweroff or reboot via sysrq commands Change-Id: I75d68b6308beba299d043e43a5fa1671b6ef3ada Closes-Bug: #1628367 --- ironic_python_agent/extensions/standby.py | 10 +++++- .../tests/unit/extensions/test_standby.py | 35 +++++++++++++++++-- ...t_in_chroot_by_sysrq-42447fc4cdd7dafe.yaml | 5 +++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/coreos_ipa_image_poweroff_reboot_in_chroot_by_sysrq-42447fc4cdd7dafe.yaml diff --git a/ironic_python_agent/extensions/standby.py b/ironic_python_agent/extensions/standby.py index 1ba396ea1..637e40128 100644 --- a/ironic_python_agent/extensions/standby.py +++ b/ironic_python_agent/extensions/standby.py @@ -499,7 +499,15 @@ class StandbyExtension(base.BaseAgentExtension): except errors.CommandExecutionError as e: LOG.warning('Failed to sync file system buffers: % s', e) try: - utils.execute(command, check_exit_code=[0]) + _, stderr = utils.execute(command, use_standard_locale=True, + check_exit_code=[0]) + if 'ignoring request.' in stderr: + LOG.debug('%s command failed with error %s, ' + 'falling back to sysrq-trigger.', command, stderr) + if command == 'poweroff': + utils.execute("echo o > /proc/sysrq-trigger", shell=True) + elif command == 'reboot': + utils.execute("echo b > /proc/sysrq-trigger", shell=True) except processutils.ProcessExecutionError as e: raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr) diff --git a/ironic_python_agent/tests/unit/extensions/test_standby.py b/ironic_python_agent/tests/unit/extensions/test_standby.py index b76dd5961..6a98dd312 100644 --- a/ironic_python_agent/tests/unit/extensions/test_standby.py +++ b/ironic_python_agent/tests/unit/extensions/test_standby.py @@ -679,7 +679,34 @@ class TestStandbyExtension(test_base.BaseTestCase): self.agent_extension._run_shutdown_command('poweroff') calls = [mock.call('sync'), - mock.call('poweroff', check_exit_code=[0])] + mock.call('poweroff', use_standard_locale=True, + check_exit_code=[0])] + execute_mock.assert_has_calls(calls) + + @mock.patch('ironic_python_agent.utils.execute', autospec=True) + def test_run_shutdown_command_valid_poweroff_sysrq(self, execute_mock): + execute_mock.side_effect = [('', ''), ('', + 'Running in chroot, ignoring request.'), + ('', '')] + + self.agent_extension._run_shutdown_command('poweroff') + calls = [mock.call('sync'), + mock.call('poweroff', use_standard_locale=True, + check_exit_code=[0]), + mock.call("echo o > /proc/sysrq-trigger", shell=True)] + execute_mock.assert_has_calls(calls) + + @mock.patch('ironic_python_agent.utils.execute', autospec=True) + def test_run_shutdown_command_valid_reboot_sysrq(self, execute_mock): + execute_mock.side_effect = [('', ''), ('', + 'Running in chroot, ignoring request.'), + ('', '')] + + self.agent_extension._run_shutdown_command('reboot') + calls = [mock.call('sync'), + mock.call('reboot', use_standard_locale=True, + check_exit_code=[0]), + mock.call("echo b > /proc/sysrq-trigger", shell=True)] execute_mock.assert_has_calls(calls) @mock.patch('ironic_python_agent.utils.execute', autospec=True) @@ -689,7 +716,8 @@ class TestStandbyExtension(test_base.BaseTestCase): success_result = self.agent_extension.run_image() success_result.join() calls = [mock.call('sync'), - mock.call('reboot', check_exit_code=[0])] + mock.call('reboot', use_standard_locale=True, + check_exit_code=[0])] execute_mock.assert_has_calls(calls) self.assertEqual('SUCCEEDED', success_result.command_status) @@ -711,7 +739,8 @@ class TestStandbyExtension(test_base.BaseTestCase): success_result.join() calls = [mock.call('sync'), - mock.call('poweroff', check_exit_code=[0])] + mock.call('poweroff', use_standard_locale=True, + check_exit_code=[0])] execute_mock.assert_has_calls(calls) self.assertEqual('SUCCEEDED', success_result.command_status) diff --git a/releasenotes/notes/coreos_ipa_image_poweroff_reboot_in_chroot_by_sysrq-42447fc4cdd7dafe.yaml b/releasenotes/notes/coreos_ipa_image_poweroff_reboot_in_chroot_by_sysrq-42447fc4cdd7dafe.yaml new file mode 100644 index 000000000..0d416f5aa --- /dev/null +++ b/releasenotes/notes/coreos_ipa_image_poweroff_reboot_in_chroot_by_sysrq-42447fc4cdd7dafe.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - Fixes a bug in the CoreOS IPA images (where IPA runs in a chroot), where + IPA could not power off or reboot properly. In this case, it will now use + SYSRQ commands to forcefully reboot or power off.