summaryrefslogtreecommitdiffstats
path: root/ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py')
-rw-r--r--ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py425
1 files changed, 425 insertions, 0 deletions
diff --git a/ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py b/ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py
new file mode 100644
index 000000000..3303b4ade
--- /dev/null
+++ b/ansible_collections/dellemc/openmanage/plugins/modules/idrac_session.py
@@ -0,0 +1,425 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# Dell OpenManage Ansible Modules
+# Version 9.2.0
+# Copyright (C) 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)
+#
+
+
+from __future__ import (absolute_import, division, print_function)
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+---
+module: idrac_session
+short_description: Manage iDRAC sessions
+version_added: "9.2.0"
+description:
+ - This module allows the creation and deletion of sessions on iDRAC.
+options:
+ hostname:
+ description:
+ - IP address or hostname of the iDRAC.
+ type: str
+ username:
+ description:
+ - Username of the iDRAC.
+ - I(username) is required when I(state) is C(present).
+ type: str
+ password:
+ description:
+ - Password of the iDRAC.
+ - I(password) is required when I(state) is C(present).
+ type: str
+ port:
+ description:
+ - Port of the iDRAC.
+ type: int
+ default: 443
+ validate_certs:
+ description:
+ - If C(false), the SSL certificates will not be validated.
+ - Configure C(false) only on personally controlled sites where self-signed certificates are used.
+ type: bool
+ default: true
+ ca_path:
+ description:
+ - The Privacy Enhanced Mail (PEM) file that contains a CA certificate to be used for the validation.
+ type: path
+ timeout:
+ description:
+ - The https socket level timeout in seconds.
+ type: int
+ default: 30
+ state:
+ description:
+ - The state of the session in an iDRAC.
+ - C(present) creates a session.
+ - C(absent) deletes a session.
+ - Module will always report changes found to be applied when I(state) is C(present).
+ choices: [present, absent]
+ type: str
+ default: present
+ auth_token:
+ description:
+ - Authentication token.
+ - I(auth_token) is required when I(state) is C(absent).
+ type: str
+ session_id:
+ description:
+ - Session ID of the iDRAC.
+ - I(session_id) is required when I(state) is C(absent).
+ type: int
+requirements:
+ - "python >= 3.9.6"
+author:
+ - "Rajshekar P(@rajshekarp87)"
+notes:
+ - Run this module from a system that has direct access to Dell iDRAC.
+ - This module supports IPv4 and IPv6 addresses.
+ - This module supports C(check_mode).
+ - This module will always report changes found to be applied when I(state) is C(present).
+"""
+
+EXAMPLES = r"""
+---
+- name: Create a session
+ dellemc.openmanage.idrac_session:
+ hostname: 198.162.0.1
+ username: username
+ password: password
+ state: present
+
+- name: Delete a session
+ dellemc.openmanage.idrac_session:
+ hostname: 198.162.0.1
+ state: absent
+ auth_token: aed4aa802b748d2f3b31deec00a6b28a
+ session_is: 2
+"""
+
+RETURN = r'''
+---
+msg:
+ description: Status of the session operation.
+ returned: always
+ type: str
+ sample: "The session has been created successfully."
+session_data:
+ description: The session details.
+ returned: For session creation operation
+ type: dict
+ sample: {
+ "@Message.ExtendedInfo": [
+ {
+ "Message": "The resource has been created successfully.",
+ "MessageArgs": [],
+ "MessageId": "Base.1.12.Created",
+ "RelatedProperties": [],
+ "Resolution": "None.",
+ "Severity": "OK"
+ },
+ {
+ "Message": "A new resource is successfully created.",
+ "MessageArgs": [],
+ "MessageId": "IDRAC.2.9.SYS414",
+ "RelatedProperties": [],
+ "Resolution": "No response action is required.",
+ "Severity": "Informational"
+ }
+ ],
+ "ClientOriginIPAddress": "100.96.37.58",
+ "CreatedTime": "2024-04-05T01:14:01-05:00",
+ "Description": "User Session",
+ "Id": "74",
+ "Name": "User Session",
+ "Password": null,
+ "SessionType": "Redfish",
+ "UserName": "root"
+ }
+x_auth_token:
+ description: Authentication token.
+ returned: For session creation operation
+ type: str
+ sample: "d15f17f01cd627c30173b1582642497d"
+error_info:
+ description: Details of the HTTP Error.
+ returned: On HTTP error
+ type: dict
+ sample: {
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "Message": "Unable to complete the operation because an invalid username
+ and/or password is entered, and therefore authentication failed.",
+ "MessageArgs": [],
+ "MessageId": "IDRAC.2.9.SYS415",
+ "RelatedProperties": [],
+ "Resolution": "Enter valid user name and password and retry the operation.",
+ "Severity": "Warning"
+ }
+ ],
+ "code": "Base.1.12.GeneralError",
+ "message": "A general error has occurred. See ExtendedInfo for more information"
+ }
+ }
+'''
+
+
+import json
+from urllib.error import HTTPError, URLError
+from ansible_collections.dellemc.openmanage.plugins.module_utils.session_utils import SessionAPI
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.urls import ConnectionError, SSLValidationError
+from ansible.module_utils.common.parameters import env_fallback
+from ansible_collections.dellemc.openmanage.plugins.module_utils.utils import (
+ get_dynamic_uri, remove_key)
+
+REDFISH = "/redfish/v1"
+SESSIONS = "Sessions"
+ODATA = "@odata.id"
+ODATA_REGEX = "(.*?)@odata"
+
+CREATE_SUCCESS_MSG = "The session has been created successfully."
+DELETE_SUCCESS_MSG = "The session has been deleted successfully."
+FAILURE_MSG = "Unable to '{operation}' a session."
+CHANGES_FOUND_MSG = "Changes found to be applied."
+NO_CHANGES_FOUND_MSG = "No changes found to be applied."
+
+
+class Session():
+ """
+ Parent class for all session operations.
+ """
+ def __init__(self, idrac, module):
+ """
+ Initializes the object with the given idrac and module parameters.
+
+ Args:
+ idrac (object): The idrac object.
+ module (object): The module object.
+
+ Returns:
+ None
+ """
+ self.idrac = idrac
+ self.module = module
+
+ def get_session_url(self):
+ """
+ Retrieves the URL for the sessions endpoint from the Redfish API.
+
+ Returns:
+ str: The URL for the sessions endpoint, or None if not found.
+ """
+ v1_resp = get_dynamic_uri(self.idrac, REDFISH)
+ sessions_url = v1_resp.get('Links', {}).get(SESSIONS, {}).get(ODATA, {})
+ return sessions_url
+
+
+class CreateSession(Session):
+ """
+ Creates a session.
+ """
+ def execute(self):
+ """
+ Executes the session creation process.
+
+ This function creates a session by sending a POST request to the session URL with the
+ provided username and password.
+ If the request is successful (status code 201), it retrieves the session details, removes
+ any OData keys from the response,
+ and extracts the X-Auth-Token from the response headers. It then exits the module with a
+ success message, indicating that
+ the session was created successfully, and provides the session data and X-Auth-Token as
+ output variables.
+
+ If the request fails (status code other than 201), it exits the module with a failure
+ message, indicating that the session creation failed.
+
+ Parameters:
+ None
+
+ Returns:
+ None
+ """
+ payload = {"UserName": self.module.params.get("username"),
+ "Password": self.module.params.get("password")}
+ session_url = self.get_session_url()
+ if self.module.check_mode:
+ self.module.exit_json(msg=CHANGES_FOUND_MSG, changed=True)
+ session_response = self.idrac.invoke_request(session_url, "POST", data=payload)
+ status = session_response.status_code
+ if status == 201:
+ session_details = session_response.json_data
+ session_data = remove_key(session_details, regex_pattern=ODATA_REGEX)
+ x_auth_token = session_response.headers.get('X-Auth-Token')
+ self.module.exit_json(msg=CREATE_SUCCESS_MSG,
+ changed=True,
+ session_data=session_data,
+ x_auth_token=x_auth_token)
+ else:
+ self.module.exit_json(msg=FAILURE_MSG.format(operation="create"), failed=True)
+
+
+class DeleteSession(Session):
+ """
+ Deletes a session.
+ """
+ def execute(self):
+ """
+ Executes the deletion of a session.
+
+ This function retrieves the session ID from the module parameters and constructs the
+ session URL using the `get_session_url` method. It then invokes a DELETE request to the
+ session URL with the session ID appended. The response from the request is stored in the
+ `session_response` variable.
+
+ If the response status code is 200, indicating a successful deletion, the function exits
+ the module with a success message and sets the `changed` parameter to True. Otherwise, it
+ exits the module with a failure message and sets the `failed` parameter to True.
+
+ Parameters:
+ None
+
+ Returns:
+ None
+ """
+ session_id = self.module.params.get("session_id")
+ session_url = self.get_session_url()
+ session_status = self.get_session_status(session_url, session_id)
+ if self.module.check_mode:
+ if session_status == 200:
+ self.module.exit_json(msg=CHANGES_FOUND_MSG, changed=True)
+ else:
+ self.module.exit_json(msg=NO_CHANGES_FOUND_MSG)
+ else:
+ if session_status == 200:
+ try:
+ session_response = self.idrac.invoke_request(session_url + f"/{session_id}",
+ "DELETE")
+ status = session_response.status_code
+ if status == 200:
+ self.module.exit_json(msg=DELETE_SUCCESS_MSG, changed=True)
+ except HTTPError as err:
+ filter_err = remove_key(json.load(err), regex_pattern=ODATA_REGEX)
+ self.module.exit_json(msg=FAILURE_MSG.format(operation="delete"),
+ error_info=filter_err,
+ failed=True)
+ else:
+ self.module.exit_json(msg=NO_CHANGES_FOUND_MSG)
+
+ def get_session_status(self, session_url, session_id):
+ """
+ Retrieves the status of a session given its URL and ID.
+
+ Args:
+ session_url (str): The URL of the session.
+ session_id (str): The ID of the session.
+
+
+ Returns:
+ int: The status code of the session status response. If an HTTPError occurs, the status
+ code of the error is returned.
+ """
+ try:
+ session_status_response = self.idrac.invoke_request(session_url + f"/{session_id}",
+ "GET")
+ session_status = session_status_response.status_code
+ except HTTPError as err:
+ session_status = err.status
+ return session_status
+
+
+def main():
+ """
+ Main function that initializes the Ansible module with the argument specs and required if
+ conditions.
+ It then creates a SessionAPI object with the module parameters and performs a session operation
+ based on the state parameter.
+ If the state is "present", it creates a CreateSession object and executes it. If the state is
+ "absent", it creates a DeleteSession object and executes it.
+ The session status is returned.
+
+ Raises:
+ HTTPError: If an HTTP error occurs, the error message and filtered error information are
+ returned in the module's exit_json.
+ URLError: If a URL error occurs, the error message is returned in the module's exit_json.
+ SSLValidationError, ConnectionError, TypeError, ValueError, OSError: If any other error
+ occurs, the error message is returned in the module's exit_json.
+
+ Returns:
+ None
+ """
+ specs = get_argument_spec()
+ module = AnsibleModule(
+ argument_spec=specs,
+ required_if=[
+ ["state", "present", ("username", "password",)],
+ ["state", "absent", ("auth_token", "session_id",)]
+ ],
+ supports_check_mode=True
+ )
+
+ try:
+ idrac = SessionAPI(module.params)
+ session_operation = module.params.get("state")
+ if session_operation == "present":
+ session_operation_obj = CreateSession(idrac, module)
+ else:
+ session_operation_obj = DeleteSession(idrac, module)
+ session_operation_obj.execute()
+ except HTTPError as err:
+ filter_err = remove_key(json.load(err), regex_pattern=ODATA_REGEX)
+ module.exit_json(msg=str(err), error_info=filter_err, failed=True)
+ except URLError as err:
+ module.exit_json(msg=str(err), unreachable=True)
+ except (SSLValidationError, ConnectionError, TypeError, ValueError, OSError) as err:
+ module.exit_json(msg=str(err), failed=True)
+
+
+def get_argument_spec():
+ """
+ Returns a dictionary representing the argument specification for a module.
+
+ The dictionary contains the following keys and their corresponding values:
+ - "hostname": A string representing the hostname.
+ - "username": A string representing the username. It has a fallback option to retrieve the
+ value from the environment variable 'IDRAC_USERNAME'.
+ - "password": A string representing the password. It is marked as not to be logged and has a
+ fallback option to retrieve the value from the environment variable 'IDRAC_PASSWORD'.
+ - "port": An integer representing the port number. The default value is 443.
+ - "validate_certs": A boolean representing whether to validate certificates. The default value
+ is True.
+ - "ca_path": A path representing the certificate authority path. The default value is None.
+ - "timeout": An integer representing the timeout value. The default value is 30.
+ - "state": A string representing the state. The default value is "present". The choices are
+ ["present", "absent"].
+ - "auth_token": A string representing the authentication token. It is marked as not to be
+ logged.
+ - "session_id": An integer representing the session ID.
+
+ Returns:
+ A dictionary representing the argument specification.
+ """
+ return {
+ "hostname": {"type": "str"},
+ "username": {"type": "str", "fallback": (env_fallback, ['IDRAC_USERNAME'])},
+ "password": {"type": "str", "no_log": True, "fallback": (env_fallback, ['IDRAC_PASSWORD'])},
+ "port": {"type": "int", "default": 443},
+ "validate_certs": {"type": "bool", "default": True},
+ "ca_path": {"type": "path", "default": None},
+ "timeout": {"type": "int", "default": 30},
+ "state": {"type": 'str', "default": "present", "choices": ["present", "absent"]},
+ "auth_token": {"type": "str", "no_log": True},
+ "session_id": {"type": "int"}
+ }
+
+
+if __name__ == '__main__':
+ main()