diff --git a/changelogs/fragments/59735-add-preferred-arrays-support.yml b/changelogs/fragments/59735-add-preferred-arrays-support.yml new file mode 100644 index 00000000000..ded8d0e8d68 --- /dev/null +++ b/changelogs/fragments/59735-add-preferred-arrays-support.yml @@ -0,0 +1,2 @@ +minor_changes: + - Add I(preferred_arrays) param to enable preferred arrays to be set in a host configuration. (https://github.com/ansible/ansible/pull/59735) diff --git a/lib/ansible/modules/storage/purestorage/purefa_host.py b/lib/ansible/modules/storage/purestorage/purefa_host.py index 04610e255eb..fa0d4ae3ece 100644 --- a/lib/ansible/modules/storage/purestorage/purefa_host.py +++ b/lib/ansible/modules/storage/purestorage/purefa_host.py @@ -73,6 +73,12 @@ options: default: '' choices: ['hpux', 'vms', 'aix', 'esxi', 'solaris', 'hitachi-vsp', 'oracle-vm-server', 'delete', ''] version_added: '2.7' + preferred_array: + type: list + description: + - List of preferred arrays in an ActiveCluster environment. + - To remove existing preferred arrays from the host, specify I(delete). + version_added: '2.9' extends_documentation_fragment: - purestorage.fa ''' @@ -141,6 +147,22 @@ EXAMPLES = r''' lun: 12 fa_url: 10.10.10.2 api_token: e31060a7-21fc-e277-6240-25983c6c4592 + +- name: Add preferred arrays to host foo + purefa_host: + host: foo + preferred_array: + - array1 + - array2 + fa_url: 10.10.10.2 + api_token: e31060a7-21fc-e277-6240-25983c6c4592 + +- name: Delete preferred arrays from host foo + purefa_host: + host: foo + preferred_array: delete + fa_url: 10.10.10.2 + api_token: e31060a7-21fc-e277-6240-25983c6c4592 ''' RETURN = r''' @@ -151,16 +173,10 @@ from ansible.module_utils.pure import get_system, purefa_argument_spec AC_REQUIRED_API_VERSION = '1.14' +PREFERRED_ARRAY_API_VERSION = '1.15' NVME_API_VERSION = '1.16' -try: - from purestorage import purestorage - HAS_PURESTORAGE = True -except ImportError: - HAS_PURESTORAGE = False - - def _set_host_initiators(module, array): """Set host initiators.""" if module.params['protocol'] in ['nvme', 'mixed']: @@ -249,6 +265,15 @@ def _set_host_personality(module, array): array.set_host(module.params['host'], personality='') +def _set_preferred_array(module, array): + """Set preferred array list. Only called when supported""" + if module.params['preferred_array'] != ['delete']: + array.set_host(module.params['host'], + preferred_array=module.params['preferred_array']) + else: + array.set_host(module.params['host'], personality='') + + def _update_host_personality(module, array, answer=False): """Change host personality. Only called when supported""" personality = array.get_host(module.params['host'], personality=True)['personality'] @@ -276,6 +301,33 @@ def _update_host_personality(module, array, answer=False): return answer +def _update_preferred_array(module, array, answer=False): + """Update existing preferred array list. Only called when supported""" + preferred_array = array.get_host(module.params['host'], preferred_array=True)['preferred_array'] + if preferred_array == [] and module.params['preferred_array'] != ['delete']: + try: + array.set_host(module.params['host'], + preferred_array=module.params['preferred_array']) + answer = True + except Exception: + module.fail_json(msg='Preferred array list creation failed for {0}.'.format(module.params['host'])) + elif preferred_array != []: + if module.params['preferred_array'] == ['delete']: + try: + array.set_host(module.params['host'], preferred_array=[]) + answer = True + except Exception: + module.fail_json(msg='Preferred array list deletion failed for {0}.'.format(module.params['host'])) + elif preferred_array != module.params['preferred_array']: + try: + array.set_host(module.params['host'], + preferred_array=module.params['preferred_array']) + answer = True + except Exception: + module.fail_json(msg='Preferred array list change failed for {0}.'.format(module.params['host'])) + return answer + + def get_host(module, array): host = None for hst in array.list_hosts(): @@ -286,54 +338,60 @@ def get_host(module, array): def make_host(module, array): - changed = False - try: - array.create_host(module.params['host']) - changed = True - except Exception: - module.fail_json(msg='Host {0} creation failed.'.format(module.params['host'])) - try: - _set_host_initiators(module, array) - api_version = array._list_available_rest_versions() - if AC_REQUIRED_API_VERSION in api_version and module.params['personality']: - _set_host_personality(module, array) - if module.params['volume']: - if module.params['lun']: - array.connect_host(module.params['host'], - module.params['volume'], - lun=module.params['lun']) - else: - array.connect_host(module.params['host'], module.params['volume']) - except Exception: - module.fail_json(msg='Host {0} configuration failed.'.format(module.params['host'])) + changed = True + if not module.check_mode: + try: + array.create_host(module.params['host']) + except Exception: + module.fail_json(msg='Host {0} creation failed.'.format(module.params['host'])) + try: + _set_host_initiators(module, array) + api_version = array._list_available_rest_versions() + if AC_REQUIRED_API_VERSION in api_version and module.params['personality']: + _set_host_personality(module, array) + if PREFERRED_ARRAY_API_VERSION in api_version and module.params['preferred_array']: + _set_preferred_array(module, array) + if module.params['volume']: + if module.params['lun']: + array.connect_host(module.params['host'], + module.params['volume'], + lun=module.params['lun']) + else: + array.connect_host(module.params['host'], module.params['volume']) + except Exception: + module.fail_json(msg='Host {0} configuration failed.'.format(module.params['host'])) module.exit_json(changed=changed) def update_host(module, array): - changed = False - volumes = array.list_host_connections(module.params['host']) - if module.params['iqn'] or module.params['wwns'] or module.params['nqn']: - changed = _update_host_initiators(module, array) - if module.params['volume']: - current_vols = [vol['vol'] for vol in volumes] - if not module.params['volume'] in current_vols: - changed = _connect_new_volume(module, array) - api_version = array._list_available_rest_versions() - if AC_REQUIRED_API_VERSION in api_version: - if module.params['personality']: - changed = _update_host_personality(module, array) + changed = True + if not module.check_mode: + volumes = array.list_host_connections(module.params['host']) + if module.params['iqn'] or module.params['wwns'] or module.params['nqn']: + changed = _update_host_initiators(module, array) + if module.params['volume']: + current_vols = [vol['vol'] for vol in volumes] + if not module.params['volume'] in current_vols: + changed = _connect_new_volume(module, array) + api_version = array._list_available_rest_versions() + if AC_REQUIRED_API_VERSION in api_version: + if module.params['personality']: + changed = _update_host_personality(module, array) + if PREFERRED_ARRAY_API_VERSION in api_version: + if module.params['preferred_array']: + changed = _update_preferred_array(module, array) module.exit_json(changed=changed) def delete_host(module, array): - changed = False - try: - for vol in array.list_host_connections(module.params['host']): - array.disconnect_host(module.params['host'], vol["vol"]) - array.delete_host(module.params['host']) - changed = True - except Exception: - module.fail_json(msg='Host {0} deletion failed'.format(module.params['host'])) + changed = True + if not module.check_mode: + try: + for vol in array.list_host_connections(module.params['host']): + array.disconnect_host(module.params['host'], vol["vol"]) + array.delete_host(module.params['host']) + except Exception: + module.fail_json(msg='Host {0} deletion failed'.format(module.params['host'])) module.exit_json(changed=changed) @@ -351,12 +409,10 @@ def main(): personality=dict(type='str', default='', choices=['hpux', 'vms', 'aix', 'esxi', 'solaris', 'hitachi-vsp', 'oracle-vm-server', 'delete', '']), + preferred_array=dict(type='list'), )) - module = AnsibleModule(argument_spec, supports_check_mode=False) - - if not HAS_PURESTORAGE: - module.fail_json(msg='purestorage sdk is required for this module in host') + module = AnsibleModule(argument_spec, supports_check_mode=True) array = get_system(module) api_version = array._list_available_rest_versions() @@ -371,6 +427,21 @@ def main(): array.get_volume(module.params['volume']) except Exception: module.fail_json(msg='Volume {0} not found'.format(module.params['volume'])) + if module.params['preferred_array']: + try: + if module.params['preferred_array'] != ['delete']: + all_connected_arrays = array.list_array_connections() + if not all_connected_arrays: + module.fail_json(msg='No target arrays connected to source array. Setting preferred arrays not possible.') + else: + current_arrays = [] + for current_array in range(0, len(all_connected_arrays)): + current_arrays.append(all_connected_arrays[current_array]['array_name']) + for array_to_connect in range(0, len(module.params['preferred_array'])): + if module.params['preferred_array'][array_to_connect] not in current_arrays: + module.fail_json(msg='Array {0} not in existing array connections.'.format(module.params['preferred_array'][array_to_connect])) + except Exception: + module.fail_json(msg='Failed to get existing array connections.') if host is None and state == 'present': make_host(module, array)