summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnsible Core Team <info@ansible.com>2020-03-09 09:40:37 +0000
committerAnsible Core Team <info@ansible.com>2020-03-09 09:40:37 +0000
commit7a06a632a5cf5ba1ad4aacd279572815fe9cbb7b (patch)
tree0adfb6492c016c005b3b45ca4c328f7c45dee272
parent174b9c0e4ce30e5c47b44318e35a782a7713c710 (diff)
downloadansible-7a06a632a5cf5ba1ad4aacd279572815fe9cbb7b.tar.gz
Migrated to purestorage.flasharray
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_alert.py172
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_arrayname.py90
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_banner.py116
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_connect.py155
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_dns.py133
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_ds.py326
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_dsrole.py164
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_hg.py263
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_host.py476
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_info.py1019
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_ntp.py128
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_offload.py270
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_pg.py489
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_pgsnap.py294
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_phonehome.py99
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_ra.py113
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_smtp.py150
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_snap.py238
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_snmp.py333
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_syslog.py158
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_user.py222
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_vg.py189
-rw-r--r--lib/ansible/modules/storage/purestorage/purefa_volume.py498
-rw-r--r--test/sanity/ignore.txt34
24 files changed, 0 insertions, 6129 deletions
diff --git a/lib/ansible/modules/storage/purestorage/purefa_alert.py b/lib/ansible/modules/storage/purestorage/purefa_alert.py
deleted file mode 100644
index 23c683a4b6..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_alert.py
+++ /dev/null
@@ -1,172 +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_alert
-version_added: '2.9'
-short_description: Configure Pure Storage FlashArray alert email settings
-description:
-- Configure alert email configuration for Pure Storage FlashArrays.
-- Add or delete an individual syslog server to the existing
- list of serves.
-author:
-- Simon Dodsley (@sdodsley)
-options:
- state:
- type: str
- description:
- - Create or delete alert email
- default: present
- choices: [ absent, present ]
- address:
- type: str
- description:
- - Email address (valid format required)
- required: true
- enabled:
- type: bool
- default: true
- description:
- - Set specified email address to be enabled or disabled
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Add new email recipient and enable, or enable existing email
- purefa_alert:
- address: "user@domain.com"
- enabled: true
- state: present
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete existing email recipient
- purefa_alert:
- state: absent
- address: "user@domain.com"
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def create_alert(module, array):
- """Create Alert Email"""
- changed = False
- if not module.check_mode:
- try:
- array.create_alert_recipient(module.params['address'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to create alert email: {0}'.format(module.params['address']))
-
- if not module.params['enabled']:
- try:
- array.disable_alert_recipient(module.params['address'])
- except Exception:
- module.fail_json(msg='Failed to create alert email: {0}'.format(module.params['address']))
- changed = True
-
- module.exit_json(changed=changed)
-
-
-def enable_alert(module, array):
- """Enable Alert Email"""
- changed = False
- if not module.check_mode:
- try:
- array.enable_alert_recipient(module.params['address'])
- except Exception:
- module.fail_json(msg='Failed to enable alert email: {0}'.format(module.params['address']))
- changed = True
-
- module.exit_json(changed=changed)
-
-
-def disable_alert(module, array):
- """Disable Alert Email"""
- changed = False
- if not module.check_mode:
- try:
- array.disable_alert_recipient(module.params['address'])
- except Exception:
- module.fail_json(msg='Failed to disable alert email: {0}'.format(module.params['address']))
- changed = True
-
- module.exit_json(changed=changed)
-
-
-def delete_alert(module, array):
- """Delete Alert Email"""
- changed = False
- if module.params['address'] == "flasharray-alerts@purestorage.com":
- module.fail_json(msg='Built-in address {0} cannot be deleted.'.format(module.params['address']))
- if not module.check_mode:
- try:
- array.delete_alert_recipient(module.params['address'])
- except Exception:
- module.fail_json(msg='Failed to delete alert email: {0}'.format(module.params['address']))
- changed = True
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- address=dict(type='str', required=True),
- enabled=dict(type='bool', default=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True)
-
- pattern = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
- if not pattern.match(module.params['address']):
- module.fail_json(msg='Valid email address not provided.')
-
- array = get_system(module)
-
- exists = False
- try:
- emails = array.list_alert_recipients()
- except Exception:
- module.fail_json(msg='Failed to get existing email list')
- for email in range(0, len(emails)):
- if emails[email]['name'] == module.params['address']:
- exists = True
- enabled = emails[email]['enabled']
- break
- if module.params['state'] == 'present' and not exists:
- create_alert(module, array)
- elif module.params['state'] == 'present' and exists and not enabled and module.params['enabled']:
- enable_alert(module, array)
- elif module.params['state'] == 'present' and exists and enabled and not module.params['enabled']:
- disable_alert(module, array)
- elif module.params['state'] == 'absent' and exists:
- delete_alert(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_arrayname.py b/lib/ansible/modules/storage/purestorage/purefa_arrayname.py
deleted file mode 100644
index fe765d4f4f..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_arrayname.py
+++ /dev/null
@@ -1,90 +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_arrayname
-version_added: '2.9'
-short_description: Configure Pure Storage FlashArray array name
-description:
-- Configure name of array for Pure Storage FlashArrays.
-- Ideal for Day 0 initial configuration.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description: Set the array name
- type: str
- default: present
- choices: [ present ]
- name:
- description:
- - Name of the array. Must conform to correct naming schema.
- type: str
- required: true
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Set new array name
- purefa_arrayname:
- name: new-array-name
- state: present
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-import re
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def update_name(module, array):
- """Change array name"""
- changed = False
-
- try:
- array.set(name=module.params['name'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to change array name to {0}'.format(module.params['name']))
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['present']),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=False)
-
- array = get_system(module)
- pattern = re.compile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,54}[a-zA-Z0-9])?$")
- if not pattern.match(module.params['name']):
- module.fail_json(msg='Array name {0} does not conform to array name rules. See documentation.'.format(module.params['name']))
- if module.params['name'] != array.get()['array_name']:
- update_name(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_banner.py b/lib/ansible/modules/storage/purestorage/purefa_banner.py
deleted file mode 100644
index ca89d1fb5a..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_banner.py
+++ /dev/null
@@ -1,116 +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_banner
-version_added: '2.9'
-short_description: Configure Pure Storage FlashArray GUI and SSH MOTD message
-description:
-- Configure MOTD for Pure Storage FlashArrays.
-- This will be shown during an SSH or GUI login to the array.
-- Multiple line messages can be achieved using \\n.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description: Set ot delete the MOTD
- default: present
- type: str
- choices: [ present, absent ]
- banner:
- description: Banner text, or MOTD, to use
- type: str
- default: "Welcome to the machine..."
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Set new banner text
- purefa_banner:
- banner: "Banner over\ntwo lines"
- state: present
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete banner text
- purefa_banner:
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def set_banner(module, array):
- """Set MOTD banner text"""
- changed = False
-
- try:
- if not module.params['banner']:
- module.fail_json(msg='Invalid MOTD banner given')
-
- if not module.check_mode:
- array.set(banner=module.params['banner'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to set MOTD banner text')
-
- module.exit_json(changed=changed)
-
-
-def delete_banner(module, array):
- """Delete MOTD banner text"""
- changed = False
- try:
- array.set(banner="")
- changed = True
- except Exception:
- module.fail_json(msg='Failed to delete current MOTD banner text')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- banner=dict(type='str', default="Welcome to the machine..."),
- state=dict(type='str', default='present', choices=['present', 'absent']),
- ))
-
- required_if = [('state', 'present', ['banner'])]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
- current_banner = array.get(banner=True)['banner']
- # set banner if empty value or value differs
- if state == 'present' and (not current_banner or current_banner != module.params['banner']):
- set_banner(module, array)
- # clear banner if it has a value
- elif state == 'absent' and current_banner:
- delete_banner(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_connect.py b/lib/ansible/modules/storage/purestorage/purefa_connect.py
deleted file mode 100644
index 80976a4650..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_connect.py
+++ /dev/null
@@ -1,155 +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_connect
-version_added: '2.9'
-short_description: Manage replication connections between two FlashArrays
-description:
-- Manage array connections to specified target array
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Create or delete array connection
- default: present
- type: str
- choices: [ absent, present ]
- target_url:
- description:
- - Management IP address of remote array.
- type: str
- required: true
- target_api:
- description:
- - API token for target array
- type: str
- connection:
- description: Type of connection between arrays.
- type: str
- choices: [ sync, async ]
- default: async
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create an async connection to remote array
- purefa_connect:
- target_url: 10.10.10.20
- target_api:
- connection: async
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete connection to remote array
- purefa_connect:
- state: absent
- target_url: 10.10.10.20
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-'''
-
-RETURN = r'''
-'''
-
-HAS_PURESTORAGE = True
-try:
- from purestorage import FlashArray
-except ImportError:
- HAS_PURESTORAGE = False
-
-import platform
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def _check_connected(module, array):
- connected_arrays = array.list_array_connections()
- for target in range(0, len(connected_arrays)):
- if connected_arrays[target]['management_address'] == module.params['target_url'] and \
- connected_arrays[target]['connected']:
- return connected_arrays[target]
- return None
-
-
-def break_connection(module, array, target_array):
- """Break connection between arrays"""
- changed = True
- if not module.check_mode:
- source_array = array.get()['array_name']
- try:
- array.disconnect_array(target_array['array_name'])
- except Exception:
- module.fail_json(msg="Failed to disconnect {0} from {1}.".format(target_array['array_name'], source_array))
- module.exit_json(changed=changed)
-
-
-def create_connection(module, array):
- """Create connection between arrays"""
- changed = True
- if not module.check_mode:
- remote_array = module.params['target_url']
- user_agent = '%(base)s %(class)s/%(version)s (%(platform)s)' % {
- 'base': 'Ansible',
- 'class': __name__,
- 'version': 1.2,
- 'platform': platform.platform()
- }
- try:
- remote_system = FlashArray(module.params['target_url'],
- api_token=module.params['target_api'],
- user_agent=user_agent)
- connection_key = remote_system.get(connection_key=True)['connection_key']
- remote_array = remote_system.get()['array_name']
- array.connect_array(module.params['target_url'], connection_key, [module.params['connection']])
- except Exception:
- module.fail_json(msg="Failed to connect to remote array {0}.".format(remote_array))
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='present', choices=['absent', 'present']),
- connection=dict(type='str', default='async', choices=['async', 'sync']),
- target_url=dict(type='str', required=True),
- target_api=dict(type='str'),
- ))
-
- required_if = [('state', 'present', ['target_api'])]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- if not HAS_PURESTORAGE:
- module.fail_json(msg='purestorage sdk is required for this module')
-
- state = module.params['state']
- array = get_system(module)
- target_array = _check_connected(module, array)
-
- if state == 'present' and target_array is None:
- create_connection(module, array)
- elif state == 'absent'and target_array is not None:
- break_connection(module, array, target_array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_dns.py b/lib/ansible/modules/storage/purestorage/purefa_dns.py
deleted file mode 100644
index c8cf215100..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_dns.py
+++ /dev/null
@@ -1,133 +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_dns
-version_added: '2.8'
-short_description: Configure FlashArray DNS settings
-description:
-- Set or erase configuration for the DNS settings.
-- Nameservers provided will overwrite any existing nameservers.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Set or delete directory service configuration
- default: present
- type: str
- choices: [ absent, present ]
- domain:
- description:
- - Domain suffix to be appended when performing DNS lookups.
- type: str
- nameservers:
- description:
- - List of up to 3 unique DNS server IP addresses. These can be
- IPv4 or IPv6 - No validation is done of the addresses is performed.
- type: list
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing DNS settings
- purefa_dns:
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Set DNS settings
- purefa_dns:
- domain: purestorage.com
- nameservers:
- - 8.8.8.8
- - 8.8.4.4
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def remove(duplicate):
- final_list = []
- for num in duplicate:
- if num not in final_list:
- final_list.append(num)
- return final_list
-
-
-def delete_dns(module, array):
- """Delete DNS settings"""
- changed = False
- current_dns = array.get_dns()
- if current_dns['domain'] == '' and current_dns['nameservers'] == ['']:
- module.exit_json(changed=changed)
- else:
- try:
- array.set_dns(domain='', nameservers=[])
- changed = True
- except Exception:
- module.fail_json(msg='Delete DNS settings failed')
- module.exit_json(changed=changed)
-
-
-def create_dns(module, array):
- """Set DNS settings"""
- changed = False
- current_dns = array.get_dns()
- if current_dns['domain'] != module.params['domain'] or sorted(module.params['nameservers']) != sorted(current_dns['nameservers']):
- try:
- array.set_dns(domain=module.params['domain'],
- nameservers=module.params['nameservers'][0:3])
- changed = True
- except Exception:
- module.fail_json(msg='Set DNS settings failed: Check configuration')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='present', choices=['absent', 'present']),
- domain=dict(type='str'),
- nameservers=dict(type='list'),
- ))
-
- required_if = [('state', 'present', ['domain', 'nameservers'])]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
-
- if state == 'absent':
- delete_dns(module, array)
- elif state == 'present':
- module.params['nameservers'] = remove(module.params['nameservers'])
- create_dns(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_ds.py b/lib/ansible/modules/storage/purestorage/purefa_ds.py
deleted file mode 100644
index 361dc200b5..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_ds.py
+++ /dev/null
@@ -1,326 +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_ds
-version_added: '2.6'
-short_description: Configure FlashArray Directory Service
-description:
-- Set or erase configuration for the directory service. There is no facility
- to SSL certificates at this time. Use the FlashArray GUI for this
- additional configuration work.
-- To modify an existing directory service configuration you must first delete
- an existing configuration and then recreate with new settings.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- type: str
- description:
- - Create or delete directory service configuration
- default: present
- choices: [ absent, present ]
- enable:
- description:
- - Whether to enable or disable directory service support.
- default: false
- type: bool
- uri:
- type: list
- description:
- - A list of up to 30 URIs of the directory servers. Each URI must include
- the scheme ldap:// or ldaps:// (for LDAP over SSL), a hostname, and a
- domain name or IP address. For example, ldap://ad.company.com configures
- the directory service with the hostname "ad" in the domain "company.com"
- while specifying the unencrypted LDAP protocol.
- base_dn:
- type: str
- description:
- - Sets the base of the Distinguished Name (DN) of the directory service
- groups. The base should consist of only Domain Components (DCs). The
- base_dn will populate with a default value when a URI is entered by
- parsing domain components from the URI. The base DN should specify DC=
- for each domain component and multiple DCs should be separated by commas.
- required: true
- bind_password:
- type: str
- description:
- - Sets the password of the bind_user user name account.
- bind_user:
- type: str
- description:
- - Sets the user name that can be used to bind to and query the directory.
- - For Active Directory, enter the username - often referred to as
- sAMAccountName or User Logon Name - of the account that is used to
- perform directory lookups.
- - For OpenLDAP, enter the full DN of the user.
- group_base:
- type: str
- description:
- - Specifies where the configured groups are located in the directory
- tree. This field consists of Organizational Units (OUs) that combine
- with the base DN attribute and the configured group CNs to complete
- the full Distinguished Name of the groups. The group base should
- specify OU= for each OU and multiple OUs should be separated by commas.
- The order of OUs is important and should get larger in scope from left
- to right. Each OU should not exceed 64 characters in length.
- - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module.
- ro_group:
- type: str
- description:
- - Sets the common Name (CN) of the configured directory service group
- containing users with read-only privileges on the FlashArray. This
- name should be just the Common Name of the group without the CN=
- specifier. Common Names should not exceed 64 characters in length.
- - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module.
- sa_group:
- type: str
- description:
- - Sets the common Name (CN) of the configured directory service group
- containing administrators with storage-related privileges on the
- FlashArray. This name should be just the Common Name of the group
- without the CN= specifier. Common Names should not exceed 64
- characters in length.
- - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module.
- aa_group:
- type: str
- description:
- - Sets the common Name (CN) of the directory service group containing
- administrators with full privileges when managing the FlashArray.
- The name should be just the Common Name of the group without the
- CN= specifier. Common Names should not exceed 64 characters in length.
- - Not Supported from Purity 5.2.0 or higher. Use I(purefa_dsrole) module.
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing directory service
- purefa_ds:
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create directory service (disabled) - Pre-5.2.0
- purefa_ds:
- uri: "ldap://lab.purestorage.com"
- base_dn: "DC=lab,DC=purestorage,DC=com"
- bind_user: Administrator
- bind_password: password
- group_base: "OU=Pure-Admin"
- ro_group: PureReadOnly
- sa_group: PureStorage
- aa_group: PureAdmin
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create directory service (disabled) - 5.2.0 or higher
- purefa_ds:
- uri: "ldap://lab.purestorage.com"
- base_dn: "DC=lab,DC=purestorage,DC=com"
- bind_user: Administrator
- bind_password: password
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Enable existing directory service
- purefa_ds:
- enable: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Disable existing directory service
- purefa_ds:
- enable: false
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create directory service (enabled) - Pre-5.2.0
- purefa_ds:
- enable: true
- uri: "ldap://lab.purestorage.com"
- base_dn: "DC=lab,DC=purestorage,DC=com"
- bind_user: Administrator
- bind_password: password
- group_base: "OU=Pure-Admin"
- ro_group: PureReadOnly
- sa_group: PureStorage
- aa_group: PureAdmin
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create directory service (enabled) - 5.2.0 or higher
- purefa_ds:
- enable: true
- uri: "ldap://lab.purestorage.com"
- base_dn: "DC=lab,DC=purestorage,DC=com"
- bind_user: Administrator
- bind_password: password
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-DS_ROLE_REQUIRED_API_VERSION = '1.16'
-
-
-def update_ds(module, array):
- """Update Directory Service"""
- changed = False
- module.exit_json(changed=changed)
-
-
-def enable_ds(module, array):
- """Enable Directory Service"""
- changed = False
- try:
- array.enable_directory_service()
- changed = True
- except Exception:
- module.fail_json(msg='Enable Directory Service failed: Check Configuration')
- module.exit_json(changed=changed)
-
-
-def disable_ds(module, array):
- """Disable Directory Service"""
- """Disable Directory Service"""
- changed = False
- try:
- array.disable_directory_service()
- changed = True
- except Exception:
- module.fail_json(msg='Disable Directory Service failed')
- module.exit_json(changed=changed)
-
-
-def delete_ds(module, array):
- """Delete Directory Service"""
- changed = False
- try:
- api_version = array._list_available_rest_versions()
- array.set_directory_service(enabled=False)
- if DS_ROLE_REQUIRED_API_VERSION in api_version:
- array.set_directory_service(uri=[''],
- base_dn="",
- bind_user="",
- bind_password="",
- certificate="")
- changed = True
- else:
- array.set_directory_service(uri=[''],
- base_dn="",
- group_base="",
- bind_user="",
- bind_password="",
- readonly_group="",
- storage_admin_group="",
- array_admin_group="",
- certificate="")
- changed = True
- except Exception:
- module.fail_json(msg='Delete Directory Service failed')
- module.exit_json(changed=changed)
-
-
-def create_ds(module, array):
- """Create Directory Service"""
- changed = False
- api_version = array._list_available_rest_versions()
- if DS_ROLE_REQUIRED_API_VERSION in api_version:
- if not module.params['role']:
- module.fail_json(msg='At least one role must be configured')
- try:
- array.set_directory_service(uri=module.params['uri'],
- base_dn=module.params['base_dn'],
- bind_user=module.params['bind_user'],
- bind_password=module.params['bind_password'])
- array.set_directory_service(enabled=module.params['enable'])
- changed = True
- except Exception:
- module.fail_json(msg='Create Directory Service failed: Check configuration')
- else:
- groups_rule = [not module.params['ro_group'],
- not module.params['sa_group'],
- not module.params['aa_group']]
-
- if all(groups_rule):
- module.fail_json(msg='At least one group must be configured')
- try:
- array.set_directory_service(uri=module.params['uri'],
- base_dn=module.params['base_dn'],
- group_base=module.params['group_base'],
- bind_user=module.params['bind_user'],
- bind_password=module.params['bind_password'],
- readonly_group=module.params['ro_group'],
- storage_admin_group=module.params['sa_group'],
- array_admin_group=module.params['aa_group'])
- array.set_directory_service(enabled=module.params['enable'])
- changed = True
- except Exception:
- module.fail_json(msg='Create Directory Service failed: Check configuration')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- uri=dict(type='list'),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- enable=dict(type='bool', default=False),
- bind_password=dict(type='str', no_log=True),
- bind_user=dict(type='str'),
- base_dn=dict(type='str'),
- group_base=dict(type='str'),
- ro_group=dict(type='str'),
- sa_group=dict(type='str'),
- aa_group=dict(type='str'),
- ))
-
- required_together = [['uri', 'bind_password', 'bind_user',
- 'base_dn', 'group_base']]
-
- module = AnsibleModule(argument_spec,
- required_together=required_together,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
- ds_exists = False
- dirserv = array.get_directory_service()
- ds_enabled = dirserv['enabled']
- if dirserv['base_dn']:
- ds_exists = True
-
- if state == 'absent' and ds_exists:
- delete_ds(module, array)
- elif ds_exists and module.params['enable'] and ds_enabled:
- update_ds(module, array)
- elif ds_exists and not module.params['enable'] and ds_enabled:
- disable_ds(module, array)
- elif ds_exists and module.params['enable'] and not ds_enabled:
- enable_ds(module, array)
- elif not ds_exists and state == 'present':
- create_ds(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_dsrole.py b/lib/ansible/modules/storage/purestorage/purefa_dsrole.py
deleted file mode 100644
index cbc35223c6..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_dsrole.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2019, 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_dsrole
-version_added: '2.8'
-short_description: Configure FlashArray Directory Service Roles
-description:
-- Set or erase directory services role configurations.
-- Only available for FlashArray running Purity 5.2.0 or higher
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Create or delete directory service role
- type: str
- default: present
- choices: [ absent, present ]
- role:
- description:
- - The directory service role to work on
- choices: [ array_admin, ops_admin, readonly, storage_admin ]
- group_base:
- type: str
- description:
- - Specifies where the configured group is located in the directory
- tree. This field consists of Organizational Units (OUs) that combine
- with the base DN attribute and the configured group CNs to complete
- the full Distinguished Name of the groups. The group base should
- specify OU= for each OU and multiple OUs should be separated by commas.
- The order of OUs is important and should get larger in scope from left
- to right.
- - Each OU should not exceed 64 characters in length.
- group:
- type: str
- description:
- - Sets the common Name (CN) of the configured directory service group
- containing users for the FlashBlade. This name should be just the
- Common Name of the group without the CN= specifier.
- - Common Names should not exceed 64 characters in length.
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing array_admin directory service role
- purefa_dsrole:
- role: array_admin
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create array_admin directory service role
- purefa_dsrole:
- role: array_admin
- group_base: "OU=PureGroups,OU=SANManagers"
- group: pureadmins
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Update ops_admin directory service role
- purefa_dsrole:
- role: ops_admin
- group_base: "OU=PureGroups"
- group: opsgroup
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def update_role(module, array):
- """Update Directory Service Role"""
- changed = False
- role = array.list_directory_services_roles(names=[module.params['role']])
- if role['group_base'] != module.params['group_base'] or role['group'] != module.params['group']:
- try:
- array.set_directory_services_roles(names=[module.params['role']],
- group_base=module.params['group_base'],
- group=module.params['group'])
- changed = True
- except Exception:
- module.fail_json(msg='Update Directory Service Role {0} failed'.format(module.params['role']))
- module.exit_json(changed=changed)
-
-
-def delete_role(module, array):
- """Delete Directory Service Role"""
- changed = False
- try:
- array.set_directory_services_roles(names=[module.params['role']],
- group_base='',
- group='')
- changed = True
- except Exception:
- module.fail_json(msg='Delete Directory Service Role {0} failed'.format(module.params['role']))
- module.exit_json(changed=changed)
-
-
-def create_role(module, array):
- """Create Directory Service Role"""
- changed = False
- try:
- array.set_directory_services_roles(names=[module.params['role']],
- group_base=module.params['group_base'],
- group=module.params['group'])
- changed = True
- except Exception:
- module.fail_json(msg='Create Directory Service Role {0} failed: Check configuration'.format(module.params['role']))
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- role=dict(required=True, type='str', choices=['array_admin', 'ops_admin', 'readonly', 'storage_admin']),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- group_base=dict(type='str'),
- group=dict(type='str'),
- ))
-
- required_together = [['group', 'group_base']]
-
- module = AnsibleModule(argument_spec,
- required_together=required_together,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
- role_configured = False
- role = array.list_directory_services_roles(names=[module.params['role']])
- if role['group'] is not None:
- role_configured = True
-
- if state == 'absent' and role_configured:
- delete_role(module, array)
- elif role_configured and state == 'present':
- update_role(module, array)
- elif not role_configured and state == 'present':
- create_role(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_hg.py b/lib/ansible/modules/storage/purestorage/purefa_hg.py
deleted file mode 100644
index 0614d66872..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_hg.py
+++ /dev/null
@@ -1,263 +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_hg
-version_added: '2.4'
-short_description: Manage hostgroups on Pure Storage FlashArrays
-description:
-- Create, delete or modify hostgroups on Pure Storage FlashArrays.
-author:
-- Pure Storage ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- hostgroup:
- description:
- - The name of the hostgroup.
- type: str
- required: true
- state:
- description:
- - Define whether the hostgroup should exist or not.
- type: str
- default: present
- choices: [ absent, present ]
- host:
- type: list
- description:
- - List of existing hosts to add to hostgroup.
- volume:
- type: list
- description:
- - List of existing volumes to add to hostgroup.
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create empty hostgroup
- purefa_hg:
- hostgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Add hosts and volumes to existing or new hostgroup
- purefa_hg:
- hostgroup: foo
- host:
- - host1
- - host2
- volume:
- - vol1
- - vol2
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete hosts and volumes from hostgroup
- purefa_hg:
- hostgroup: foo
- host:
- - host1
- - host2
- volume:
- - vol1
- - vol2
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-# This will disconnect all hosts and volumes in the hostgroup
-- name: Delete hostgroup
- purefa_hg:
- hostgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Create host group with hosts and volumes
- purefa_hg:
- hostgroup: bar
- host:
- - host1
- - host2
- volume:
- - vol1
- - vol2
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-try:
- from purestorage import purestorage
- HAS_PURESTORAGE = True
-except ImportError:
- HAS_PURESTORAGE = False
-
-
-def get_hostgroup(module, array):
-
- hostgroup = None
-
- for host in array.list_hgroups():
- if host["name"] == module.params['hostgroup']:
- hostgroup = host
- break
-
- return hostgroup
-
-
-def make_hostgroup(module, array):
-
- changed = True
-
- try:
- array.create_hgroup(module.params['hostgroup'])
- except Exception:
- changed = False
- if module.params['host']:
- array.set_hgroup(module.params['hostgroup'], hostlist=module.params['host'])
- if module.params['volume']:
- for vol in module.params['volume']:
- array.connect_hgroup(module.params['hostgroup'], vol)
- module.exit_json(changed=changed)
-
-
-def update_hostgroup(module, array):
- changed = False
- hgroup = get_hostgroup(module, array)
- volumes = array.list_hgroup_connections(module.params['hostgroup'])
- if module.params['state'] == "present":
- if module.params['host']:
- new_hosts = list(set(module.params['host']).difference(hgroup['hosts']))
- if new_hosts:
- try:
- array.set_hgroup(module.params['hostgroup'], addhostlist=new_hosts)
- changed = True
- except Exception:
- module.fail_josn(msg='Failed to add host(s) to hostgroup')
- if module.params['volume']:
- if volumes:
- current_vols = [vol['vol'] for vol in volumes]
- new_volumes = list(set(module.params['volume']).difference(set(current_vols)))
- for cvol in new_volumes:
- try:
- array.connect_hgroup(module.params['hostgroup'], cvol)
- changed = True
- except Exception:
- changed = False
- else:
- for cvol in module.params['volume']:
- try:
- array.connect_hgroup(module.params['hostgroup'], cvol)
- changed = True
- except Exception:
- changed = False
- else:
- if module.params['host']:
- old_hosts = list(set(module.params['host']).intersection(hgroup['hosts']))
- if old_hosts:
- try:
- array.set_hgroup(module.params['hostgroup'], remhostlist=old_hosts)
- changed = True
- except Exception:
- changed = False
- if module.params['volume']:
- old_volumes = list(set(module.params['volume']).difference(set([vol['name'] for vol in volumes])))
- for cvol in old_volumes:
- try:
- array.disconnect_hgroup(module.params['hostgroup'], cvol)
- changed = True
- except Exception:
- changed = False
-
- module.exit_json(changed=changed)
-
-
-def delete_hostgroup(module, array):
- changed = True
- try:
- vols = array.list_hgroup_connections(module.params['hostgroup'])
- for vol in vols:
- try:
- array.disconnect_hgroup(module.params['hostgroup'], vol["vol"])
- except Exception:
- changed = False
- host = array.get_hgroup(module.params['hostgroup'])
- try:
- array.set_hgroup(module.params['hostgroup'], remhostlist=host['hosts'])
- try:
- array.delete_hgroup(module.params['hostgroup'])
- except Exception:
- changed = False
- except Exception:
- changed = False
- except Exception:
- changed = False
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- hostgroup=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- host=dict(type='list'),
- volume=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')
-
- state = module.params['state']
- array = get_system(module)
- hostgroup = get_hostgroup(module, array)
-
- if module.params['host']:
- try:
- for hst in module.params['host']:
- array.get_host(hst)
- except Exception:
- module.fail_json(msg='Host {0} not found'.format(hst))
-
- if module.params['volume']:
- try:
- for vol in module.params['volume']:
- array.get_volume(vol)
- except Exception:
- module.fail_json(msg='Volume {0} not found'.format(vol))
-
- if hostgroup and state == 'present':
- update_hostgroup(module, array)
- elif hostgroup and module.params['volume'] and state == 'absent':
- update_hostgroup(module, array)
- elif hostgroup and module.params['host'] and state == 'absent':
- update_hostgroup(module, array)
- elif hostgroup and state == 'absent':
- delete_hostgroup(module, array)
- elif hostgroup is None and state == 'absent':
- module.exit_json(changed=False)
- else:
- make_hostgroup(module, array)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_host.py b/lib/ansible/modules/storage/purestorage/purefa_host.py
deleted file mode 100644
index aeeb82b634..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_host.py
+++ /dev/null
@@ -1,476 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, 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_host
-version_added: '2.4'
-short_description: Manage hosts on Pure Storage FlashArrays
-description:
-- Create, delete or modify hosts on Pure Storage FlashArrays.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-notes:
-- If specifying C(lun) option ensure host support requested value
-options:
- host:
- description:
- - The name of the host.
- type: str
- required: true
- state:
- description:
- - Define whether the host should exist or not.
- - When removing host all connected volumes will be disconnected.
- type: str
- default: present
- choices: [ absent, present ]
- protocol:
- description:
- - Defines the host connection protocol for volumes.
- type: str
- default: iscsi
- choices: [ fc, iscsi, nvme, mixed ]
- wwns:
- type: list
- description:
- - List of wwns of the host if protocol is fc or mixed.
- iqn:
- type: list
- description:
- - List of IQNs of the host if protocol is iscsi or mixed.
- nqn:
- type: list
- description:
- - List of NQNs of the host if protocol is nvme or mixed.
- version_added: '2.8'
- volume:
- type: str
- description:
- - Volume name to map to the host.
- lun:
- description:
- - LUN ID to assign to volume for host. Must be unique.
- - If not provided the ID will be automatically assigned.
- - Range for LUN ID is 1 to 4095.
- type: int
- version_added: '2.8'
- personality:
- type: str
- description:
- - Define which operating system the host is. Recommended for
- ActiveCluster integration.
- 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
-'''
-
-EXAMPLES = r'''
-- name: Create new AIX host
- purefa_host:
- host: foo
- personality: aix
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete host
- purefa_host:
- host: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Make host bar with wwn ports
- purefa_host:
- host: bar
- protocol: fc
- wwns:
- - 00:00:00:00:00:00:00
- - 11:11:11:11:11:11:11
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Make host bar with iSCSI ports
- purefa_host:
- host: bar
- protocol: iscsi
- iqn:
- - iqn.1994-05.com.redhat:7d366003913
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Make host bar with NVMe ports
- purefa_host:
- host: bar
- protocol: nvme
- nqn:
- - nqn.2014-08.com.vendor:nvme:nvm-subsystem-sn-d78432
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Make mixed protocol host
- purefa_host:
- host: bar
- protocol: mixed
- nqn:
- - nqn.2014-08.com.vendor:nvme:nvm-subsystem-sn-d78432
- iqn:
- - iqn.1994-05.com.redhat:7d366003914
- wwns:
- - 00:00:00:00:00:00:01
- - 11:11:11:11:11:11:12
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Map host foo to volume bar as LUN ID 12
- purefa_host:
- host: foo
- volume: bar
- 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'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-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'
-
-
-def _is_cbs(module, array, is_cbs=False):
- """Is the selected array a Cloud Block Store"""
- model = ''
- ct0_model = array.get_hardware('CT0')['model']
- if ct0_model:
- model = ct0_model
- else:
- ct1_model = array.get_hardware('CT1')['model']
- model = ct1_model
- if 'CBS' in model:
- is_cbs = True
- return is_cbs
-
-
-def _set_host_initiators(module, array):
- """Set host initiators."""
- if module.params['protocol'] in ['nvme', 'mixed']:
- if module.params['nqn']:
- try:
- array.set_host(module.params['host'],
- nqnlist=module.params['nqn'])
- except Exception:
- module.fail_json(msg='Setting of NVMe NQN failed.')
- if module.params['protocol'] in ['iscsi', 'mixed']:
- if module.params['iqn']:
- try:
- array.set_host(module.params['host'],
- iqnlist=module.params['iqn'])
- except Exception:
- module.fail_json(msg='Setting of iSCSI IQN failed.')
- if module.params['protocol'] in ['fc', 'mixed']:
- if module.params['wwns']:
- try:
- array.set_host(module.params['host'],
- wwnlist=module.params['wwns'])
- except Exception:
- module.fail_json(msg='Setting of FC WWNs failed.')
-
-
-def _update_host_initiators(module, array, answer=False):
- """Change host initiator if iscsi or nvme or add new FC WWNs"""
- if module.params['protocol'] in ['nvme', 'mixed']:
- if module.params['nqn']:
- current_nqn = array.get_host(module.params['host'])['nqn']
- if current_nqn != module.params['nqn']:
- try:
- array.set_host(module.params['host'],
- nqnlist=module.params['nqn'])
- answer = True
- except Exception:
- module.fail_json(msg='Change of NVMe NQN failed.')
- if module.params['protocol'] in ['iscsi', 'mixed']:
- if module.params['iqn']:
- current_iqn = array.get_host(module.params['host'])['iqn']
- if current_iqn != module.params['iqn']:
- try:
- array.set_host(module.params['host'],
- iqnlist=module.params['iqn'])
- answer = True
- except Exception:
- module.fail_json(msg='Change of iSCSI IQN failed.')
- if module.params['protocol'] in ['fc', 'mixed']:
- if module.params['wwns']:
- module.params['wwns'] = [wwn.replace(':', '') for wwn in module.params['wwns']]
- module.params['wwns'] = [wwn.upper() for wwn in module.params['wwns']]
- current_wwn = array.get_host(module.params['host'])['wwn']
- if current_wwn != module.params['wwns']:
- try:
- array.set_host(module.params['host'],
- wwnlist=module.params['wwns'])
- answer = True
- except Exception:
- module.fail_json(msg='FC WWN change failed.')
- return answer
-
-
-def _connect_new_volume(module, array, answer=False):
- """Connect volume to host"""
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version and module.params['lun']:
- try:
- array.connect_host(module.params['host'],
- module.params['volume'],
- lun=module.params['lun'])
- answer = True
- except Exception:
- module.fail_json(msg='LUN ID {0} invalid. Check for duplicate LUN IDs.'.format(module.params['lun']))
- else:
- array.connect_host(module.params['host'], module.params['volume'])
- answer = True
- return answer
-
-
-def _set_host_personality(module, array):
- """Set host personality. Only called when supported"""
- if module.params['personality'] != 'delete':
- array.set_host(module.params['host'],
- personality=module.params['personality'])
- else:
- 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']
- if personality is None and module.params['personality'] != 'delete':
- try:
- array.set_host(module.params['host'],
- personality=module.params['personality'])
- answer = True
- except Exception:
- module.fail_json(msg='Personality setting failed.')
- if personality is not None:
- if module.params['personality'] == 'delete':
- try:
- array.set_host(module.params['host'], personality='')
- answer = True
- except Exception:
- module.fail_json(msg='Personality deletion failed.')
- elif personality != module.params['personality']:
- try:
- array.set_host(module.params['host'],
- personality=module.params['personality'])
- answer = True
- except Exception:
- module.fail_json(msg='Personality change failed.')
- 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():
- if hst["name"] == module.params['host']:
- host = hst
- break
- return host
-
-
-def make_host(module, array):
- 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 = True
- if not module.check_mode:
- init_changed = vol_changed = pers_changed = pref_changed = False
- volumes = array.list_host_connections(module.params['host'])
- if module.params['iqn'] or module.params['wwns'] or module.params['nqn']:
- init_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:
- vol_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']:
- pers_changed = _update_host_personality(module, array)
- if PREFERRED_ARRAY_API_VERSION in api_version:
- if module.params['preferred_array']:
- pref_changed = _update_preferred_array(module, array)
- changed = init_changed or vol_changed or pers_changed or pref_changed
- module.exit_json(changed=changed)
-
-
-def delete_host(module, array):
- 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)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- host=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- protocol=dict(type='str', default='iscsi', choices=['fc', 'iscsi', 'nvme', 'mixed']),
- nqn=dict(type='list'),
- iqn=dict(type='list'),
- wwns=dict(type='list'),
- volume=dict(type='str'),
- lun=dict(type='int'),
- 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=True)
-
- array = get_system(module)
- if _is_cbs(module, array) and module.params['wwns'] or module.params['nqn']:
- module.fail_json(msg='Cloud block Store only support iSCSI as a protocol')
- api_version = array._list_available_rest_versions()
- if module.params['nqn'] is not None and NVME_API_VERSION not in api_version:
- module.fail_json(msg='NVMe protocol not supported. Please upgrade your array.')
- state = module.params['state']
- host = get_host(module, array)
- if module.params['lun'] and not 1 <= module.params['lun'] <= 4095:
- module.fail_json(msg='LUN ID of {0} is out of range (1 to 4095)'.format(module.params['lun']))
- if module.params['volume']:
- try:
- 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 = [array.get()['array_name']]
- for current_array in range(0, len(all_connected_arrays)):
- if all_connected_arrays[current_array]['type'] == "sync-replication":
- 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} is not a synchronously connected array.'.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)
- elif host and state == 'present':
- update_host(module, array)
- elif host and state == 'absent':
- delete_host(module, array)
- elif host is None and state == 'absent':
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_info.py b/lib/ansible/modules/storage/purestorage/purefa_info.py
deleted file mode 100644
index 78080506f6..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_info.py
+++ /dev/null
@@ -1,1019 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2019, 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_info
-version_added: '2.9'
-short_description: Collect information from Pure Storage FlashArray
-description:
- - Collect information from a Pure Storage Flasharray running the
- Purity//FA operating system. By default, the module will collect basic
- information including hosts, host groups, protection
- groups and volume counts. Additional information can be collected
- based on the configured set of arguments.
-author:
- - Pure Storage ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- gather_subset:
- description:
- - When supplied, this argument will define the information to be collected.
- Possible values for this include all, minimum, config, performance,
- capacity, network, subnet, interfaces, hgroups, pgroups, hosts,
- admins, volumes, snapshots, pods, vgroups, offload, apps, arrays,
- certs and kmip.
- type: list
- required: false
- default: minimum
-extends_documentation_fragment:
- - purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: collect default set of information
- purefa_info:
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- register: array_info
-- name: show default information
- debug:
- msg: "{{ array_info['purefa_info']['default'] }}"
-
-- name: collect configuration and capacity information
- purefa_info:
- gather_subset:
- - config
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- register: array_info
-- name: show configuration information
- debug:
- msg: "{{ array_info['purefa_info']['config'] }}"
-
-- name: collect all information
- purefa_info:
- gather_subset:
- - all
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-- name: show all information
- debug:
- msg: "{{ array_info['purefa_info'] }}"
-'''
-
-RETURN = r'''
-purefa_info:
- description: Returns the information collected from the FlashArray
- returned: always
- type: complex
- sample: {
- "admins": {
- "pureuser": {
- "role": "array_admin",
- "type": "local"
- }
- },
- "apps": {
- "offload": {
- "description": "Snapshot offload to NFS or Amazon S3",
- "status": "healthy",
- "version": "5.2.1"
- }
- },
- "arrays": {},
- "capacity": {
- "data_reduction": 11.664774599686346,
- "free_space": 6995782867042,
- "provisioned_space": 442391871488,
- "shared_space": 3070918120,
- "snapshot_space": 284597118,
- "system_space": 0,
- "thin_provisioning": 0.8201773449669771,
- "total_capacity": 7002920315199,
- "total_reduction": 64.86821472825108,
- "volume_space": 3781932919
- },
- "config": {
- "directory_service": {
- "base_dn": null,
- "bind_password": null,
- "bind_user": null,
- "check_peer": false,
- "enabled": false,
- "uri": [],
- "user_login_attribute": null,
- "user_object_class": null
- },
- "directory_service_roles": {
- "array_admin": {
- "group": null,
- "group_base": null
- },
- "ops_admin": {
- "group": null,
- "group_base": null
- },
- "readonly": {
- "group": null,
- "group_base": null
- },
- "storage_admin": {
- "group": null,
- "group_base": null
- }
- },
- "dns": {
- "domain": "acme.com",
- "nameservers": [
- "8.8.4.4"
- ]
- },
- "global_admin": {
- "lockout_duration": null,
- "max_login_attempts": null,
- "min_password_length": 1,
- "single_sign_on_enabled": false
- },
- "idle_timeout": 0,
- "ntp": [
- "prod-ntp1.puretec.purestorage.com"
- ],
- "phonehome": "enabled",
- "proxy": "",
- "relayhost": "smtp.puretec.purestorage.com",
- "scsi_timeout": 60,
- "senderdomain": "purestorage.com",
- "smtp": [
- {
- "enabled": true,
- "name": "flasharray-alerts@purestorage.com"
- }
- ],
- "snmp": [
- {
- "auth_passphrase": null,
- "auth_protocol": null,
- "community": "****",
- "host": "10.21.23.34",
- "name": "manager1",
- "notification": "trap",
- "privacy_passphrase": null,
- "privacy_protocol": null,
- "user": null,
- "version": "v2c"
- }
- ],
- "syslog": [
- "udp://prod-ntp2.puretec.purestorage.com:333"
- ]
- },
- "default": {
- "admins": 1,
- "array_model": "FA-405",
- "array_name": "array",
- "connected_arrays": 0,
- "connection_key": "c6033033-fe69-2515-a9e8-966bb7fe4b40",
- "hostgroups": 0,
- "hosts": 15,
- "pods": 1,
- "protection_groups": 1,
- "purity_version": "5.2.1",
- "snapshots": 2,
- "volume_groups": 1
- },
- "hgroups": {},
- "hosts": {
- "@offload": {
- "hgroup": null,
- "iqn": [],
- "nqn": [],
- "personality": null,
- "preferred_array": [],
- "target_port": [],
- "wwn": []
- },
- "docker-host": {
- "hgroup": null,
- "iqn": [
- "iqn.1994-05.com.redhat:d97adf78472"
- ],
- "nqn": [],
- "personality": null,
- "preferred_array": [],
- "target_port": [
- "CT0.ETH4",
- "CT1.ETH4"
- ],
- "wwn": []
- }
- },
- "interfaces": {
- "CT0.ETH4": "iqn.2010-06.com.purestorage:flasharray.2111b767484e4682",
- "CT1.ETH4": "iqn.2010-06.com.purestorage:flasharray.2111b767484e4682",
- },
- "network": {
- "@offload.data0": {
- "address": "10.21.200.222",
- "gateway": "10.21.200.1",
- "hwaddr": "52:54:30:02:b9:4e",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "app"
- ],
- "speed": 10000000000
- },
- "ct0.eth0": {
- "address": "10.21.200.211",
- "gateway": "10.21.200.1",
- "hwaddr": "ec:f4:bb:c8:8a:04",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "management"
- ],
- "speed": 1000000000
- },
- "ct0.eth2": {
- "address": "10.21.200.218",
- "gateway": null,
- "hwaddr": "ec:f4:bb:c8:8a:00",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "replication"
- ],
- "speed": 10000000000
- },
- "ct0.eth4": {
- "address": "10.21.200.214",
- "gateway": null,
- "hwaddr": "90:e2:ba:83:79:0c",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "iscsi"
- ],
- "speed": 10000000000
- },
- "ct1.eth0": {
- "address": "10.21.200.212",
- "gateway": "10.21.200.1",
- "hwaddr": "ec:f4:bb:e4:c6:3c",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "management"
- ],
- "speed": 1000000000
- },
- "ct1.eth2": {
- "address": "10.21.200.220",
- "gateway": null,
- "hwaddr": "ec:f4:bb:e4:c6:38",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "replication"
- ],
- "speed": 10000000000
- },
- "ct1.eth4": {
- "address": "10.21.200.216",
- "gateway": null,
- "hwaddr": "90:e2:ba:8b:b1:8c",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "iscsi"
- ],
- "speed": 10000000000
- },
- "vir0": {
- "address": "10.21.200.210",
- "gateway": "10.21.200.1",
- "hwaddr": "fe:ba:e9:e7:6b:0f",
- "mtu": 1500,
- "netmask": "255.255.255.0",
- "services": [
- "management"
- ],
- "speed": 1000000000
- }
- },
- "nfs_offload": {},
- "performance": {
- "input_per_sec": 0,
- "local_queue_usec_per_op": 0,
- "output_per_sec": 0,
- "qos_rate_limit_usec_per_read_op": 0,
- "qos_rate_limit_usec_per_write_op": 0,
- "queue_depth": 0,
- "queue_usec_per_read_op": 0,
- "queue_usec_per_write_op": 0,
- "reads_per_sec": 0,
- "san_usec_per_read_op": 0,
- "san_usec_per_write_op": 0,
- "time": "2019-08-14T21:33:51Z",
- "usec_per_read_op": 0,
- "usec_per_write_op": 0,
- "writes_per_sec": 0
- },
- "pgroups": {
- "test_pg": {
- "hgroups": null,
- "hosts": null,
- "source": "docker-host",
- "targets": null,
- "volumes": null
- }
- },
- "pods": {
- "test": {
- "arrays": [
- {
- "array_id": "043be47c-1233-4399-b9d6-8fe38727dd9d",
- "mediator_status": "online",
- "name": "array2",
- "status": "online"
- }
- ],
- "source": null
- }
- },
- "s3_offload": {
- "s3-offload": {
- "access_key_id": "AKIAILNVEPWZTV4FGWZQ",
- "bucket": "offload-bucket",
- "protocol": "s3",
- "status": "connected"
- }
- },
- "snapshots": {
- "@offload_boot.1": {
- "created": "2019-03-14T15:29:20Z",
- "size": 68719476736,
- "source": "@offload_boot"
- }
- },
- "subnet": {},
- "vgroups": {
- "test": {
- "volumes": [
- "test/test",
- "test/test1"
- ]
- }
- },
- "volumes": {
- "@offload_boot": {
- "bandwidth": null,
- "hosts": [
- [
- "@offload",
- 1
- ]
- ],
- "serial": "43BE47C12334399B00013959",
- "size": 68719476736,
- "source": null
- },
- "docker-store": {
- "bandwidth": null,
- "hosts": [
- [
- "docker-host",
- 1
- ]
- ],
- "serial": "43BE47C12334399B00011418",
- "size": 21474836480,
- "source": null
- }
- }
- }
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-import time
-
-ADMIN_API_VERSION = '1.14'
-S3_REQUIRED_API_VERSION = '1.16'
-LATENCY_REQUIRED_API_VERSION = '1.16'
-AC_REQUIRED_API_VERSION = '1.14'
-CAP_REQUIRED_API_VERSION = '1.6'
-SAN_REQUIRED_API_VERSION = '1.10'
-NVME_API_VERSION = '1.16'
-PREFERRED_API_VERSION = '1.15'
-P53_API_VERSION = '1.17'
-
-
-def generate_default_dict(array):
- default_info = {}
- defaults = array.get()
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version:
- default_info['volume_groups'] = len(array.list_vgroups())
- default_info['connected_arrays'] = len(array.list_array_connections())
- default_info['pods'] = len(array.list_pods())
- default_info['connection_key'] = array.get(connection_key=True)['connection_key']
- hosts = array.list_hosts()
- admins = array.list_admins()
- snaps = array.list_volumes(snap=True, pending=True)
- pgroups = array.list_pgroups(pending=True)
- hgroups = array.list_hgroups()
- # Old FA arrays only report model from the primary controller
- ct0_model = array.get_hardware('CT0')['model']
- if ct0_model:
- model = ct0_model
- else:
- ct1_model = array.get_hardware('CT1')['model']
- model = ct1_model
- default_info['array_model'] = model
- default_info['array_name'] = defaults['array_name']
- default_info['purity_version'] = defaults['version']
- default_info['hosts'] = len(hosts)
- default_info['snapshots'] = len(snaps)
- default_info['protection_groups'] = len(pgroups)
- default_info['hostgroups'] = len(hgroups)
- default_info['admins'] = len(admins)
- if P53_API_VERSION in api_version:
- default_info['maintenance_window'] = array.list_maintenance_windows()
- return default_info
-
-
-def generate_perf_dict(array):
- perf_info = {}
- api_version = array._list_available_rest_versions()
- if LATENCY_REQUIRED_API_VERSION in api_version:
- latency_info = array.get(action='monitor', latency=True)[0]
- perf_info = array.get(action='monitor')[0]
- # IOPS
- perf_info['writes_per_sec'] = perf_info['writes_per_sec']
- perf_info['reads_per_sec'] = perf_info['reads_per_sec']
-
- # Bandwidth
- perf_info['input_per_sec'] = perf_info['input_per_sec']
- perf_info['output_per_sec'] = perf_info['output_per_sec']
-
- # Latency
- if LATENCY_REQUIRED_API_VERSION in api_version:
- perf_info['san_usec_per_read_op'] = latency_info['san_usec_per_read_op']
- perf_info['san_usec_per_write_op'] = latency_info['san_usec_per_write_op']
- perf_info['queue_usec_per_read_op'] = latency_info['queue_usec_per_read_op']
- perf_info['queue_usec_per_write_op'] = latency_info['queue_usec_per_write_op']
- perf_info['qos_rate_limit_usec_per_read_op'] = latency_info['qos_rate_limit_usec_per_read_op']
- perf_info['qos_rate_limit_usec_per_write_op'] = latency_info['qos_rate_limit_usec_per_write_op']
- perf_info['local_queue_usec_per_op'] = perf_info['local_queue_usec_per_op']
- perf_info['usec_per_read_op'] = perf_info['usec_per_read_op']
- perf_info['usec_per_write_op'] = perf_info['usec_per_write_op']
- perf_info['queue_depth'] = perf_info['queue_depth']
- return perf_info
-
-
-def generate_config_dict(array):
- config_info = {}
- api_version = array._list_available_rest_versions()
- # DNS
- config_info['dns'] = array.get_dns()
- # SMTP
- config_info['smtp'] = array.list_alert_recipients()
- # SNMP
- config_info['snmp'] = array.list_snmp_managers()
- config_info['snmp_v3_engine_id'] = array.get_snmp_engine_id()['engine_id']
- # DS
- config_info['directory_service'] = array.get_directory_service()
- if S3_REQUIRED_API_VERSION in api_version:
- config_info['directory_service_roles'] = {}
- roles = array.list_directory_service_roles()
- for role in range(0, len(roles)):
- role_name = roles[role]['name']
- config_info['directory_service_roles'][role_name] = {
- 'group': roles[role]['group'],
- 'group_base': roles[role]['group_base'],
- }
- else:
- config_info['directory_service'].update(array.get_directory_service(groups=True))
- # NTP
- config_info['ntp'] = array.get(ntpserver=True)['ntpserver']
- # SYSLOG
- config_info['syslog'] = array.get(syslogserver=True)['syslogserver']
- # Phonehome
- config_info['phonehome'] = array.get(phonehome=True)['phonehome']
- # Proxy
- config_info['proxy'] = array.get(proxy=True)['proxy']
- # Relay Host
- config_info['relayhost'] = array.get(relayhost=True)['relayhost']
- # Sender Domain
- config_info['senderdomain'] = array.get(senderdomain=True)['senderdomain']
- # SYSLOG
- config_info['syslog'] = array.get(syslogserver=True)['syslogserver']
- # Idle Timeout
- config_info['idle_timeout'] = array.get(idle_timeout=True)['idle_timeout']
- # SCSI Timeout
- config_info['scsi_timeout'] = array.get(scsi_timeout=True)['scsi_timeout']
- # Global Admin settings
- if S3_REQUIRED_API_VERSION in api_version:
- config_info['global_admin'] = array.get_global_admin_attributes()
- return config_info
-
-
-def generate_admin_dict(array):
- admin_info = {}
- api_version = array._list_available_rest_versions()
- if ADMIN_API_VERSION in api_version:
- admins = array.list_admins()
- for admin in range(0, len(admins)):
- admin_name = admins[admin]['name']
- admin_info[admin_name] = {
- 'type': admins[admin]['type'],
- 'role': admins[admin]['role'],
- }
- return admin_info
-
-
-def generate_subnet_dict(array):
- sub_info = {}
- subnets = array.list_subnets()
- for sub in range(0, len(subnets)):
- sub_name = subnets[sub]['name']
- if subnets[sub]['enabled']:
- sub_info[sub_name] = {
- 'gateway': subnets[sub]['gateway'],
- 'mtu': subnets[sub]['mtu'],
- 'vlan': subnets[sub]['vlan'],
- 'prefix': subnets[sub]['prefix'],
- 'interfaces': subnets[sub]['interfaces'],
- 'services': subnets[sub]['services'],
- }
- return sub_info
-
-
-def generate_network_dict(array):
- net_info = {}
- ports = array.list_network_interfaces()
- for port in range(0, len(ports)):
- int_name = ports[port]['name']
- net_info[int_name] = {
- 'hwaddr': ports[port]['hwaddr'],
- 'mtu': ports[port]['mtu'],
- 'enabled': ports[port]['enabled'],
- 'speed': ports[port]['speed'],
- 'address': ports[port]['address'],
- 'slaves': ports[port]['slaves'],
- 'services': ports[port]['services'],
- 'gateway': ports[port]['gateway'],
- 'netmask': ports[port]['netmask'],
- }
- if ports[port]['subnet']:
- subnets = array.get_subnet(ports[port]['subnet'])
- if subnets['enabled']:
- net_info[int_name]['subnet'] = {
- 'name': subnets['name'],
- 'prefix': subnets['prefix'],
- 'vlan': subnets['vlan'],
- }
- return net_info
-
-
-def generate_capacity_dict(array):
- capacity_info = {}
- api_version = array._list_available_rest_versions()
- if CAP_REQUIRED_API_VERSION in api_version:
- volumes = array.list_volumes(pending=True)
- capacity_info['provisioned_space'] = sum(item['size'] for item in volumes)
- capacity = array.get(space=True)
- total_capacity = capacity[0]['capacity']
- used_space = capacity[0]["total"]
- capacity_info['free_space'] = total_capacity - used_space
- capacity_info['total_capacity'] = total_capacity
- capacity_info['data_reduction'] = capacity[0]['data_reduction']
- capacity_info['system_space'] = capacity[0]['system']
- capacity_info['volume_space'] = capacity[0]['volumes']
- capacity_info['shared_space'] = capacity[0]['shared_space']
- capacity_info['snapshot_space'] = capacity[0]['snapshots']
- capacity_info['thin_provisioning'] = capacity[0]['thin_provisioning']
- capacity_info['total_reduction'] = capacity[0]['total_reduction']
-
- return capacity_info
-
-
-def generate_snap_dict(array):
- snap_info = {}
- snaps = array.list_volumes(snap=True)
- for snap in range(0, len(snaps)):
- snapshot = snaps[snap]['name']
- snap_info[snapshot] = {
- 'size': snaps[snap]['size'],
- 'source': snaps[snap]['source'],
- 'created': snaps[snap]['created'],
- }
- return snap_info
-
-
-def generate_vol_dict(array):
- volume_info = {}
- vols = array.list_volumes()
- for vol in range(0, len(vols)):
- volume = vols[vol]['name']
- volume_info[volume] = {
- 'source': vols[vol]['source'],
- 'size': vols[vol]['size'],
- 'serial': vols[vol]['serial'],
- 'hosts': [],
- 'bandwidth': ""
- }
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version:
- qvols = array.list_volumes(qos=True)
- for qvol in range(0, len(qvols)):
- volume = qvols[qvol]['name']
- qos = qvols[qvol]['bandwidth_limit']
- volume_info[volume]['bandwidth'] = qos
- if P53_API_VERSION in api_version:
- iops = qvols[qvol]['iops_limit']
- volume_info[volume]['iops_limit'] = iops
- vvols = array.list_volumes(protocol_endpoint=True)
- for vvol in range(0, len(vvols)):
- volume = vvols[vvol]['name']
- volume_info[volume] = {
- 'source': vvols[vvol]['source'],
- 'serial': vvols[vvol]['serial'],
- 'hosts': []
- }
- if P53_API_VERSION in array._list_available_rest_versions():
- pe_e2ees = array.list_volumes(protocol_endpoint=True, host_encryption_key=True)
- for pe_e2ee in range(0, len(pe_e2ees)):
- volume = pe_e2ees[pe_e2ee]['name']
- volume_info[volume]['host_encryption_key_status'] = pe_e2ees[pe_e2ee]['host_encryption_key_status']
- if P53_API_VERSION in array._list_available_rest_versions():
- e2ees = array.list_volumes(host_encryption_key=True)
- for e2ee in range(0, len(e2ees)):
- volume = e2ees[e2ee]['name']
- volume_info[volume]['host_encryption_key_status'] = e2ees[e2ee]['host_encryption_key_status']
- cvols = array.list_volumes(connect=True)
- for cvol in range(0, len(cvols)):
- volume = cvols[cvol]['name']
- voldict = {'host': cvols[cvol]['host'], 'lun': cvols[cvol]['lun']}
- volume_info[volume]['hosts'].append(voldict)
- return volume_info
-
-
-def generate_host_dict(array):
- api_version = array._list_available_rest_versions()
- host_info = {}
- hosts = array.list_hosts()
- for host in range(0, len(hosts)):
- hostname = hosts[host]['name']
- tports = []
- host_all_info = array.get_host(hostname, all=True)
- if host_all_info:
- tports = host_all_info[0]['target_port']
- host_info[hostname] = {
- 'hgroup': hosts[host]['hgroup'],
- 'iqn': hosts[host]['iqn'],
- 'wwn': hosts[host]['wwn'],
- 'personality': array.get_host(hostname,
- personality=True)['personality'],
- 'target_port': tports
- }
- if NVME_API_VERSION in api_version:
- host_info[hostname]['nqn'] = hosts[host]['nqn']
- if PREFERRED_API_VERSION in api_version:
- hosts = array.list_hosts(preferred_array=True)
- for host in range(0, len(hosts)):
- hostname = hosts[host]['name']
- host_info[hostname]['preferred_array'] = hosts[host]['preferred_array']
- return host_info
-
-
-def generate_pgroups_dict(array):
- pgroups_info = {}
- pgroups = array.list_pgroups()
- for pgroup in range(0, len(pgroups)):
- protgroup = pgroups[pgroup]['name']
- pgroups_info[protgroup] = {
- 'hgroups': pgroups[pgroup]['hgroups'],
- 'hosts': pgroups[pgroup]['hosts'],
- 'source': pgroups[pgroup]['source'],
- 'targets': pgroups[pgroup]['targets'],
- 'volumes': pgroups[pgroup]['volumes'],
- }
- prot_sched = array.get_pgroup(protgroup, schedule=True)
- prot_reten = array.get_pgroup(protgroup, retention=True)
- if prot_sched['snap_enabled'] or prot_sched['replicate_enabled']:
- pgroups_info[protgroup]['snap_freqyency'] = prot_sched['snap_frequency']
- pgroups_info[protgroup]['replicate_freqyency'] = prot_sched['replicate_frequency']
- pgroups_info[protgroup]['snap_enabled'] = prot_sched['snap_enabled']
- pgroups_info[protgroup]['replicate_enabled'] = prot_sched['replicate_enabled']
- pgroups_info[protgroup]['snap_at'] = prot_sched['snap_at']
- pgroups_info[protgroup]['replicate_at'] = prot_sched['replicate_at']
- pgroups_info[protgroup]['replicate_blackout'] = prot_sched['replicate_blackout']
- pgroups_info[protgroup]['per_day'] = prot_reten['per_day']
- pgroups_info[protgroup]['target_per_day'] = prot_reten['target_per_day']
- pgroups_info[protgroup]['target_days'] = prot_reten['target_days']
- pgroups_info[protgroup]['days'] = prot_reten['days']
- pgroups_info[protgroup]['all_for'] = prot_reten['all_for']
- pgroups_info[protgroup]['target_all_for'] = prot_reten['target_all_for']
- if ":" in protgroup:
- snap_transfers = array.get_pgroup(protgroup, snap=True, transfer=True)
- pgroups_info[protgroup]['snaps'] = {}
- for snap_transfer in range(0, len(snap_transfers)):
- snap = snap_transfers[snap_transfer]['name']
- pgroups_info[protgroup]['snaps'][snap] = {
- 'created': snap_transfers[snap_transfer]['created'],
- 'started': snap_transfers[snap_transfer]['started'],
- 'completed': snap_transfers[snap_transfer]['completed'],
- 'physical_bytes_written': snap_transfers[snap_transfer]['physical_bytes_written'],
- 'data_transferred': snap_transfers[snap_transfer]['data_transferred'],
- 'progress': snap_transfers[snap_transfer]['progress'],
- }
- return pgroups_info
-
-
-def generate_pods_dict(array):
- pods_info = {}
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version:
- pods = array.list_pods()
- for pod in range(0, len(pods)):
- acpod = pods[pod]['name']
- pods_info[acpod] = {
- 'source': pods[pod]['source'],
- 'arrays': pods[pod]['arrays'],
- }
- return pods_info
-
-
-def generate_conn_array_dict(array):
- conn_array_info = {}
- api_version = array._list_available_rest_versions()
- carrays = array.list_array_connections()
- for carray in range(0, len(carrays)):
- arrayname = carrays[carray]['array_name']
- conn_array_info[arrayname] = {
- 'array_id': carrays[carray]['id'],
- 'throttled': carrays[carray]['throttled'],
- 'version': carrays[carray]['version'],
- 'type': carrays[carray]['type'],
- 'mgmt_ip': carrays[carray]['management_address'],
- 'repl_ip': carrays[carray]['replication_address'],
- }
- if P53_API_VERSION in api_version:
- conn_array_info[arrayname]['status'] = carrays[carray]['status']
- throttles = array.list_array_connections(throttle=True)
- for throttle in range(0, len(throttles)):
- arrayname = throttles[throttle]['array_name']
- if conn_array_info[arrayname]['throttled']:
- conn_array_info[arrayname]['throttling'] = {
- 'default_limit': throttles[throttle]['default_limit'],
- 'window_limit': throttles[throttle]['window_limit'],
- 'window': throttles[throttle]['window'],
- }
- return conn_array_info
-
-
-def generate_apps_dict(array):
- apps_info = {}
- api_version = array._list_available_rest_versions()
- if SAN_REQUIRED_API_VERSION in api_version:
- apps = array.list_apps()
- for app in range(0, len(apps)):
- appname = apps[app]['name']
- apps_info[appname] = {
- 'version': apps[app]['version'],
- 'status': apps[app]['status'],
- 'description': apps[app]['description'],
- }
- return apps_info
-
-
-def generate_vgroups_dict(array):
- vgroups_info = {}
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version:
- vgroups = array.list_vgroups()
- for vgroup in range(0, len(vgroups)):
- virtgroup = vgroups[vgroup]['name']
- vgroups_info[virtgroup] = {
- 'volumes': vgroups[vgroup]['volumes'],
- }
- return vgroups_info
-
-
-def generate_certs_dict(array):
- certs_info = {}
- api_version = array._list_available_rest_versions()
- if P53_API_VERSION in api_version:
- certs = array.list_certificates()
- for cert in range(0, len(certs)):
- certificate = certs[cert]['name']
- valid_from = time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime(certs[cert]['valid_from'] / 1000))
- valid_to = time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime(certs[cert]['valid_to'] / 1000))
- certs_info[certificate] = {
- 'status': certs[cert]['status'],
- 'issued_to': certs[cert]['issued_to'],
- 'valid_from': valid_from,
- 'locality': certs[cert]['locality'],
- 'country': certs[cert]['country'],
- 'issued_by': certs[cert]['issued_by'],
- 'valid_to': valid_to,
- 'state': certs[cert]['state'],
- 'key_size': certs[cert]['key_size'],
- 'org_unit': certs[cert]['organizational_unit'],
- 'common_name': certs[cert]['common_name'],
- 'organization': certs[cert]['organization'],
- 'email': certs[cert]['email'],
- }
- return certs_info
-
-
-def generate_kmip_dict(array):
- kmip_info = {}
- api_version = array._list_available_rest_versions()
- if P53_API_VERSION in api_version:
- kmips = array.list_kmip()
- for kmip in range(0, len(kmips)):
- key = kmips[kmip]['name']
- kmip_info[key] = {
- 'certificate': kmips[kmip]['certificate'],
- 'ca_cert_configured': kmips[kmip]['ca_certificate_configured'],
- 'uri': kmips[kmip]['uri'],
- }
- return kmip_info
-
-
-def generate_nfs_offload_dict(array):
- offload_info = {}
- api_version = array._list_available_rest_versions()
- if AC_REQUIRED_API_VERSION in api_version:
- offload = array.list_nfs_offload()
- for target in range(0, len(offload)):
- offloadt = offload[target]['name']
- offload_info[offloadt] = {
- 'status': offload[target]['status'],
- 'mount_point': offload[target]['mount_point'],
- 'protocol': offload[target]['protocol'],
- 'mount_options': offload[target]['mount_options'],
- 'address': offload[target]['address'],
- }
- return offload_info
-
-
-def generate_s3_offload_dict(array):
- offload_info = {}
- api_version = array._list_available_rest_versions()
- if S3_REQUIRED_API_VERSION in api_version:
- offload = array.list_s3_offload()
- for target in range(0, len(offload)):
- offloadt = offload[target]['name']
- offload_info[offloadt] = {
- 'status': offload[target]['status'],
- 'bucket': offload[target]['bucket'],
- 'protocol': offload[target]['protocol'],
- 'access_key_id': offload[target]['access_key_id'],
- }
- if P53_API_VERSION in api_version:
- offload_info[offloadt]['placement_strategy'] = offload[target]['placement_strategy']
- return offload_info
-
-
-def generate_azure_offload_dict(array):
- offload_info = {}
- api_version = array._list_available_rest_versions()
- if P53_API_VERSION in api_version:
- offload = array.list_azure_offload()
- for target in range(0, len(offload)):
- offloadt = offload[target]['name']
- offload_info[offloadt] = {
- 'status': offload[target]['status'],
- 'account_name': offload[target]['account_name'],
- 'protocol': offload[target]['protocol'],
- 'secret_access_key': offload[target]['secret_access_key'],
- 'container_name': offload[target]['container_name'],
- }
- return offload_info
-
-
-def generate_hgroups_dict(array):
- hgroups_info = {}
- hgroups = array.list_hgroups()
- for hgroup in range(0, len(hgroups)):
- hostgroup = hgroups[hgroup]['name']
- hgroups_info[hostgroup] = {
- 'hosts': hgroups[hgroup]['hosts'],
- 'pgs': [],
- 'vols': [],
- }
- pghgroups = array.list_hgroups(protect=True)
- for pghg in range(0, len(pghgroups)):
- pgname = pghgroups[pghg]['name']
- hgroups_info[pgname]['pgs'].append(pghgroups[pghg]['protection_group'])
- volhgroups = array.list_hgroups(connect=True)
- for pgvol in range(0, len(volhgroups)):
- pgname = volhgroups[pgvol]['name']
- volpgdict = [volhgroups[pgvol]['vol'], volhgroups[pgvol]['lun']]
- hgroups_info[pgname]['vols'].append(volpgdict)
- return hgroups_info
-
-
-def generate_interfaces_dict(array):
- api_version = array._list_available_rest_versions()
- int_info = {}
- ports = array.list_ports()
- for port in range(0, len(ports)):
- int_name = ports[port]['name']
- if ports[port]['wwn']:
- int_info[int_name] = ports[port]['wwn']
- if ports[port]['iqn']:
- int_info[int_name] = ports[port]['iqn']
- if NVME_API_VERSION in api_version:
- if ports[port]['nqn']:
- int_info[int_name] = ports[port]['nqn']
- return int_info
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- gather_subset=dict(default='minimum', type='list',)
- ))
-
- module = AnsibleModule(argument_spec, supports_check_mode=False)
- array = get_system(module)
-
- subset = [test.lower() for test in module.params['gather_subset']]
- valid_subsets = ('all', 'minimum', 'config', 'performance', 'capacity',
- 'network', 'subnet', 'interfaces', 'hgroups', 'pgroups',
- 'hosts', 'admins', 'volumes', 'snapshots', 'pods',
- 'vgroups', 'offload', 'apps', 'arrays', 'certs', 'kmip')
- subset_test = (test in valid_subsets for test in subset)
- if not all(subset_test):
- module.fail_json(msg="value must gather_subset must be one or more of: %s, got: %s"
- % (",".join(valid_subsets), ",".join(subset)))
-
- info = {}
-
- if 'minimum' in subset or 'all' in subset or 'apps' in subset:
- info['default'] = generate_default_dict(array)
- if 'performance' in subset or 'all' in subset:
- info['performance'] = generate_perf_dict(array)
- if 'config' in subset or 'all' in subset:
- info['config'] = generate_config_dict(array)
- if 'capacity' in subset or 'all' in subset:
- info['capacity'] = generate_capacity_dict(array)
- if 'network' in subset or 'all' in subset:
- info['network'] = generate_network_dict(array)
- if 'subnet' in subset or 'all' in subset:
- info['subnet'] = generate_subnet_dict(array)
- if 'interfaces' in subset or 'all' in subset:
- info['interfaces'] = generate_interfaces_dict(array)
- if 'hosts' in subset or 'all' in subset:
- info['hosts'] = generate_host_dict(array)
- if 'volumes' in subset or 'all' in subset:
- info['volumes'] = generate_vol_dict(array)
- if 'snapshots' in subset or 'all' in subset:
- info['snapshots'] = generate_snap_dict(array)
- if 'hgroups' in subset or 'all' in subset:
- info['hgroups'] = generate_hgroups_dict(array)
- if 'pgroups' in subset or 'all' in subset:
- info['pgroups'] = generate_pgroups_dict(array)
- if 'pods' in subset or 'all' in subset:
- info['pods'] = generate_pods_dict(array)
- if 'admins' in subset or 'all' in subset:
- info['admins'] = generate_admin_dict(array)
- if 'vgroups' in subset or 'all' in subset:
- info['vgroups'] = generate_vgroups_dict(array)
- if 'offload' in subset or 'all' in subset:
- info['azure_offload'] = generate_azure_offload_dict(array)
- info['nfs_offload'] = generate_nfs_offload_dict(array)
- info['s3_offload'] = generate_s3_offload_dict(array)
- if 'apps' in subset or 'all' in subset:
- if 'CBS' not in info['default']['array_model']:
- info['apps'] = generate_apps_dict(array)
- else:
- info['apps'] = {}
- if 'arrays' in subset or 'all' in subset:
- info['arrays'] = generate_conn_array_dict(array)
- if 'certs' in subset or 'all' in subset:
- info['certs'] = generate_certs_dict(array)
- if 'kmip' in subset or 'all' in subset:
- info['kmip'] = generate_kmip_dict(array)
-
- module.exit_json(changed=False, purefa_info=info)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_ntp.py b/lib/ansible/modules/storage/purestorage/purefa_ntp.py
deleted file mode 100644
index a47c5016e8..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_ntp.py
+++ /dev/null
@@ -1,128 +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_ntp
-version_added: '2.8'
-short_description: Configure Pure Storage FlashArray NTP settings
-description:
-- Set or erase NTP configuration for Pure Storage FlashArrays.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Create or delete NTP servers configuration
- type: str
- default: present
- choices: [ absent, present ]
- ntp_servers:
- type: list
- description:
- - A list of up to 4 alternate NTP servers. These may include IPv4,
- IPv6 or FQDNs. Invalid IP addresses will cause the module to fail.
- No validation is performed for FQDNs.
- - If more than 4 servers are provided, only the first 4 unique
- nameservers will be used.
- - if no servers are given a default of I(0.pool.ntp.org) will be used.
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing NTP server entries
- purefa_ntp:
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Set array NTP servers
- purefa_ntp:
- state: present
- ntp_servers:
- - "0.pool.ntp.org"
- - "1.pool.ntp.org"
- - "2.pool.ntp.org"
- - "3.pool.ntp.org"
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def remove(duplicate):
- final_list = []
- for num in duplicate:
- if num not in final_list:
- final_list.append(num)
- return final_list
-
-
-def delete_ntp(module, array):
- """Delete NTP Servers"""
- changed = False
- if array.get(ntpserver=True)['ntpserver'] != []:
- try:
- array.set(ntpserver=[])
- changed = True
- except Exception:
- module.fail_json(msg='Deletion of NTP servers failed')
- module.exit_json(changed=changed)
-
-
-def create_ntp(module, array):
- """Set NTP Servers"""
- changed = False
- if not module.params['ntp_servers']:
- module.params['ntp_servers'] = ['0.pool.ntp.org']
- try:
- array.set(ntpserver=module.params['ntp_servers'][0:4])
- changed = True
- except Exception:
- module.fail_json(msg='Update of NTP servers failed')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- ntp_servers=dict(type='list'),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- ))
-
- required_if = [['state', 'present', ['ntp_servers']]]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=False)
-
- array = get_system(module)
-
- if module.params['state'] == 'absent':
- delete_ntp(module, array)
- else:
- module.params['ntp_servers'] = remove(module.params['ntp_servers'])
- if sorted(array.get(ntpserver=True)['ntpserver']) != sorted(module.params['ntp_servers'][0:4]):
- create_ntp(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_offload.py b/lib/ansible/modules/storage/purestorage/purefa_offload.py
deleted file mode 100644
index 25a061b491..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_offload.py
+++ /dev/null
@@ -1,270 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2019, 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_offload
-version_added: '2.8'
-short_description: Create, modify and delete NFS or S3 offload targets
-description:
-- Create, modify and delete NFS or S3 offload targets.
-- Only supported on Purity v5.2.0 or higher.
-- You must have a correctly configured offload network for offload to work.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Define state of offload
- default: present
- choices: [ absent, present ]
- type: str
- name:
- description:
- - The name of the offload target
- required: true
- type: str
- protocol:
- description:
- - Define which protocol the offload engine uses
- default: nfs
- choices: [ nfs, s3 ]
- type: str
- address:
- description:
- - The IP or FQDN address of the NFS server
- type: str
- share:
- description:
- - NFS export on the NFS server
- type: str
- options:
- description:
- - Additional mount options for the NFS share
- - Supported mount options include I(port), I(rsize),
- I(wsize), I(nfsvers), and I(tcp) or I(udp)
- required: false
- default: ""
- type: str
- access_key:
- description:
- - Access Key ID of the S3 target
- type: str
- bucket:
- description:
- - Name of the bucket for the S3 target
- type: str
- secret:
- description:
- - Secret Access Key for the S3 target
- type: str
- initialize:
- description:
- - Define whether to initialize the S3 bucket
- type: bool
- default: true
-
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create NFS offload target
- purefa_offload:
- name: nfs-offload
- protocol: nfs
- address: 10.21.200.4
- share: "/offload_target"
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create S3 offload target
- purefa_offload:
- name: s3-offload
- protocol: s3
- access_key: "3794fb12c6204e19195f"
- bucket: offload-bucket
- secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete offload target
- purefa_offload:
- name: nfs-offload
- protocol: nfs
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-
-'''
-
-RETURN = r'''
-'''
-
-import re
-from distutils.version import LooseVersion
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-MIN_REQUIRED_API_VERSION = '1.16'
-REGEX_TARGET_NAME = re.compile(r"^[a-zA-Z0-9\-]*$")
-
-
-def get_target(module, array):
- """Return target or None"""
- try:
- return array.get_offload(module.params['name'])
- except Exception:
- return None
-
-
-def create_offload(module, array):
- """Create offload target"""
- changed = False
- # First check if the offload network interface is there and enabled
- try:
- if not array.get_network_interface('@offload.data')['enabled']:
- module.fail_json(msg='Offload Network interface not enabled. Please resolve.')
- except Exception:
- module.fail_json(msg='Offload Network interface not correctly configured. Please resolve.')
- if module.params['protocol'] == 'nfs':
- try:
- array.connect_nfs_offload(module.params['name'],
- mount_point=module.params['share'],
- address=module.params['address'],
- mount_options=module.params['options'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to create NFS offload {0}. '
- 'Please perform diagnostic checks.'.format(module.params['name']))
- if module.params['protocol'] == 's3':
- try:
- array.connect_s3_offload(module.params['name'],
- access_key_id=module.params['access_key'],
- secret_access_key=module.params['secret'],
- bucket=module.params['bucket'],
- initialize=module.params['initialize'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to create S3 offload {0}. '
- 'Please perform diagnostic checks.'.format(module.params['name']))
- module.exit_json(changed=changed)
-
-
-def update_offload(module, array):
- """Update offload target"""
- changed = False
- module.exit_json(changed=changed)
-
-
-def delete_offload(module, array):
- """Delete offload target"""
- changed = False
- if module.params['protocol'] == 'nfs':
- try:
- array.disconnect_nfs_offload(module.params['name'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to delete NFS offload {0}.'.format(module.params['name']))
- if module.params['protocol'] == 's3':
- try:
- array.disconnect_nfs_offload(module.params['name'])
- changed = True
- except Exception:
- module.fail_json(msg='Failed to delete S3 offload {0}.'.format(module.params['name']))
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='present', choices=['present', 'absent']),
- protocol=dict(type='str', default='nfs', choices=['nfs', 's3']),
- name=dict(type='str', required=True),
- initialize=dict(default=True, type='bool'),
- access_key=dict(type='str'),
- secret=dict(type='str', no_log=True),
- bucket=dict(type='str'),
- share=dict(type='str'),
- address=dict(type='str'),
- options=dict(type='str', default=''),
- ))
-
- required_if = []
-
- if argument_spec['state'] == "present":
- required_if = [
- ('protocol', 'nfs', ['address', 'share']),
- ('protocol', 's3', ['access_key', 'secret', 'bucket'])
- ]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=False)
-
- array = get_system(module)
- api_version = array._list_available_rest_versions()
-
- if MIN_REQUIRED_API_VERSION not in api_version:
- module.fail_json(msg='FlashArray REST version not supported. '
- 'Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
-
- if not re.match(r"^[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9]$", module.params['name']) or len(module.params['name']) > 56:
- module.fail_json(msg='Target name invalid. '
- 'Target name must be between 1 and 56 characters (alphanumeric and -) in length '
- 'and begin and end with a letter or number. The name must include at least one letter.')
- if module.params['protocol'] == "s3":
- if not re.match(r"^[a-z0-9][a-z0-9.\-]*[a-z0-9]$", module.params['bucket']) or len(module.params['bucket']) > 63:
- module.fail_json(msg='Bucket name invalid. '
- 'Bucket name must be between 3 and 63 characters '
- '(ilowercase, alphanumeric, dash or period) in length '
- 'and begin and end with a letter or number.')
-
- apps = array.list_apps()
- app_version = 0
- all_good = False
- for app in range(0, len(apps)):
- if apps[app]['name'] == 'offload':
- if (apps[app]['enabled'] and
- apps[app]['status'] == 'healthy' and
- LooseVersion(apps[app]['version']) >= LooseVersion('5.2.0')):
- all_good = True
- app_version = apps[app]['version']
- break
-
- if not all_good:
- module.fail_json(msg='Correct Offload app not installed or incorrectly configured')
- else:
- if LooseVersion(array.get()['version']) != LooseVersion(app_version):
- module.fail_json(msg='Offload app version must match Purity version. Please upgrade.')
-
- target = get_target(module, array)
- if module.params['state'] == 'present' and not target:
- target_count = len(array.list_offload())
- # Currently only 1 offload target is supported
- # TODO: (SD) when more targets supported add in REST version check as well
- if target_count != 0:
- module.fail_json(msg='Currently only 1 Offload Target is supported.')
- create_offload(module, array)
- elif module.params['state'] == 'present' and target:
- update_offload(module, array)
- elif module.params['state'] == 'absent' and target:
- delete_offload(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_pg.py b/lib/ansible/modules/storage/purestorage/purefa_pg.py
deleted file mode 100644
index ad45cb33f4..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_pg.py
+++ /dev/null
@@ -1,489 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, 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_pg
-version_added: '2.4'
-short_description: Manage protection groups on Pure Storage FlashArrays
-description:
-- Create, delete or modify protection groups on Pure Storage FlashArrays.
-- If a protection group exists and you try to add non-valid types, eg. a host
- to a volume protection group the module will ignore the invalid types.
-- Protection Groups on Offload targets are supported.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- pgroup:
- description:
- - The name of the protection group.
- type: str
- required: true
- state:
- description:
- - Define whether the protection group should exist or not.
- type: str
- default: present
- choices: [ absent, present ]
- volume:
- description:
- - List of existing volumes to add to protection group.
- type: list
- host:
- description:
- - List of existing hosts to add to protection group.
- type: list
- hostgroup:
- description:
- - List of existing hostgroups to add to protection group.
- type: list
- eradicate:
- description:
- - Define whether to eradicate the protection group on delete and leave in trash.
- type : bool
- default: 'no'
- enabled:
- description:
- - Define whether to enabled snapshots for the protection group.
- type : bool
- default: 'yes'
- target:
- description:
- - List of remote arrays or offload target for replication protection group
- to connect to.
- - Note that all replicated protection groups are asynchronous.
- - Target arrays or offload targets must already be connected to the source array.
- - Maximum number of targets per Protection Group is 4, assuming your
- configuration supports this.
- type: list
- version_added: '2.8'
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create new local protection group
- purefa_pg:
- pgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create new replicated protection group
- purefa_pg:
- pgroup: foo
- target:
- - arrayb
- - arrayc
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create new replicated protection group to offload target and remote array
- purefa_pg:
- pgroup: foo
- target:
- - offload
- - arrayc
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create new protection group with snapshots disabled
- purefa_pg:
- pgroup: foo
- enabled: false
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Delete protection group
- purefa_pg:
- pgroup: foo
- eradicate: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Eradicate protection group foo on offload target where source array is arrayA
- purefa_pg:
- pgroup: "arrayA:foo"
- target: offload
- eradicate: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Create protection group for hostgroups
- purefa_pg:
- pgroup: bar
- hostgroup:
- - hg1
- - hg2
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create protection group for hosts
- purefa_pg:
- pgroup: bar
- host:
- - host1
- - host2
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create replicated protection group for volumes
- purefa_pg:
- pgroup: bar
- volume:
- - vol1
- - vol2
- target: arrayb
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-OFFLOAD_API_VERSION = '1.16'
-
-
-def get_targets(array):
- """Get Offload Targets"""
- targets = []
- try:
- target_details = array.list_offload()
- except Exception:
- return None
-
- for targetcnt in range(0, len(target_details)):
- if target_details[targetcnt]['status'] == "connected":
- targets.append(target_details[targetcnt]['name'])
- return targets
-
-
-def get_arrays(array):
- """ Get Connected Arrays"""
- arrays = []
- array_details = array.list_array_connections()
- for arraycnt in range(0, len(array_details)):
- if array_details[arraycnt]['connected']:
- arrays.append(array_details[arraycnt]['array_name'])
-
- return arrays
-
-
-def get_pending_pgroup(module, array):
- """ Get Protection Group"""
- pgroup = None
- if ":" in module.params['pgroup']:
- for pgrp in array.list_pgroups(pending=True, on="*"):
- if pgrp["name"] == module.params['pgroup'] and pgrp['time_remaining']:
- pgroup = pgrp
- break
- else:
- for pgrp in array.list_pgroups(pending=True):
- if pgrp["name"] == module.params['pgroup'] and pgrp['time_remaining']:
- pgroup = pgrp
- break
-
- return pgroup
-
-
-def get_pgroup(module, array):
- """ Get Protection Group"""
- pgroup = None
- if ":" in module.params['pgroup']:
- for pgrp in array.list_pgroups(on="*"):
- if pgrp["name"] == module.params['pgroup']:
- pgroup = pgrp
- break
- else:
- for pgrp in array.list_pgroups():
- if pgrp["name"] == module.params['pgroup']:
- pgroup = pgrp
- break
-
- return pgroup
-
-
-def get_pgroup_sched(module, array):
- """ Get Protection Group Schedule"""
- pgroup = None
-
- for pgrp in array.list_pgroups(schedule=True):
- if pgrp["name"] == module.params['pgroup']:
- pgroup = pgrp
- break
-
- return pgroup
-
-
-def check_pg_on_offload(module, array):
- """ Check if PG already exists on offload target """
- array_name = array.get()['array_name']
- remote_pg = array_name + ":" + module.params['pgroup']
- targets = get_targets(array)
- for target in targets:
- remote_pgs = array.list_pgroups(pending=True, on=target)
- for rpg in range(0, len(remote_pgs)):
- if remote_pg == remote_pgs[rpg]['name']:
- return target
- return None
-
-
-def make_pgroup(module, array):
- """ Create Protection Group"""
- changed = False
- if module.params['target']:
- api_version = array._list_available_rest_versions()
- connected_targets = []
- connected_arrays = get_arrays(array)
- if OFFLOAD_API_VERSION in api_version:
- connected_targets = get_targets(array)
- offload_name = check_pg_on_offload(module, array)
- if offload_name and offload_name in module.params['target'][0:4]:
- module.fail_json(msg='Protection Group {0} already exists on offload target {1}.'.format(module.params['pgroup'], offload_name))
-
- connected_arrays = connected_arrays + connected_targets
- if connected_arrays == []:
- module.fail_json(msg='No connected targets on source array.')
- if set(module.params['target'][0:4]).issubset(connected_arrays):
- try:
- array.create_pgroup(module.params['pgroup'], targetlist=module.params['target'][0:4])
- except Exception:
- module.fail_json(msg='Creation of replicated pgroup {0} failed. {1}'.format(module.params['pgroup'], module.params['target'][0:4]))
- else:
- module.fail_json(msg='Check all selected targets are connected to the source array.')
- else:
- try:
- array.create_pgroup(module.params['pgroup'])
- except Exception:
- module.fail_json(msg='Creation of pgroup {0} failed.'.format(module.params['pgroup']))
- try:
- if module.params['target']:
- array.set_pgroup(module.params['pgroup'], replicate_enabled=module.params['enabled'])
- else:
- array.set_pgroup(module.params['pgroup'], snap_enabled=module.params['enabled'])
- except Exception:
- module.fail_json(msg='Enabling pgroup {0} failed.'.format(module.params['pgroup']))
- if module.params['volume']:
- try:
- array.set_pgroup(module.params['pgroup'], vollist=module.params['volume'])
- except Exception:
- module.fail_json(msg='Adding volumes to pgroup {0} failed.'.format(module.params['pgroup']))
- if module.params['host']:
- try:
- array.set_pgroup(module.params['pgroup'], hostlist=module.params['host'])
- except Exception:
- module.fail_json(msg='Adding hosts to pgroup {0} failed.'.format(module.params['pgroup']))
- if module.params['hostgroup']:
- try:
- array.set_pgroup(module.params['pgroup'], hgrouplist=module.params['hostgroup'])
- except Exception:
- module.fail_json(msg='Adding hostgroups to pgroup {0} failed.'.format(module.params['pgroup']))
- changed = True
- module.exit_json(changed=changed)
-
-
-def update_pgroup(module, array):
- """ Update Protection Group"""
- changed = False
- if module.params['target']:
- api_version = array._list_available_rest_versions()
- connected_targets = []
- connected_arrays = get_arrays(array)
-
- if OFFLOAD_API_VERSION in api_version:
- connected_targets = get_targets(array)
- offload_name = check_pg_on_offload(module, array)
- if offload_name and offload_name in module.params['target'][0:4]:
- module.fail_json(msg='Protection Group {0} already exists on offload target {1}.'.format(module.params['pgroup'], offload_name))
-
- connected_arrays = connected_arrays + connected_targets
- if connected_arrays == []:
- module.fail_json(msg='No targets connected to source array.')
- current_connects = array.get_pgroup(module.params['pgroup'])['targets']
- current_targets = []
-
- if current_connects:
- for targetcnt in range(0, len(current_connects)):
- current_targets.append(current_connects[targetcnt]['name'])
-
- if set(module.params['target'][0:4]) != set(current_targets):
- if not set(module.params['target'][0:4]).issubset(connected_arrays):
- module.fail_json(msg='Check all selected targets are connected to the source array.')
- try:
- array.set_pgroup(module.params['pgroup'], targetlist=module.params['target'][0:4])
- changed = True
- except Exception:
- module.fail_json(msg='Changing targets for pgroup {0} failed.'.format(module.params['pgroup']))
-
- if module.params['target'] and module.params['enabled'] != get_pgroup_sched(module, array)['replicate_enabled']:
- try:
- array.set_pgroup(module.params['pgroup'], replicate_enabled=module.params['enabled'])
- changed = True
- except Exception:
- module.fail_json(msg='Changing enabled status of pgroup {0} failed.'.format(module.params['pgroup']))
- elif not module.params['target'] and module.params['enabled'] != get_pgroup_sched(module, array)['snap_enabled']:
- try:
- array.set_pgroup(module.params['pgroup'], snap_enabled=module.params['enabled'])
- changed = True
- except Exception:
- module.fail_json(msg='Changing enabled status of pgroup {0} failed.'.format(module.params['pgroup']))
-
- if module.params['volume'] and get_pgroup(module, array)['hosts'] is None and get_pgroup(module, array)['hgroups'] is None:
- if get_pgroup(module, array)['volumes'] is None:
- try:
- array.set_pgroup(module.params['pgroup'], vollist=module.params['volume'])
- changed = True
- except Exception:
- module.fail_json(msg='Adding volumes to pgroup {0} failed.'.format(module.params['pgroup']))
- else:
- if not all(x in get_pgroup(module, array)['volumes'] for x in module.params['volume']):
- try:
- array.set_pgroup(module.params['pgroup'], vollist=module.params['volume'])
- changed = True
- except Exception:
- module.fail_json(msg='Changing volumes in pgroup {0} failed.'.format(module.params['pgroup']))
-
- if module.params['host'] and get_pgroup(module, array)['volumes'] is None and get_pgroup(module, array)['hgroups'] is None:
- if not get_pgroup(module, array)['hosts'] is None:
- try:
- array.set_pgroup(module.params['pgroup'], hostlist=module.params['host'])
- changed = True
- except Exception:
- module.fail_json(msg='Adding hosts to pgroup {0} failed.'.format(module.params['pgroup']))
- else:
- if not all(x in get_pgroup(module, array)['hosts'] for x in module.params['host']):
- try:
- array.set_pgroup(module.params['pgroup'], hostlist=module.params['host'])
- changed = True
- except Exception:
- module.fail_json(msg='Changing hosts in pgroup {0} failed.'.format(module.params['pgroup']))
-
- if module.params['hostgroup'] and get_pgroup(module, array)['hosts'] is None and get_pgroup(module, array)['volumes'] is None:
- if not get_pgroup(module, array)['hgroups'] is None:
- try:
- array.set_pgroup(module.params['pgroup'], hgrouplist=module.params['hostgroup'])
- changed = True
- except Exception:
- module.fail_json(msg='Adding hostgroups to pgroup {0} failed.'.format(module.params['pgroup']))
- else:
- if not all(x in get_pgroup(module, array)['hgroups'] for x in module.params['hostgroup']):
- try:
- array.set_pgroup(module.params['pgroup'], hgrouplist=module.params['hostgroup'])
- changed = True
- except Exception:
- module.fail_json(msg='Changing hostgroups in pgroup {0} failed.'.format(module.params['pgroup']))
-
- module.exit_json(changed=changed)
-
-
-def eradicate_pgroup(module, array):
- """ Eradicate Protection Group"""
- changed = False
- if ":" in module.params['pgroup']:
- try:
- target = ''.join(module.params['target'])
- array.destroy_pgroup(module.params['pgroup'], on=target, eradicate=True)
- changed = True
- except Exception:
- module.fail_json(msg='Eradicating pgroup {0} failed.'.format(module.params['pgroup']))
- else:
- try:
- array.destroy_pgroup(module.params['pgroup'], eradicate=True)
- changed = True
- except Exception:
- module.fail_json(msg='Eradicating pgroup {0} failed.'.format(module.params['pgroup']))
- module.exit_json(changed=changed)
-
-
-def delete_pgroup(module, array):
- """ Delete Protection Group"""
- changed = False
- if ":" in module.params['pgroup']:
- try:
- target = ''.join(module.params['target'])
- array.destroy_pgroup(module.params['pgroup'], on=target)
- changed = True
- except Exception:
- module.fail_json(msg='Deleting pgroup {0} failed.'.format(module.params['pgroup']))
- else:
- try:
- array.destroy_pgroup(module.params['pgroup'])
- changed = True
- except Exception:
- module.fail_json(msg='Deleting pgroup {0} failed.'.format(module.params['pgroup']))
- if module.params['eradicate']:
- eradicate_pgroup(module, array)
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- pgroup=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- volume=dict(type='list'),
- host=dict(type='list'),
- hostgroup=dict(type='list'),
- target=dict(type='list'),
- eradicate=dict(type='bool', default=False),
- enabled=dict(type='bool', default=True),
- ))
-
- mutually_exclusive = [['volume', 'host', 'hostgroup']]
- module = AnsibleModule(argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
- api_version = array._list_available_rest_versions()
- if ":" in module.params['pgroup'] and OFFLOAD_API_VERSION not in api_version:
- module.fail_json(msg='API version does not support offload protection groups.')
-
- pgroup = get_pgroup(module, array)
- xpgroup = get_pending_pgroup(module, array)
-
- if module.params['host']:
- try:
- for hst in module.params['host']:
- array.get_host(hst)
- except Exception:
- module.fail_json(msg='Host {0} not found'.format(hst))
-
- if module.params['hostgroup']:
- try:
- for hstg in module.params['hostgroup']:
- array.get_hgroup(hstg)
- except Exception:
- module.fail_json(msg='Hostgroup {0} not found'.format(hstg))
-
- if pgroup and state == 'present':
- update_pgroup(module, array)
- elif pgroup and state == 'absent':
- delete_pgroup(module, array)
- elif xpgroup and state == 'absent' and module.params['eradicate']:
- eradicate_pgroup(module, array)
- elif not pgroup and not xpgroup and state == 'present':
- make_pgroup(module, array)
- elif pgroup is None and state == 'absent':
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py b/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py
deleted file mode 100644
index d672692eb6..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2017, 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_pgsnap
-version_added: '2.6'
-short_description: Manage protection group snapshots on Pure Storage FlashArrays
-description:
-- Create or delete protection group snapshots on Pure Storage FlashArray.
-- Recovery of replicated snapshots on the replica target array is enabled.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- name:
- description:
- - The name of the source protection group.
- type: str
- required: true
- suffix:
- description:
- - Suffix of snapshot name.
- state:
- description:
- - Define whether the protection group snapshot should exist or not.
- Copy (added in 2.7) will create a full read/write clone of the
- snapshot.
- type: str
- choices: [ absent, present, copy ]
- default: present
- eradicate:
- description:
- - Define whether to eradicate the snapshot on delete or leave in trash.
- type: bool
- default: 'no'
- restore:
- description:
- - Restore a specific volume from a protection group snapshot.
- type: str
- version_added: 2.7
- overwrite:
- description:
- - Define whether to overwrite the target volume if it already exists.
- type: bool
- default: 'no'
- version_added: 2.8
- target:
- description:
- - Volume to restore a specified volume to.
- - If not supplied this will default to the volume defined in I(restore)
- type: str
- version_added: 2.8
- now:
- description: Whether to initiate a snapshot of the protection group immediately
- type: bool
- default: False
- version_added: 2.9
- apply_retention:
- description: Apply retention schedule settings to the snapshot
- type: bool
- default: False
- version_added: 2.9
- remote:
- description: Force immeadiate snapshot to remote targets
- type: bool
- default: False
- version_added: 2.9
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create protection group snapshot foo.ansible
- purefa_pgsnap:
- name: foo
- suffix: ansible
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Delete and eradicate protection group snapshot named foo.snap
- purefa_pgsnap:
- name: foo
- suffix: snap
- eradicate: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Restore volume data from local protection group snapshot named foo.snap to volume data2
- purefa_pgsnap:
- name: foo
- suffix: snap
- restore: data
- target: data2
- overwrite: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: copy
-
-- name: Restore remote protection group snapshot arrayA:pgname.snap.data to local copy
- purefa_pgsnap:
- name: arrayA:pgname
- suffix: snap
- restore: data
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: copy
-
-- name: Create snapshot of existing pgroup foo with suffix and force immeadiate copy to remote targets
- purefa_pgsnap:
- name: pgname
- suffix: force
- now: True
- apply_retention: True
- remote: True
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: copy
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-from datetime import datetime
-
-
-def get_pgroup(module, array):
- """Return Protection Group or None"""
- try:
- return array.get_pgroup(module.params['name'])
- except Exception:
- return None
-
-
-def get_pgroupvolume(module, array):
- """Return Protection Group Volume or None"""
- try:
- pgroup = array.get_pgroup(module.params['name'])
- for volume in pgroup['volumes']:
- if volume == module.params['restore']:
- return volume
- except Exception:
- return None
-
-
-def get_rpgsnapshot(module, array):
- """Return iReplicated Snapshot or None"""
- try:
- snapname = module.params['name'] + "." + module.params['suffix'] + "." + module.params['restore']
- for snap in array.list_volumes(snap=True):
- if snap['name'] == snapname:
- return snapname
- except Exception:
- return None
-
-
-def get_pgsnapshot(module, array):
- """Return Snapshot (active or deleted) or None"""
- try:
- snapname = module.params['name'] + "." + module.params['suffix']
- for snap in array.get_pgroup(module.params['name'], snap=True, pending=True):
- if snap['name'] == snapname:
- return snapname
- except Exception:
- return None
-
-
-def create_pgsnapshot(module, array):
- """Create Protection Group Snapshot"""
- changed = True
- if not module.check_mode:
- try:
- if module.params['now'] and array.get_pgroup(module.params['name'])['targets'] is not None:
- array.create_pgroup_snapshot(source=module.params['name'],
- suffix=module.params['suffix'],
- snap=True,
- apply_retention=module.params['apply_retention'],
- replicate_now=module.params['remote'])
- else:
- array.create_pgroup_snapshot(source=module.params['name'],
- suffix=module.params['suffix'],
- snap=True,
- apply_retention=module.params['apply_retention'])
- except Exception:
- module.fail_json(msg="Snapshot of pgroup {0} failed.".format(module.params['name']))
- module.exit_json(changed=changed)
-
-
-def restore_pgsnapvolume(module, array):
- """Restore a Protection Group Snapshot Volume"""
- changed = True
- if not module.check_mode:
- if ":" in module.params['name']:
- if get_rpgsnapshot(module, array)is None:
- module.fail_json(msg="Selected restore snapshot {0} does not exist in the Protection Group".format(module.params['restore']))
- else:
- if get_pgroupvolume(module, array) is None:
- module.fail_json(msg="Selected restore volume {0} does not exist in the Protection Group".format(module.params['restore']))
- volume = module.params['name'] + "." + module.params['suffix'] + "." + module.params['restore']
- try:
- array.copy_volume(volume, module.params['target'], overwrite=module.params['overwrite'])
- except Exception:
- module.fail_json(msg="Failed to restore {0} from pgroup {1}".format(volume, module.params['name']))
- module.exit_json(changed=changed)
-
-
-def update_pgsnapshot(module, array):
- """Update Protection Group Snapshot"""
- changed = True
- module.exit_json(changed=changed)
-
-
-def delete_pgsnapshot(module, array):
- """ Delete Protection Group Snapshot"""
- changed = True
- if not module.check_mode:
- snapname = module.params['name'] + "." + module.params['suffix']
- try:
- array.destroy_pgroup(snapname)
- if module.params['eradicate']:
- try:
- array.eradicate_pgroup(snapname)
- except Exception:
- module.fail_json(msg="Failed to eradicate pgroup {0}".format(snapname))
- except Exception:
- module.fail_json(msg="Failed to delete pgroup {0}".format(snapname))
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- suffix=dict(type='str'),
- restore=dict(type='str'),
- overwrite=dict(type='bool', default=False),
- target=dict(type='str'),
- eradicate=dict(type='bool', default=False),
- now=dict(type='bool', default=False),
- apply_retention=dict(type='bool', default=False),
- remote=dict(type='bool', default=False),
- state=dict(type='str', default='present', choices=['absent', 'present', 'copy']),
- ))
-
- required_if = [('state', 'copy', ['suffix', 'restore'])]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- if module.params['suffix'] is None:
- suffix = "snap-" + str((datetime.utcnow() - datetime(1970, 1, 1, 0, 0, 0, 0)).total_seconds())
- module.params['suffix'] = suffix.replace(".", "")
-
- if not module.params['target'] and module.params['restore']:
- module.params['target'] = module.params['restore']
-
- state = module.params['state']
- array = get_system(module)
- pgroup = get_pgroup(module, array)
- if pgroup is None:
- module.fail_json(msg="Protection Group {0} does not exist.".format(module.params['name']))
- pgsnap = get_pgsnapshot(module, array)
-
- if state == 'copy':
- restore_pgsnapvolume(module, array)
- elif state == 'present' and not pgsnap:
- create_pgsnapshot(module, array)
- elif state == 'present' and pgsnap:
- update_pgsnapshot(module, array)
- elif state == 'absent' and pgsnap:
- delete_pgsnapshot(module, array)
- elif state == 'absent' and not pgsnap:
- module.exit_json(changed=False)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_phonehome.py b/lib/ansible/modules/storage/purestorage/purefa_phonehome.py
deleted file mode 100644
index 07def6084a..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_phonehome.py
+++ /dev/null
@@ -1,99 +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_phonehome
-version_added: '2.9'
-short_description: Enable or Disable Pure Storage FlashArray Phonehome
-description:
-- Enable or Disable Phonehome for a Pure Storage FlashArray.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Define state of phonehome
- type: str
- default: present
- choices: [ present, absent ]
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Enable Phonehome
- purefa_phonehome:
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Disable Phonehome
- purefa_phonehome:
- state: disable
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def enable_ph(module, array):
- """Enable Remote Assist"""
- changed = False
- if array.get_phonehome()['phonehome'] != 'enabled':
- try:
- if not module.check_mode:
- array.enable_phonehome()
- changed = True
- except Exception:
- module.fail_json(msg='Enabling Phonehome failed')
- module.exit_json(changed=changed)
-
-
-def disable_ph(module, array):
- """Disable Remote Assist"""
- changed = False
- if array.get_phonehome()['phonehome'] == 'enabled':
- try:
- if not module.check_mode:
- array.disable_phonehome()
- changed = True
- except Exception:
- module.fail_json(msg='Disabling Remote Assist failed')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='present', choices=['present', 'absent']),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True)
-
- array = get_system(module)
-
- if module.params['state'] == 'present':
- enable_ph(module, array)
- else:
- disable_ph(module, array)
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_ra.py b/lib/ansible/modules/storage/purestorage/purefa_ra.py
deleted file mode 100644
index b3d5ec0229..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_ra.py
+++ /dev/null
@@ -1,113 +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_ra
-version_added: '2.8'
-short_description: Enable or Disable Pure Storage FlashArray Remote Assist
-description:
-- Enable or Disable Remote Assist for a Pure Storage FlashArray.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Define state of remote assist
- - When set to I(enable) the RA port can be exposed using the
- I(debug) module.
- type: str
- default: enable
- choices: [ enable, disable ]
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Enable Remote Assist port
- purefa_ra:
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- register: result
-
-- debug:
- msg: "Remote Assist: {{ result['ra_info'] }}"
-
-- name: Disable Remote Assist port
- purefa_ra:
- state: disable
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def enable_ra(module, array):
- """Enable Remote Assist"""
- changed = False
- ra_facts = {}
- if array.get_remote_assist_status()['status'] != 'enabled':
- try:
- ra_data = array.enable_remote_assist()
- ra_facts['fa_ra'] = {'name': ra_data['name'],
- 'port': ra_data['port']}
- changed = True
- except Exception:
- module.fail_json(msg='Enabling Remote Assist failed')
- else:
- try:
- ra_data = array.get_remote_assist_status()
- ra_facts['fa_ra'] = {'name': ra_data['name'],
- 'port': ra_data['port']}
- except Exception:
- module.fail_json(msg='Getting Remote Assist failed')
- module.exit_json(changed=changed, ra_info=ra_facts)
-
-
-def disable_ra(module, array):
- """Disable Remote Assist"""
- changed = False
- if array.get_remote_assist_status()['status'] == 'enabled':
- try:
- array.disable_remote_assist()
- changed = True
- except Exception:
- module.fail_json(msg='Disabling Remote Assist failed')
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='enable', choices=['enable', 'disable']),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=False)
-
- array = get_system(module)
-
- if module.params['state'] == 'enable':
- enable_ra(module, array)
- else:
- disable_ra(module, array)
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_smtp.py b/lib/ansible/modules/storage/purestorage/purefa_smtp.py
deleted file mode 100644
index 70c07c6c82..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_smtp.py
+++ /dev/null
@@ -1,150 +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_smtp
-version_added: '2.9'
-author:
- - Pure Storage ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-short_description: Configure FlashArray SMTP settings
-description:
-- Set or erase configuration for the SMTP settings.
-- If username/password are set this will always force a change as there is
- no way to see if the password is different from the current SMTP configuration.
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Set or delete SMTP configuration
- default: present
- type: str
- choices: [ absent, present ]
- password:
- description:
- - The SMTP password.
- type: str
- user:
- description:
- - The SMTP username.
- type: str
- relay_host:
- description:
- - IPv4 or IPv6 address or FQDN. A port number may be appended.
- type: str
- sender_domain:
- description:
- - Domain name.
- type: str
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing SMTP settings
- purefa_smtp:
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Set SMTP settings
- purefa_smtp:
- sender_domain: purestorage.com
- password: account_password
- user: smtp_account
- relay_host: 10.2.56.78:2345
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def delete_smtp(module, array):
- """Delete SMTP settings"""
- changed = True
- if not module.check_mode:
- try:
- array.set_smtp(sender_domain='', username='', password='', relay_host='')
- except Exception:
- module.fail_json(msg='Delete SMTP settings failed')
- module.exit_json(changed=changed)
-
-
-def create_smtp(module, array):
- """Set SMTP settings"""
- changed = True
- current_smtp = array.get_smtp()
- if not module.check_mode:
- if module.params['sender_domain'] and current_smtp['sender_domain'] != module.params['sender_domain']:
- try:
- array.set_smtp(sender_domain=module.params['sender_domain'])
- changed_sender = True
- except Exception:
- module.fail_json(msg='Set SMTP sender domain failed.')
- else:
- changed_sender = False
- if module.params['relay_host'] and current_smtp['relay_host'] != module.params['relay_host']:
- try:
- array.set_smtp(relay_host=module.params['relay_host'])
- changed_relay = True
- except Exception:
- module.fail_json(msg='Set SMTP relay host failed.')
- else:
- changed_relay = False
- if module.params['user']:
- try:
- array.set_smtp(user_name=module.params['user'], password=module.params['password'])
- changed_creds = True
- except Exception:
- module.fail_json(msg='Set SMTP username/password failed.')
- else:
- changed_creds = False
- changed = bool(changed_sender or changed_relay or changed_creds)
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- state=dict(type='str', default='present', choices=['absent', 'present']),
- sender_domain=dict(type='str'),
- password=dict(type='str', no_log=True),
- user=dict(type='str'),
- relay_host=dict(type='str'),
- ))
-
- required_together = [['user', 'password']]
-
- module = AnsibleModule(argument_spec,
- required_together=required_together,
- supports_check_mode=True)
-
- state = module.params['state']
- array = get_system(module)
-
- if state == 'absent':
- delete_smtp(module, array)
- elif state == 'present':
- create_smtp(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_snap.py b/lib/ansible/modules/storage/purestorage/purefa_snap.py
deleted file mode 100644
index 6f7a776502..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_snap.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2017, 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_snap
-version_added: '2.4'
-short_description: Manage volume snapshots on Pure Storage FlashArrays
-description:
-- Create or delete volumes and volume snapshots on Pure Storage FlashArray.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- name:
- description:
- - The name of the source volume.
- type: str
- required: true
- suffix:
- description:
- - Suffix of snapshot name.
- type: str
- target:
- description:
- - Name of target volume if creating from snapshot.
- type: str
- overwrite:
- description:
- - Define whether to overwrite existing volume when creating from snapshot.
- type: bool
- default: 'no'
- state:
- description:
- - Define whether the volume snapshot should exist or not.
- choices: [ absent, copy, present ]
- type: str
- default: present
- eradicate:
- description:
- - Define whether to eradicate the snapshot on delete or leave in trash.
- type: bool
- default: 'no'
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create snapshot foo.ansible
- purefa_snap:
- name: foo
- suffix: ansible
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: present
-
-- name: Create R/W clone foo_clone from snapshot foo.snap
- purefa_snap:
- name: foo
- suffix: snap
- target: foo_clone
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: copy
-
-- name: Overwrite existing volume foo_clone with snapshot foo.snap
- purefa_snap:
- name: foo
- suffix: snap
- target: foo_clone
- overwrite: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: copy
-
-- name: Delete and eradicate snapshot named foo.snap
- purefa_snap:
- name: foo
- suffix: snap
- eradicate: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-from datetime import datetime
-
-try:
- from purestorage import purestorage
- HAS_PURESTORAGE = True
-except ImportError:
- HAS_PURESTORAGE = False
-
-
-def get_volume(module, array):
- """Return Volume or None"""
- try:
- return array.get_volume(module.params['name'])
- except Exception:
- return None
-
-
-def get_target(module, array):
- """Return Volume or None"""
- try:
- return array.get_volume(module.params['target'])
- except Exception:
- return None
-
-
-def get_snapshot(module, array):
- """Return Snapshot or None"""
- try:
- snapname = module.params['name'] + "." + module.params['suffix']
- for s in array.get_volume(module.params['name'], snap='true'):
- if s['name'] == snapname:
- return snapname
- except Exception:
- return None
-
-
-def create_snapshot(module, array):
- """Create Snapshot"""
- changed = True
- if not module.check_mode:
- try:
- array.create_snapshot(module.params['name'], suffix=module.params['suffix'])
- except Exception:
- changed = False
- module.exit_json(changed=changed)
-
-
-def create_from_snapshot(module, array):
- """Create Volume from Snapshot"""
- source = module.params['name'] + "." + module.params['suffix']
- tgt = get_target(module, array)
- if tgt is None:
- changed = True
- if not module.check_mode:
- array.copy_volume(source,
- module.params['target'])
- elif tgt is not None and module.params['overwrite']:
- changed = True
- if not module.check_mode:
- array.copy_volume(source,
- module.params['target'],
- overwrite=module.params['overwrite'])
- elif tgt is not None and not module.params['overwrite']:
- changed = False
- module.exit_json(changed=changed)
-
-
-def update_snapshot(module, array):
- """Update Snapshot"""
- changed = False
- module.exit_json(changed=changed)
-
-
-def delete_snapshot(module, array):
- """ Delete Snapshot"""
- changed = True
- if not module.check_mode:
- snapname = module.params['name'] + "." + module.params['suffix']
- try:
- array.destroy_volume(snapname)
- if module.params['eradicate']:
- try:
- array.eradicate_volume(snapname)
- except Exception:
- changed = False
- except Exception:
- changed = False
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- suffix=dict(type='str'),
- target=dict(type='str'),
- overwrite=dict(type='bool', default=False),
- eradicate=dict(type='bool', default=False),
- state=dict(type='str', default='present', choices=['absent', 'copy', 'present']),
- ))
-
- required_if = [('state', 'copy', ['target', 'suffix'])]
-
- module = AnsibleModule(argument_spec,
- required_if=required_if,
- supports_check_mode=True)
-
- if not HAS_PURESTORAGE:
- module.fail_json(msg='purestorage sdk is required for this module in volume')
-
- if module.params['suffix'] is None:
- suffix = "snap-" + str((datetime.utcnow() - datetime(1970, 1, 1, 0, 0, 0, 0)).total_seconds())
- module.params['suffix'] = suffix.replace(".", "")
-
- state = module.params['state']
- array = get_system(module)
- volume = get_volume(module, array)
- target = get_target(module, array)
- snap = get_snapshot(module, array)
-
- if state == 'present' and volume and not snap:
- create_snapshot(module, array)
- elif state == 'present' and volume and snap:
- update_snapshot(module, array)
- elif state == 'present' and not volume:
- update_snapshot(module, array)
- elif state == 'copy' and snap:
- create_from_snapshot(module, array)
- elif state == 'copy' and not snap:
- update_snapshot(module, array)
- elif state == 'absent' and snap:
- delete_snapshot(module, array)
- elif state == 'absent' and not snap:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_snmp.py b/lib/ansible/modules/storage/purestorage/purefa_snmp.py
deleted file mode 100644
index c2479de861..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_snmp.py
+++ /dev/null
@@ -1,333 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# (c) 2019, 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_snmp
-version_added: '2.9'
-short_description: Configure FlashArray SNMP Managers
-description:
-- Manage SNMP managers on a Pure Storage FlashArray.
-- Changing of a named SNMP managers version is not supported.
-- This module is not idempotent and will always modify an
- existing SNMP manager due to hidden parameters that cannot
- be compared to the play parameters.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- name:
- description:
- - Name of SNMP Manager
- required: True
- type: str
- state:
- description:
- - Create or delete SNMP manager
- type: str
- default: present
- choices: [ absent, present ]
- auth_passphrase:
- type: str
- description:
- - SNMPv3 only. Passphrase of 8 - 32 characters.
- auth_protocol:
- type: str
- description:
- - SNMP v3 only. Hash algorithm to use
- choices: [ MD5, SHA ]
- community:
- type: str
- description:
- - SNMP v2c only. Manager community ID. Between 1 and 32 characters long.
- host:
- type: str
- description:
- - IPv4 or IPv6 address or FQDN to send trap messages to.
- required: True
- user:
- type: str
- description:
- - SNMP v3 only. User ID recognized by the specified SNMP manager.
- Must be between 1 and 32 characters.
- version:
- type: str
- description:
- - Version of SNMP protocol to use for the manager.
- choices: [ v2c, v3 ]
- default: v2c
- notification:
- type: str
- description:
- - Action to perform on event.
- default: trap
- choices: [ inform, trap ]
- privacy_passphrase:
- type: str
- description:
- - SNMPv3 only. Passphrase to encrypt SNMP messages.
- Must be between 8 and 63 non-space ASCII characters.
- privacy_protocol:
- type: str
- description:
- - SNMP v3 only. Encryption protocol to use
- choices: [ AES, DES ]
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing SNMP manager
- purefa_snmp:
- name: manager1
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create v2c SNMP manager
- purefa_snmp:
- name: manager1
- community: public
- host: 10.21.22.23
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Create v3 SNMP manager
- purefa_snmp:
- name: manager2
- version: v3
- auth_protocol: MD5
- auth_passphrase: password
- host: 10.21.22.23
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Update existing SNMP manager
- purefa_snmp:
- name: manager1
- community: private
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def update_manager(module, array):
- """Update SNMP Manager"""
- changed = True
- if not module.check_mode:
- try:
- mgr = array.get_snmp_manager(module.params['name'])
- except Exception:
- module.fail_json(msg="Failed to get current configuration for SNMP manager {0}.".format(module.params['name']))
- if mgr['version'] != module.params['version']:
- module.fail_json(msg="Changing an SNMP managers version is not supported.")
- elif module.params['version'] == "v2c":
- try:
- array.set_snmp_manager(module.params['name'],
- community=module.params['community'],
- notification=module.params['notification'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to update SNMP manager {0}.".format(module.params['name']))
- else:
- if module.params['auth_protocol'] and module.params['privacy_protocol']:
- try:
- array.set_snmp_manager(module.params['name'],
- auth_passphrase=module.params['auth_passphrase'],
- auth_protocol=module.params['auth_protocol'],
- privacy_passphrase=module.params['privacy_passphrase'],
- privacy_protocol=module.params['privacy_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to update SNMP manager {0}.".format(module.params['name']))
- elif module.params['auth_protocol'] and not module.params['privacy_protocol']:
- try:
- array.set_snmp_manager(module.params['name'],
- version=module.params['version'],
- auth_passphrase=module.params['auth_passphrase'],
- auth_protocol=module.params['auth_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to update SNMP manager {0}.".format(module.params['name']))
- elif not module.params['auth_protocol'] and module.params['privacy_protocol']:
- try:
- array.set_snmp_manager(module.params['name'],
- version=module.params['version'],
- privacy_passphrase=module.params['privacy_passphrase'],
- privacy_protocol=module.params['privacy_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to update SNMP manager {0}.".format(module.params['name']))
- elif not module.params['auth_protocol'] and not module.params['privacy_protocol']:
- try:
- array.set_snmp_manager(module.params['name'],
- version=module.params['version'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to update SNMP manager {0}.".format(module.params['name']))
- else:
- module.fail_json(msg="Invalid parameters selected in update. Please raise issue in Ansible GitHub")
-
- module.exit_json(changed=changed)
-
-
-def delete_manager(module, array):
- """Delete SNMP Manager"""
- changed = True
- if not module.check_mode:
- try:
- array.delete_snmp_manager(module.params['name'])
- except Exception:
- module.fail_json(msg='Delete SNMP manager {0} failed'.format(module.params['name']))
- module.exit_json(changed=changed)
-
-
-def create_manager(module, array):
- """Create SNMP Manager"""
- changed = True
- if not module.check_mode:
- if module.params['version'] == "v2c":
- try:
- array.create_snmp_manager(module.params['name'],
- version=module.params['version'],
- community=module.params['community'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to create SNMP manager {0}.".format(module.params['name']))
- else:
- if module.params['auth_protocol'] and module.params['privacy_protocol']:
- try:
- array.create_snmp_manager(module.params['name'],
- version=module.params['version'],
- auth_passphrase=module.params['auth_passphrase'],
- auth_protocol=module.params['auth_protocol'],
- privacy_passphrase=module.params['privacy_passphrase'],
- privacy_protocol=module.params['privacy_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to create SNMP manager {0}.".format(module.params['name']))
- elif module.params['auth_protocol'] and not module.params['privacy_protocol']:
- try:
- array.create_snmp_manager(module.params['name'],
- version=module.params['version'],
- auth_passphrase=module.params['auth_passphrase'],
- auth_protocol=module.params['auth_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to create SNMP manager {0}.".format(module.params['name']))
- elif not module.params['auth_protocol'] and module.params['privacy_protocol']:
- try:
- array.create_snmp_manager(module.params['name'],
- version=module.params['version'],
- privacy_passphrase=module.params['privacy_passphrase'],
- privacy_protocol=module.params['privacy_protocol'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to create SNMP manager {0}.".format(module.params['name']))
- elif not module.params['auth_protocol'] and not module.params['privacy_protocol']:
- try:
- array.create_snmp_manager(module.params['name'],
- version=module.params['version'],
- notification=module.params['notification'],
- user=module.params['user'],
- host=module.params['host']
- )
- except Exception:
- module.fail_json(msg="Failed to create SNMP manager {0}.".format(module.params['name']))
- else:
- module.fail_json(msg="Invalid parameters selected in create. Please raise issue in Ansible GitHub")
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(type='str', required=True),
- host=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- user=dict(type='str'),
- notification=dict(type='str', choices=['inform', 'trap'], default='trap'),
- auth_passphrase=dict(type='str', no_log=True),
- auth_protocol=dict(type='str', choices=['MD5', 'SHA']),
- privacy_passphrase=dict(type='str', no_log=True),
- privacy_protocol=dict(type='str', choices=['AES', 'DES']),
- version=dict(type='str', default='v2c', choices=['v2c', 'v3']),
- community=dict(type='str'),
- ))
-
- required_together = [['auth_passphrase', 'auth_protocol'],
- ['privacy_passphrase', 'privacy_protocol']]
- required_if = [['version', 'v2c', ['community', 'host']],
- ['version', 'v3', ['host', 'user']]]
-
- module = AnsibleModule(argument_spec,
- required_together=required_together,
- required_if=required_if,
- supports_check_mode=True)
-
- state = module.params['state']
- array = get_system(module)
- mgr_configured = False
- mgrs = array.list_snmp_managers()
- for mgr in range(0, len(mgrs)):
- if mgrs[mgr]['name'] == module.params['name']:
- mgr_configured = True
- break
- if module.params['version'] == "v3":
- if module.params['auth_passphrase'] and (8 > len(module.params['auth_passphrase']) > 32):
- module.fail_json(msg="auth_password must be between 8 and 32 characters")
- if module.params['privacy_passphrase'] and 8 > len(module.params['privacy_passphrase']) > 63:
- module.fail_json(msg="privacy_password must be between 8 and 63 characters")
- if state == 'absent' and mgr_configured:
- delete_manager(module, array)
- elif mgr_configured and state == 'present':
- update_manager(module, array)
- elif not mgr_configured and state == 'present':
- create_manager(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_syslog.py b/lib/ansible/modules/storage/purestorage/purefa_syslog.py
deleted file mode 100644
index b94c398de0..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_syslog.py
+++ /dev/null
@@ -1,158 +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_syslog
-version_added: '2.9'
-short_description: Configure Pure Storage FlashArray syslog settings
-description:
-- Configure syslog configuration for Pure Storage FlashArrays.
-- Add or delete an individual syslog server to the existing
- list of serves.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Create or delete syslog servers configuration
- default: present
- type: str
- choices: [ absent, present ]
- protocol:
- description:
- - Protocol which server uses
- required: true
- type: str
- choices: [ tcp, tls, udp ]
- port:
- description:
- - Port at which the server is listening. If no port is specified
- the system will use 514
- type: str
- address:
- description:
- - Syslog server address.
- This field supports IPv4, IPv6 or FQDN.
- An invalid IP addresses will cause the module to fail.
- No validation is performed for FQDNs.
- type: str
- required: true
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Delete existing syslog server entries
- purefa_syslog:
- address: syslog1.com
- protocol: tcp
- state: absent
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Set array syslog servers
- purefa_syslog:
- state: present
- address: syslog1.com
- protocol: udp
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-def delete_syslog(module, array):
- """Delete Syslog Server"""
- changed = False
- noport_address = module.params['protocol'] + "://" + module.params['address']
-
- if module.params['port']:
- full_address = noport_address + ":" + module.params['port']
- else:
- full_address = noport_address
-
- address_list = array.get(syslogserver=True)['syslogserver']
-
- if address_list:
- for address in range(0, len(address_list)):
- if address_list[address] == full_address:
- del address_list[address]
- try:
- array.set(syslogserver=address_list)
- changed = True
- break
- except Exception:
- module.fail_json(msg='Failed to remove syslog server: {0}'.format(full_address))
-
- module.exit_json(changed=changed)
-
-
-def add_syslog(module, array):
- """Add Syslog Server"""
- changed = False
- noport_address = module.params['protocol'] + "://" + module.params['address']
-
- if module.params['port']:
- full_address = noport_address + ":" + module.params['port']
- else:
- full_address = noport_address
-
- address_list = array.get(syslogserver=True)['syslogserver']
- exists = False
-
- if address_list:
- for address in range(0, len(address_list)):
- if address_list[address] == full_address:
- exists = True
- break
- if not exists:
- try:
- address_list.append(full_address)
- array.set(syslogserver=address_list)
- changed = True
- except Exception:
- module.fail_json(msg='Failed to add syslog server: {0}'.format(full_address))
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- address=dict(type='str', required=True),
- protocol=dict(type='str', choices=['tcp', 'tls', 'udp'], required=True),
- port=dict(type='str'),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=False)
-
- array = get_system(module)
-
- if module.params['state'] == 'absent':
- delete_syslog(module, array)
- else:
- add_syslog(module, array)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_user.py b/lib/ansible/modules/storage/purestorage/purefa_user.py
deleted file mode 100644
index 5e687c3851..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_user.py
+++ /dev/null
@@ -1,222 +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_user
-version_added: '2.8'
-short_description: Create, modify or delete FlashArray local user account
-description:
-- Create, modify or delete local users on a Pure Storage FlashArray.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- state:
- description:
- - Create, delete or update local user account
- default: present
- type: str
- choices: [ absent, present ]
- name:
- description:
- - The name of the local user account
- type: str
- role:
- description:
- - Sets the local user's access level to the array
- type: str
- choices: [ readonly, storage_admin, array_admin ]
- password:
- description:
- - Password for the local user.
- type: str
- old_password:
- description:
- - If changing an existing password, you must provide the old password for security
- type: str
- api:
- description:
- - Define whether to create an API token for this user
- - Token can be exposed using the I(debug) module
- type: bool
- default: false
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create new user ansible with API token
- purefa_user:
- name: ansible
- password: apassword
- role: storage_admin
- api: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- register: result
-
- debug:
- msg: "API Token: {{ result['user_info']['user_api'] }}"
-
-- name: Change role type for existing user
- purefa_user:
- name: ansible
- role: array_admin
- state: update
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Change password type for existing user (NOT IDEMPOTENT)
- purefa_user:
- name: ansible
- password: anewpassword
- old_password: apassword
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Change API token for existing user
- purefa_user:
- name: ansible
- api: true
- state: update
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- register: result
-
- debug:
- msg: "API Token: {{ result['user_info']['user_api'] }}"
-'''
-
-RETURN = r'''
-'''
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-MIN_REQUIRED_API_VERSION = '1.14'
-
-
-def get_user(module, array):
- """Return Local User Account or None"""
- user = None
- users = array.list_admins()
- for acct in range(0, len(users)):
- if users[acct]['name'] == module.params['name']:
- user = users[acct]
- return user
-
-
-def create_user(module, array):
- """Create or Update Local User Account"""
- changed = False
- user = get_user(module, array)
- role = module.params['role']
- api_changed = False
- role_changed = False
- passwd_changed = False
- user_token = {}
- if not user:
- try:
- if not role:
- role = 'readonly'
- array.create_admin(module.params['name'], role=role,
- password=module.params['password'])
- if module.params['api']:
- try:
- user_token['user_api'] = array.create_api_token(module.params['name'])['api_token']
- except Exception:
- array.delete_user(module.params['name'])
- module.fail_json(msg='Local User {0}: Creation failed'.format(module.params['name']))
- changed = True
- except Exception:
- module.fail_json(msg='Local User {0}: Creation failed'.format(module.params['name']))
- else:
- if module.params['password'] and not module.params['old_password']:
- changed = False
- module.exit_json(changed=changed)
- if module.params['password'] and module.params['old_password']:
- if module.params['old_password'] and (module.params['password'] != module.params['old_password']):
- try:
- array.set_admin(module.params['name'], password=module.params['password'],
- old_password=module.params['old_password'])
- passwd_changed = True
- except Exception:
- module.fail_json(msg='Local User {0}: Password reset failed. '
- 'Check old password.'.format(module.params['name']))
- else:
- module.fail_json(msg='Local User Account {0}: Password change failed - '
- 'Check both old and new passwords'.format(module.params['name']))
- if module.params['api']:
- try:
- if not array.get_api_token(module.params['name'])['api_token'] is None:
- array.delete_api_token(module.params['name'])
- user_token['user_api'] = array.create_api_token(module.params['name'])['api_token']
- api_changed = True
- except Exception:
- module.fail_json(msg='Local User {0}: API token change failed'.format(module.params['name']))
- if module.params['role'] != user['role']:
- try:
- array.set_admin(module.params['name'], role=module.params['role'])
- role_changed = True
- except Exception:
- module.fail_json(msg='Local User {0}: Role changed failed'.format(module.params['name']))
- if passwd_changed or role_changed or api_changed:
- changed = True
- module.exit_json(changed=changed, user_info=user_token)
-
-
-def delete_user(module, array):
- """Delete Local User Account"""
- changed = False
- if get_user(module, array):
- try:
- array.delete_admin(module.params['name'])
- changed = True
- except Exception:
- module.fail_json(msg='Object Store Account {0}: Deletion failed'.format(module.params['name']))
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- name=dict(required=True, type='str'),
- role=dict(type='str', choices=['readonly', 'storage_admin', 'array_admin']),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- password=dict(type='str', no_log=True),
- old_password=dict(type='str', no_log=True),
- api=dict(type='bool', default=False),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=False)
-
- state = module.params['state']
- array = get_system(module)
- api_version = array._list_available_rest_versions()
-
- if MIN_REQUIRED_API_VERSION not in api_version:
- module.fail_json(msg='FlashArray REST version not supported. '
- 'Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
-
- if state == 'absent':
- delete_user(module, array)
- elif state == 'present':
- create_user(module, array)
- else:
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/storage/purestorage/purefa_vg.py b/lib/ansible/modules/storage/purestorage/purefa_vg.py
deleted file mode 100644
index 2bb3591b40..0000000000
--- a/lib/ansible/modules/storage/purestorage/purefa_vg.py
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, 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_vg
-version_added: '2.9'
-short_description: Manage volume groups on Pure Storage FlashArrays
-description:
-- Create, delete or modify volume groups on Pure Storage FlashArrays.
-author:
-- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
-options:
- vgroup:
- description:
- - The name of the volume group.
- type: str
- required: true
- state:
- description:
- - Define whether the volume group should exist or not.
- type: str
- default: present
- choices: [ absent, present ]
- eradicate:
- description:
- - Define whether to eradicate the volume group on delete and leave in trash.
- type : bool
- default: 'no'
-extends_documentation_fragment:
-- purestorage.fa
-'''
-
-EXAMPLES = r'''
-- name: Create new volume group
- purefa_vg:
- vgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Destroy volume group
- purefa_vg:
- vgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-
-- name: Recover deleted volume group
- purefa_vg:
- vgroup: foo
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
-
-- name: Destroy and Eradicate volume group
- purefa_vg:
- vgroup: foo
- eradicate: true
- fa_url: 10.10.10.2
- api_token: e31060a7-21fc-e277-6240-25983c6c4592
- state: absent
-'''
-
-RETURN = r'''
-'''
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.pure import get_system, purefa_argument_spec
-
-
-VGROUP_API_VERSION = '1.13'
-
-
-def get_pending_vgroup(module, array):
- """ Get Deleted Volume Group"""
- vgroup = None
- for vgrp in array.list_vgroups(pending=True):
- if vgrp["name"] == module.params['vgroup'] and vgrp['time_remaining']:
- vgroup = vgrp
- break
-
- return vgroup
-
-
-def get_vgroup(module, array):
- """ Get Volume Group"""
- vgroup = None
- for vgrp in array.list_vgroups():
- if vgrp["name"] == module.params['vgroup']:
- vgroup = vgrp
- break
-
- return vgroup
-
-
-def make_vgroup(module, array):
- """ Create Volume Group"""
- changed = True
- if not module.check_mode:
- try:
- array.create_vgroup(module.params['vgroup'])
- except Exception:
- module.fail_json(msg='creation of volume group {0} failed.'.format(module.params['vgroup']))
-
- module.exit_json(changed=changed)
-
-
-def recover_vgroup(module, array):
- """ Recover Volume Group"""
- changed = True
- if not module.check_mode:
- try:
- array.recover_vgroup(module.params['vgroup'])
- except Exception:
- module.fail_json(msg='Recovery of volume group {0} failed.'.format(module.params['vgroup']))
-
- module.exit_json(changed=changed)
-
-
-def eradicate_vgroup(module, array):
- """ Eradicate Volume Group"""
- changed = True
- if not module.check_mode:
- try:
- array.eradicate_vgroup(module.params['vgroup'])
- except Exception:
- module.fail_json(msg='Eradicating vgroup {0} failed.'.format(module.params['vgroup']))
- module.exit_json(changed=changed)
-
-
-def delete_vgroup(module, array):
- """ Delete Volume Group"""
- changed = True
- if not module.check_mode:
- try:
- array.destroy_vgroup(module.params['vgroup'])
- except Exception:
- module.fail_json(msg='Deleting vgroup {0} failed.'.format(module.params['vgroup']))
- if module.params['eradicate']:
- eradicate_vgroup(module, array)
-
- module.exit_json(changed=changed)
-
-
-def main():
- argument_spec = purefa_argument_spec()
- argument_spec.update(dict(
- vgroup=dict(type='str', required=True),
- state=dict(type='str', default='present', choices=['absent', 'present']),
- eradicate=dict(type='bool', default=False),
- ))
-
- module = AnsibleModule(argument_spec,
- supports_check_mode=True)
-
- state = module.params['state']
- array = get_system(module)
- api_version = array._list_available_rest_versions()
- if VGROUP_API_VERSION not in api_version:
- module.fail_json(msg='API version does not support volume groups.')
-
- vgroup = get_vgroup(module, array)
- xvgroup = get_pending_vgroup(module, array)
-
- if xvgroup and state == 'present':
- recover_vgroup(module, array)
- elif vgroup and state == 'absent':
- delete_vgroup(module, array)
- elif xvgroup and state == 'absent' and module.params['eradicate']:
- eradicate_vgroup(module, array)
- elif not vgroup and not xvgroup and state == 'present':
- make_vgroup(module, array)
- elif vgroup is None and state == 'absent':
- module.exit_json(changed=False)
-
- module.exit_json(changed=False)
-
-
-if __name__ == '__main__':
- main()
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()
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index ef3fc3cf0a..78f741bf38 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -993,40 +993,6 @@ lib/ansible/modules/source_control/git.py validate-modules:parameter-type-not-in
lib/ansible/modules/source_control/subversion.py validate-modules:doc-required-mismatch
lib/ansible/modules/source_control/subversion.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/source_control/subversion.py validate-modules:undocumented-parameter
-lib/ansible/modules/storage/purestorage/purefa_alert.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_arrayname.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_banner.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_connect.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_dns.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_dns.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_ds.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_ds.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_dsrole.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_dsrole.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/storage/purestorage/purefa_hg.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_hg.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_host.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_host.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_info.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_info.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_info.py validate-modules:return-syntax-error
-lib/ansible/modules/storage/purestorage/purefa_ntp.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_ntp.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_offload.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_pg.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_pg.py validate-modules:parameter-list-no-elements
-lib/ansible/modules/storage/purestorage/purefa_pgsnap.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_pgsnap.py validate-modules:parameter-type-not-in-doc
-lib/ansible/modules/storage/purestorage/purefa_phonehome.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_ra.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_smtp.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_snap.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_snmp.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_syslog.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_user.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_vg.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_volume.py validate-modules:doc-required-mismatch
-lib/ansible/modules/storage/purestorage/purefa_volume.py validate-modules:mutually_exclusive-unknown
lib/ansible/modules/storage/purestorage/purefb_ds.py validate-modules:doc-required-mismatch
lib/ansible/modules/storage/purestorage/purefb_ds.py validate-modules:parameter-list-no-elements
lib/ansible/modules/storage/purestorage/purefb_dsrole.py validate-modules:doc-required-mismatch