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 10 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
12 changes: 12 additions & 0 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
43 changes: 36 additions & 7 deletions plugins/modules/idrac_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@
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"
Expand Down Expand Up @@ -324,15 +341,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 +373,18 @@ 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:
return
if self.reset_to_default in PASSWORD_CHANGE_OPTIONS and post_op and self.status_code_after_wait == 401:
if 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 +420,11 @@ 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
self.status_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
self.status_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 +555,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