gluster_peer: Module to create/dismantle trusted storage pool (#37771)

* gluster_peer: Module to create/dismantle trusted storage pool

* gluster_peer: Module to create/dismantle trusted storage pool

Added __init__.py and added function main() in the module.

* gluster_peer: Module to create/dismantle trusted storage pool

Empty __init__.py was needed. Removed comment from the file.

* gluster_peer: Module to create/dismantle trusted storage pool

Addressed review comments.

* gluster_peer: Module to create/dismantle trusted storage pool

Do version check more sanely, improve parameter handling.

* gluster_peer: Module to create/dismantle trusted storage pool

Use isinstance for type comparison.

* gluster_peer: Module to create/dismantle trusted storage pool

Use type=list for nodes parameter, get rid of literal_eval.

* gluster_peer: Module to create/dismantle trusted storage pool

Add parameter check_mode, had missed this somewhere in between.

* gluster_peer: do not set `force' in case of state=present

* gluster_peer: Fix typo in the documentation

* gluster_peer: make peer probe idempotent

* gluster_peer: Fix a logical error while evaluating booleans

* gluster_peer: set locale to C, pass list to run_command
pull/33986/merge
Sachidananda Urs 6 years ago committed by Adam Miller
parent 9f732d2f05
commit 5861d5f74e

@ -0,0 +1,176 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2015 Nandaja Varma <nvarma@redhat.com>
# Copyright 2018 Red Hat, Inc.
#
# 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
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: gluster_peer
short_description: Attach/Detach peers to/from the cluster
description:
- Create or diminish a GlusterFS trusted storage pool. A set of nodes can be
added into an existing trusted storage pool or a new storage pool can be
formed. Or, nodes can be removed from an existing trusted storage pool.
version_added: "2.6"
author: Sachidananda Urs (@sac)
options:
state:
choices: ["present", "absent"]
default: "present"
description:
- Determines whether the nodes should be attached to the pool or
removed from the pool. If the state is present, nodes will be
attached to the pool. If state is absent, nodes will be detached
from the pool.
required: true
nodes:
description:
- List of nodes that have to be probed into the pool.
required: true
force:
type: bool
default: "false"
description:
- Applicable only while removing the nodes from the pool. gluster
will refuse to detach a node from the pool if any one of the node
is down, in such cases force can be used.
requirements:
- GlusterFS > 3.2
notes:
- This module does not support check mode.
'''
EXAMPLES = '''
- name: Create a trusted storage pool
gluster_peer:
state: present
nodes:
- 10.0.1.5
- 10.0.1.10
- name: Delete a node from the trusted storage pool
gluster_peer:
state: absent
nodes:
- 10.0.1.10
- name: Delete a node from the trusted storage pool by force
gluster_peer:
state: absent
nodes:
- 10.0.0.1
force: true
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from distutils.version import LooseVersion
class Peer(object):
def __init__(self, module):
self.module = module
self.state = self.module.params['state']
self.nodes = self.module.params['nodes']
self.glustercmd = self.module.get_bin_path('gluster', True)
self.lang = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')
self.action = ''
self.force = ''
def gluster_peer_ops(self):
if not self.nodes:
self.module.fail_json(msg="nodes list cannot be empty")
self.force = 'force' if self.module.params.get('force') else ''
if self.state == 'present':
self.nodes = self.get_to_be_probed_hosts(self.nodes)
self.action = 'probe'
# In case of peer probe, we do not need `force'
self.force = ''
else:
self.action = 'detach'
self.call_peer_commands()
def get_to_be_probed_hosts(self, hosts):
peercmd = [self.glustercmd, 'pool', 'list']
rc, output, err = self.module.run_command(peercmd,
environ_update=self.lang)
peers_in_cluster = [line.split('\t')[1].strip() for
line in filter(None, output.split('\n')[1:])]
try:
peers_in_cluster.remove('localhost')
except ValueError:
# It is ok not to have localhost in list
pass
hosts_to_be_probed = [host for host in hosts if host not in
peers_in_cluster]
return hosts_to_be_probed
def call_peer_commands(self):
result = {}
result['msg'] = ''
result['changed'] = False
for node in self.nodes:
peercmd = [self.glustercmd, 'peer', self.action, node]
if self.force:
peercmd.append(self.force)
rc, out, err = self.module.run_command(peercmd,
environ_update=self.lang)
if rc:
result['rc'] = rc
result['msg'] = err
# Fail early, do not wait for the loop to finish
self.module.fail_json(**result)
else:
if 'already in peer' in out or \
'localhost not needed' in out:
result['changed'] |= False
else:
result['changed'] = True
self.module.exit_json(**result)
def main():
module = AnsibleModule(
argument_spec=dict(
force=dict(type='bool', required=False),
nodes=dict(type='list', required=True),
state=dict(type='str', choices=['absent', 'present'],
default='present'),
),
supports_check_mode=False
)
pops = Peer(module)
required_version = "3.2"
# Verify if required GlusterFS version is installed
if is_invalid_gluster_version(module, required_version):
module.fail_json(msg="GlusterFS version > %s is required" %
required_version)
pops.gluster_peer_ops()
def is_invalid_gluster_version(module, required_version):
cmd = module.get_bin_path('gluster', True) + ' --version'
result = module.run_command(cmd)
ver_line = result[1].split('\n')[0]
version = ver_line.split(' ')[1]
# If the installed version is less than 3.2, it is an invalid version
# return True
return LooseVersion(version) < LooseVersion(required_version)
if __name__ == "__main__":
main()
Loading…
Cancel
Save