diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 06:22:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-26 06:22:20 +0000 |
commit | 18bd2207b6c1977e99a93673a7be099e23f0f547 (patch) | |
tree | 40fd9e5913462a88be6ba24be6953383c5b39874 /ansible_collections/dellemc/openmanage/plugins/module_utils | |
parent | Releasing progress-linux version 10.0.1+dfsg-1~progress7.99u1. (diff) | |
download | ansible-18bd2207b6c1977e99a93673a7be099e23f0f547.tar.xz ansible-18bd2207b6c1977e99a93673a7be099e23f0f547.zip |
Merging upstream version 10.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/dellemc/openmanage/plugins/module_utils')
4 files changed, 204 insertions, 25 deletions
diff --git a/ansible_collections/dellemc/openmanage/plugins/module_utils/idrac_redfish.py b/ansible_collections/dellemc/openmanage/plugins/module_utils/idrac_redfish.py index cf4581e89..7e55364a1 100644 --- a/ansible_collections/dellemc/openmanage/plugins/module_utils/idrac_redfish.py +++ b/ansible_collections/dellemc/openmanage/plugins/module_utils/idrac_redfish.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # Dell OpenManage Ansible Modules -# Version 8.0.0 -# Copyright (C) 2019-2023 Dell Inc. or its subsidiaries. All Rights Reserved. +# Version 9.3.0 +# Copyright (C) 2019-2024 Dell Inc. or its subsidiaries. All Rights Reserved. # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -38,6 +38,7 @@ from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible.module_utils.common.parameters import env_fallback from ansible_collections.dellemc.openmanage.plugins.module_utils.utils import config_ipv6 +from ansible.module_utils.basic import AnsibleModule idrac_auth_params = { "idrac_ip": {"required": True, "type": 'str'}, @@ -101,6 +102,7 @@ class iDRACRedfishAPI(object): self.ipaddress = module_params['idrac_ip'] self.username = module_params['idrac_user'] self.password = module_params['idrac_password'] + self.x_auth_token = module_params.get('x_auth_token') self.port = module_params['idrac_port'] self.validate_certs = module_params.get("validate_certs", False) self.ca_path = module_params.get("ca_path") @@ -180,7 +182,7 @@ class iDRACRedfishAPI(object): def __enter__(self): """Creates sessions by passing it to header""" - if self.req_session: + if self.req_session and not self.x_auth_token: payload = {'UserName': self.username, 'Password': self.password} path = SESSION_RESOURCE_COLLECTION["SESSION"] @@ -191,6 +193,8 @@ class iDRACRedfishAPI(object): else: msg = "Could not create the session" raise ConnectionError(msg) + elif self.x_auth_token is not None: + self._headers["X-Auth-Token"] = self.x_auth_token return self def __exit__(self, exc_type, exc_value, traceback): @@ -300,7 +304,7 @@ class iDRACRedfishAPI(object): return response def import_scp_share(self, shutdown_type=None, host_powerstate=None, job_wait=True, - target=None, import_buffer=None, share=None): + target=None, import_buffer=None, share=None, time_to_wait=300): """ This method imports system configuration using share. :param shutdown_type: graceful @@ -312,7 +316,7 @@ class iDRACRedfishAPI(object): :return: json response """ payload = {"ShutdownType": shutdown_type, "EndHostPowerState": host_powerstate, - "ShareParameters": {"Target": target}} + "ShareParameters": {"Target": target}, "TimeToWait": time_to_wait} if import_buffer is not None: payload["ImportBuffer"] = import_buffer if share is None: @@ -384,7 +388,7 @@ class iDRACRedfishAPI(object): response = self.wait_for_job_complete(task_uri, job_wait=job_wait) return response - def import_scp(self, import_buffer=None, target=None, job_wait=False): + def import_scp(self, import_buffer=None, target=None, job_wait=False, time_to_wait=300): """ This method imports system configuration details to the system. :param import_buffer: import buffer payload content xml or json format @@ -392,7 +396,7 @@ class iDRACRedfishAPI(object): :param job_wait: True or False decide whether to wait till the job completion. :return: json response """ - payload = {"ImportBuffer": import_buffer, "ShareParameters": {"Target": target}} + payload = {"ImportBuffer": import_buffer, "ShareParameters": {"Target": target}, "TimeToWait": time_to_wait} response = self.invoke_request(IMPORT_URI, "POST", data=payload) if response.status_code == 202 and job_wait: task_uri = response.headers["Location"] @@ -433,3 +437,42 @@ class iDRACRedfishAPI(object): def _get_omam_ca_env(self): """Check if the value is set in REQUESTS_CA_BUNDLE or CURL_CA_BUNDLE or OMAM_CA_BUNDLE or returns None""" return os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("CURL_CA_BUNDLE") or os.environ.get("OMAM_CA_BUNDLE") + + +class IdracAnsibleModule(AnsibleModule): + def __init__(self, argument_spec, bypass_checks=False, no_log=False, + mutually_exclusive=None, required_together=None, + required_one_of=None, add_file_common_args=False, + supports_check_mode=False, required_if=None, required_by=None): + idrac_argument_spec = { + "idrac_ip": {"required": True, "type": 'str'}, + "idrac_user": {"required": False, "type": 'str', "fallback": (env_fallback, ['IDRAC_USERNAME'])}, + "idrac_password": {"required": False, "type": 'str', "aliases": ['idrac_pwd'], "no_log": True, "fallback": (env_fallback, ['IDRAC_PASSWORD'])}, + "x_auth_token": {"required": False, "type": 'str', "no_log": True, "fallback": (env_fallback, ['IDRAC_X_AUTH_TOKEN'])}, + "idrac_port": {"required": False, "default": 443, "type": 'int'}, + "validate_certs": {"type": "bool", "default": True}, + "ca_path": {"type": "path"}, + "timeout": {"type": "int", "default": 30}, + } + argument_spec.update(idrac_argument_spec) + + auth_mutually_exclusive = [("idrac_user", "x_auth_token"), ("idrac_password", "x_auth_token")] + auth_required_one_of = [("idrac_user", "x_auth_token")] + auth_required_together = [("idrac_user", "idrac_password")] + + if mutually_exclusive is None: + mutually_exclusive = [] + mutually_exclusive.extend(auth_mutually_exclusive) + if required_together is None: + required_together = [] + required_together.extend(auth_required_together) + if required_one_of is None: + required_one_of = [] + required_one_of.extend(auth_required_one_of) + if required_by is None: + required_by = {} + + super().__init__(argument_spec, bypass_checks, no_log, + mutually_exclusive, required_together, + required_one_of, add_file_common_args, + supports_check_mode, required_if, required_by) diff --git a/ansible_collections/dellemc/openmanage/plugins/module_utils/ome.py b/ansible_collections/dellemc/openmanage/plugins/module_utils/ome.py index cd0bb6be0..4aeba6201 100644 --- a/ansible_collections/dellemc/openmanage/plugins/module_utils/ome.py +++ b/ansible_collections/dellemc/openmanage/plugins/module_utils/ome.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # Dell OpenManage Ansible Modules -# Version 8.2.0 -# Copyright (C) 2019-2023 Dell Inc. or its subsidiaries. All Rights Reserved. +# Version 9.3.0 +# Copyright (C) 2019-2024 Dell Inc. or its subsidiaries. All Rights Reserved. # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -38,6 +38,7 @@ from ansible.module_utils.common.parameters import env_fallback from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible_collections.dellemc.openmanage.plugins.module_utils.utils import config_ipv6 +from ansible.module_utils.basic import AnsibleModule ome_auth_params = { "hostname": {"required": True, "type": "str"}, @@ -96,6 +97,7 @@ class RestOME(object): self.hostname = str(self.module_params["hostname"]).strip('][') self.username = self.module_params["username"] self.password = self.module_params["password"] + self.x_auth_token = self.module_params.get("x_auth_token") self.port = self.module_params["port"] self.validate_certs = self.module_params.get("validate_certs", True) self.ca_path = self.module_params.get("ca_path") @@ -191,7 +193,7 @@ class RestOME(object): def __enter__(self): """Creates sessions by passing it to header""" - if self.req_session: + if self.req_session and not self.x_auth_token: payload = {'UserName': self.username, 'Password': self.password, 'SessionType': 'API', } @@ -203,6 +205,8 @@ class RestOME(object): else: msg = "Could not create the session" raise ConnectionError(msg) + elif self.x_auth_token is not None: + self._headers["X-Auth-Token"] = self.x_auth_token return self def __exit__(self, exc_type, exc_value, traceback): @@ -401,3 +405,42 @@ class RestOME(object): def _get_omam_ca_env(self): """Check if the value is set in REQUESTS_CA_BUNDLE or CURL_CA_BUNDLE or OMAM_CA_BUNDLE or returns None""" return os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("CURL_CA_BUNDLE") or os.environ.get("OMAM_CA_BUNDLE") + + +class OmeAnsibleModule(AnsibleModule): + def __init__(self, argument_spec, bypass_checks=False, no_log=False, + mutually_exclusive=None, required_together=None, + required_one_of=None, add_file_common_args=False, + supports_check_mode=False, required_if=None, required_by=None): + ome_argument_spec = { + "hostname": {"required": True, "type": "str"}, + "username": {"required": False, "type": "str", "fallback": (env_fallback, ['OME_USERNAME'])}, + "password": {"required": False, "type": "str", "no_log": True, "fallback": (env_fallback, ['OME_PASSWORD'])}, + "x_auth_token": {"required": False, "type": "str", "no_log": True, "fallback": (env_fallback, ['OME_X_AUTH_TOKEN'])}, + "port": {"type": "int", "default": 443}, + "validate_certs": {"type": "bool", "default": True}, + "ca_path": {"type": "path"}, + "timeout": {"type": "int", "default": 30}, + } + argument_spec.update(ome_argument_spec) + + auth_mutually_exclusive = [("username", "x_auth_token"), ("password", "x_auth_token")] + auth_required_one_of = [("username", "x_auth_token")] + auth_required_together = [("username", "password")] + + if mutually_exclusive is None: + mutually_exclusive = [] + mutually_exclusive.extend(auth_mutually_exclusive) + if required_together is None: + required_together = [] + required_together.extend(auth_required_together) + if required_one_of is None: + required_one_of = [] + required_one_of.extend(auth_required_one_of) + if required_by is None: + required_by = {} + + super().__init__(argument_spec, bypass_checks, no_log, + mutually_exclusive, required_together, + required_one_of, add_file_common_args, + supports_check_mode, required_if, required_by) diff --git a/ansible_collections/dellemc/openmanage/plugins/module_utils/redfish.py b/ansible_collections/dellemc/openmanage/plugins/module_utils/redfish.py index 8a26eaf60..7e1615ab4 100644 --- a/ansible_collections/dellemc/openmanage/plugins/module_utils/redfish.py +++ b/ansible_collections/dellemc/openmanage/plugins/module_utils/redfish.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # Dell OpenManage Ansible Modules -# Version 8.2.0 -# Copyright (C) 2019-2023 Dell Inc. or its subsidiaries. All Rights Reserved. +# Version 9.3.0 +# Copyright (C) 2019-2024 Dell Inc. or its subsidiaries. All Rights Reserved. # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -36,6 +36,7 @@ from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible.module_utils.common.parameters import env_fallback from ansible_collections.dellemc.openmanage.plugins.module_utils.utils import config_ipv6 +from ansible.module_utils.basic import AnsibleModule redfish_auth_params = { "baseuri": {"required": True, "type": "str"}, @@ -96,6 +97,7 @@ class Redfish(object): self.hostname = self.module_params["baseuri"] self.username = self.module_params["username"] self.password = self.module_params["password"] + self.x_auth_token = self.module_params.get("x_auth_token") self.validate_certs = self.module_params.get("validate_certs", True) self.ca_path = self.module_params.get("ca_path") self.timeout = self.module_params.get("timeout", 30) @@ -191,7 +193,7 @@ class Redfish(object): def __enter__(self): """Creates sessions by passing it to header""" - if self.req_session: + if self.req_session and not self.x_auth_token: payload = {'UserName': self.username, 'Password': self.password} path = SESSION_RESOURCE_COLLECTION["SESSION"] @@ -202,6 +204,8 @@ class Redfish(object): else: msg = "Could not create the session" raise ConnectionError(msg) + elif self.x_auth_token is not None: + self._headers["X-Auth-Token"] = self.x_auth_token return self def __exit__(self, exc_type, exc_value, traceback): @@ -222,3 +226,41 @@ class Redfish(object): def _get_omam_ca_env(self): """Check if the value is set in REQUESTS_CA_BUNDLE or CURL_CA_BUNDLE or OMAM_CA_BUNDLE or returns None""" return os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("CURL_CA_BUNDLE") or os.environ.get("OMAM_CA_BUNDLE") + + +class RedfishAnsibleModule(AnsibleModule): + def __init__(self, argument_spec, bypass_checks=False, no_log=False, + mutually_exclusive=None, required_together=None, + required_one_of=None, add_file_common_args=False, + supports_check_mode=False, required_if=None, required_by=None): + redfish_argument_spec = { + "baseuri": {"required": True, "type": "str"}, + "username": {"required": False, "type": "str", "fallback": (env_fallback, ['IDRAC_USERNAME'])}, + "password": {"required": False, "type": "str", "no_log": True, "fallback": (env_fallback, ['IDRAC_PASSWORD'])}, + "x_auth_token": {"required": False, "type": "str", "no_log": True, "fallback": (env_fallback, ['IDRAC_X_AUTH_TOKEN'])}, + "validate_certs": {"type": "bool", "default": True}, + "ca_path": {"type": "path"}, + "timeout": {"type": "int", "default": 30}, + } + argument_spec.update(redfish_argument_spec) + + auth_mutually_exclusive = [("username", "x_auth_token"), ("password", "x_auth_token")] + auth_required_one_of = [("username", "x_auth_token")] + auth_required_together = [("username", "password")] + + if mutually_exclusive is None: + mutually_exclusive = [] + mutually_exclusive.extend(auth_mutually_exclusive) + if required_together is None: + required_together = [] + required_together.extend(auth_required_together) + if required_one_of is None: + required_one_of = [] + required_one_of.extend(auth_required_one_of) + if required_by is None: + required_by = {} + + super().__init__(argument_spec, bypass_checks, no_log, + mutually_exclusive, required_together, + required_one_of, add_file_common_args, + supports_check_mode, required_if, required_by) diff --git a/ansible_collections/dellemc/openmanage/plugins/module_utils/session_utils.py b/ansible_collections/dellemc/openmanage/plugins/module_utils/session_utils.py index 4bead057a..54728a771 100644 --- a/ansible_collections/dellemc/openmanage/plugins/module_utils/session_utils.py +++ b/ansible_collections/dellemc/openmanage/plugins/module_utils/session_utils.py @@ -34,6 +34,8 @@ import os from ansible.module_utils.urls import open_url from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible_collections.dellemc.openmanage.plugins.module_utils.utils import config_ipv6 +from ansible.module_utils.urls import open_url +from abc import ABC, abstractmethod HEADER_TYPE = "application/json" @@ -177,7 +179,7 @@ class SessionAPI(): self._headers = { 'Content-Type': HEADER_TYPE, 'Accept': HEADER_TYPE, - 'X-Auth-Token': module_params.get("auth_token") + 'X-Auth-Token': module_params.get("x_auth_token") } def _get_url(self, uri): @@ -220,7 +222,7 @@ class SessionAPI(): url += f"?{urlencode(query_param)}" return url - def _url_common_args_spec(self, method, api_timeout, headers=None): + def _url_common_args_spec(self, method, api_timeout, headers=None, url_kwargs=None): """ Generates the common arguments for a URL request. @@ -242,25 +244,27 @@ class SessionAPI(): - follow_redirects (str): The policy for following redirects. """ - req_header = self._headers - if headers: - req_header.update(headers) if api_timeout is None: api_timeout = self.timeout if self.ca_path is None: self.ca_path = self._get_omam_ca_env() - url_kwargs = { + req_header = self._headers + if headers: + req_header.update(headers) + url_params = { "method": method, "validate_certs": self.validate_certs, "ca_path": self.ca_path, "use_proxy": self.use_proxy, "headers": req_header, "timeout": api_timeout, - "follow_redirects": 'all', + "follow_redirects": 'all' } - return url_kwargs + if url_kwargs: + url_params.update(url_kwargs) + return url_params - def _args_session(self, method, api_timeout, headers=None): + def _args_session(self, method, api_timeout, headers=None, url_kwargs=None): """ Returns a dictionary containing the arguments needed to establish a session. @@ -275,11 +279,11 @@ class SessionAPI(): req_header = self._headers if headers: req_header.update(headers) - url_kwargs = self._url_common_args_spec(method, api_timeout, headers=headers) + url_kwargs = self._url_common_args_spec(method, api_timeout, headers=headers, url_kwargs=url_kwargs) return url_kwargs def invoke_request(self, uri, method, data=None, query_param=None, headers=None, - api_timeout=None, dump=True): + api_timeout=None, dump=True, url_kwargs=None): """ Invokes a request to the specified URI using the given method and optional parameters. @@ -300,7 +304,7 @@ class SessionAPI(): :return: The response data from the request. :rtype: OpenURLResponse """ - url_kwargs = self._args_session(method, api_timeout, headers=headers) + url_kwargs = self._args_session(method, api_timeout, headers=headers, url_kwargs=url_kwargs) if data and dump: data = json.dumps(data) url = self._build_url(uri, query_param=query_param) @@ -320,3 +324,50 @@ class SessionAPI(): return (os.environ.get("REQUESTS_CA_BUNDLE") or os.environ.get("CURL_CA_BUNDLE") or os.environ.get("OMAM_CA_BUNDLE")) + + +class Session(ABC): + """ + Parent class for all session operations. + """ + def __init__(self, module): + """ + Initializes the object with the given instance and module parameters. + + Args: + instance (object): The ome object. + module (object): The module object. + + Returns: + None + """ + self.instance = SessionAPI(module.params) + self.module = module + + @abstractmethod + def create_session(self): + """ + Abstract method to create a session. + Must be implemented by subclasses. + + Args: + None + + Returns: + None + """ + pass + + @abstractmethod + def delete_session(self): + """ + Abstract method to delete a session. + Must be implemented by subclasses. + + Args: + None + + Returns: + None + """ + pass |