From 2b7393141fa29e607b43166a6bd8e2916cd2091f Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 21 Jan 2020 13:42:32 -0500 Subject: [PATCH] reboot - add boot_time_command parameter (#62680) Allow the built in commands for checking boot time to be overridden. This is mainly for containers and other odd systems where it would add too much complexity to the plugin code to try and discern the correct command to use. --- .../reboot-add-last-boot-time-parameter.yaml | 5 +++++ lib/ansible/modules/system/reboot.py | 8 ++++++++ lib/ansible/modules/windows/win_reboot.py | 7 +++++++ lib/ansible/plugins/action/reboot.py | 20 ++++++++++++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/reboot-add-last-boot-time-parameter.yaml diff --git a/changelogs/fragments/reboot-add-last-boot-time-parameter.yaml b/changelogs/fragments/reboot-add-last-boot-time-parameter.yaml new file mode 100644 index 00000000000..829ee1e6df8 --- /dev/null +++ b/changelogs/fragments/reboot-add-last-boot-time-parameter.yaml @@ -0,0 +1,5 @@ +bugfixes: + - >- + reboot, win_reboot - add ``boot_time_command`` parameter to override the default command used to + determine whether or not a system was rebooted + (https://github.com/ansible/ansible/issues/58868) diff --git a/lib/ansible/modules/system/reboot.py b/lib/ansible/modules/system/reboot.py index ef00874e38f..0fab23a6099 100644 --- a/lib/ansible/modules/system/reboot.py +++ b/lib/ansible/modules/system/reboot.py @@ -65,6 +65,14 @@ options: type: list default: ['/sbin', '/usr/sbin', '/usr/local/sbin'] version_added: '2.8' + + boot_time_command: + description: + - Command to run that returns a unique string indicating the last time the system was booted. + - Setting this to a command that has different output each time it is run will cause the task to fail. + type: str + default: 'cat /proc/sys/kernel/random/boot_id' + version_added: '2.10' seealso: - module: win_reboot author: diff --git a/lib/ansible/modules/windows/win_reboot.py b/lib/ansible/modules/windows/win_reboot.py index b252c927b6b..1431804143d 100644 --- a/lib/ansible/modules/windows/win_reboot.py +++ b/lib/ansible/modules/windows/win_reboot.py @@ -61,6 +61,13 @@ options: - Message to display to users. type: str default: Reboot initiated by Ansible + boot_time_command: + description: + - Command to run that returns a unique string indicating the last time the system was booted. + - Setting this to a command that has different output each time it is run will cause the task to fail. + type: str + default: '(Get-WmiObject -ClassName Win32_OperatingSystem).LastBootUpTime' + version_added: '2.10' notes: - If a shutdown was already scheduled on the system, C(win_reboot) will abort the scheduled shutdown and enforce its own shutdown. - Beware that when C(win_reboot) returns, the Windows system may not have settled yet and some base services could be in limbo. diff --git a/lib/ansible/plugins/action/reboot.py b/lib/ansible/plugins/action/reboot.py index 4578997c0e3..1a7ecfcb134 100644 --- a/lib/ansible/plugins/action/reboot.py +++ b/lib/ansible/plugins/action/reboot.py @@ -13,6 +13,7 @@ from datetime import datetime, timedelta from ansible.errors import AnsibleError, AnsibleConnectionFailure from ansible.module_utils._text import to_native, to_text from ansible.module_utils.common.collections import is_string +from ansible.module_utils.common.validation import check_type_str from ansible.plugins.action import ActionBase from ansible.utils.display import Display @@ -25,7 +26,16 @@ class TimedOutException(Exception): class ActionModule(ActionBase): TRANSFERS_FILES = False - _VALID_ARGS = frozenset(('connect_timeout', 'msg', 'post_reboot_delay', 'pre_reboot_delay', 'test_command', 'reboot_timeout', 'search_paths')) + _VALID_ARGS = frozenset(( + 'boot_time_command', + 'connect_timeout', + 'msg', + 'post_reboot_delay', + 'pre_reboot_delay', + 'test_command', + 'reboot_timeout', + 'search_paths' + )) DEFAULT_REBOOT_TIMEOUT = 600 DEFAULT_CONNECT_TIMEOUT = None @@ -178,6 +188,14 @@ class ActionModule(ActionBase): def get_system_boot_time(self, distribution): boot_time_command = self._get_value_from_facts('BOOT_TIME_COMMANDS', distribution, 'DEFAULT_BOOT_TIME_COMMAND') + if self._task.args.get('boot_time_command'): + boot_time_command = self._task.args.get('boot_time_command') + + try: + check_type_str(boot_time_command, allow_conversion=False) + except TypeError as e: + raise AnsibleError("Invalid value given for 'boot_time_command': %s." % to_native(e)) + display.debug("{action}: getting boot time with command: '{command}'".format(action=self._task.action, command=boot_time_command)) command_result = self._low_level_execute_command(boot_time_command, sudoable=self.DEFAULT_SUDOABLE)