|
|
@ -46,15 +46,22 @@ options:
|
|
|
|
size:
|
|
|
|
size:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- Volume size in M, G, T or P units.
|
|
|
|
- Volume size in M, G, T or P units.
|
|
|
|
|
|
|
|
qos:
|
|
|
|
|
|
|
|
description:
|
|
|
|
|
|
|
|
- Bandwidth limit for volume in M or G units.
|
|
|
|
|
|
|
|
M will set MB/s
|
|
|
|
|
|
|
|
G will set GB/s
|
|
|
|
|
|
|
|
version_added: '2.8'
|
|
|
|
extends_documentation_fragment:
|
|
|
|
extends_documentation_fragment:
|
|
|
|
- purestorage.fa
|
|
|
|
- purestorage.fa
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
EXAMPLES = r'''
|
|
|
|
EXAMPLES = r'''
|
|
|
|
- name: Create new volume named foo
|
|
|
|
- name: Create new volume named foo with a QoS limit
|
|
|
|
purefa_volume:
|
|
|
|
purefa_volume:
|
|
|
|
name: foo
|
|
|
|
name: foo
|
|
|
|
size: 1T
|
|
|
|
size: 1T
|
|
|
|
|
|
|
|
qos: 58M
|
|
|
|
fa_url: 10.10.10.2
|
|
|
|
fa_url: 10.10.10.2
|
|
|
|
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
|
|
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
|
|
state: present
|
|
|
|
state: present
|
|
|
@ -96,12 +103,6 @@ EXAMPLES = r'''
|
|
|
|
RETURN = r'''
|
|
|
|
RETURN = r'''
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
from purestorage import purestorage
|
|
|
|
|
|
|
|
HAS_PURESTORAGE = True
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
HAS_PURESTORAGE = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
from ansible.module_utils.pure import get_system, purefa_argument_spec
|
|
|
|
from ansible.module_utils.pure import get_system, purefa_argument_spec
|
|
|
|
|
|
|
|
|
|
|
@ -138,6 +139,17 @@ def get_volume(module, array):
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_destroyed_volume(module, array):
|
|
|
|
|
|
|
|
"""Return Destroyed Volume or None"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
if array.get_volume(module.params['name'], pending=True)['time_remaining'] != '':
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_target(module, array):
|
|
|
|
def get_target(module, array):
|
|
|
|
"""Return Volume or None"""
|
|
|
|
"""Return Volume or None"""
|
|
|
|
try:
|
|
|
|
try:
|
|
|
@ -148,13 +160,24 @@ def get_target(module, array):
|
|
|
|
|
|
|
|
|
|
|
|
def create_volume(module, array):
|
|
|
|
def create_volume(module, array):
|
|
|
|
"""Create Volume"""
|
|
|
|
"""Create Volume"""
|
|
|
|
size = module.params['size']
|
|
|
|
changed = False
|
|
|
|
|
|
|
|
if module.params['qos']:
|
|
|
|
|
|
|
|
if 549755813888 >= int(human_to_bytes(module.params['qos'])) >= 1048576:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
array.create_volume(module.params['name'], module.params['size'],
|
|
|
|
|
|
|
|
bandwidth_limit=module.params['qos'])
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
if not module.check_mode:
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
module.fail_json(msg='QoS value {0} out of range.'.format(module.params['qos']))
|
|
|
|
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
array.create_volume(module.params['name'], size)
|
|
|
|
array.create_volume(module.params['name'], module.params['size'])
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
changed = False
|
|
|
|
module.fail_json(msg='Volume {0} creation failed.'.format(module.params['name']))
|
|
|
|
|
|
|
|
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -165,35 +188,59 @@ def copy_from_volume(module, array):
|
|
|
|
tgt = get_target(module, array)
|
|
|
|
tgt = get_target(module, array)
|
|
|
|
|
|
|
|
|
|
|
|
if tgt is None:
|
|
|
|
if tgt is None:
|
|
|
|
changed = True
|
|
|
|
try:
|
|
|
|
if not module.check_mode:
|
|
|
|
|
|
|
|
array.copy_volume(module.params['name'],
|
|
|
|
array.copy_volume(module.params['name'],
|
|
|
|
module.params['target'])
|
|
|
|
module.params['target'])
|
|
|
|
elif tgt is not None and module.params['overwrite']:
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
changed = True
|
|
|
|
if not module.check_mode:
|
|
|
|
except:
|
|
|
|
|
|
|
|
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:
|
|
|
|
array.copy_volume(module.params['name'],
|
|
|
|
array.copy_volume(module.params['name'],
|
|
|
|
module.params['target'],
|
|
|
|
module.params['target'],
|
|
|
|
overwrite=module.params['overwrite'])
|
|
|
|
overwrite=module.params['overwrite'])
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Copy volume {0} to volume {1} failed.'.format(module.params['name'],
|
|
|
|
|
|
|
|
module.params['target']))
|
|
|
|
|
|
|
|
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_volume(module, array):
|
|
|
|
def update_volume(module, array):
|
|
|
|
"""Update Volume"""
|
|
|
|
"""Update Volume size and/or QoS"""
|
|
|
|
changed = True
|
|
|
|
changed = False
|
|
|
|
vol = array.get_volume(module.params['name'])
|
|
|
|
vol = array.get_volume(module.params['name'])
|
|
|
|
|
|
|
|
vol_qos = array.get_volume(module.params['name'], qos=True)
|
|
|
|
|
|
|
|
if vol_qos['bandwidth_limit'] is None:
|
|
|
|
|
|
|
|
vol_qos['bandwidth_limit'] = 0
|
|
|
|
|
|
|
|
if module.params['size']:
|
|
|
|
|
|
|
|
if human_to_bytes(module.params['size']) != vol['size']:
|
|
|
|
if human_to_bytes(module.params['size']) > vol['size']:
|
|
|
|
if human_to_bytes(module.params['size']) > vol['size']:
|
|
|
|
if not module.check_mode:
|
|
|
|
try:
|
|
|
|
array.extend_volume(module.params['name'], module.params['size'])
|
|
|
|
array.extend_volume(module.params['name'], module.params['size'])
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Volume {0} resize failed.'.format(module.params['name']))
|
|
|
|
|
|
|
|
if module.params['qos']:
|
|
|
|
|
|
|
|
if human_to_bytes(module.params['qos']) != vol_qos['bandwidth_limit']:
|
|
|
|
|
|
|
|
if 549755813888 >= int(human_to_bytes(module.params['qos'])) >= 1048576:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
array.set_volume(module.params['name'],
|
|
|
|
|
|
|
|
bandwidth_limit=module.params['qos'])
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Volume {0} QoS change failed.'.format(module.params['name']))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
changed = False
|
|
|
|
module.fail_json(msg='QoS value {0} out of range. Check documentation.'.format(module.params['qos']))
|
|
|
|
|
|
|
|
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_volume(module, array):
|
|
|
|
def delete_volume(module, array):
|
|
|
|
""" Delete Volume"""
|
|
|
|
""" Delete Volume"""
|
|
|
|
changed = True
|
|
|
|
changed = False
|
|
|
|
if not module.check_mode:
|
|
|
|
if not module.check_mode:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
array.destroy_volume(module.params['name'])
|
|
|
|
array.destroy_volume(module.params['name'])
|
|
|
@ -201,10 +248,22 @@ def delete_volume(module, array):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
array.eradicate_volume(module.params['name'])
|
|
|
|
array.eradicate_volume(module.params['name'])
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
changed = False
|
|
|
|
module.fail_json(msg='Eradicate volume {0} failed.'.format(module.params['name']))
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Delete volume {0} failed.'.format(module.params['name']))
|
|
|
|
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def eradicate_volume(module, array):
|
|
|
|
|
|
|
|
""" Eradicate Deleted Volume"""
|
|
|
|
changed = False
|
|
|
|
changed = False
|
|
|
|
module.exit_json(changed=True)
|
|
|
|
try:
|
|
|
|
|
|
|
|
array.eradicate_volume(module.params['name'])
|
|
|
|
|
|
|
|
changed = True
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
module.fail_json(msg='Eradication of volume {0} failed'.format(module.params['name']))
|
|
|
|
|
|
|
|
module.exit_json(changed=changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
@ -215,27 +274,28 @@ def main():
|
|
|
|
overwrite=dict(type='bool', default=False),
|
|
|
|
overwrite=dict(type='bool', default=False),
|
|
|
|
eradicate=dict(type='bool', default=False),
|
|
|
|
eradicate=dict(type='bool', default=False),
|
|
|
|
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
|
|
state=dict(type='str', default='present', choices=['absent', 'present']),
|
|
|
|
|
|
|
|
qos=dict(type='str'),
|
|
|
|
size=dict(type='str'),
|
|
|
|
size=dict(type='str'),
|
|
|
|
))
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
mutually_exclusive = [['size', 'target']]
|
|
|
|
mutually_exclusive = [['size', 'target'], ['qos', 'target']]
|
|
|
|
|
|
|
|
|
|
|
|
module = AnsibleModule(argument_spec,
|
|
|
|
module = AnsibleModule(argument_spec,
|
|
|
|
mutually_exclusive=mutually_exclusive,
|
|
|
|
mutually_exclusive=mutually_exclusive,
|
|
|
|
supports_check_mode=True)
|
|
|
|
supports_check_mode=False)
|
|
|
|
|
|
|
|
|
|
|
|
if not HAS_PURESTORAGE:
|
|
|
|
|
|
|
|
module.fail_json(msg='purestorage sdk is required for this module in volume')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size = module.params['size']
|
|
|
|
size = module.params['size']
|
|
|
|
|
|
|
|
qos = module.params['qos']
|
|
|
|
state = module.params['state']
|
|
|
|
state = module.params['state']
|
|
|
|
array = get_system(module)
|
|
|
|
array = get_system(module)
|
|
|
|
volume = get_volume(module, array)
|
|
|
|
volume = get_volume(module, array)
|
|
|
|
|
|
|
|
if not volume:
|
|
|
|
|
|
|
|
destroyed = get_destroyed_volume(module, array)
|
|
|
|
target = get_target(module, array)
|
|
|
|
target = get_target(module, array)
|
|
|
|
|
|
|
|
|
|
|
|
if state == 'present' and not volume and size:
|
|
|
|
if state == 'present' and not volume and size:
|
|
|
|
create_volume(module, array)
|
|
|
|
create_volume(module, array)
|
|
|
|
elif state == 'present' and volume and size:
|
|
|
|
elif state == 'present' and volume and (size or qos):
|
|
|
|
update_volume(module, array)
|
|
|
|
update_volume(module, array)
|
|
|
|
elif state == 'present' and volume and target:
|
|
|
|
elif state == 'present' and volume and target:
|
|
|
|
copy_from_volume(module, array)
|
|
|
|
copy_from_volume(module, array)
|
|
|
@ -243,6 +303,8 @@ def main():
|
|
|
|
copy_from_volume(module, array)
|
|
|
|
copy_from_volume(module, array)
|
|
|
|
elif state == 'absent' and volume:
|
|
|
|
elif state == 'absent' and volume:
|
|
|
|
delete_volume(module, array)
|
|
|
|
delete_volume(module, array)
|
|
|
|
|
|
|
|
elif state == 'absent' and destroyed:
|
|
|
|
|
|
|
|
eradicate_volume(module, array)
|
|
|
|
elif state == 'present' and not volume or not size:
|
|
|
|
elif state == 'present' and not volume or not size:
|
|
|
|
module.exit_json(changed=False)
|
|
|
|
module.exit_json(changed=False)
|
|
|
|
elif state == 'absent' and not volume:
|
|
|
|
elif state == 'absent' and not volume:
|
|
|
|