@ -50,14 +50,23 @@ options:
description :
description :
- Volume size in M , G , T or P units .
- Volume size in M , G , T or P units .
type : str
type : str
qos:
bw_ qos:
description :
description :
- Bandwidth limit for volume in M or G units .
- Bandwidth limit for volume in M or G units .
M will set MB / s
M will set MB / s
G will set GB / s
G will set GB / s
To clear an existing Qo s setting using 0 ( zero )
To clear an existing Qo S setting use 0 ( zero )
version_added : ' 2.8 '
version_added : ' 2.8 '
type : str
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.9 '
type : str
extends_documentation_fragment :
extends_documentation_fragment :
- purestorage . fa
- purestorage . fa
'''
'''
@ -67,7 +76,8 @@ EXAMPLES = r'''
purefa_volume :
purefa_volume :
name : foo
name : foo
size : 1 T
size : 1 T
qos : 58 M
bw_qos : 58 M
iops_qos : 23 K
fa_url : 10.10 .10 .2
fa_url : 10.10 .10 .2
api_token : e31060a7 - 21 fc - e277 - 6240 - 25983 c6c4592
api_token : e31060a7 - 21 fc - e277 - 6240 - 25983 c6c4592
state : present
state : present
@ -108,7 +118,8 @@ EXAMPLES = r'''
- name : Clear volume QoS from volume foo
- name : Clear volume QoS from volume foo
purefa_volume :
purefa_volume :
name : foo
name : foo
qos : 0
bw_qos : 0
iops_qos : 0
fa_url : 10.10 .10 .2
fa_url : 10.10 .10 .2
api_token : e31060a7 - 21 fc - e277 - 6240 - 25983 c6c4592
api_token : e31060a7 - 21 fc - e277 - 6240 - 25983 c6c4592
state : present
state : present
@ -138,6 +149,12 @@ volume:
size :
size :
description : Volume size in bytes
description : Volume size in bytes
type : int
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 . basic import AnsibleModule
@ -147,6 +164,7 @@ from ansible.module_utils.pure import get_system, purefa_argument_spec
QOS_API_VERSION = " 1.14 "
QOS_API_VERSION = " 1.14 "
VGROUPS_API_VERSION = " 1.13 "
VGROUPS_API_VERSION = " 1.13 "
POD_API_VERSION = " 1.13 "
POD_API_VERSION = " 1.13 "
IOPS_API_VERSION = " 1.17 "
def human_to_bytes ( size ) :
def human_to_bytes ( size ) :
@ -166,6 +184,8 @@ def human_to_bytes(size):
bytes * = 1073741824
bytes * = 1073741824
elif unit == ' M ' :
elif unit == ' M ' :
bytes * = 1048576
bytes * = 1048576
elif unit == ' K ' :
bytes * = 1024
else :
else :
bytes = 0
bytes = 0
else :
else :
@ -173,6 +193,26 @@ def human_to_bytes(size):
return bytes
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 ) :
def get_volume ( module , array ) :
""" Return Volume or None """
""" Return Volume or None """
try :
try :
@ -184,10 +224,7 @@ def get_volume(module, array):
def get_destroyed_volume ( module , array ) :
def get_destroyed_volume ( module , array ) :
""" Return Destroyed Volume or None """
""" Return Destroyed Volume or None """
try :
try :
if array . get_volume ( module . params [ ' name ' ] , pending = True ) [ ' time_remaining ' ] != ' ' :
return bool ( array . get_volume ( module . params [ ' name ' ] , pending = True ) [ ' time_remaining ' ] != ' ' )
return True
else :
return False
except Exception :
except Exception :
return False
return False
@ -240,28 +277,52 @@ def check_pod(module, array):
def create_volume ( module , array ) :
def create_volume ( module , array ) :
""" Create Volume """
""" Create Volume """
changed = False
changed = True
if not module . check_mode :
if " / " in module . params [ ' name ' ] and not check_vgroup ( module , array ) :
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 " ] ) )
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 ) :
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 " ] ) )
module . fail_json ( msg = " Failed to create volume {0} . Poid does not exist " . format ( module . params [ " name " ] ) )
volfact = [ ]
volfact = [ ]
api_version = array . _list_available_rest_versions ( )
api_version = array . _list_available_rest_versions ( )
if module . params [ ' qos ' ] and QOS_API_VERSION in api_version :
if module . params [ ' bw_qos ' ] or module . params [ ' iops_qos ' ] :
if 549755813888 > = int ( human_to_bytes ( module . params [ ' qos ' ] ) ) > = 1048576 :
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 :
try :
volfact = array . create_volume ( module . params [ ' name ' ] ,
volfact = array . create_volume ( module . params [ ' name ' ] ,
module . params [ ' size ' ] ,
module . params [ ' size ' ] ,
bandwidth_limit = module . params [ ' qos ' ] )
bandwidth_limit = module . params [ ' bw_qos ' ] )
changed = True
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 :
except Exception :
module . fail_json ( msg = ' Volume {0} creation failed. ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Volume {0} creation failed. ' . format ( module . params [ ' name ' ] ) )
else :
else :
module . fail_json ( msg = ' QoS value {0} out of range. ' . format ( module . params [ ' qos ' ] ) )
module . fail_json ( msg = ' IOPs or Bandwidth QoS value out of range. ' )
else :
else :
try :
try :
volfact = array . create_volume ( module . params [ ' name ' ] , module . params [ ' size ' ] )
volfact = array . create_volume ( module . params [ ' name ' ] , module . params [ ' size ' ] )
changed = True
except Exception :
except Exception :
module . fail_json ( msg = ' Volume {0} creation failed. ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Volume {0} creation failed. ' . format ( module . params [ ' name ' ] ) )
@ -270,7 +331,8 @@ def create_volume(module, array):
def copy_from_volume ( module , array ) :
def copy_from_volume ( module , array ) :
""" Create Volume Clone """
""" Create Volume Clone """
changed = False
changed = True
if not module . check_mode :
volfact = [ ]
volfact = [ ]
tgt = get_target ( module , array )
tgt = get_target ( module , array )
@ -278,7 +340,6 @@ def copy_from_volume(module, array):
try :
try :
volfact = array . copy_volume ( module . params [ ' name ' ] ,
volfact = array . copy_volume ( module . params [ ' name ' ] ,
module . params [ ' target ' ] )
module . params [ ' target ' ] )
changed = True
except Exception :
except Exception :
module . fail_json ( msg = ' Copy volume {0} to volume {1} failed. ' . format ( module . params [ ' name ' ] ,
module . fail_json ( msg = ' Copy volume {0} to volume {1} failed. ' . format ( module . params [ ' name ' ] ,
module . params [ ' target ' ] ) )
module . params [ ' target ' ] ) )
@ -287,7 +348,6 @@ def copy_from_volume(module, array):
volfact = array . copy_volume ( module . params [ ' name ' ] ,
volfact = array . copy_volume ( module . params [ ' name ' ] ,
module . params [ ' target ' ] ,
module . params [ ' target ' ] ,
overwrite = module . params [ ' overwrite ' ] )
overwrite = module . params [ ' overwrite ' ] )
changed = True
except Exception :
except Exception :
module . fail_json ( msg = ' Copy volume {0} to volume {1} failed. ' . format ( module . params [ ' name ' ] ,
module . fail_json ( msg = ' Copy volume {0} to volume {1} failed. ' . format ( module . params [ ' name ' ] ,
module . params [ ' target ' ] ) )
module . params [ ' target ' ] ) )
@ -297,46 +357,70 @@ def copy_from_volume(module, array):
def update_volume ( module , array ) :
def update_volume ( module , array ) :
""" Update Volume size and/or QoS """
""" Update Volume size and/or QoS """
changed = False
changed = True
if not module . check_mode :
change = False
volfact = [ ]
volfact = [ ]
api_version = array . _list_available_rest_versions ( )
api_version = array . _list_available_rest_versions ( )
vol = array . get_volume ( module . params [ ' name ' ] )
vol = array . get_volume ( module . params [ ' name ' ] )
if QOS_API_VERSION in api_version :
vol_qos = array . get_volume ( module . params [ ' name ' ] , qos = True )
vol_qos = array . get_volume ( module . params [ ' name ' ] , qos = True )
if QOS_API_VERSION in api_version :
if vol_qos [ ' bandwidth_limit ' ] is None :
if vol_qos [ ' bandwidth_limit ' ] is None :
vol_qos [ ' bandwidth_limit ' ] = 0
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 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 human_to_bytes ( module . params [ ' size ' ] ) > vol [ ' size ' ] :
try :
try :
volfact = array . extend_volume ( module . params [ ' name ' ] , module . params [ ' size ' ] )
volfact = array . extend_volume ( module . params [ ' name ' ] , module . params [ ' size ' ] )
change d = True
change = True
except Exception :
except Exception :
module . fail_json ( msg = ' Volume {0} resize failed. ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Volume {0} resize failed. ' . format ( module . params [ ' name ' ] ) )
if module . params [ ' qos' ] and QOS_API_VERSION in api_version :
if module . params [ ' bw_ qos' ] and QOS_API_VERSION in api_version :
if human_to_bytes ( module . params [ ' qos' ] ) != vol_qos [ ' bandwidth_limit ' ] :
if human_to_bytes ( module . params [ ' bw_ qos' ] ) != vol_qos [ ' bandwidth_limit ' ] :
if module . params [ ' qos' ] == ' 0 ' :
if module . params [ ' bw_ qos' ] == ' 0 ' :
try :
try :
volfact = array . set_volume ( module . params [ ' name ' ] , bandwidth_limit = ' ' )
volfact = array . set_volume ( module . params [ ' name ' ] , bandwidth_limit = ' ' )
change d = True
change = True
except Exception :
except Exception :
module . fail_json ( msg = ' Volume {0} QoS removal failed.' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Volume {0} Bandwidth QoS removal failed.' . format ( module . params [ ' name ' ] ) )
elif 549755813888 > = int ( human_to_bytes ( module . params [ ' qos' ] ) ) > = 1048576 :
elif 549755813888 > = int ( human_to_bytes ( module . params [ ' bw_ qos' ] ) ) > = 1048576 :
try :
try :
volfact = array . set_volume ( module . params [ ' name ' ] ,
volfact = array . set_volume ( module . params [ ' name ' ] ,
bandwidth_limit = module . params [ ' qos' ] )
bandwidth_limit = module . params [ ' bw_ qos' ] )
change d = True
change = True
except Exception :
except Exception :
module . fail_json ( msg = ' Volume {0} QoS change failed.' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Volume {0} Bandwidth QoS change failed.' . format ( module . params [ ' name ' ] ) )
else :
else :
module . fail_json ( msg = ' QoS value {0} out of range. Check documentation. ' . format ( module . params [ ' qos ' ] ) )
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 = changed , volume = volfact )
module . exit_json ( changed = change , volume = volfact )
module . exit_json ( changed = changed )
def delete_volume ( module , array ) :
def delete_volume ( module , array ) :
""" Delete Volume """
""" Delete Volume """
changed = False
changed = True
if not module . check_mode :
volfact = [ ]
volfact = [ ]
try :
try :
array . destroy_volume ( module . params [ ' name ' ] )
array . destroy_volume ( module . params [ ' name ' ] )
@ -345,7 +429,6 @@ def delete_volume(module, array):
volfact = array . eradicate_volume ( module . params [ ' name ' ] )
volfact = array . eradicate_volume ( module . params [ ' name ' ] )
except Exception :
except Exception :
module . fail_json ( msg = ' Eradicate volume {0} failed. ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Eradicate volume {0} failed. ' . format ( module . params [ ' name ' ] ) )
changed = True
except Exception :
except Exception :
module . fail_json ( msg = ' Delete volume {0} failed. ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Delete volume {0} failed. ' . format ( module . params [ ' name ' ] ) )
module . exit_json ( changed = changed , volume = volfact )
module . exit_json ( changed = changed , volume = volfact )
@ -353,12 +436,12 @@ def delete_volume(module, array):
def eradicate_volume ( module , array ) :
def eradicate_volume ( module , array ) :
""" Eradicate Deleted Volume """
""" Eradicate Deleted Volume """
changed = False
changed = True
if not module . check_mode :
volfact = [ ]
volfact = [ ]
if module . params [ ' eradicate ' ] :
if module . params [ ' eradicate ' ] :
try :
try :
array . eradicate_volume ( module . params [ ' name ' ] )
array . eradicate_volume ( module . params [ ' name ' ] )
changed = True
except Exception :
except Exception :
module . fail_json ( msg = ' Eradication of volume {0} failed ' . format ( module . params [ ' name ' ] ) )
module . fail_json ( msg = ' Eradication of volume {0} failed ' . format ( module . params [ ' name ' ] ) )
module . exit_json ( changed = changed , volume = volfact )
module . exit_json ( changed = changed , volume = volfact )
@ -372,7 +455,8 @@ 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 ' ) ,
bw_qos = dict ( type = ' str ' , aliases = [ ' qos ' ] ) ,
iops_qos = dict ( type = ' str ' ) ,
size = dict ( type = ' str ' ) ,
size = dict ( type = ' str ' ) ,
) )
) )
@ -380,10 +464,11 @@ def main():
module = AnsibleModule ( argument_spec ,
module = AnsibleModule ( argument_spec ,
mutually_exclusive = mutually_exclusive ,
mutually_exclusive = mutually_exclusive ,
supports_check_mode = Fals e)
supports_check_mode = Tru e)
size = module . params [ ' size ' ]
size = module . params [ ' size ' ]
qos = module . params [ ' qos ' ]
bw_qos = module . params [ ' bw_qos ' ]
iops_qos = module . params [ ' iops_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 )
@ -393,7 +478,7 @@ def main():
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 or qos) :
elif state == ' present ' and volume and ( size or bw_qos or iops_ 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 )