summaryrefslogtreecommitdiff
path: root/lib/ansible/modules/storage/purestorage/purefa_volume.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/modules/storage/purestorage/purefa_volume.py')
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_volume.py498
1 files changed, 0 insertions, 498 deletions
diff --git a/lib/ansible/modules/storage/purestorage/purefa_volume.py b/lib/ansible/modules/storage/purestorage/purefa_volume.py
deleted file mode 100644
index 9749125928..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_volume.py
+++ /dev/null
@@ -1,498 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2018, Simon Dodsley (simon@purestorage.com)
-# 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 = r'''
----
-module: purefa_volume
-version_added: '2.4'
-short_description: Manage volumes on Pure Storage FlashArrays
-description:
-- Create, delete or extend the capacity of a volume on Pure Storage FlashArray.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- name:
- description:
- - The name of the volume.
- type: str
- required: true
- target:
- description:
- - The name of the target volume, if copying.
- type: str
- state:
- description:
- - Define whether the volume should exist or not.
- default: present
- choices: [ absent, present ]
- type: str
- eradicate:
- description:
- - Define whether to eradicate the volume on delete or leave in trash.
- type: bool
- default: 'no'
- overwrite:
- description:
- - Define whether to overwrite a target volume if it already exists.
- type: bool
- default: 'no'
- size:
- description:
- - Volume size in M, G, T or P units.
- type: str
- bw_qos:
- description:
- - Bandwidth limit for volume in M or G units.
- M will set MB/s
- G will set GB/s
- To clear an existing QoS setting use 0 (zero)
- version_added: '2.8'
- type: str
- aliases: [ qos ]
- iops_qos:
- description:
- - IOPs limit for volume - use value or K or M
- K will mean 1000
- M will mean 1000000
- To clear an existing IOPs setting use 0 (zero)
- version_added: '2.10'
- type: str
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create new volume named foo with a QoS limit
- purefa_volume:
- name: foo
- size: 1T
- bw_qos: 58M
- iops_qos: 23K
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Extend the size of an existing volume named foo
- purefa_volume:
- name: foo
- size: 2T
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Delete and eradicate volume named foo
- purefa_volume:
- name: foo
- eradicate: yes
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Create clone of volume bar named foo
- purefa_volume:
- name: foo
- target: bar
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Overwrite volume bar with volume foo
- purefa_volume:
- name: foo
- target: bar
- overwrite: yes
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Clear volume QoS from volume foo
- purefa_volume:
- name: foo
- bw_qos: 0
- iops_qos: 0
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-'''
-
-RETURN = r'''
-volume:
- description: A dictionary describing the changed volume. Only some
- attributes below will be returned with various actions.
- type: dict
- returned: success
- contains:
- source:
- description: Volume name of source volume used for volume copy
- type: str
- serial:
- description: Volume serial number
- type: str
- sample: '361019ECACE43D83000120A4'
- created:
- description: Volume creation time
- type: str
- sample: '2019-03-13T22:49:24Z'
- name:
- description: Volume name
- type: str
- size:
- description: Volume size in bytes
- type: int
- bandwidth_limit:
- description: Volume bandwidth limit in bytes/sec
- type: int
- iops_limit:
- description: Volume IOPs limit
- type: int
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-QOS_API_VERSION = "1.14"
-VGROUPS_API_VERSION = "1.13"
-POD_API_VERSION = "1.13"
-IOPS_API_VERSION = "1.17"
-
-
-def human_to_bytes(size):
- """Given a human-readable byte string (e.g. 2G, 30M),
- return the number of bytes. Will return 0 if the argument has
- unexpected form.
- """
- bytes = size[:-1]
- unit = size[-1]
- if bytes.isdigit():
- bytes = int(bytes)
- if unit == 'P':
- bytes *= 1125899906842624
- elif unit == 'T':
- bytes *= 1099511627776
- elif unit == 'G':
- bytes *= 1073741824
- elif unit == 'M':
- bytes *= 1048576
- elif unit == 'K':
- bytes *= 1024
- else:
- bytes = 0
- else:
- bytes = 0
- return bytes
-
-
-def human_to_real(iops):
- """Given a human-readable IOPs string (e.g. 2K, 30M),
- return the real number. Will return 0 if the argument has
- unexpected form.
- """
- digit = iops[:-1]
- unit = iops[-1]
- if digit.isdigit():
- digit = int(digit)
- if unit == 'M':
- digit *= 1000000
- elif unit == 'K':
- digit *= 1000
- else:
- digit = 0
- else:
- digit = 0
- return digit
-
-
-def get_volume(module, array):
- """Return Volume or None"""
- try:
- return array.get_volume(module.params['name'])
- except Exception:
- return None
-
-
-def get_destroyed_volume(module, array):
- """Return Destroyed Volume or None"""
- try:
- return bool(array.get_volume(module.params['name'], pending=True)['time_remaining'] != '')
- except Exception:
- return False
-
-
-def get_target(module, array):
- """Return Volume or None"""
- try:
- return array.get_volume(module.params['target'])
- except Exception:
- return None
-
-
-def check_vgroup(module, array):
- """Check is the requested VG to create volume in exists"""
- vg_exists = False
- api_version = array._list_available_rest_versions()
- if VGROUPS_API_VERSION in api_version:
- vg_name = module.params["name"].split("/")[0]
- try:
- vgs = array.list_vgroups()
- except Exception:
- module.fail_json(msg="Failed to get volume groups list. Check array.")
- for vgroup in range(0, len(vgs)):
- if vg_name == vgs[vgroup]['name']:
- vg_exists = True
- break
- else:
- module.fail_json(msg="VG volumes are not supported. Please upgrade your FlashArray.")
- return vg_exists
-
-
-def check_pod(module, array):
- """Check is the requested pod to create volume in exists"""
- pod_exists = False
- api_version = array._list_available_rest_versions()
- if POD_API_VERSION in api_version:
- pod_name = module.params["name"].split("::")[0]
- try:
- pods = array.list_pods()
- except Exception:
- module.fail_json(msg="Failed to get pod list. Check array.")
- for pod in range(0, len(pods)):
- if pod_name == pods[pod]['name']:
- pod_exists = True
- break
- else:
- module.fail_json(msg="Pod volumes are not supported. Please upgrade your FlashArray.")
- return pod_exists
-
-
-def create_volume(module, array):
- """Create Volume"""
- changed = True
- volfact = []
- if not module.check_mode:
- if "/" in module.params['name'] and not check_vgroup(module, array):
- module.fail_json(msg="Failed to create volume {0}. Volume Group does not exist.".format(module.params["name"]))
- if "::" in module.params['name'] and not check_pod(module, array):
- module.fail_json(msg="Failed to create volume {0}. Poid does not exist".format(module.params["name"]))
- api_version = array._list_available_rest_versions()
- if module.params['bw_qos'] or module.params['iops_qos']:
- if module.params['bw_qos'] and QOS_API_VERSION in api_version or module.params['iops_qos'] and IOPS_API_VERSION in api_version:
- if module.params['bw_qos'] and not module.params['iops_qos']:
- if 549755813888 >= int(human_to_bytes(module.params['bw_qos'])) >= 1048576:
- try:
- volfact = array.create_volume(module.params['name'],
- module.params['size'],
- bandwidth_limit=module.params['bw_qos'])
- except Exception:
- module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
- else:
- module.fail_json(msg='Bandwidth QoS value {0} out of range.'.format(module.params['bw_qos']))
- elif module.params['iops_qos'] and not module.params['bw_qos']:
- if 100000000 >= int(human_to_real(module.params['iops_qos'])) >= 100:
- try:
- volfact = array.create_volume(module.params['name'],
- module.params['size'],
- iops_limit=module.params['iops_qos'])
- except Exception:
- module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
- else:
- module.fail_json(msg='IOPs QoS value {0} out of range.'.format(module.params['iops_qos']))
- else:
- bw_qos_size = int(human_to_bytes(module.params['bw_qos']))
- if 100000000 >= int(human_to_real(module.params['iops_qos'])) >= 100 and 549755813888 >= bw_qos_size >= 1048576:
- try:
- volfact = array.create_volume(module.params['name'],
- module.params['size'],
- iops_limit=module.params['iops_qos'],
- bandwidth_limit=module.params['bw_qos'])
- except Exception:
- module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
- else:
- module.fail_json(msg='IOPs or Bandwidth QoS value out of range.')
-
- else:
- try:
- volfact = array.create_volume(module.params['name'], module.params['size'])
- except Exception:
- module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
-
- module.exit_json(changed=changed, volume=volfact)
-
-
-def copy_from_volume(module, array):
- """Create Volume Clone"""
- changed = True
- volfact = []
- if not module.check_mode:
- tgt = get_target(module, array)
-
- if tgt is None:
- try:
- volfact = array.copy_volume(module.params['name'],
- module.params['target'])
- except Exception:
- module.fail_json(msg='Copy volume {0} to volume {1} failed.'.format(module.params['name'],
- module.params['target']))
- elif tgt is not None and module.params['overwrite']:
- try:
- volfact = array.copy_volume(module.params['name'],
- module.params['target'],
- overwrite=module.params['overwrite'])
- except Exception:
- module.fail_json(msg='Copy volume {0} to volume {1} failed.'.format(module.params['name'],
- module.params['target']))
-
- module.exit_json(changed=changed, volume=volfact)
-
-
-def update_volume(module, array):
- """Update Volume size and/or QoS"""
- changed = True
- volfact = []
- if not module.check_mode:
- change = False
- api_version = array._list_available_rest_versions()
- vol = array.get_volume(module.params['name'])
- vol_qos = array.get_volume(module.params['name'], qos=True)
- if QOS_API_VERSION in api_version:
- if vol_qos['bandwidth_limit'] is None:
- vol_qos['bandwidth_limit'] = 0
- if IOPS_API_VERSION in api_version:
- if vol_qos['iops_limit'] is None:
- vol_qos['iops_limit'] = 0
- if module.params['size']:
- if human_to_bytes(module.params['size']) != vol['size']:
- if human_to_bytes(module.params['size']) > vol['size']:
- try:
- volfact = array.extend_volume(module.params['name'], module.params['size'])
- change = True
- except Exception:
- module.fail_json(msg='Volume {0} resize failed.'.format(module.params['name']))
- if module.params['bw_qos'] and QOS_API_VERSION in api_version:
- if human_to_bytes(module.params['bw_qos']) != vol_qos['bandwidth_limit']:
- if module.params['bw_qos'] == '0':
- try:
- volfact = array.set_volume(module.params['name'], bandwidth_limit='')
- change = True
- except Exception:
- module.fail_json(msg='Volume {0} Bandwidth QoS removal failed.'.format(module.params['name']))
- elif 549755813888 >= int(human_to_bytes(module.params['bw_qos'])) >= 1048576:
- try:
- volfact = array.set_volume(module.params['name'],
- bandwidth_limit=module.params['bw_qos'])
- change = True
- except Exception:
- module.fail_json(msg='Volume {0} Bandwidth QoS change failed.'.format(module.params['name']))
- else:
- module.fail_json(msg='Bandwidth QoS value {0} out of range.'.format(module.params['bw_qos']))
- if module.params['iops_qos'] and IOPS_API_VERSION in api_version:
- if human_to_real(module.params['iops_qos']) != vol_qos['iops_limit']:
- if module.params['iops_qos'] == '0':
- try:
- volfact = array.set_volume(module.params['name'], iops_limit='')
- change = True
- except Exception:
- module.fail_json(msg='Volume {0} IOPs QoS removal failed.'.format(module.params['name']))
- elif 100000000 >= int(human_to_real(module.params['iops_qos'])) >= 100:
- try:
- volfact = array.set_volume(module.params['name'],
- iops_limit=module.params['iops_qos'])
- except Exception:
- module.fail_json(msg='Volume {0} IOPs QoS change failed.'.format(module.params['name']))
- else:
- module.fail_json(msg='Bandwidth QoS value {0} out of range.'.format(module.params['bw_qos']))
-
- module.exit_json(changed=change, volume=volfact)
-
- module.exit_json(changed=changed)
-
-
-def delete_volume(module, array):
- """ Delete Volume"""
- changed = True
- volfact = []
- if not module.check_mode:
- try:
- array.destroy_volume(module.params['name'])
- if module.params['eradicate']:
- try:
- volfact = array.eradicate_volume(module.params['name'])
- except Exception:
- module.fail_json(msg='Eradicate volume {0} failed.'.format(module.params['name']))
- except Exception:
- module.fail_json(msg='Delete volume {0} failed.'.format(module.params['name']))
- module.exit_json(changed=changed, volume=volfact)
-
-
-def eradicate_volume(module, array):
- """ Eradicate Deleted Volume"""
- changed = True
- volfact = []
- if not module.check_mode:
- if module.params['eradicate']:
- try:
- array.eradicate_volume(module.params['name'])
- except Exception:
- module.fail_json(msg='Eradication of volume {0} failed'.format(module.params['name']))
- module.exit_json(changed=changed, volume=volfact)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- target=dict(type='str'),
- overwrite=dict(type='bool', default=False),
- eradicate=dict(type='bool', default=False),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- bw_qos=dict(type='str', aliases=['qos']),
- iops_qos=dict(type='str'),
- size=dict(type='str'),
- ))
-
- mutually_exclusive = [['size', 'target'], ['qos', 'target']]
-
- module = AnsibleModule(argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True)
-
- size = module.params['size']
- bw_qos = module.params['bw_qos']
- iops_qos = module.params['iops_qos']
- state = module.params['state']
- array = get_system(module)
- volume = get_volume(module, array)
- if not volume:
- destroyed = get_destroyed_volume(module, array)
- target = get_target(module, array)
-
- if state == 'present' and not volume and size:
- create_volume(module, array)
- elif state == 'present' and volume and (size or bw_qos or iops_qos):
- update_volume(module, array)
- elif state == 'present' and volume and target:
- copy_from_volume(module, array)
- elif state == 'present' and volume and not target:
- copy_from_volume(module, array)
- elif state == 'absent' and volume:
- delete_volume(module, array)
- elif state == 'absent' and destroyed:
- eradicate_volume(module, array)
- elif state == 'present' and not volume or not size:
- module.exit_json(changed=False)
- elif state == 'absent' and not volume:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()