From 9948349b10b6bb694f92813243598a7a7c84d3f8 Mon Sep 17 00:00:00 2001 From: Bharath kumar Date: Mon, 19 Sep 2016 12:41:04 +0000 Subject: [PATCH] Moving Reboot bashscript to python Currently a reboot bash script file is used to call reboot and poweroff operation. Deleting this file and moving the code to python file using utils.execute() Partial-Bug: #1557542 Change-Id: Iad9cd9d15417e9a954d108d2759e6303452fca27 Author: Bharath kumar Co-Authored-By: Annie Lezil --- ironic_python_agent/extensions/standby.py | 36 ++++++++-------- ironic_python_agent/shell/shutdown.sh | 26 ------------ .../tests/unit/extensions/test_standby.py | 41 +++++++++++++------ 3 files changed, 46 insertions(+), 57 deletions(-) delete mode 100644 ironic_python_agent/shell/shutdown.sh diff --git a/ironic_python_agent/extensions/standby.py b/ironic_python_agent/extensions/standby.py index c088a4135..1ba396ea1 100644 --- a/ironic_python_agent/extensions/standby.py +++ b/ironic_python_agent/extensions/standby.py @@ -481,25 +481,25 @@ class StandbyExtension(base.BaseAgentExtension): LOG.info(result_msg) return result_msg - def _run_shutdown_script(self, parameter): - """Runs the agent's shutdown script with the specified parameter. + def _run_shutdown_command(self, command): + """Run the shutdown or reboot command - The script only takes the following parameters: - - -h : 'halts' the machine by turning the power off. - -r : 'runs' the installed image by rebooting the machine. - - Only one parameter should be specified. - - :param parameter: The parameter to send to the shutdown script. - :raises: SystemRebootError if calling the shutdown script returns an - unsuccessful exit code. + :param command: A string having the command to be run. + :raises: InvalidCommandParamsError if the passed command is not + equal to poweroff or reboot. + :raises: SystemRebootError if the command errors out with an + unsuccessful exit code. """ - script = _path_to_script('shell/shutdown.sh') - command = ['/bin/bash', script, parameter] - # this should never return if successful + if command not in ('reboot', 'poweroff'): + msg = (('Expected the command "poweroff" or "reboot" ' + 'but received "%s".') % command) + raise errors.InvalidCommandParamsError(msg) try: - stdout, stderr = utils.execute(*command, check_exit_code=[0]) + self.sync() + except errors.CommandExecutionError as e: + LOG.warning('Failed to sync file system buffers: % s', e) + try: + utils.execute(command, check_exit_code=[0]) except processutils.ProcessExecutionError as e: raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr) @@ -507,13 +507,13 @@ class StandbyExtension(base.BaseAgentExtension): def run_image(self): """Runs image on agent's system via reboot.""" LOG.info('Rebooting system') - self._run_shutdown_script('-r') + self._run_shutdown_command('reboot') @base.async_command('power_off') def power_off(self): """Powers off the agent's system.""" LOG.info('Powering off system') - self._run_shutdown_script('-h') + self._run_shutdown_command('poweroff') @base.sync_command('sync') def sync(self): diff --git a/ironic_python_agent/shell/shutdown.sh b/ironic_python_agent/shell/shutdown.sh deleted file mode 100644 index b685d28f7..000000000 --- a/ironic_python_agent/shell/shutdown.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Copyright 2013 Rackspace, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -e - -# flush file system buffers -sync - -if [[ $1 = '-h' ]]; then - poweroff -elif [[ $1 = '-r' ]]; then - reboot -fi diff --git a/ironic_python_agent/tests/unit/extensions/test_standby.py b/ironic_python_agent/tests/unit/extensions/test_standby.py index ecdabf3e0..b76dd5961 100644 --- a/ironic_python_agent/tests/unit/extensions/test_standby.py +++ b/ironic_python_agent/tests/unit/extensions/test_standby.py @@ -662,16 +662,35 @@ class TestStandbyExtension(test_base.BaseTestCase): image_info['stream_raw_images'] = False self._test_prepare_image_raw(image_info) + @mock.patch('ironic_python_agent.utils.execute', autospec=True) + def test_run_shutdown_command_invalid(self, execute_mock): + self.assertRaises(errors.InvalidCommandParamsError, + self.agent_extension._run_shutdown_command, 'boot') + + @mock.patch('ironic_python_agent.utils.execute', autospec=True) + def test_run_shutdown_command_fails(self, execute_mock): + execute_mock.side_effect = processutils.ProcessExecutionError + self.assertRaises(errors.SystemRebootError, + self.agent_extension._run_shutdown_command, 'reboot') + + @mock.patch('ironic_python_agent.utils.execute', autospec=True) + def test_run_shutdown_command_valid(self, execute_mock): + execute_mock.return_value = ('', '') + + self.agent_extension._run_shutdown_command('poweroff') + calls = [mock.call('sync'), + mock.call('poweroff', check_exit_code=[0])] + execute_mock.assert_has_calls(calls) + @mock.patch('ironic_python_agent.utils.execute', autospec=True) def test_run_image(self, execute_mock): - script = standby._path_to_script('shell/shutdown.sh') - command = ['/bin/bash', script, '-r'] execute_mock.return_value = ('', '') success_result = self.agent_extension.run_image() success_result.join() - - execute_mock.assert_called_once_with(*command, check_exit_code=[0]) + calls = [mock.call('sync'), + mock.call('reboot', check_exit_code=[0])] + execute_mock.assert_has_calls(calls) self.assertEqual('SUCCEEDED', success_result.command_status) execute_mock.reset_mock() @@ -681,23 +700,19 @@ class TestStandbyExtension(test_base.BaseTestCase): failed_result = self.agent_extension.run_image() failed_result.join() - execute_mock.assert_called_once_with(*command, check_exit_code=[0]) + execute_mock.assert_any_call('sync') self.assertEqual('FAILED', failed_result.command_status) - def test_path_to_script(self): - script = standby._path_to_script('shell/reboot.sh') - self.assertTrue(script.endswith('extensions/../shell/reboot.sh')) - @mock.patch('ironic_python_agent.utils.execute', autospec=True) def test_power_off(self, execute_mock): - script = standby._path_to_script('shell/shutdown.sh') - command = ['/bin/bash', script, '-h'] execute_mock.return_value = ('', '') success_result = self.agent_extension.power_off() success_result.join() - execute_mock.assert_called_once_with(*command, check_exit_code=[0]) + calls = [mock.call('sync'), + mock.call('poweroff', check_exit_code=[0])] + execute_mock.assert_has_calls(calls) self.assertEqual('SUCCEEDED', success_result.command_status) execute_mock.reset_mock() @@ -707,7 +722,7 @@ class TestStandbyExtension(test_base.BaseTestCase): failed_result = self.agent_extension.power_off() failed_result.join() - execute_mock.assert_called_once_with(*command, check_exit_code=[0]) + execute_mock.assert_any_call('sync') self.assertEqual('FAILED', failed_result.command_status) @mock.patch('ironic_python_agent.utils.execute', autospec=True)