New options to volume (#58531)

* updates to volume

* fix ansibot

* fix issues

* Revert "fix issues"

This reverts commit 54988709ae7b03841452b01ec22ad01b5ccfacd4.
This commit is contained in:
Chris Archibald 2019-07-11 14:42:01 -07:00 committed by Jake Jackson
parent bc3a599678
commit 9cb78b4826
2 changed files with 181 additions and 63 deletions

View file

@ -36,16 +36,19 @@ options:
name: name:
description: description:
- The name of the volume to manage. - The name of the volume to manage.
type: str
required: true required: true
vserver: vserver:
description: description:
- Name of the vserver to use. - Name of the vserver to use.
type: str
required: true required: true
from_name: from_name:
description: description:
- Name of the existing volume to be renamed to name. - Name of the existing volume to be renamed to name.
type: str
version_added: '2.7' version_added: '2.7'
is_infinite: is_infinite:
@ -64,44 +67,53 @@ options:
description: description:
- The name of the aggregate the flexvol should exist on. - The name of the aggregate the flexvol should exist on.
- Required when C(state=present). - Required when C(state=present).
type: str
size: size:
description: description:
- The size of the volume in (size_unit). Required when C(state=present). - The size of the volume in (size_unit). Required when C(state=present).
type: int
size_unit: size_unit:
description: description:
- The unit used to interpret the size parameter. - The unit used to interpret the size parameter.
choices: ['bytes', 'b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb'] choices: ['bytes', 'b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb']
default: gb type: str
default: 'gb'
type: type:
description: description:
- The volume type, either read-write (RW) or data-protection (DP). - The volume type, either read-write (RW) or data-protection (DP).
type: str
policy: policy:
description: description:
- Name of the export policy. - Name of the export policy.
type: str
junction_path: junction_path:
description: description:
- Junction path of the volume. - Junction path of the volume.
- To unmount, use junction path C(''). - To unmount, use junction path C('').
type: str
space_guarantee: space_guarantee:
description: description:
- Space guarantee style for the volume. - Space guarantee style for the volume.
choices: ['none', 'file', 'volume'] choices: ['none', 'file', 'volume']
type: str
percent_snapshot_space: percent_snapshot_space:
description: description:
- Amount of space reserved for snapshot copies of the volume. - Amount of space reserved for snapshot copies of the volume.
type: int
volume_security_style: volume_security_style:
description: description:
- The security style associated with this volume. - The security style associated with this volume.
choices: ['mixed', 'ntfs', 'unified', 'unix'] choices: ['mixed', 'ntfs', 'unified', 'unix']
default: 'mixed' default: 'mixed'
type: str
encrypt: encrypt:
type: bool type: bool
@ -113,6 +125,7 @@ options:
efficiency_policy: efficiency_policy:
description: description:
- Allows a storage efficiency policy to be set on volume creation. - Allows a storage efficiency policy to be set on volume creation.
type: str
version_added: '2.7' version_added: '2.7'
unix_permissions: unix_permissions:
@ -120,22 +133,26 @@ options:
- Unix permission bits in octal or symbolic format. - Unix permission bits in octal or symbolic format.
- For example, 0 is equivalent to ------------, 777 is equivalent to ---rwxrwxrwx,both formats are accepted. - For example, 0 is equivalent to ------------, 777 is equivalent to ---rwxrwxrwx,both formats are accepted.
- The valid octal value ranges between 0 and 777 inclusive. - The valid octal value ranges between 0 and 777 inclusive.
type: str
version_added: '2.8' version_added: '2.8'
snapshot_policy: snapshot_policy:
description: description:
- The name of the snapshot policy. - The name of the snapshot policy.
- the default policy name is 'default'. - the default policy name is 'default'.
type: str
version_added: '2.8' version_added: '2.8'
aggr_list: aggr_list:
description: description:
- an array of names of aggregates to be used for FlexGroup constituents. - an array of names of aggregates to be used for FlexGroup constituents.
type: list
version_added: '2.8' version_added: '2.8'
aggr_list_multiplier: aggr_list_multiplier:
description: description:
- The number of times to iterate over the aggregates listed with the aggr_list parameter when creating a FlexGroup. - The number of times to iterate over the aggregates listed with the aggr_list parameter when creating a FlexGroup.
type: int
version_added: '2.8' version_added: '2.8'
auto_provision_as: auto_provision_as:
@ -143,6 +160,7 @@ options:
- Automatically provision a FlexGroup volume. - Automatically provision a FlexGroup volume.
version_added: '2.8' version_added: '2.8'
choices: ['flexgroup'] choices: ['flexgroup']
type: str
snapdir_access: snapdir_access:
description: description:
@ -179,6 +197,7 @@ options:
- if 0, the request is asynchronous. - if 0, the request is asynchronous.
- default is set to 3 minutes. - default is set to 3 minutes.
default: 180 default: 180
type: int
version_added: '2.8' version_added: '2.8'
language: language:
@ -221,6 +240,7 @@ options:
- zh_tw Traditional Chinese euc-tw - zh_tw Traditional Chinese euc-tw
- zh_tw.big5 Traditional Chinese Big 5 - zh_tw.big5 Traditional Chinese Big 5
- To use UTF-8 as the NFS character set, append '.UTF-8' to the language code - To use UTF-8 as the NFS character set, append '.UTF-8' to the language code
type: str
version_added: '2.8' version_added: '2.8'
qos_policy_group: qos_policy_group:
@ -233,6 +253,37 @@ options:
- Specifies a QoS adaptive policy group to be set on volume. - Specifies a QoS adaptive policy group to be set on volume.
version_added: '2.9' version_added: '2.9'
tiering_policy:
description:
- The tiering policy that is to be associated with the volume.
- This policy decides whether the blocks of a volume will be tiered to the capacity tier.
- snapshot-only policy allows tiering of only the volume snapshot copies not associated with the active file system.
- auto policy allows tiering of both snapshot and active file system user data to the capacity tier.
- backup policy on DP volumes allows all transferred user data blocks to start in the capacity tier.
- When set to none, the Volume blocks will not be tiered to the capacity tier.
- If no value specified, the volume is assigned snapshot only by default.
choices: ['snapshot-only', 'auto', 'backup', 'none']
type: str
version_added: '2.9'
space_slo:
description:
- Specifies the space SLO type for the volume. The space SLO type is the Service Level Objective for space management for the volume.
- The space SLO value is used to enforce existing volume settings so that sufficient space is set aside on the aggregate to meet the space SLO.
- This parameter is not supported on Infinite Volumes.
choices: ['none', 'thick', 'semi-thick']
type: str
version_added: '2.9'
nvfail_enabled:
description:
- If true, the controller performs additional work at boot and takeover times if it finds that there has been any potential data loss in the volume's
constituents due to an NVRAM failure.
- The volume's constituents would be put in a special state called 'in-nvfailed-state' such that protocol access is blocked.
- This will cause the client applications to crash and thus prevent access to stale data.
- To get out of this situation, the admin needs to manually clear the 'in-nvfailed-state' on the volume's constituents.
type: bool
version_added: '2.9'
''' '''
EXAMPLES = """ EXAMPLES = """
@ -246,11 +297,14 @@ EXAMPLES = """
size: 100 size: 100
size_unit: mb size_unit: mb
space_guarantee: none space_guarantee: none
tiering_policy: auto
policy: default policy: default
percent_snapshot_space: 60 percent_snapshot_space: 60
qos_policy_group: max_performance_gold qos_policy_group: max_performance_gold
vserver: ansibleVServer vserver: ansibleVServer
wait_for_completion: True wait_for_completion: True
space_slo: none
nvfail_enabled: False
hostname: "{{ netapp_hostname }}" hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}" username: "{{ netapp_username }}"
password: "{{ netapp_password }}" password: "{{ netapp_password }}"
@ -333,6 +387,7 @@ EXAMPLES = """
username: "{{ netapp_username }}" username: "{{ netapp_username }}"
password: "{{ netapp_password }}" password: "{{ netapp_password }}"
""" """
RETURN = """ RETURN = """
@ -403,7 +458,11 @@ class NetAppOntapVolume(object):
time_out=dict(required=False, type='int', default=180), time_out=dict(required=False, type='int', default=180),
language=dict(type='str', required=False), language=dict(type='str', required=False),
qos_policy_group=dict(required=False, type='str'), qos_policy_group=dict(required=False, type='str'),
qos_adaptive_policy_group=dict(required=False, type='str') qos_adaptive_policy_group=dict(required=False, type='str'),
nvfail_enabled=dict(type='bool', required=False),
space_slo=dict(type='str', required=False, choices=['none', 'thick', 'semi-thick']),
tiering_policy=dict(type='str', required=False, choices=['snapshot-only', 'auto',
'backup', 'none'])
)) ))
self.module = AnsibleModule( self.module = AnsibleModule(
argument_spec=self.argument_spec, argument_spec=self.argument_spec,
@ -439,6 +498,7 @@ class NetAppOntapVolume(object):
volume_attributes = netapp_utils.zapi.NaElement('volume-attributes') volume_attributes = netapp_utils.zapi.NaElement('volume-attributes')
volume_id_attributes = netapp_utils.zapi.NaElement('volume-id-attributes') volume_id_attributes = netapp_utils.zapi.NaElement('volume-id-attributes')
volume_id_attributes.add_new_child('name', vol_name) volume_id_attributes.add_new_child('name', vol_name)
volume_id_attributes.add_new_child('vserver', self.parameters['vserver'])
volume_attributes.add_child_elem(volume_id_attributes) volume_attributes.add_child_elem(volume_id_attributes)
query = netapp_utils.zapi.NaElement('query') query = netapp_utils.zapi.NaElement('query')
query.add_child_elem(volume_attributes) query.add_child_elem(volume_attributes)
@ -475,6 +535,7 @@ class NetAppOntapVolume(object):
volume_security_unix_attributes = volume_attributes['volume-security-attributes']['volume-security-unix-attributes'] volume_security_unix_attributes = volume_attributes['volume-security-attributes']['volume-security-unix-attributes']
volume_snapshot_attributes = volume_attributes['volume-snapshot-attributes'] volume_snapshot_attributes = volume_attributes['volume-snapshot-attributes']
volume_performance_attributes = volume_attributes['volume-performance-attributes'] volume_performance_attributes = volume_attributes['volume-performance-attributes']
volume_comp_aggr_attributes = volume_attributes['volume-comp-aggr-attributes']
# Get volume's state (online/offline) # Get volume's state (online/offline)
current_state = volume_state_attributes['state'] current_state = volume_state_attributes['state']
is_online = (current_state == "online") is_online = (current_state == "online")
@ -485,11 +546,21 @@ class NetAppOntapVolume(object):
'is_online': is_online, 'is_online': is_online,
'policy': volume_export_attributes['policy'], 'policy': volume_export_attributes['policy'],
'unix_permissions': volume_security_unix_attributes['permissions'], 'unix_permissions': volume_security_unix_attributes['permissions'],
'snapshot_policy': volume_snapshot_attributes['snapshot-policy'] 'snapshot_policy': volume_snapshot_attributes['snapshot-policy'],
'tiering_policy': volume_comp_aggr_attributes['tiering-policy']
} }
if volume_space_attributes.get_child_by_name('encrypt'):
return_value['encrypt'] = volume_attributes['encrypt']
if volume_space_attributes.get_child_by_name('percentage-snapshot-reserve'): if volume_space_attributes.get_child_by_name('percentage-snapshot-reserve'):
return_value['percent_snapshot_space'] = volume_space_attributes['percentage-snapshot-reserve'] return_value['percent_snapshot_space'] = int(volume_space_attributes['percentage-snapshot-reserve'])
if volume_space_attributes.get_child_by_name('space-slo'):
return_value['space_slo'] = volume_space_attributes['space-slo']
else:
return_value['space_slo'] = None
if volume_state_attributes.get_child_by_name('is-nvfail-enabled') is not None:
return_value['nvfail_enabled'] = volume_state_attributes['is-nvfail-enabled'] == 'true'
else:
return_value['nvfail_enabled'] = None
if volume_id_attributes.get_child_by_name('containing-aggregate-name'): if volume_id_attributes.get_child_by_name('containing-aggregate-name'):
return_value['aggregate_name'] = volume_id_attributes['containing-aggregate-name'] return_value['aggregate_name'] = volume_id_attributes['containing-aggregate-name']
else: else:
@ -592,11 +663,8 @@ class NetAppOntapVolume(object):
options['auto-provision-as'] = self.parameters['auto_provision_as'] options['auto-provision-as'] = self.parameters['auto_provision_as']
if self.parameters.get('space_guarantee'): if self.parameters.get('space_guarantee'):
options['space-guarantee'] = self.parameters['space_guarantee'] options['space-guarantee'] = self.parameters['space_guarantee']
if self.parameters.get('size'):
options['size'] = str(self.parameters['size'])
else: else:
options['volume'] = self.parameters['name'] options['volume'] = self.parameters['name']
options['size'] = str(self.parameters['size'])
if self.parameters.get('aggregate_name') is None: if self.parameters.get('aggregate_name') is None:
self.module.fail_json(msg='Error provisioning volume %s: aggregate_name is required' self.module.fail_json(msg='Error provisioning volume %s: aggregate_name is required'
% self.parameters['name']) % self.parameters['name'])
@ -604,6 +672,8 @@ class NetAppOntapVolume(object):
if self.parameters.get('space_guarantee'): if self.parameters.get('space_guarantee'):
options['space-reserve'] = self.parameters['space_guarantee'] options['space-reserve'] = self.parameters['space_guarantee']
if self.parameters.get('size'):
options['size'] = str(self.parameters['size'])
if self.parameters.get('snapshot_policy'): if self.parameters.get('snapshot_policy'):
options['snapshot-policy'] = self.parameters['snapshot_policy'] options['snapshot-policy'] = self.parameters['snapshot_policy']
if self.parameters.get('unix_permissions'): if self.parameters.get('unix_permissions'):
@ -616,14 +686,22 @@ class NetAppOntapVolume(object):
options['junction-path'] = self.parameters['junction_path'] options['junction-path'] = self.parameters['junction_path']
if self.parameters.get('type'): if self.parameters.get('type'):
options['volume-type'] = self.parameters['type'] options['volume-type'] = self.parameters['type']
if self.parameters.get('percent_snapshot_space'): if self.parameters.get('percent_snapshot_space') is not None:
options['percentage-snapshot-reserve'] = self.parameters['percent_snapshot_space'] options['percentage-snapshot-reserve'] = str(self.parameters['percent_snapshot_space'])
if self.parameters.get('language'): if self.parameters.get('language'):
options['language-code'] = self.parameters['language'] options['language-code'] = self.parameters['language']
if self.parameters.get('qos_policy_group'): if self.parameters.get('qos_policy_group'):
options['qos-policy-group-name'] = self.parameters['qos_policy_group'] options['qos-policy-group-name'] = self.parameters['qos_policy_group']
if self.parameters.get('qos_adaptive_policy_group'): if self.parameters.get('qos_adaptive_policy_group'):
options['qos-adaptive-policy-group-name'] = self.parameters['qos_adaptive_policy_group'] options['qos-adaptive-policy-group-name'] = self.parameters['qos_adaptive_policy_group']
if self.parameters.get('nvfail_enabled') is not None:
options['is-nvfail-enabled'] = str(self.parameters['nvfail_enabled'])
if self.parameters.get('space_slo'):
options['space-slo'] = self.parameters['space_slo']
if self.parameters.get('tiering_policy'):
options['tiering-policy'] = self.parameters['tiering_policy']
if self.parameters.get('encrypt'):
options['encrypt'] = str(self.parameters['encrypt'])
return options return options
def delete_volume(self): def delete_volume(self):
@ -736,65 +814,87 @@ class NetAppOntapVolume(object):
% (self.parameters['name'], state, to_native(error)), % (self.parameters['name'], state, to_native(error)),
exception=traceback.format_exc()) exception=traceback.format_exc())
def volume_modify_attributes(self): def create_volume_attribute(self, zapi_object, parent_attribute, attribute, value):
"""
:param parent_attribute:
:param child_attribute:
:param value:
:return:
"""
if isinstance(parent_attribute, str):
vol_attribute = netapp_utils.zapi.NaElement(parent_attribute)
vol_attribute.add_new_child(attribute, value)
zapi_object.add_child_elem(vol_attribute)
else:
zapi_object.add_new_child(attribute, value)
parent_attribute.add_child_elem(zapi_object)
def volume_modify_attributes(self, params):
""" """
modify volume parameter 'policy','unix_permissions','snapshot_policy','space_guarantee', 'percent_snapshot_space', modify volume parameter 'policy','unix_permissions','snapshot_policy','space_guarantee', 'percent_snapshot_space',
'qos_policy_group', 'qos_adaptive_policy_group' 'qos_policy_group', 'qos_adaptive_policy_group'
""" """
# TODO: refactor this method # TODO: refactor this method
vol_mod_iter = None
if self.volume_style == 'flexGroup' or self.parameters['is_infinite']: if self.volume_style == 'flexGroup' or self.parameters['is_infinite']:
vol_mod_iter = netapp_utils.zapi.NaElement('volume-modify-iter-async') vol_mod_iter = netapp_utils.zapi.NaElement('volume-modify-iter-async')
else: else:
vol_mod_iter = netapp_utils.zapi.NaElement('volume-modify-iter') vol_mod_iter = netapp_utils.zapi.NaElement('volume-modify-iter')
attributes = netapp_utils.zapi.NaElement('attributes') attributes = netapp_utils.zapi.NaElement('attributes')
vol_mod_attributes = netapp_utils.zapi.NaElement('volume-attributes') vol_mod_attributes = netapp_utils.zapi.NaElement('volume-attributes')
# Volume-attributes is split in to 25 sub categories
# volume-space-attributes
vol_space_attributes = netapp_utils.zapi.NaElement('volume-space-attributes') vol_space_attributes = netapp_utils.zapi.NaElement('volume-space-attributes')
if self.parameters.get('policy'):
vol_export_attributes = netapp_utils.zapi.NaElement(
'volume-export-attributes')
vol_export_attributes.add_new_child('policy', self.parameters['policy'])
vol_mod_attributes.add_child_elem(vol_export_attributes)
if self.parameters.get('space_guarantee'): if self.parameters.get('space_guarantee'):
vol_space_attributes.add_new_child( self.create_volume_attribute(vol_space_attributes, vol_mod_attributes,
'space-guarantee', self.parameters['space_guarantee']) 'space-guarantee', self.parameters['space_guarantee'])
vol_mod_attributes.add_child_elem(vol_space_attributes) if self.parameters.get('percent_snapshot_space') is not None:
if self.parameters.get('percent_snapshot_space'): self.create_volume_attribute(vol_space_attributes, vol_mod_attributes,
vol_space_attributes.add_new_child( 'percentage-snapshot-reserve', str(self.parameters['percent_snapshot_space']))
'percentage-snapshot-reserve', str(self.parameters['percent_snapshot_space'])) if self.parameters.get('space_slo'):
vol_mod_attributes.add_child_elem(vol_space_attributes) self.create_volume_attribute(vol_space_attributes, vol_mod_attributes, 'space-slo', self.parameters['space_slo'])
# volume-snapshot-attributes
vol_snapshot_attributes = netapp_utils.zapi.NaElement('volume-snapshot-attributes')
if self.parameters.get('snapshot_policy'):
self.create_volume_attribute(vol_snapshot_attributes, vol_mod_attributes,
'snapshot-policy', self.parameters['snapshot_policy'])
if self.parameters.get('snapdir_access'):
self.create_volume_attribute(vol_snapshot_attributes, vol_mod_attributes,
'snapdir-access-enabled', self.parameters['snapdir_access'])
# volume-export-attributes
if self.parameters.get('policy'):
self.create_volume_attribute(vol_mod_attributes, 'volume-export-attributes',
'policy', self.parameters['policy'])
# volume-security-attributes
if self.parameters.get('unix_permissions'): if self.parameters.get('unix_permissions'):
vol_unix_permissions_attributes = netapp_utils.zapi.NaElement( vol_security_attributes = netapp_utils.zapi.NaElement('volume-security-attributes')
'volume-security-unix-attributes') self.create_volume_attribute(vol_security_attributes, 'volume-security-unix-attributes',
vol_unix_permissions_attributes.add_new_child('permissions', self.parameters['unix_permissions']) 'permissions', self.parameters['unix_permissions'])
vol_security_attributes = netapp_utils.zapi.NaElement(
'volume-security-attributes')
vol_security_attributes.add_child_elem(vol_unix_permissions_attributes)
vol_mod_attributes.add_child_elem(vol_security_attributes) vol_mod_attributes.add_child_elem(vol_security_attributes)
if self.parameters.get('snapshot_policy') or self.parameters.get('snapdir_access'): # volume-performance-attributes
vol_snapshot_policy_attributes = netapp_utils.zapi.NaElement('volume-snapshot-attributes')
if self.parameters.get('snapshot_policy'):
vol_snapshot_policy_attributes.add_new_child('snapshot-policy', self.parameters['snapshot_policy'])
if self.parameters.get('snapdir_access'):
vol_snapshot_policy_attributes.add_new_child('snapdir-access-enabled', self.parameters.get('snapdir_access'))
vol_mod_attributes.add_child_elem(vol_snapshot_policy_attributes)
if self.parameters.get('atime_update'): if self.parameters.get('atime_update'):
vol_performance_attributes = netapp_utils.zapi.NaElement('volume-performance-attributes') self.create_volume_attribute(vol_mod_attributes, 'volume-performance-attributes',
vol_performance_attributes.add_new_child('is-atime-update-enabled', self.parameters.get('atime_update')) 'is-atime-update-enabled', self.parameters['atime_update'])
vol_mod_attributes.add_child_elem(vol_performance_attributes) # volume-qos-attributes
if self.parameters.get('qos_policy_group') or self.parameters.get('qos_adaptive_policy_group'): if self.parameters.get('qos_policy_group'):
vol_qos_attributes = netapp_utils.zapi.NaElement('volumes-qos-attributes') self.create_volume_attribute(vol_mod_attributes, 'volumes-qos-attributes',
if self.parameters.get('qos_policy_group'): 'policy-group-name', self.parameters['qos_policy_group'])
vol_qos_attributes.add_new_child('policy-group-name', self.parameters['qos_policy_group']) if self.parameters.get('qos_adaptive_policy_group'):
if self.parameters.get('qos_adaptive_policy_group'): self.create_volume_attribute(vol_mod_attributes, 'volumes-qos-attributes',
vol_qos_attributes.add_new_child('adaptive-policy-group-name', self.parameters['qos_adaptive_policy_group']) 'adaptive-policy-group-name', self.parameters['qos_adaptive_policy_group'])
vol_mod_attributes.add_child_elem(vol_qos_attributes) # volume-comp-aggr-attributes
if params and params.get('tiering_policy'):
self.create_volume_attribute(vol_mod_attributes, 'volume-comp-aggr-attributes',
'tiering-policy', self.parameters['tiering_policy'])
# volume-state-attributes
if self.parameters.get('nvfail_enabled') is not None:
self.create_volume_attribute(vol_mod_attributes, 'volume-state-attributes', 'is-nvfail-enabled', str(self.parameters['nvfail_enabled']))
# End of Volume-attributes sub attributes
attributes.add_child_elem(vol_mod_attributes) attributes.add_child_elem(vol_mod_attributes)
query = netapp_utils.zapi.NaElement('query') query = netapp_utils.zapi.NaElement('query')
vol_query_attributes = netapp_utils.zapi.NaElement('volume-attributes') vol_query_attributes = netapp_utils.zapi.NaElement('volume-attributes')
vol_id_attributes = netapp_utils.zapi.NaElement('volume-id-attributes') self.create_volume_attribute(vol_query_attributes, 'volume-id-attributes',
vol_id_attributes.add_new_child('name', self.parameters['name']) 'name', self.parameters['name'])
vol_query_attributes.add_child_elem(vol_id_attributes)
query.add_child_elem(vol_query_attributes) query.add_child_elem(vol_query_attributes)
vol_mod_iter.add_child_elem(attributes) vol_mod_iter.add_child_elem(attributes)
vol_mod_iter.add_child_elem(query) vol_mod_iter.add_child_elem(query)
@ -875,9 +975,10 @@ class NetAppOntapVolume(object):
self.change_volume_state() self.change_volume_state()
if attribute == 'aggregate_name': if attribute == 'aggregate_name':
self.move_volume() self.move_volume()
if attribute in ['space_guarantee', 'policy', 'unix_permissions', 'snapshot_policy', 'percent_snapshot_space', if attribute in ['space_guarantee', 'policy', 'unix_permissions', 'tiering_policy',
'snapdir_access', 'atime_update', 'qos_policy_group', 'qos_adaptive_policy_group']: 'snapshot_policy', 'percent_snapshot_space', 'snapdir_access', 'atime_update',
self.volume_modify_attributes() 'nvfail_enabled', 'space_slo', 'qos_policy_group', 'qos_adaptive_policy_group']:
self.volume_modify_attributes(modify)
if attribute == 'junction_path': if attribute == 'junction_path':
if modify.get('junction_path') == '': if modify.get('junction_path') == '':
self.volume_unmount() self.volume_unmount()
@ -950,7 +1051,6 @@ class NetAppOntapVolume(object):
return None return None
self.module.fail_json(msg='Error fetching job info: %s' % to_native(error), self.module.fail_json(msg='Error fetching job info: %s' % to_native(error),
exception=traceback.format_exc()) exception=traceback.format_exc())
job_info = result.get_child_by_name('attributes').get_child_by_name('job-info') job_info = result.get_child_by_name('attributes').get_child_by_name('job-info')
results = { results = {
'job-progress': job_info['job-progress'], 'job-progress': job_info['job-progress'],
@ -970,6 +1070,7 @@ class NetAppOntapVolume(object):
sleep_time = 5 sleep_time = 5
time_out = self.parameters['time_out'] time_out = self.parameters['time_out']
results = self.get_job(jobid, server) results = self.get_job(jobid, server)
error = 'timeout'
while time_out > 0: while time_out > 0:
results = self.get_job(jobid, server) results = self.get_job(jobid, server)
@ -1071,7 +1172,7 @@ class NetAppOntapVolume(object):
current = self.get_volume() current = self.get_volume()
self.volume_style = self.get_volume_style(current) self.volume_style = self.get_volume_style(current)
# rename and create are mutually exclusive # rename and create are mutually exclusive
rename, cd_action = None, None rename, cd_action, modify = None, None, None
if self.parameters.get('from_name'): if self.parameters.get('from_name'):
rename = self.na_helper.is_rename_action(self.get_volume(self.parameters['from_name']), current) rename = self.na_helper.is_rename_action(self.get_volume(self.parameters['from_name']), current)
else: else:
@ -1081,9 +1182,8 @@ class NetAppOntapVolume(object):
# unix_permission in self.parameter can be either numeric or character. # unix_permission in self.parameter can be either numeric or character.
if self.compare_chmod_value(current): if self.compare_chmod_value(current):
del self.parameters['unix_permissions'] del self.parameters['unix_permissions']
if self.parameters.get('percent_snapshot_space'): if cd_action is None and self.parameters['state'] == 'present':
self.parameters['percent_snapshot_space'] = str(self.parameters['percent_snapshot_space']) modify = self.na_helper.get_modified_attributes(current, self.parameters)
modify = self.na_helper.get_modified_attributes(current, self.parameters)
if self.na_helper.changed: if self.na_helper.changed:
if self.module.check_mode: if self.module.check_mode:
pass pass
@ -1094,7 +1194,8 @@ class NetAppOntapVolume(object):
self.create_volume() self.create_volume()
# if we create, and modify only variable are set (snapdir_access or atime_update) we need to run a modify # if we create, and modify only variable are set (snapdir_access or atime_update) we need to run a modify
if 'snapdir_access' in self.parameters or 'atime_update' in self.parameters: if 'snapdir_access' in self.parameters or 'atime_update' in self.parameters:
self.volume_modify_attributes() self.volume_modify_attributes({'snapdir_access': self.parameters['snapdir_access'],
'atime_update': self.parameters['atime_update']})
elif cd_action == 'delete': elif cd_action == 'delete':
self.delete_volume() self.delete_volume()
elif modify: elif modify:

View file

@ -102,16 +102,21 @@ class MockONTAPConnection(object):
'is-atime-update-enabled': 'true' 'is-atime-update-enabled': 'true'
}, },
'volume-state-attributes': { 'volume-state-attributes': {
'state': "online" 'state': "online",
'is-nvfail-enabled': 'true'
}, },
'volume-space-attributes': { 'volume-space-attributes': {
'space-guarantee': 'none', 'space-guarantee': 'none',
'size': vol_details['size'], 'size': vol_details['size'],
'percentage-snapshot-reserve': vol_details['percent_snapshot_space'] 'percentage-snapshot-reserve': vol_details['percent_snapshot_space'],
'space-slo': 'thick'
}, },
'volume-snapshot-attributes': { 'volume-snapshot-attributes': {
'snapshot-policy': vol_details['snapshot_policy'] 'snapshot-policy': vol_details['snapshot_policy']
}, },
'volume-comp-aggr-attributes': {
'tiering-policy': 'snapshot-only'
},
'volume-security-attributes': { 'volume-security-attributes': {
'volume-security-unix-attributes': { 'volume-security-unix-attributes': {
'permissions': vol_details['unix_permissions'] 'permissions': vol_details['unix_permissions']
@ -264,7 +269,9 @@ class TestMyModule(unittest.TestCase):
'size_unit': 'mb', 'size_unit': 'mb',
'junction_path': '/test', 'junction_path': '/test',
'percent_snapshot_space': 60, 'percent_snapshot_space': 60,
'type': 'type' 'type': 'type',
'nvfail_enabled': True,
'space_slo': 'thick'
} }
if tag is None: if tag is None:
args['aggregate_name'] = self.mock_vol['aggregate'] args['aggregate_name'] = self.mock_vol['aggregate']
@ -341,6 +348,7 @@ class TestMyModule(unittest.TestCase):
''' Test successful create ''' ''' Test successful create '''
data = self.mock_args() data = self.mock_args()
data['size'] = 20 data['size'] = 20
data['encrypt'] = True
set_module_args(data) set_module_args(data)
with pytest.raises(AnsibleExitJson) as exc: with pytest.raises(AnsibleExitJson) as exc:
self.get_volume_mock_object().apply() self.get_volume_mock_object().apply()
@ -394,7 +402,7 @@ class TestMyModule(unittest.TestCase):
data = self.mock_args() data = self.mock_args()
set_module_args(data) set_module_args(data)
with pytest.raises(AnsibleFailJson) as exc: with pytest.raises(AnsibleFailJson) as exc:
self.get_volume_mock_object('error_modify').volume_modify_attributes() self.get_volume_mock_object('error_modify').volume_modify_attributes(dict())
assert exc.value.args[0]['msg'] == 'Error modifying volume test_vol: modify error message' assert exc.value.args[0]['msg'] == 'Error modifying volume test_vol: modify error message'
def test_mount_volume(self): def test_mount_volume(self):
@ -908,3 +916,12 @@ class TestMyModule(unittest.TestCase):
with pytest.raises(AnsibleFailJson) as exc: with pytest.raises(AnsibleFailJson) as exc:
obj.assign_efficiency_policy_async() obj.assign_efficiency_policy_async()
assert exc.value.args[0]['msg'] == 'Error enable efficiency on volume test_vol: NetApp API failed. Reason - test:error' assert exc.value.args[0]['msg'] == 'Error enable efficiency on volume test_vol: NetApp API failed. Reason - test:error'
def test_successful_modify_tiering_policy(self):
''' Test successful modify tiering policy '''
data = self.mock_args()
data['tiering_policy'] = 'auto'
set_module_args(data)
with pytest.raises(AnsibleExitJson) as exc:
self.get_volume_mock_object('volume').apply()
assert exc.value.args[0]['changed']