--- /dev/null
+# Copyright Red Hat
+# SPDX-License-Identifier: Apache-2.0
+# Author: Guillaume Abrioux <gabrioux@redhat.com>
+
+from __future__ import absolute_import, division, print_function
+from typing import List, Tuple
+__metaclass__ = type
+
+from ansible.module_utils.basic import AnsibleModule # type: ignore
+try:
+ from ansible.module_utils.ca_common import exit_module, generate_cmd, fatal, is_containerized # type: ignore
+except ImportError:
+ from module_utils.ca_common import exit_module, generate_cmd, fatal, is_containerized # type: ignore
+
+import datetime
+import json
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: ceph_config
+short_description: set ceph config
+version_added: "2.10"
+description:
+ - Set Ceph config options.
+options:
+ fsid:
+ description:
+ - the fsid of the Ceph cluster to interact with.
+ required: false
+ image:
+ description:
+ - The Ceph container image to use.
+ required: false
+ action:
+ description:
+ - whether to get or set the parameter specified in 'option'
+ required: false
+ default: 'set'
+ who:
+ description:
+ - which daemon the configuration should be set to
+ required: true
+ option:
+ description:
+ - name of the parameter to be set
+ required: true
+ value:
+ description:
+ - value of the parameter
+ required: true if action is 'set'
+
+author:
+ - Guillaume Abrioux <gabrioux@redhat.com>
+'''
+
+EXAMPLES = '''
+- name: set osd_memory_target for osd.0
+ ceph_config:
+ action: set
+ who: osd.0
+ option: osd_memory_target
+ value: 5368709120
+
+- name: set osd_memory_target for host ceph-osd-02
+ ceph_config:
+ action: set
+ who: osd/host:ceph-osd-02
+ option: osd_memory_target
+ value: 5368709120
+
+- name: get osd_pool_default_size value
+ ceph_config:
+ action: get
+ who: global
+ option: osd_pool_default_size
+ value: 1
+'''
+
+RETURN = '''# '''
+
+
+def set_option(module,
+ who,
+ option,
+ value,
+ container_image=None):
+
+ args = []
+ args.extend([who, option, value])
+
+ cmd = generate_cmd(sub_cmd=['config', 'set'],
+ args=args,
+ cluster=module.params.get('cluster'),
+ container_image=container_image)
+
+ rc, out, err = module.run_command(cmd)
+
+ return rc, cmd, out.strip(), err
+
+
+def get_config_dump(module, container_image=None):
+ cmd = generate_cmd(sub_cmd=['config', 'dump', '--format', 'json'],
+ args=[],
+ cluster=module.params.get('cluster'),
+ container_image=container_image)
+ rc, out, err = module.run_command(cmd)
+ if rc:
+ fatal(message=f"Can't get current configuration via `ceph config dump`.Error:\n{err}", module=module)
+ out = out.strip()
+ return rc, cmd, out, err
+
+
+def get_current_value(who, option, config_dump):
+ for config in config_dump:
+ if config['section'] == who and config['name'] == option:
+ return config['value']
+ return None
+
+
+def main() -> None:
+ module = AnsibleModule(
+ argument_spec=dict(
+ who=dict(type='str', required=True),
+ action=dict(type='str', required=False, choices=['get', 'set'], default='set'),
+ option=dict(type='str', required=True),
+ value=dict(type='str', required=False),
+ fsid=dict(type='str', required=False),
+ image=dict(type='str', required=False),
+ cluster=dict(type='str', required=False, default='ceph')
+ ),
+ supports_check_mode=True,
+ required_if=[['action', 'set', ['value']]]
+ )
+
+ # Gather module parameters in variables
+ who = module.params.get('who')
+ option = module.params.get('option')
+ value = module.params.get('value')
+ action = module.params.get('action')
+
+ container_image = is_containerized()
+
+ if module.check_mode:
+ module.exit_json(
+ changed=False,
+ stdout='',
+ cmd=[],
+ stderr='',
+ rc=0,
+ start='',
+ end='',
+ delta='',
+ )
+
+ startd = datetime.datetime.now()
+ changed = False
+
+ rc, cmd, out, err = get_config_dump(module, container_image=container_image)
+ config_dump = json.loads(out)
+ current_value = get_current_value(who, option, config_dump)
+
+ if action == 'set':
+ if value.lower() == current_value:
+ out = 'who={} option={} value={} already set. Skipping.'.format(who, option, value, container_image=container_image)
+ else:
+ rc, cmd, out, err = set_option(module, who, option, value, container_image=container_image)
+ changed = True
+ else:
+ if current_value is None:
+ out = ''
+ err = 'No value found for who={} option={}'.format(who, option)
+ else:
+ out = current_value
+
+ exit_module(module=module, out=out, rc=rc,
+ cmd=cmd, err=err, startd=startd,
+ changed=changed)
+
+
+if __name__ == '__main__':
+ main()