summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSachidananda Urs <sacchi@gmail.com>2018-05-25 01:40:55 +0530
committerAdam Miller <admiller@redhat.com>2018-05-24 15:10:55 -0500
commit5861d5f74ea447c1171289cef343d0792805f09f (patch)
tree80b2124b505ccebe33b54e182baba4d347ee941e
parent9f732d2f05f8ec85e27306de3062bd950a9cfe29 (diff)
downloadansible-5861d5f74ea447c1171289cef343d0792805f09f.tar.gz
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
-rw-r--r--lib/ansible/modules/storage/glusterfs/__init__.py0
-rw-r--r--lib/ansible/modules/storage/glusterfs/gluster_peer.py176
2 files changed, 176 insertions, 0 deletions
diff --git a/lib/ansible/modules/storage/glusterfs/__init__.py b/lib/ansible/modules/storage/glusterfs/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ansible/modules/storage/glusterfs/__init__.py
diff --git a/lib/ansible/modules/storage/glusterfs/gluster_peer.py b/lib/ansible/modules/storage/glusterfs/gluster_peer.py
new file mode 100644
index 0000000000..a0d9104396
--- /dev/null
+++ b/lib/ansible/modules/storage/glusterfs/gluster_peer.py
@@ -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()