Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[idrac_reset] - Fixing issue #652 #675

Merged
merged 15 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ For more information about how to use the collection, refer to [OME modules](htt

For more information about Unit testing, see [Unit testing](https://github.com/dell/dellemc-openmanage-ansible-modules/blob/collections/tests/README.md).

For more information about Integration testing, see [Intergation testing](https://github.com/dell/dellemc-openmanage-ansible-modules/blob/collections/tests/integrations/README.md).
For more information about Integration testing, see [Integration testing](https://github.com/dell/dellemc-openmanage-ansible-modules/blob/collections/tests/integrations/README.md).

## Support

Expand Down
26 changes: 21 additions & 5 deletions docs/modules/idrac_reset.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ Parameters
This option is applicable only for iDRAC9.


default_username (optional, str, None)
This parameter is only applied when \ :emphasis:`reset\_to\_default`\ is \ :literal:`All`\ or \ :literal:`ResetAllWithRootDefaults`\ .

This parameter is required to track LifeCycle status of the server after the reset operation is performed. If this parameter is not provided, then the LifeCycle status is not tracked after the reset operation.


default_password (optional, str, None)
This parameter is only applied when \ :emphasis:`reset\_to\_default`\ is \ :literal:`All`\ or \ :literal:`ResetAllWithRootDefaults`\ .

This parameter is required to track LifeCycle status of the server after the reset operation is performed. If this parameter is not provided, then the LifeCycle status is not tracked after the reset operation.


idrac_ip (True, str, None)
iDRAC IP Address.

Expand Down Expand Up @@ -142,22 +154,25 @@ Examples


---
- name: Reset the iDRAC to all and wait till the iDRAC is accessible.
- name: Reset the iDRAC to default and do not wait till the iDRAC is accessible.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "All"
reset_to_default: "Default"
wait_for_idrac: false

- name: Reset the iDRAC to default and do not wait till the iDRAC is accessible.
- name: Reset the iDRAC to All and wait for lifecycle controller status to be ready.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "Default"
wait_for_idrac: false
reset_to_default: "All"
wait_for_idrac: true
default_username: "user_name"
default_password: "user_password"

- name: Force reset the iDRAC to default.
dellemc.openmanage.idrac_reset:
Expand Down Expand Up @@ -227,4 +242,5 @@ Authors
- Felix Stephen (@felixs88)
- Anooja Vardhineni (@anooja-vardhineni)
- Lovepreet Singh (@singh-lovepreet1)
- Abhishek Sinha (@ABHISHEK-SINHA10)

17 changes: 10 additions & 7 deletions playbooks/idrac/idrac_reset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
gather_facts: false

tasks:
- name: Reset the iDRAC to all and wait till the iDRAC is accessible.
- name: Reset the iDRAC to default and
do not wait till the iDRAC is accessible.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "All"
reset_to_default: "Default"
wait_for_idrac: false
delegate_to: localhost

- name: Reset the iDRAC to default and
do not wait till the iDRAC is accessible.
- name: Reset the iDRAC to all and wait for lifecycle controller
status to be ready after reset.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "Default"
wait_for_idrac: false
delegate_to: localhost
reset_to_default: "All"
wait_for_idrac: true
default_username: "user_name"
default_password: "user_password"

- name: Force reset the iDRAC to default.
dellemc.openmanage.idrac_reset:
Expand Down
56 changes: 44 additions & 12 deletions plugins/modules/idrac_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#
# Dell OpenManage Ansible Modules
# Version 9.3.0
# Version 9.4.0
# Copyright (C) 2018-2024 Dell Inc. or its subsidiaries. All Rights Reserved.

# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
Expand Down Expand Up @@ -66,13 +66,31 @@
type: bool
default: false
version_added: 9.2.0
default_username:
description:
- This parameter is only applied when I(reset_to_default) is C(All) or C(ResetAllWithRootDefaults).
- This parameter is required to track LifeCycle status of the server after the reset operation is
performed. If this parameter is not provided, then the LifeCycle status is not tracked after the
reset operation.
type: str
version_added: 9.4.0
default_password:
description:
- This parameter is only applied when I(reset_to_default) is C(All) or C(ResetAllWithRootDefaults).
- This parameter is required to track LifeCycle status of the server after the reset operation is
performed. If this parameter is not provided, then the LifeCycle status is not tracked after the
reset operation.
type: str
version_added: 9.4.0


requirements:
- "python >= 3.9.6"
author:
- "Felix Stephen (@felixs88)"
- "Anooja Vardhineni (@anooja-vardhineni)"
- "Lovepreet Singh (@singh-lovepreet1)"
- "Abhishek Sinha (@ABHISHEK-SINHA10)"
notes:
- Run this module from a system that has direct access to Dell iDRAC.
- This module supports both IPv4 and IPv6 address for I(idrac_ip).
Expand All @@ -83,22 +101,25 @@

EXAMPLES = r'''
---
- name: Reset the iDRAC to all and wait till the iDRAC is accessible.
- name: Reset the iDRAC to default and do not wait till the iDRAC is accessible.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "All"
reset_to_default: "Default"
wait_for_idrac: false

- name: Reset the iDRAC to default and do not wait till the iDRAC is accessible.
- name: Reset the iDRAC to All and wait for lifecycle controller status to be ready.
dellemc.openmanage.idrac_reset:
idrac_ip: "192.168.0.1"
idrac_user: "user_name"
idrac_password: "user_password"
ca_path: "/path/to/ca_cert.pem"
reset_to_default: "Default"
wait_for_idrac: false
reset_to_default: "All"
wait_for_idrac: true
default_username: "user_name"
default_password: "user_password"

- name: Force reset the iDRAC to default.
dellemc.openmanage.idrac_reset:
Expand Down Expand Up @@ -324,15 +345,15 @@ def execute(self):
skipped=True)
if self.module.check_mode:
self.check_mode_output(is_idrac9)
if is_idrac9 and not self.force_reset:
if is_idrac9 and self.reset_to_default and not self.force_reset:
self.check_lcstatus(post_op=False)
reset_status_mapping = {key: self.reset_to_default_mapped for key in ['Default', 'All', 'ResetAllWithRootDefaults']}
reset_status_mapping.update({
'CustomDefaults': self.reset_custom_defaults,
'None': self.graceful_restart
})
msg_res, job_res = reset_status_mapping[str(self.reset_to_default)]()
if is_idrac9 and self.wait_for_idrac:
if is_idrac9 and self.wait_for_idrac and self.reset_to_default:
self.check_lcstatus()
return msg_res, job_res

Expand All @@ -356,9 +377,19 @@ def is_check_idrac_latest(self):
if LooseVersion(self.idrac_firmware_version) >= '3.0':
return True

def update_credentials_for_post_lc_statuc_check(self):
if (default_username := self.module.params.get("default_username")) and (
default_password := self.module.params.get("default_password")
):
self.idrac.username = default_username
self.idrac.password = default_password
return True

def check_lcstatus(self, post_op=True):
if self.reset_to_default in PASSWORD_CHANGE_OPTIONS and post_op and self.staus_code_after_wait == 401:
if self.reset_to_default in PASSWORD_CHANGE_OPTIONS and post_op and \
not self.update_credentials_for_post_lc_statuc_check():
return

lc_status_dict = {}
lc_status_dict['LCStatus'] = ""
retry_count = 1
Expand Down Expand Up @@ -394,11 +425,9 @@ def create_output(self, status):
result['idracreset']['Data'] = {'StatusCode': status}
result['idracreset']['StatusCode'] = status
track_failed, wait_msg = None, None
self.staus_code_after_wait = 202
if status in STATUS_SUCCESS:
if self.wait_for_idrac:
track_failed, status_code, wait_msg = self.wait_for_port_open()
self.staus_code_after_wait = status_code
if track_failed:
self.module.exit_json(msg=wait_msg, changed=True)
tmp_res['msg'] = IDRAC_RESET_SUCCESS_MSG if self.wait_for_idrac else IDRAC_RESET_RESET_TRIGGER_MSG
Expand Down Expand Up @@ -529,12 +558,15 @@ def main():
"custom_defaults_buffer": {"type": "str"},
"wait_for_idrac": {"type": "bool", "default": True},
"job_wait_timeout": {"type": 'int', "default": 600},
"force_reset": {"type": "bool", "default": False}
"force_reset": {"type": "bool", "default": False},
"default_username": {"type": "str"},
"default_password": {"type": "str", "no_log": True}
}

module = IdracAnsibleModule(
argument_spec=specs,
mutually_exclusive=[("custom_defaults_file", "custom_defaults_buffer")],
required_together=[('default_username', 'default_password')],
supports_check_mode=True)
try:
with iDRACRedfishAPI(module.params) as idrac:
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/plugins/modules/test_idrac_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,35 @@ def test_check_mode_output(self, idrac_default_args, idrac_connection_reset_mock
reset_obj.check_mode_output(True)
assert exc.value.args[0] == CHANGES_NOT_FOUND

def test_check_lcstatus(self, idrac_default_args, idrac_connection_reset_mock, mocker):
allowed_values = ["All", "Default", "ResetAllWithRootDefaults", "CustomDefaults"]

def mock_get_dynamic_uri_request(*args, **kwargs):
if len(args) > 2 and args[2] == 'Links':
return {"Oem": {"Dell": {"DellLCService": {}}}}
mocker.patch(MODULE_PATH + "validate_and_get_first_resource_id_uri",
return_value=(IDRAC_URI, ''))
mocker.patch(MODULE_PATH + "get_dynamic_uri",
side_effect=mock_get_dynamic_uri_request)
# Scenario: When default_username and default_password is not given
idrac_default_args.update({"reset_to_default": 'All'})
f_module = self.get_module_mock(params=idrac_default_args, check_mode=False)
reset_obj = self.module.FactoryReset(idrac_connection_reset_mock, f_module, allowed_choices=allowed_values)
reset_obj.status_code_after_wait = 401
data = reset_obj.check_lcstatus()
assert data is None

# Scneario: When default_username and default_password is given
idrac_default_args.update({"reset_to_default": 'All',
"default_username": "admin",
"default_password": "XXXXX"})
f_module = self.get_module_mock(params=idrac_default_args, check_mode=False)
reset_obj = self.module.FactoryReset(idrac_connection_reset_mock, f_module, allowed_choices=allowed_values)
reset_obj.status_code_after_wait = 401
with pytest.raises(Exception) as exc:
reset_obj.check_lcstatus()
assert exc.value.args[0] == UNSUPPORTED_LC_STATUS_MSG

def test_execute(self, idrac_default_args, idrac_connection_reset_mock, mocker):
allowed_values = ["All", "Default", "ResetAllWithRootDefaults", "CustomDefaults"]
allowed_values_without_cd = ["All", "Default", "ResetAllWithRootDefaults"]
Expand Down
Loading