Migrated to purestorage.flashblade
This commit is contained in:
parent
d9920706d7
commit
fe0f4750e1
13 changed files with 0 additions and 3104 deletions
|
@ -1,216 +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 = '''
|
|
||||||
---
|
|
||||||
module: purefb_bucket
|
|
||||||
version_added: "2.8"
|
|
||||||
short_description: Manage Object Store Buckets on a Pure Storage FlashBlade.
|
|
||||||
description:
|
|
||||||
- This module managess object store (s3) buckets on Pure Storage FlashBlade.
|
|
||||||
author: Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- Bucket Name.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
account:
|
|
||||||
description:
|
|
||||||
- Object Store Account for Bucket.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create, delete or modifies a bucket.
|
|
||||||
required: false
|
|
||||||
default: present
|
|
||||||
type: str
|
|
||||||
choices: [ "present", "absent" ]
|
|
||||||
eradicate:
|
|
||||||
description:
|
|
||||||
- Define whether to eradicate the bucket on delete or leave in trash.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
- name: Create new bucket named foo in account bar
|
|
||||||
purefb_bucket:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Delete bucket named foo in account bar
|
|
||||||
purefb_bucket:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Recover deleted bucket named foo in account bar
|
|
||||||
purefb_bucket:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Eradicate bucket named foo in account bar
|
|
||||||
purefb_bucket:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
state: absent
|
|
||||||
eradicate: true
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = '''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import Bucket, Reference
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = '1.5'
|
|
||||||
|
|
||||||
|
|
||||||
def get_s3acc(module, blade):
|
|
||||||
"""Return Object Store Account or None"""
|
|
||||||
s3acc = None
|
|
||||||
accts = blade.object_store_accounts.list_object_store_accounts()
|
|
||||||
for acct in range(0, len(accts.items)):
|
|
||||||
if accts.items[acct].name == module.params['account']:
|
|
||||||
s3acc = accts.items[acct]
|
|
||||||
return s3acc
|
|
||||||
|
|
||||||
|
|
||||||
def get_bucket(module, blade):
|
|
||||||
"""Return Bucket or None"""
|
|
||||||
s3bucket = None
|
|
||||||
buckets = blade.buckets.list_buckets()
|
|
||||||
for bucket in range(0, len(buckets.items)):
|
|
||||||
if buckets.items[bucket].name == module.params['name']:
|
|
||||||
s3bucket = buckets.items[bucket]
|
|
||||||
return s3bucket
|
|
||||||
|
|
||||||
|
|
||||||
def create_bucket(module, blade):
|
|
||||||
"""Create bucket"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
attr = Bucket()
|
|
||||||
attr.account = Reference(name=module.params['account'])
|
|
||||||
blade.buckets.create_buckets(names=[module.params['name']], account=attr)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Bucket {0}: Creation failed'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_bucket(module, blade):
|
|
||||||
""" Delete Bucket"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
blade.buckets.update_buckets(names=[module.params['name']],
|
|
||||||
destroyed=Bucket(destroyed=True))
|
|
||||||
changed = True
|
|
||||||
if module.params['eradicate']:
|
|
||||||
try:
|
|
||||||
blade.buckets.delete_buckets(names=[module.params['name']])
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Bucket {0}: Eradication failed'.format(module.params['name']))
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Bucket {0}: Deletion failed'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def recover_bucket(module, blade):
|
|
||||||
""" Recover Bucket"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
blade.buckets.update_buckets(names=[module.params['name']],
|
|
||||||
destroyed=Bucket(destroyed=False))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Bucket {0}: Recovery failed'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def eradicate_bucket(module, blade):
|
|
||||||
""" Eradicate Bucket"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
blade.buckets.delete_buckets(names=[module.params['name']])
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Bucket {0}: Eradication failed'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(
|
|
||||||
dict(
|
|
||||||
name=dict(required=True),
|
|
||||||
account=dict(required=True),
|
|
||||||
eradicate=dict(default='false', type='bool'),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if MIN_REQUIRED_API_VERSION not in api_version:
|
|
||||||
module.fail_json(msg="Purity//FB must be upgraded to support this module.")
|
|
||||||
bucket = get_bucket(module, blade)
|
|
||||||
if not get_s3acc(module, blade):
|
|
||||||
module.fail_json(msg="Object Store Account {0} does not exist.".format(module.params['account']))
|
|
||||||
|
|
||||||
if state == 'present' and not bucket:
|
|
||||||
create_bucket(module, blade)
|
|
||||||
elif state == 'present' and bucket and bucket.destroyed:
|
|
||||||
recover_bucket(module, blade)
|
|
||||||
elif state == 'absent' and bucket and not bucket.destroyed:
|
|
||||||
delete_bucket(module, blade)
|
|
||||||
elif state == 'absent' and bucket and bucket.destroyed and module.params['eradicate']:
|
|
||||||
eradicate_bucket(module, blade)
|
|
||||||
elif state == 'absent' and not bucket:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,347 +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: purefb_ds
|
|
||||||
version_added: '2.8'
|
|
||||||
short_description: Configure FlashBlade Directory Service
|
|
||||||
description:
|
|
||||||
- Create or erase directory services configurations. There is no facility
|
|
||||||
to SSL certificates at this time. Use the FlashBlade 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:
|
|
||||||
description:
|
|
||||||
- Create or delete directory service configuration
|
|
||||||
default: present
|
|
||||||
type: str
|
|
||||||
choices: [ absent, present ]
|
|
||||||
dstype:
|
|
||||||
description:
|
|
||||||
- The type of directory service to work on
|
|
||||||
choices: [ management, nfs, smb ]
|
|
||||||
type: str
|
|
||||||
enable:
|
|
||||||
description:
|
|
||||||
- Whether to enable or disable directory service support.
|
|
||||||
default: false
|
|
||||||
type: bool
|
|
||||||
uri:
|
|
||||||
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.
|
|
||||||
type: list
|
|
||||||
base_dn:
|
|
||||||
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
|
|
||||||
type: str
|
|
||||||
bind_password:
|
|
||||||
description:
|
|
||||||
- Sets the password of the bind_user user name account.
|
|
||||||
type: str
|
|
||||||
bind_user:
|
|
||||||
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.
|
|
||||||
type: str
|
|
||||||
nis_servers:
|
|
||||||
description:
|
|
||||||
- A list of up to 30 IP addresses or FQDNs for NIS servers.
|
|
||||||
- This cannot be used in conjunction with LDAP configurations.
|
|
||||||
type: list
|
|
||||||
version_added: 2.9
|
|
||||||
nis_domain:
|
|
||||||
description:
|
|
||||||
- The NIS domain to search
|
|
||||||
- This cannot be used in conjunction with LDAP configurations.
|
|
||||||
type: str
|
|
||||||
version_added: 2.9
|
|
||||||
join_ou:
|
|
||||||
description:
|
|
||||||
- The optional organizational unit (OU) where the machine account
|
|
||||||
for the directory service will be created.
|
|
||||||
type: str
|
|
||||||
version_added: 2.9
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Delete existing management directory service
|
|
||||||
purefb_ds:
|
|
||||||
dstype: management
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Create NFS directory service (disabled)
|
|
||||||
purefb_ds:
|
|
||||||
dstype: nfs
|
|
||||||
uri: "ldaps://lab.purestorage.com"
|
|
||||||
base_dn: "DC=lab,DC=purestorage,DC=com"
|
|
||||||
bind_user: Administrator
|
|
||||||
bind_password: password
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Enable existing SMB directory service
|
|
||||||
purefb_ds:
|
|
||||||
dstypr: smb
|
|
||||||
enable: true
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Disable existing management directory service
|
|
||||||
purefb_ds:
|
|
||||||
dstype: management
|
|
||||||
enable: false
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Create NFS directory service (enabled)
|
|
||||||
purefb_ds:
|
|
||||||
dstype: nfs
|
|
||||||
enable: true
|
|
||||||
uri: "ldaps://lab.purestorage.com"
|
|
||||||
base_dn: "DC=lab,DC=purestorage,DC=com"
|
|
||||||
bind_user: Administrator
|
|
||||||
bind_password: password
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
NIS_API_VERSION = '1.7'
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import DirectoryService
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
def update_ds(module, blade):
|
|
||||||
"""Update Directory Service"""
|
|
||||||
# This module is a place-holder until we figure out a way to
|
|
||||||
# update the config on the fly rather than deleting and resetting
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def enable_ds(module, blade):
|
|
||||||
"""Enable Directory Service"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
blade.directory_services.update_directory_services(names=[module.params['dstype']],
|
|
||||||
directory_service=DirectoryService(enabled=True))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Enable {0} Directory Service failed: Check Configuration'.format(module.params['dstype']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def disable_ds(module, blade):
|
|
||||||
"""Disable Directory Service"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
blade.directory_services.update_directory_services(names=[module.params['dstype']],
|
|
||||||
directory_service=DirectoryService(enabled=False))
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Disable {0} Directory Service failed'.format(module.params['dstype']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_ds(module, blade):
|
|
||||||
"""Delete Directory Service"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
dirserv = blade.directory_services.list_directory_services(names=[module.params['dstype']])
|
|
||||||
try:
|
|
||||||
if module.params['dstype'] == 'management':
|
|
||||||
if dirserv.items[0].uris:
|
|
||||||
dir_service = DirectoryService(uris=[''],
|
|
||||||
base_dn="",
|
|
||||||
bind_user="",
|
|
||||||
bind_password="",
|
|
||||||
enabled=False)
|
|
||||||
else:
|
|
||||||
changed = False
|
|
||||||
elif module.params['dstype'] == 'smb':
|
|
||||||
if dirserv.items[0].uris:
|
|
||||||
smb_attrs = {'join_ou': ''}
|
|
||||||
dir_service = DirectoryService(uris=[''],
|
|
||||||
base_dn='',
|
|
||||||
bind_user='',
|
|
||||||
bind_password='',
|
|
||||||
smb=smb_attrs,
|
|
||||||
enabled=False)
|
|
||||||
else:
|
|
||||||
changed = False
|
|
||||||
elif module.params['dstype'] == 'nfs':
|
|
||||||
if dirserv.items[0].uris:
|
|
||||||
dir_service = DirectoryService(uris=[''],
|
|
||||||
base_dn='',
|
|
||||||
bind_user='',
|
|
||||||
bind_password='',
|
|
||||||
enabled=False)
|
|
||||||
elif dirserv.items[0].nfs.nis_domains:
|
|
||||||
nfs_attrs = {'nis_domains': [],
|
|
||||||
'nis_servers': []}
|
|
||||||
dir_service = DirectoryService(nfs=nfs_attrs,
|
|
||||||
enabled=False)
|
|
||||||
else:
|
|
||||||
changed = False
|
|
||||||
if changed:
|
|
||||||
blade.directory_services.update_directory_services(names=[module.params['dstype']],
|
|
||||||
directory_service=dir_service)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Delete {0} Directory Service failed'.format(module.params['dstype']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def create_ds(module, blade):
|
|
||||||
"""Create Directory Service"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
if module.params['dstype'] == 'management':
|
|
||||||
if module.params['uri']:
|
|
||||||
dir_service = DirectoryService(uris=module.params['uri'][0:30],
|
|
||||||
base_dn=module.params['base_dn'],
|
|
||||||
bind_user=module.params['bind_user'],
|
|
||||||
bind_password=module.params['bind_password'],
|
|
||||||
enabled=module.params['enable'])
|
|
||||||
else:
|
|
||||||
module.fail_json(msg="URI and associated params must be specified to create dstype {0}".format(module.params['dstype']))
|
|
||||||
elif module.params['dstype'] == 'smb':
|
|
||||||
if module.params['uri']:
|
|
||||||
smb_attrs = {'join_ou': module.params['join_ou']}
|
|
||||||
dir_service = DirectoryService(uris=module.params['uri'][0:30],
|
|
||||||
base_dn=module.params['base_dn'],
|
|
||||||
bind_user=module.params['bind_user'],
|
|
||||||
bind_password=module.params['bind_password'],
|
|
||||||
smb=smb_attrs,
|
|
||||||
enabled=module.params['enable'])
|
|
||||||
else:
|
|
||||||
module.fail_json(msg="URI and associated params must be specified to create dstype {0}".format(module.params['dstype']))
|
|
||||||
elif module.params['dstype'] == 'nfs':
|
|
||||||
if module.params['nis_domain']:
|
|
||||||
nfs_attrs = {'nis_domains': [module.params['nis_domain']],
|
|
||||||
'nis_servers': module.params['nis_servers'][0:30]}
|
|
||||||
dir_service = DirectoryService(nfs=nfs_attrs,
|
|
||||||
enabled=module.params['enable'])
|
|
||||||
else:
|
|
||||||
dir_service = DirectoryService(uris=module.params['uri'][0:30],
|
|
||||||
base_dn=module.params['base_dn'],
|
|
||||||
bind_user=module.params['bind_user'],
|
|
||||||
bind_password=module.params['bind_password'],
|
|
||||||
enabled=module.params['enable'])
|
|
||||||
blade.directory_services.update_directory_services(names=[module.params['dstype']],
|
|
||||||
directory_service=dir_service)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Create {0} Directory Service failed: Check configuration'.format(module.params['dstype']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
uri=dict(type='list'),
|
|
||||||
dstype=dict(required=True, type='str', choices=['management', 'nfs', 'smb']),
|
|
||||||
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'),
|
|
||||||
join_ou=dict(type='str'),
|
|
||||||
nis_domain=dict(type='str'),
|
|
||||||
nis_servers=dict(type='list'),
|
|
||||||
))
|
|
||||||
|
|
||||||
required_together = [['uri', 'bind_password', 'bind_user', 'base_dn'],
|
|
||||||
['nis_servers', 'nis_domain'],
|
|
||||||
['join_ou', 'uri']]
|
|
||||||
mutually_exclusive = [['uri', 'nis_domain']]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
required_together=required_together,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
ds_configured = False
|
|
||||||
dirserv = blade.directory_services.list_directory_services(names=[module.params['dstype']])
|
|
||||||
ds_enabled = dirserv.items[0].enabled
|
|
||||||
if dirserv.items[0].base_dn is not None:
|
|
||||||
ds_configured = True
|
|
||||||
if (module.params['nis_domain'] or module.params['join_ou']) and (NIS_API_VERSION not in api_version):
|
|
||||||
module.fail_json(msg="NFS or SMB directory service attributes are not supported in your FlashBlade Purity version.")
|
|
||||||
ldap_uri = False
|
|
||||||
set_ldap = False
|
|
||||||
for uri in range(0, len(dirserv.items[0].uris)):
|
|
||||||
if "ldap" in dirserv.items[0].uris[uri].lower():
|
|
||||||
ldap_uri = True
|
|
||||||
if module.params['uri']:
|
|
||||||
for uri in range(0, len(module.params['uri'])):
|
|
||||||
if "ldap" in module.params['uri'][uri].lower():
|
|
||||||
set_ldap = True
|
|
||||||
if not module.params['uri'] and ldap_uri or \
|
|
||||||
module.params['uri'] and set_ldap:
|
|
||||||
if module.params['nis_servers'] or module.params['nis_domain']:
|
|
||||||
module.fail_json(msg="NIS configuration not supported in an LDAP environment")
|
|
||||||
if state == 'absent':
|
|
||||||
delete_ds(module, blade)
|
|
||||||
elif ds_configured and module.params['enable'] and ds_enabled:
|
|
||||||
update_ds(module, blade)
|
|
||||||
elif ds_configured and not module.params['enable'] and ds_enabled:
|
|
||||||
disable_ds(module, blade)
|
|
||||||
elif ds_configured and module.params['enable'] and not ds_enabled:
|
|
||||||
enable_ds(module, blade)
|
|
||||||
# Now we have enabled the DS lets make sure there aren't any new updates...
|
|
||||||
update_ds(module, blade)
|
|
||||||
elif not ds_configured and state == 'present':
|
|
||||||
create_ds(module, blade)
|
|
||||||
else:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,176 +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: purefb_dsrole
|
|
||||||
version_added: '2.8'
|
|
||||||
short_description: Configure FlashBlade Management Directory Service Roles
|
|
||||||
description:
|
|
||||||
- Set or erase directory services role configurations.
|
|
||||||
author:
|
|
||||||
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create or delete directory service role
|
|
||||||
default: present
|
|
||||||
type: str
|
|
||||||
choices: [ absent, present ]
|
|
||||||
role:
|
|
||||||
description:
|
|
||||||
- The directory service role to work on
|
|
||||||
choices: [ array_admin, ops_admin, readonly, storage_admin ]
|
|
||||||
type: str
|
|
||||||
group_base:
|
|
||||||
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.
|
|
||||||
type: str
|
|
||||||
group:
|
|
||||||
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.
|
|
||||||
type: str
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Delete existing array_admin directory service role
|
|
||||||
purefb_dsrole:
|
|
||||||
role: array_admin
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Create array_admin directory service role
|
|
||||||
purefb_dsrole:
|
|
||||||
role: array_admin
|
|
||||||
group_base: "OU=PureGroups,OU=SANManagers"
|
|
||||||
group: pureadmins
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Update ops_admin directory service role
|
|
||||||
purefb_dsrole:
|
|
||||||
role: ops_admin
|
|
||||||
group_base: "OU=PureGroups"
|
|
||||||
group: opsgroup
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import DirectoryServiceRole
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
def update_role(module, blade):
|
|
||||||
"""Update Directory Service Role"""
|
|
||||||
changed = False
|
|
||||||
role = blade.directory_services.list_directory_services_roles(names=[module.params['role']])
|
|
||||||
if role.items[0].group_base != module.params['group_base'] or role.items[0].group != module.params['group']:
|
|
||||||
try:
|
|
||||||
role = DirectoryServiceRole(group_base=module.params['group_base'],
|
|
||||||
group=module.params['group'])
|
|
||||||
blade.directory_services.update_directory_services_roles(names=[module.params['role']],
|
|
||||||
directory_service_role=role)
|
|
||||||
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, blade):
|
|
||||||
"""Delete Directory Service Role"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
role = DirectoryServiceRole(group_base='',
|
|
||||||
group='')
|
|
||||||
blade.directory_services.update_directory_services_roles(names=[module.params['role']],
|
|
||||||
directory_service_role=role)
|
|
||||||
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, blade):
|
|
||||||
"""Create Directory Service Role"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
role = DirectoryServiceRole(group_base=module.params['group_base'],
|
|
||||||
group=module.params['group'])
|
|
||||||
blade.directory_services.update_directory_services_roles(names=[module.params['role']],
|
|
||||||
directory_service_role=role)
|
|
||||||
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 = purefb_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)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
role_configured = False
|
|
||||||
role = blade.directory_services.list_directory_services_roles(names=[module.params['role']])
|
|
||||||
if role.items[0].group is not None:
|
|
||||||
role_configured = True
|
|
||||||
|
|
||||||
if state == 'absent' and role_configured:
|
|
||||||
delete_role(module, blade)
|
|
||||||
elif role_configured and state == 'present':
|
|
||||||
update_role(module, blade)
|
|
||||||
elif not role_configured and state == 'present':
|
|
||||||
create_role(module, blade)
|
|
||||||
else:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,438 +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 = '''
|
|
||||||
---
|
|
||||||
module: purefb_fs
|
|
||||||
version_added: "2.6"
|
|
||||||
short_description: Manage filesystemon Pure Storage FlashBlade`
|
|
||||||
description:
|
|
||||||
- This module manages filesystems on Pure Storage FlashBlade.
|
|
||||||
author: Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- Filesystem Name.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create, delete or modifies a filesystem.
|
|
||||||
required: false
|
|
||||||
default: present
|
|
||||||
type: str
|
|
||||||
choices: [ "present", "absent" ]
|
|
||||||
eradicate:
|
|
||||||
description:
|
|
||||||
- Define whether to eradicate the filesystem on delete or leave in trash.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
size:
|
|
||||||
description:
|
|
||||||
- Volume size in M, G, T or P units. See examples.
|
|
||||||
type: str
|
|
||||||
required: false
|
|
||||||
default: 32G
|
|
||||||
nfsv3:
|
|
||||||
description:
|
|
||||||
- Define whether to NFSv3 protocol is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: true
|
|
||||||
version_added: 2.9
|
|
||||||
nfsv4:
|
|
||||||
description:
|
|
||||||
- Define whether to NFSv4.1 protocol is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: true
|
|
||||||
version_added: 2.9
|
|
||||||
nfs_rules:
|
|
||||||
description:
|
|
||||||
- Define the NFS rules in operation.
|
|
||||||
required: false
|
|
||||||
default: '*(rw,no_root_squash)'
|
|
||||||
type: str
|
|
||||||
smb:
|
|
||||||
description:
|
|
||||||
- Define whether to SMB protocol is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
http:
|
|
||||||
description:
|
|
||||||
- Define whether to HTTP/HTTPS protocol is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
snapshot:
|
|
||||||
description:
|
|
||||||
- Define whether a snapshot directory is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
fastremove:
|
|
||||||
description:
|
|
||||||
- Define whether the fast remove directory is enabled for the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
hard_limit:
|
|
||||||
description:
|
|
||||||
- Define whether the capacity for a filesystem is a hard limit.
|
|
||||||
- CAUTION This will cause the filesystem to go Read-Only if the
|
|
||||||
capacity has already exceeded the logical size of the filesystem.
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
version_added: 2.8
|
|
||||||
user_quota:
|
|
||||||
description:
|
|
||||||
- Default quota in M, G, T or P units for a user under this file system.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
version_added: 2.9
|
|
||||||
group_quota:
|
|
||||||
description:
|
|
||||||
- Default quota in M, G, T or P units for a group under this file system.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
version_added: 2.9
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
- name: Create new filesystem named foo
|
|
||||||
purefb_fs:
|
|
||||||
name: foo
|
|
||||||
size: 1T
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Delete filesystem named foo
|
|
||||||
purefb_fs:
|
|
||||||
name: foo
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Recover filesystem named foo
|
|
||||||
purefb_fs:
|
|
||||||
name: foo
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Eradicate filesystem named foo
|
|
||||||
purefb_fs:
|
|
||||||
name: foo
|
|
||||||
state: absent
|
|
||||||
eradicate: true
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Modify attributes of an existing filesystem named foo
|
|
||||||
purefb_fs:
|
|
||||||
name: foo
|
|
||||||
size: 2T
|
|
||||||
nfsv3 : false
|
|
||||||
nfsv4 : true
|
|
||||||
user_quota: 10K
|
|
||||||
group_quota: 25M
|
|
||||||
nfs_rules: '*(ro)'
|
|
||||||
snapshot: true
|
|
||||||
fastremove: true
|
|
||||||
hard_limit: true
|
|
||||||
smb: true
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641'''
|
|
||||||
|
|
||||||
RETURN = '''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import FileSystem, ProtocolRule, NfsRule
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, human_to_bytes
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
HARD_LIMIT_API_VERSION = '1.4'
|
|
||||||
NFSV4_API_VERSION = '1.6'
|
|
||||||
|
|
||||||
|
|
||||||
def get_fs(module, blade):
|
|
||||||
"""Return Filesystem or None"""
|
|
||||||
fsys = []
|
|
||||||
fsys.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
res = blade.file_systems.list_file_systems(names=fsys)
|
|
||||||
return res.items[0]
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_fs(module, blade):
|
|
||||||
"""Create Filesystem"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
|
|
||||||
if not module.params['size']:
|
|
||||||
module.params['size'] = '32G'
|
|
||||||
|
|
||||||
size = human_to_bytes(module.params['size'])
|
|
||||||
|
|
||||||
if module.params['user_quota']:
|
|
||||||
user_quota = human_to_bytes(module.params['user_quota'])
|
|
||||||
else:
|
|
||||||
user_quota = None
|
|
||||||
if module.params['group_quota']:
|
|
||||||
group_quota = human_to_bytes(module.params['group_quota'])
|
|
||||||
else:
|
|
||||||
group_quota = None
|
|
||||||
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if HARD_LIMIT_API_VERSION in api_version:
|
|
||||||
if NFSV4_API_VERSION in api_version:
|
|
||||||
fs_obj = FileSystem(name=module.params['name'],
|
|
||||||
provisioned=size,
|
|
||||||
fast_remove_directory_enabled=module.params['fastremove'],
|
|
||||||
hard_limit_enabled=module.params['hard_limit'],
|
|
||||||
snapshot_directory_enabled=module.params['snapshot'],
|
|
||||||
nfs=NfsRule(v3_enabled=module.params['nfsv3'],
|
|
||||||
v4_1_enabled=module.params['nfsv4'],
|
|
||||||
rules=module.params['nfs_rules']),
|
|
||||||
smb=ProtocolRule(enabled=module.params['smb']),
|
|
||||||
http=ProtocolRule(enabled=module.params['http']),
|
|
||||||
default_user_quota=user_quota,
|
|
||||||
default_group_quota=group_quota
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
fs_obj = FileSystem(name=module.params['name'],
|
|
||||||
provisioned=size,
|
|
||||||
fast_remove_directory_enabled=module.params['fastremove'],
|
|
||||||
hard_limit_enabled=module.params['hard_limit'],
|
|
||||||
snapshot_directory_enabled=module.params['snapshot'],
|
|
||||||
nfs=NfsRule(enabled=module.params['nfsv3'], rules=module.params['nfs_rules']),
|
|
||||||
smb=ProtocolRule(enabled=module.params['smb']),
|
|
||||||
http=ProtocolRule(enabled=module.params['http'])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
fs_obj = FileSystem(name=module.params['name'],
|
|
||||||
provisioned=size,
|
|
||||||
fast_remove_directory_enabled=module.params['fastremove'],
|
|
||||||
snapshot_directory_enabled=module.params['snapshot'],
|
|
||||||
nfs=NfsRule(enabled=module.params['nfsv3'], rules=module.params['nfs_rules']),
|
|
||||||
smb=ProtocolRule(enabled=module.params['smb']),
|
|
||||||
http=ProtocolRule(enabled=module.params['http'])
|
|
||||||
)
|
|
||||||
blade.file_systems.create_file_systems(fs_obj)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg="Failed to create filesystem {0}.".format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def modify_fs(module, blade):
|
|
||||||
"""Modify Filesystem"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
mod_fs = False
|
|
||||||
attr = {}
|
|
||||||
if module.params['user_quota']:
|
|
||||||
user_quota = human_to_bytes(module.params['user_quota'])
|
|
||||||
if module.params['group_quota']:
|
|
||||||
group_quota = human_to_bytes(module.params['group_quota'])
|
|
||||||
fsys = get_fs(module, blade)
|
|
||||||
if fsys.destroyed:
|
|
||||||
attr['destroyed'] = False
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['size']:
|
|
||||||
if human_to_bytes(module.params['size']) != fsys.provisioned:
|
|
||||||
attr['provisioned'] = human_to_bytes(module.params['size'])
|
|
||||||
mod_fs = True
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if NFSV4_API_VERSION in api_version:
|
|
||||||
if module.params['nfsv3'] and not fsys.nfs.v3_enabled:
|
|
||||||
attr['nfs'] = NfsRule(v3_enabled=module.params['nfsv3'])
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['nfsv3'] and fsys.nfs.v3_enabled:
|
|
||||||
attr['nfs'] = NfsRule(v3_enabled=module.params['nfsv3'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['nfsv4'] and not fsys.nfs.v4_1_enabled:
|
|
||||||
attr['nfs'] = NfsRule(v4_1_enabled=module.params['nfsv4'])
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['nfsv4'] and fsys.nfs.v4_1_enabled:
|
|
||||||
attr['nfs'] = NfsRule(v4_1_enabled=module.params['nfsv4'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['nfsv3'] or module.params['nfsv4'] and fsys.nfs.v3_enabled or fsys.nfs.v4_1_enabled:
|
|
||||||
if fsys.nfs.rules != module.params['nfs_rules']:
|
|
||||||
attr['nfs'] = NfsRule(rules=module.params['nfs_rules'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['user_quota'] and user_quota != fsys.default_user_quota:
|
|
||||||
attr['default_user_quota'] = user_quota
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['group_quota'] and group_quota != fsys.default_group_quota:
|
|
||||||
attr['default_group_quota'] = group_quota
|
|
||||||
mod_fs = True
|
|
||||||
else:
|
|
||||||
if module.params['nfsv3'] and not fsys.nfs.enabled:
|
|
||||||
attr['nfs'] = NfsRule(enabled=module.params['nfsv3'])
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['nfsv3'] and fsys.nfs.enabled:
|
|
||||||
attr['nfs'] = NfsRule(enabled=module.params['nfsv3'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['nfsv3'] and fsys.nfs.enabled:
|
|
||||||
if fsys.nfs.rules != module.params['nfs_rules']:
|
|
||||||
attr['nfs'] = NfsRule(rules=module.params['nfs_rules'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['smb'] and not fsys.smb.enabled:
|
|
||||||
attr['smb'] = ProtocolRule(enabled=module.params['smb'])
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['smb'] and fsys.smb.enabled:
|
|
||||||
attr['smb'] = ProtocolRule(enabled=module.params['smb'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['http'] and not fsys.http.enabled:
|
|
||||||
attr['http'] = ProtocolRule(enabled=module.params['http'])
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['http'] and fsys.http.enabled:
|
|
||||||
attr['http'] = ProtocolRule(enabled=module.params['http'])
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['snapshot'] and not fsys.snapshot_directory_enabled:
|
|
||||||
attr['snapshot_directory_enabled'] = module.params['snapshot']
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['snapshot'] and fsys.snapshot_directory_enabled:
|
|
||||||
attr['snapshot_directory_enabled'] = module.params['snapshot']
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['fastremove'] and not fsys.fast_remove_directory_enabled:
|
|
||||||
attr['fast_remove_directory_enabled'] = module.params['fastremove']
|
|
||||||
mod_fs = True
|
|
||||||
if not module.params['fastremove'] and fsys.fast_remove_directory_enabled:
|
|
||||||
attr['fast_remove_directory_enabled'] = module.params['fastremove']
|
|
||||||
mod_fs = True
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if HARD_LIMIT_API_VERSION in api_version:
|
|
||||||
if not module.params['hard_limit'] and fsys.hard_limit_enabled:
|
|
||||||
attr['hard_limit_enabled'] = module.params['hard_limit']
|
|
||||||
mod_fs = True
|
|
||||||
if module.params['hard_limit'] and not fsys.hard_limit_enabled:
|
|
||||||
attr['hard_limit_enabled'] = module.params['hard_limit']
|
|
||||||
mod_fs = True
|
|
||||||
if mod_fs:
|
|
||||||
n_attr = FileSystem(**attr)
|
|
||||||
try:
|
|
||||||
blade.file_systems.update_file_systems(name=module.params['name'], attributes=n_attr)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg="Failed to update filesystem {0}.".format(module.params['name']))
|
|
||||||
else:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_fs(module, blade):
|
|
||||||
""" Delete Filesystem"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if NFSV4_API_VERSION in api_version:
|
|
||||||
blade.file_systems.update_file_systems(name=module.params['name'],
|
|
||||||
attributes=FileSystem(nfs=NfsRule(v3_enabled=False,
|
|
||||||
v4_1_enabled=False),
|
|
||||||
smb=ProtocolRule(enabled=False),
|
|
||||||
http=ProtocolRule(enabled=False),
|
|
||||||
destroyed=True)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
blade.file_systems.update_file_systems(name=module.params['name'],
|
|
||||||
attributes=FileSystem(nfs=NfsRule(enabled=False),
|
|
||||||
smb=ProtocolRule(enabled=False),
|
|
||||||
http=ProtocolRule(enabled=False),
|
|
||||||
destroyed=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
if module.params['eradicate']:
|
|
||||||
try:
|
|
||||||
blade.file_systems.delete_file_systems(module.params['name'])
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg="Failed to delete filesystem {0}.".format(module.params['name']))
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg="Failed to update filesystem {0} prior to deletion.".format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def eradicate_fs(module, blade):
|
|
||||||
""" Eradicate Filesystem"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
try:
|
|
||||||
blade.file_systems.delete_file_systems(module.params['name'])
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg="Failed to eradicate filesystem {0}.".format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(
|
|
||||||
dict(
|
|
||||||
name=dict(required=True),
|
|
||||||
eradicate=dict(default='false', type='bool'),
|
|
||||||
nfsv3=dict(default='true', type='bool'),
|
|
||||||
nfsv4=dict(default='true', type='bool'),
|
|
||||||
nfs_rules=dict(default='*(rw,no_root_squash)'),
|
|
||||||
smb=dict(default='false', type='bool'),
|
|
||||||
http=dict(default='false', type='bool'),
|
|
||||||
snapshot=dict(default='false', type='bool'),
|
|
||||||
fastremove=dict(default='false', type='bool'),
|
|
||||||
hard_limit=dict(default='false', type='bool'),
|
|
||||||
user_quota=dict(type='str'),
|
|
||||||
group_quota=dict(type='str'),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
size=dict()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
fsys = get_fs(module, blade)
|
|
||||||
|
|
||||||
if state == 'present' and not fsys:
|
|
||||||
create_fs(module, blade)
|
|
||||||
elif state == 'present' and fsys:
|
|
||||||
modify_fs(module, blade)
|
|
||||||
elif state == 'absent' and fsys and not fsys.destroyed:
|
|
||||||
delete_fs(module, blade)
|
|
||||||
elif state == 'absent' and fsys and fsys.destroyed and module.params['eradicate']:
|
|
||||||
eradicate_fs(module, blade)
|
|
||||||
elif state == 'absent' and not fsys:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,663 +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: purefb_info
|
|
||||||
version_added: '2.9'
|
|
||||||
short_description: Collect information from Pure Storage FlashBlade
|
|
||||||
description:
|
|
||||||
- Collect information from a Pure Storage FlashBlade running the
|
|
||||||
Purity//FB 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, subnets, lags, filesystems and snapshots.
|
|
||||||
required: false
|
|
||||||
type: list
|
|
||||||
default: minimum
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: collect default set of info
|
|
||||||
purefb_info:
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
register: blade_info
|
|
||||||
- name: show default information
|
|
||||||
debug:
|
|
||||||
msg: "{{ blade_info['purefb_info']['default'] }}"
|
|
||||||
|
|
||||||
- name: collect configuration and capacity info
|
|
||||||
purefb_info:
|
|
||||||
gather_subset:
|
|
||||||
- config
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
register: blade_info
|
|
||||||
- name: show config information
|
|
||||||
debug:
|
|
||||||
msg: "{{ blade_info['purefb_info']['config'] }}"
|
|
||||||
|
|
||||||
- name: collect all info
|
|
||||||
purefb_info:
|
|
||||||
gather_subset:
|
|
||||||
- all
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
register: blade_info
|
|
||||||
- name: show all information
|
|
||||||
debug:
|
|
||||||
msg: "{{ blade_info['purefb_info'] }}"
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
purefb_info:
|
|
||||||
description: Returns the information collected from the FlashBlade
|
|
||||||
returned: always
|
|
||||||
type: complex
|
|
||||||
sample: {
|
|
||||||
"capacity": {
|
|
||||||
"aggregate": {
|
|
||||||
"data_reduction": 1.1179228,
|
|
||||||
"snapshots": 0,
|
|
||||||
"total_physical": 17519748439,
|
|
||||||
"unique": 17519748439,
|
|
||||||
"virtual": 19585726464
|
|
||||||
},
|
|
||||||
"file-system": {
|
|
||||||
"data_reduction": 1.3642412,
|
|
||||||
"snapshots": 0,
|
|
||||||
"total_physical": 4748219708,
|
|
||||||
"unique": 4748219708,
|
|
||||||
"virtual": 6477716992
|
|
||||||
},
|
|
||||||
"object-store": {
|
|
||||||
"data_reduction": 1.0263462,
|
|
||||||
"snapshots": 0,
|
|
||||||
"total_physical": 12771528731,
|
|
||||||
"unique": 12771528731,
|
|
||||||
"virtual": 6477716992
|
|
||||||
},
|
|
||||||
"total": 83359896948925
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"alert_watchers": {
|
|
||||||
"enabled": true,
|
|
||||||
"name": "notify@acmestorage.com"
|
|
||||||
},
|
|
||||||
"array_management": {
|
|
||||||
"base_dn": null,
|
|
||||||
"bind_password": null,
|
|
||||||
"bind_user": null,
|
|
||||||
"enabled": false,
|
|
||||||
"name": "management",
|
|
||||||
"services": [
|
|
||||||
"management"
|
|
||||||
],
|
|
||||||
"uris": []
|
|
||||||
},
|
|
||||||
"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": "demo.acmestorage.com",
|
|
||||||
"name": "demo-fb-1",
|
|
||||||
"nameservers": [
|
|
||||||
"8.8.8.8"
|
|
||||||
],
|
|
||||||
"search": [
|
|
||||||
"demo.acmestorage.com"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nfs_directory_service": {
|
|
||||||
"base_dn": null,
|
|
||||||
"bind_password": null,
|
|
||||||
"bind_user": null,
|
|
||||||
"enabled": false,
|
|
||||||
"name": "nfs",
|
|
||||||
"services": [
|
|
||||||
"nfs"
|
|
||||||
],
|
|
||||||
"uris": []
|
|
||||||
},
|
|
||||||
"ntp": [
|
|
||||||
"0.ntp.pool.org"
|
|
||||||
],
|
|
||||||
"smb_directory_service": {
|
|
||||||
"base_dn": null,
|
|
||||||
"bind_password": null,
|
|
||||||
"bind_user": null,
|
|
||||||
"enabled": false,
|
|
||||||
"name": "smb",
|
|
||||||
"services": [
|
|
||||||
"smb"
|
|
||||||
],
|
|
||||||
"uris": []
|
|
||||||
},
|
|
||||||
"smtp": {
|
|
||||||
"name": "demo-fb-1",
|
|
||||||
"relay_host": null,
|
|
||||||
"sender_domain": "acmestorage.com"
|
|
||||||
},
|
|
||||||
"ssl_certs": {
|
|
||||||
"certificate": "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----",
|
|
||||||
"common_name": "Acme Storage",
|
|
||||||
"country": "US",
|
|
||||||
"email": null,
|
|
||||||
"intermediate_certificate": null,
|
|
||||||
"issued_by": "Acme Storage",
|
|
||||||
"issued_to": "Acme Storage",
|
|
||||||
"key_size": 4096,
|
|
||||||
"locality": null,
|
|
||||||
"name": "global",
|
|
||||||
"organization": "Acme Storage",
|
|
||||||
"organizational_unit": "Acme Storage",
|
|
||||||
"passphrase": null,
|
|
||||||
"private_key": null,
|
|
||||||
"state": null,
|
|
||||||
"status": "self-signed",
|
|
||||||
"valid_from": "1508433967000",
|
|
||||||
"valid_to": "2458833967000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"blades": 15,
|
|
||||||
"buckets": 7,
|
|
||||||
"filesystems": 2,
|
|
||||||
"flashblade_name": "demo-fb-1",
|
|
||||||
"object_store_accounts": 1,
|
|
||||||
"object_store_users": 1,
|
|
||||||
"purity_version": "2.2.0",
|
|
||||||
"snapshots": 1,
|
|
||||||
"total_capacity": 83359896948925
|
|
||||||
},
|
|
||||||
"filesystems": {
|
|
||||||
"k8s-pvc-d24b1357-579e-11e8-811f-ecf4bbc88f54": {
|
|
||||||
"destroyed": false,
|
|
||||||
"fast_remove": false,
|
|
||||||
"hard_limit": true,
|
|
||||||
"nfs_rules": "*(rw,no_root_squash)",
|
|
||||||
"provisioned": 21474836480,
|
|
||||||
"snapshot_enabled": false
|
|
||||||
},
|
|
||||||
"z": {
|
|
||||||
"destroyed": false,
|
|
||||||
"fast_remove": false,
|
|
||||||
"hard_limit": false,
|
|
||||||
"provisioned": 1073741824,
|
|
||||||
"snapshot_enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lag": {
|
|
||||||
"uplink": {
|
|
||||||
"lag_speed": 0,
|
|
||||||
"port_speed": 40000000000,
|
|
||||||
"ports": [
|
|
||||||
{
|
|
||||||
"name": "CH1.FM1.ETH1.1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CH1.FM1.ETH1.2"
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"status": "healthy"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"fm1.admin0": {
|
|
||||||
"address": "10.10.100.6",
|
|
||||||
"gateway": "10.10.100.1",
|
|
||||||
"mtu": 1500,
|
|
||||||
"netmask": "255.255.255.0",
|
|
||||||
"services": [
|
|
||||||
"support"
|
|
||||||
],
|
|
||||||
"type": "vip",
|
|
||||||
"vlan": 2200
|
|
||||||
},
|
|
||||||
"fm2.admin0": {
|
|
||||||
"address": "10.10.100.7",
|
|
||||||
"gateway": "10.10.100.1",
|
|
||||||
"mtu": 1500,
|
|
||||||
"netmask": "255.255.255.0",
|
|
||||||
"services": [
|
|
||||||
"support"
|
|
||||||
],
|
|
||||||
"type": "vip",
|
|
||||||
"vlan": 2200
|
|
||||||
},
|
|
||||||
"nfs1": {
|
|
||||||
"address": "10.10.100.4",
|
|
||||||
"gateway": "10.10.100.1",
|
|
||||||
"mtu": 1500,
|
|
||||||
"netmask": "255.255.255.0",
|
|
||||||
"services": [
|
|
||||||
"data"
|
|
||||||
],
|
|
||||||
"type": "vip",
|
|
||||||
"vlan": 2200
|
|
||||||
},
|
|
||||||
"vir0": {
|
|
||||||
"address": "10.10.100.5",
|
|
||||||
"gateway": "10.10.100.1",
|
|
||||||
"mtu": 1500,
|
|
||||||
"netmask": "255.255.255.0",
|
|
||||||
"services": [
|
|
||||||
"management"
|
|
||||||
],
|
|
||||||
"type": "vip",
|
|
||||||
"vlan": 2200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"performance": {
|
|
||||||
"aggregate": {
|
|
||||||
"bytes_per_op": 0,
|
|
||||||
"bytes_per_read": 0,
|
|
||||||
"bytes_per_write": 0,
|
|
||||||
"read_bytes_per_sec": 0,
|
|
||||||
"reads_per_sec": 0,
|
|
||||||
"usec_per_other_op": 0,
|
|
||||||
"usec_per_read_op": 0,
|
|
||||||
"usec_per_write_op": 0,
|
|
||||||
"write_bytes_per_sec": 0,
|
|
||||||
"writes_per_sec": 0
|
|
||||||
},
|
|
||||||
"http": {
|
|
||||||
"bytes_per_op": 0,
|
|
||||||
"bytes_per_read": 0,
|
|
||||||
"bytes_per_write": 0,
|
|
||||||
"read_bytes_per_sec": 0,
|
|
||||||
"reads_per_sec": 0,
|
|
||||||
"usec_per_other_op": 0,
|
|
||||||
"usec_per_read_op": 0,
|
|
||||||
"usec_per_write_op": 0,
|
|
||||||
"write_bytes_per_sec": 0,
|
|
||||||
"writes_per_sec": 0
|
|
||||||
},
|
|
||||||
"nfs": {
|
|
||||||
"bytes_per_op": 0,
|
|
||||||
"bytes_per_read": 0,
|
|
||||||
"bytes_per_write": 0,
|
|
||||||
"read_bytes_per_sec": 0,
|
|
||||||
"reads_per_sec": 0,
|
|
||||||
"usec_per_other_op": 0,
|
|
||||||
"usec_per_read_op": 0,
|
|
||||||
"usec_per_write_op": 0,
|
|
||||||
"write_bytes_per_sec": 0,
|
|
||||||
"writes_per_sec": 0
|
|
||||||
},
|
|
||||||
"s3": {
|
|
||||||
"bytes_per_op": 0,
|
|
||||||
"bytes_per_read": 0,
|
|
||||||
"bytes_per_write": 0,
|
|
||||||
"read_bytes_per_sec": 0,
|
|
||||||
"reads_per_sec": 0,
|
|
||||||
"usec_per_other_op": 0,
|
|
||||||
"usec_per_read_op": 0,
|
|
||||||
"usec_per_write_op": 0,
|
|
||||||
"write_bytes_per_sec": 0,
|
|
||||||
"writes_per_sec": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"snapshots": {
|
|
||||||
"z.188": {
|
|
||||||
"destroyed": false,
|
|
||||||
"source": "z",
|
|
||||||
"source_destroyed": false,
|
|
||||||
"suffix": "188"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"subnet": {
|
|
||||||
"new-mgmt": {
|
|
||||||
"gateway": "10.10.100.1",
|
|
||||||
"interfaces": [
|
|
||||||
{
|
|
||||||
"name": "fm1.admin0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fm2.admin0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "nfs1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "vir0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lag": "uplink",
|
|
||||||
"mtu": 1500,
|
|
||||||
"prefix": "10.10.100.0/24",
|
|
||||||
"services": [
|
|
||||||
"data",
|
|
||||||
"management",
|
|
||||||
"support"
|
|
||||||
],
|
|
||||||
"vlan": 2200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = '1.3'
|
|
||||||
HARD_LIMIT_API_VERSION = '1.4'
|
|
||||||
|
|
||||||
|
|
||||||
def generate_default_dict(blade):
|
|
||||||
default_info = {}
|
|
||||||
defaults = blade.arrays.list_arrays().items[0]
|
|
||||||
default_info['flashblade_name'] = defaults.name
|
|
||||||
default_info['purity_version'] = defaults.version
|
|
||||||
default_info['filesystems'] = \
|
|
||||||
len(blade.file_systems.list_file_systems().items)
|
|
||||||
default_info['snapshots'] = \
|
|
||||||
len(blade.file_system_snapshots.list_file_system_snapshots().items)
|
|
||||||
default_info['buckets'] = len(blade.buckets.list_buckets().items)
|
|
||||||
default_info['object_store_users'] = \
|
|
||||||
len(blade.object_store_users.list_object_store_users().items)
|
|
||||||
default_info['object_store_accounts'] = \
|
|
||||||
len(blade.object_store_accounts.list_object_store_accounts().items)
|
|
||||||
default_info['blades'] = len(blade.blade.list_blades().items)
|
|
||||||
default_info['total_capacity'] = \
|
|
||||||
blade.arrays.list_arrays_space().items[0].capacity
|
|
||||||
return default_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_perf_dict(blade):
|
|
||||||
perf_info = {}
|
|
||||||
total_perf = blade.arrays.list_arrays_performance()
|
|
||||||
http_perf = blade.arrays.list_arrays_performance(protocol='http')
|
|
||||||
s3_perf = blade.arrays.list_arrays_performance(protocol='s3')
|
|
||||||
nfs_perf = blade.arrays.list_arrays_performance(protocol='nfs')
|
|
||||||
perf_info['aggregate'] = {
|
|
||||||
'bytes_per_op': total_perf.items[0].bytes_per_op,
|
|
||||||
'bytes_per_read': total_perf.items[0].bytes_per_read,
|
|
||||||
'bytes_per_write': total_perf.items[0].bytes_per_write,
|
|
||||||
'read_bytes_per_sec': total_perf.items[0].read_bytes_per_sec,
|
|
||||||
'reads_per_sec': total_perf.items[0].reads_per_sec,
|
|
||||||
'usec_per_other_op': total_perf.items[0].usec_per_other_op,
|
|
||||||
'usec_per_read_op': total_perf.items[0].usec_per_read_op,
|
|
||||||
'usec_per_write_op': total_perf.items[0].usec_per_write_op,
|
|
||||||
'write_bytes_per_sec': total_perf.items[0].write_bytes_per_sec,
|
|
||||||
'writes_per_sec': total_perf.items[0].writes_per_sec,
|
|
||||||
}
|
|
||||||
perf_info['http'] = {
|
|
||||||
'bytes_per_op': http_perf.items[0].bytes_per_op,
|
|
||||||
'bytes_per_read': http_perf.items[0].bytes_per_read,
|
|
||||||
'bytes_per_write': http_perf.items[0].bytes_per_write,
|
|
||||||
'read_bytes_per_sec': http_perf.items[0].read_bytes_per_sec,
|
|
||||||
'reads_per_sec': http_perf.items[0].reads_per_sec,
|
|
||||||
'usec_per_other_op': http_perf.items[0].usec_per_other_op,
|
|
||||||
'usec_per_read_op': http_perf.items[0].usec_per_read_op,
|
|
||||||
'usec_per_write_op': http_perf.items[0].usec_per_write_op,
|
|
||||||
'write_bytes_per_sec': http_perf.items[0].write_bytes_per_sec,
|
|
||||||
'writes_per_sec': http_perf.items[0].writes_per_sec,
|
|
||||||
}
|
|
||||||
perf_info['s3'] = {
|
|
||||||
'bytes_per_op': s3_perf.items[0].bytes_per_op,
|
|
||||||
'bytes_per_read': s3_perf.items[0].bytes_per_read,
|
|
||||||
'bytes_per_write': s3_perf.items[0].bytes_per_write,
|
|
||||||
'read_bytes_per_sec': s3_perf.items[0].read_bytes_per_sec,
|
|
||||||
'reads_per_sec': s3_perf.items[0].reads_per_sec,
|
|
||||||
'usec_per_other_op': s3_perf.items[0].usec_per_other_op,
|
|
||||||
'usec_per_read_op': s3_perf.items[0].usec_per_read_op,
|
|
||||||
'usec_per_write_op': s3_perf.items[0].usec_per_write_op,
|
|
||||||
'write_bytes_per_sec': s3_perf.items[0].write_bytes_per_sec,
|
|
||||||
'writes_per_sec': s3_perf.items[0].writes_per_sec,
|
|
||||||
}
|
|
||||||
perf_info['nfs'] = {
|
|
||||||
'bytes_per_op': nfs_perf.items[0].bytes_per_op,
|
|
||||||
'bytes_per_read': nfs_perf.items[0].bytes_per_read,
|
|
||||||
'bytes_per_write': nfs_perf.items[0].bytes_per_write,
|
|
||||||
'read_bytes_per_sec': nfs_perf.items[0].read_bytes_per_sec,
|
|
||||||
'reads_per_sec': nfs_perf.items[0].reads_per_sec,
|
|
||||||
'usec_per_other_op': nfs_perf.items[0].usec_per_other_op,
|
|
||||||
'usec_per_read_op': nfs_perf.items[0].usec_per_read_op,
|
|
||||||
'usec_per_write_op': nfs_perf.items[0].usec_per_write_op,
|
|
||||||
'write_bytes_per_sec': nfs_perf.items[0].write_bytes_per_sec,
|
|
||||||
'writes_per_sec': nfs_perf.items[0].writes_per_sec,
|
|
||||||
}
|
|
||||||
|
|
||||||
return perf_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_config_dict(blade):
|
|
||||||
config_info = {}
|
|
||||||
config_info['dns'] = blade.dns.list_dns().items[0].to_dict()
|
|
||||||
config_info['smtp'] = blade.smtp.list_smtp().items[0].to_dict()
|
|
||||||
config_info['alert_watchers'] = \
|
|
||||||
blade.alert_watchers.list_alert_watchers().items[0].to_dict()
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if HARD_LIMIT_API_VERSION in api_version:
|
|
||||||
config_info['array_management'] = \
|
|
||||||
blade.directory_services.list_directory_services(names=['management']).items[0].to_dict()
|
|
||||||
config_info['directory_service_roles'] = {}
|
|
||||||
roles = blade.directory_services.list_directory_services_roles()
|
|
||||||
for role in range(0, len(roles.items)):
|
|
||||||
role_name = roles.items[role].name
|
|
||||||
config_info['directory_service_roles'][role_name] = {
|
|
||||||
'group': roles.items[role].group,
|
|
||||||
'group_base': roles.items[role].group_base
|
|
||||||
}
|
|
||||||
config_info['nfs_directory_service'] = \
|
|
||||||
blade.directory_services.list_directory_services(names=['nfs']).items[0].to_dict()
|
|
||||||
config_info['smb_directory_service'] = \
|
|
||||||
blade.directory_services.list_directory_services(names=['smb']).items[0].to_dict()
|
|
||||||
config_info['ntp'] = blade.arrays.list_arrays().items[0].ntp_servers
|
|
||||||
config_info['ssl_certs'] = \
|
|
||||||
blade.certificates.list_certificates().items[0].to_dict()
|
|
||||||
return config_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_subnet_dict(blade):
|
|
||||||
sub_info = {}
|
|
||||||
subnets = blade.subnets.list_subnets()
|
|
||||||
for sub in range(0, len(subnets.items)):
|
|
||||||
sub_name = subnets.items[sub].name
|
|
||||||
if subnets.items[sub].enabled:
|
|
||||||
sub_info[sub_name] = {
|
|
||||||
'gateway': subnets.items[sub].gateway,
|
|
||||||
'mtu': subnets.items[sub].mtu,
|
|
||||||
'vlan': subnets.items[sub].vlan,
|
|
||||||
'prefix': subnets.items[sub].prefix,
|
|
||||||
'services': subnets.items[sub].services,
|
|
||||||
}
|
|
||||||
sub_info[sub_name]['lag'] = subnets.items[sub].link_aggregation_group.name
|
|
||||||
sub_info[sub_name]['interfaces'] = []
|
|
||||||
for iface in range(0, len(subnets.items[sub].interfaces)):
|
|
||||||
sub_info[sub_name]['interfaces'].append({'name': subnets.items[sub].interfaces[iface].name})
|
|
||||||
return sub_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_lag_dict(blade):
|
|
||||||
lag_info = {}
|
|
||||||
groups = blade.link_aggregation_groups.list_link_aggregation_groups()
|
|
||||||
for groupcnt in range(0, len(groups.items)):
|
|
||||||
lag_name = groups.items[groupcnt].name
|
|
||||||
lag_info[lag_name] = {
|
|
||||||
'lag_speed': groups.items[groupcnt].lag_speed,
|
|
||||||
'port_speed': groups.items[groupcnt].port_speed,
|
|
||||||
'status': groups.items[groupcnt].status,
|
|
||||||
}
|
|
||||||
lag_info[lag_name]['ports'] = []
|
|
||||||
for port in range(0, len(groups.items[groupcnt].ports)):
|
|
||||||
lag_info[lag_name]['ports'].append({'name': groups.items[groupcnt].ports[port].name})
|
|
||||||
return lag_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_network_dict(blade):
|
|
||||||
net_info = {}
|
|
||||||
ports = blade.network_interfaces.list_network_interfaces()
|
|
||||||
for portcnt in range(0, len(ports.items)):
|
|
||||||
int_name = ports.items[portcnt].name
|
|
||||||
if ports.items[portcnt].enabled:
|
|
||||||
net_info[int_name] = {
|
|
||||||
'type': ports.items[portcnt].type,
|
|
||||||
'mtu': ports.items[portcnt].mtu,
|
|
||||||
'vlan': ports.items[portcnt].vlan,
|
|
||||||
'address': ports.items[portcnt].address,
|
|
||||||
'services': ports.items[portcnt].services,
|
|
||||||
'gateway': ports.items[portcnt].gateway,
|
|
||||||
'netmask': ports.items[portcnt].netmask,
|
|
||||||
}
|
|
||||||
return net_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_capacity_dict(blade):
|
|
||||||
capacity_info = {}
|
|
||||||
total_cap = blade.arrays.list_arrays_space()
|
|
||||||
file_cap = blade.arrays.list_arrays_space(type='file-system')
|
|
||||||
object_cap = blade.arrays.list_arrays_space(type='object-store')
|
|
||||||
capacity_info['total'] = total_cap.items[0].capacity
|
|
||||||
capacity_info['aggregate'] = {
|
|
||||||
'data_reduction': total_cap.items[0].space.data_reduction,
|
|
||||||
'snapshots': total_cap.items[0].space.snapshots,
|
|
||||||
'total_physical': total_cap.items[0].space.total_physical,
|
|
||||||
'unique': total_cap.items[0].space.unique,
|
|
||||||
'virtual': total_cap.items[0].space.virtual,
|
|
||||||
}
|
|
||||||
capacity_info['file-system'] = {
|
|
||||||
'data_reduction': file_cap.items[0].space.data_reduction,
|
|
||||||
'snapshots': file_cap.items[0].space.snapshots,
|
|
||||||
'total_physical': file_cap.items[0].space.total_physical,
|
|
||||||
'unique': file_cap.items[0].space.unique,
|
|
||||||
'virtual': file_cap.items[0].space.virtual,
|
|
||||||
}
|
|
||||||
capacity_info['object-store'] = {
|
|
||||||
'data_reduction': object_cap.items[0].space.data_reduction,
|
|
||||||
'snapshots': object_cap.items[0].space.snapshots,
|
|
||||||
'total_physical': object_cap.items[0].space.total_physical,
|
|
||||||
'unique': object_cap.items[0].space.unique,
|
|
||||||
'virtual': file_cap.items[0].space.virtual,
|
|
||||||
}
|
|
||||||
|
|
||||||
return capacity_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_snap_dict(blade):
|
|
||||||
snap_info = {}
|
|
||||||
snaps = blade.file_system_snapshots.list_file_system_snapshots()
|
|
||||||
for snap in range(0, len(snaps.items)):
|
|
||||||
snapshot = snaps.items[snap].name
|
|
||||||
snap_info[snapshot] = {
|
|
||||||
'destroyed': snaps.items[snap].destroyed,
|
|
||||||
'source': snaps.items[snap].source,
|
|
||||||
'suffix': snaps.items[snap].suffix,
|
|
||||||
'source_destroyed': snaps.items[snap].source_destroyed,
|
|
||||||
}
|
|
||||||
return snap_info
|
|
||||||
|
|
||||||
|
|
||||||
def generate_fs_dict(blade):
|
|
||||||
fs_info = {}
|
|
||||||
fsys = blade.file_systems.list_file_systems()
|
|
||||||
for fsystem in range(0, len(fsys.items)):
|
|
||||||
share = fsys.items[fsystem].name
|
|
||||||
fs_info[share] = {
|
|
||||||
'fast_remove': fsys.items[fsystem].fast_remove_directory_enabled,
|
|
||||||
'snapshot_enabled': fsys.items[fsystem].snapshot_directory_enabled,
|
|
||||||
'provisioned': fsys.items[fsystem].provisioned,
|
|
||||||
'destroyed': fsys.items[fsystem].destroyed,
|
|
||||||
}
|
|
||||||
if fsys.items[fsystem].http.enabled:
|
|
||||||
fs_info[share]['http'] = fsys.items[fsystem].http.enabled
|
|
||||||
if fsys.items[fsystem].smb.enabled:
|
|
||||||
fs_info[share]['smb_mode'] = fsys.items[fsystem].smb.acl_mode
|
|
||||||
if fsys.items[fsystem].nfs.enabled:
|
|
||||||
fs_info[share]['nfs_rules'] = fsys.items[fsystem].nfs.rules
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if HARD_LIMIT_API_VERSION in api_version:
|
|
||||||
fs_info[share]['hard_limit'] = fsys.items[fsystem].hard_limit_enabled
|
|
||||||
|
|
||||||
return fs_info
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
gather_subset=dict(default='minimum', type='list',)
|
|
||||||
))
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec, supports_check_mode=True)
|
|
||||||
|
|
||||||
blade = get_blade(module)
|
|
||||||
versions = blade.api_version.list_versions().versions
|
|
||||||
|
|
||||||
if MIN_REQUIRED_API_VERSION not in versions:
|
|
||||||
module.fail_json(msg='FlashBlade REST version not supported. Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
|
|
||||||
|
|
||||||
subset = [test.lower() for test in module.params['gather_subset']]
|
|
||||||
valid_subsets = ('all', 'minimum', 'config', 'performance', 'capacity',
|
|
||||||
'network', 'subnets', 'lags',
|
|
||||||
'filesystems', 'snapshots')
|
|
||||||
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:
|
|
||||||
info['default'] = generate_default_dict(blade)
|
|
||||||
if 'performance' in subset or 'all' in subset:
|
|
||||||
info['performance'] = generate_perf_dict(blade)
|
|
||||||
if 'config' in subset or 'all' in subset:
|
|
||||||
info['config'] = generate_config_dict(blade)
|
|
||||||
if 'capacity' in subset or 'all' in subset:
|
|
||||||
info['capacity'] = generate_capacity_dict(blade)
|
|
||||||
if 'lags' in subset or 'all' in subset:
|
|
||||||
info['lag'] = generate_lag_dict(blade)
|
|
||||||
if 'network' in subset or 'all' in subset:
|
|
||||||
info['network'] = generate_network_dict(blade)
|
|
||||||
if 'subnets' in subset or 'all' in subset:
|
|
||||||
info['subnet'] = generate_subnet_dict(blade)
|
|
||||||
if 'filesystems' in subset or 'all' in subset:
|
|
||||||
info['filesystems'] = generate_fs_dict(blade)
|
|
||||||
if 'snapshots' in subset or 'all' in subset:
|
|
||||||
info['snapshots'] = generate_snap_dict(blade)
|
|
||||||
|
|
||||||
module.exit_json(changed=False, purefb_info=info)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,202 +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 = '''
|
|
||||||
---
|
|
||||||
module: purefb_network
|
|
||||||
version_added: "2.8"
|
|
||||||
short_description: Manage network interfaces in a Pure Storage FlashBlade
|
|
||||||
description:
|
|
||||||
- This module manages network interfaces on Pure Storage FlashBlade.
|
|
||||||
- When creating a network interface a subnet must already exist with
|
|
||||||
a network prefix that covers the IP address of the interface being
|
|
||||||
created.
|
|
||||||
author: Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- Interface Name.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create, delete or modifies a network interface.
|
|
||||||
required: false
|
|
||||||
default: present
|
|
||||||
choices: [ "present", "absent" ]
|
|
||||||
type: str
|
|
||||||
address:
|
|
||||||
description:
|
|
||||||
- IP address of interface.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
services:
|
|
||||||
description:
|
|
||||||
- Define which services are configured for the interfaces.
|
|
||||||
required: false
|
|
||||||
choices: [ "data" ]
|
|
||||||
default: data
|
|
||||||
type: str
|
|
||||||
itype:
|
|
||||||
description:
|
|
||||||
- Type of interface.
|
|
||||||
required: false
|
|
||||||
choices: [ "vip" ]
|
|
||||||
default: vip
|
|
||||||
type: str
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
- name: Create new network interface named foo
|
|
||||||
purefb_network:
|
|
||||||
name: foo
|
|
||||||
address: 10.21.200.23
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Change IP address of network interface named foo
|
|
||||||
purefb_network:
|
|
||||||
name: foo
|
|
||||||
state: present
|
|
||||||
address: 10.21.200.123
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Delete network interface named foo
|
|
||||||
purefb_network:
|
|
||||||
name: foo
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641'''
|
|
||||||
|
|
||||||
RETURN = '''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import NetworkInterface
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MINIMUM_API_VERSION = '1.3'
|
|
||||||
|
|
||||||
|
|
||||||
def get_iface(module, blade):
|
|
||||||
"""Return Filesystem or None"""
|
|
||||||
iface = []
|
|
||||||
iface.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
res = blade.network_interfaces.list_network_interfaces(names=iface)
|
|
||||||
return res.items[0]
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_iface(module, blade):
|
|
||||||
"""Create Network Interface"""
|
|
||||||
|
|
||||||
iface = []
|
|
||||||
services = []
|
|
||||||
iface.append(module.params['name'])
|
|
||||||
services.append(module.params['services'])
|
|
||||||
try:
|
|
||||||
blade.network_interfaces.create_network_interfaces(names=iface,
|
|
||||||
network_interface=NetworkInterface(address=module.params['address'],
|
|
||||||
services=services,
|
|
||||||
type=module.params['itype']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Interface creation failed. Check valid subnet exists for IP address {0}'.format(module.params['address']))
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def modify_iface(module, blade):
|
|
||||||
"""Modify Network Interface IP address"""
|
|
||||||
changed = False
|
|
||||||
iface = get_iface(module, blade)
|
|
||||||
iface_new = []
|
|
||||||
iface_new.append(module.params['name'])
|
|
||||||
if module.params['address'] != iface.address:
|
|
||||||
try:
|
|
||||||
blade.network_interfaces.update_network_interfaces(names=iface_new,
|
|
||||||
network_interface=NetworkInterface(address=module.params['address']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_iface(module, blade):
|
|
||||||
""" Delete Network Interface"""
|
|
||||||
iface = []
|
|
||||||
iface.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
blade.network_interfaces.delete_network_interfaces(names=iface)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(
|
|
||||||
dict(
|
|
||||||
name=dict(required=True),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
address=dict(),
|
|
||||||
services=dict(default='data', choices=['data']),
|
|
||||||
itype=dict(default='vip', choices=['vip']),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
required_if = [["state", "present", ["address"]]]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
required_if=required_if,
|
|
||||||
supports_check_mode=False)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if MINIMUM_API_VERSION not in api_version:
|
|
||||||
module.fail_json(msg='Upgrade Purity//FB to enable this module')
|
|
||||||
iface = get_iface(module, blade)
|
|
||||||
|
|
||||||
if state == 'present' and not iface:
|
|
||||||
create_iface(module, blade)
|
|
||||||
elif state == 'present' and iface:
|
|
||||||
modify_iface(module, blade)
|
|
||||||
elif state == 'absent' and iface:
|
|
||||||
delete_iface(module, blade)
|
|
||||||
elif state == 'absent' and not iface:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,114 +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: purefb_ra
|
|
||||||
version_added: '2.9'
|
|
||||||
short_description: Enable or Disable Pure Storage FlashBlade Remote Assist
|
|
||||||
description:
|
|
||||||
- Enable or Disable Remote Assist for a Pure Storage FlashBlade.
|
|
||||||
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: present
|
|
||||||
choices: [ present, absent ]
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Enable Remote Assist port
|
|
||||||
purefb_ra:
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-9f276a18-50ab-446e-8a0c-666a3529a1b6
|
|
||||||
|
|
||||||
- name: Disable Remote Assist port
|
|
||||||
purefb_ra:
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-9f276a18-50ab-446e-8a0c-666a3529a1b6
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import Support
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = "1.6"
|
|
||||||
|
|
||||||
|
|
||||||
def enable_ra(module, blade):
|
|
||||||
"""Enable Remote Assist"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
ra_settings = Support(remote_assist_active=True)
|
|
||||||
try:
|
|
||||||
blade.support.update_support(support=ra_settings)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Enabling Remote Assist failed')
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def disable_ra(module, blade):
|
|
||||||
"""Disable Remote Assist"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
ra_settings = Support(remote_assist_active=False)
|
|
||||||
try:
|
|
||||||
blade.support.update_support(support=ra_settings)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Disabling Remote Assist failed')
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
|
||||||
))
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if MIN_REQUIRED_API_VERSION not in api_version:
|
|
||||||
module.fail_json(msg="Purity//FB must be upgraded to support this module.")
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb SDK is required for this module')
|
|
||||||
|
|
||||||
if module.params['state'] == 'present' and not blade.support.list_support().items[0].remote_assist_active:
|
|
||||||
enable_ra(module, blade)
|
|
||||||
elif module.params['state'] == 'absent' and blade.support.list_support().items[0].remote_assist_active:
|
|
||||||
disable_ra(module, blade)
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,136 +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: purefb_s3acc
|
|
||||||
version_added: '2.8'
|
|
||||||
short_description: Create or delete FlashBlade Object Store accounts
|
|
||||||
description:
|
|
||||||
- Create or delete object store accounts on a Pure Storage FlashBlade.
|
|
||||||
author:
|
|
||||||
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create or delete object store account
|
|
||||||
default: present
|
|
||||||
choices: [ absent, present ]
|
|
||||||
type: str
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- The name of object store account
|
|
||||||
type: str
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Create object store account foo
|
|
||||||
purefb_s3acc:
|
|
||||||
name: foo
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
|
|
||||||
- name: Delete object store account foo
|
|
||||||
purefb_s3acc:
|
|
||||||
name: foo
|
|
||||||
state: absent
|
|
||||||
fb_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_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = '1.3'
|
|
||||||
|
|
||||||
|
|
||||||
def get_s3acc(module, blade):
|
|
||||||
"""Return Object Store Account or None"""
|
|
||||||
s3acc = None
|
|
||||||
accts = blade.object_store_accounts.list_object_store_accounts()
|
|
||||||
for acct in range(0, len(accts.items)):
|
|
||||||
if accts.items[acct].name == module.params['name']:
|
|
||||||
s3acc = accts.items[acct]
|
|
||||||
return s3acc
|
|
||||||
|
|
||||||
|
|
||||||
def update_s3acc(module, blade):
|
|
||||||
"""Update Object Store Account"""
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def create_s3acc(module, blade):
|
|
||||||
"""Create Object Store Account"""
|
|
||||||
changed = False
|
|
||||||
try:
|
|
||||||
blade.object_store_accounts.create_object_store_accounts(names=[module.params['name']])
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store Account {0}: Creation failed'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_s3acc(module, blade):
|
|
||||||
"""Delete Object Store Account"""
|
|
||||||
changed = False
|
|
||||||
count = len(blade.object_store_users.list_object_store_users(filter='name=\'' + module.params['name'] + '/*\'').items)
|
|
||||||
if count != 0:
|
|
||||||
module.fail_json(msg='Remove all Users from Object Store Account {0} before deletion'.format(module.params['name']))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
blade.object_store_accounts.delete_object_store_accounts(names=[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 = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
name=dict(required=True, type='str'),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
))
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=False)
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
versions = blade.api_version.list_versions().versions
|
|
||||||
|
|
||||||
if MIN_REQUIRED_API_VERSION not in versions:
|
|
||||||
module.fail_json(msg='FlashBlade REST version not supported. Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
|
|
||||||
|
|
||||||
s3acc = get_s3acc(module, blade)
|
|
||||||
|
|
||||||
if state == 'absent' and s3acc:
|
|
||||||
delete_s3acc(module, blade)
|
|
||||||
elif state == 'present' and s3acc:
|
|
||||||
update_s3acc(module, blade)
|
|
||||||
elif not s3acc and state == 'present':
|
|
||||||
create_s3acc(module, blade)
|
|
||||||
else:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,201 +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: purefb_s3user
|
|
||||||
version_added: '2.8'
|
|
||||||
short_description: Create or delete FlashBlade Object Store account users
|
|
||||||
description:
|
|
||||||
- Create or delete object store account users on a Pure Storage FlashBlade.
|
|
||||||
author:
|
|
||||||
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create or delete object store account user
|
|
||||||
default: present
|
|
||||||
choices: [ absent, present ]
|
|
||||||
type: str
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- The name of object store user
|
|
||||||
type: str
|
|
||||||
account:
|
|
||||||
description:
|
|
||||||
- The name of object store account associated with user
|
|
||||||
type: str
|
|
||||||
access_key:
|
|
||||||
description:
|
|
||||||
- Create secret access key.
|
|
||||||
- Key can be exposed using the I(debug) module
|
|
||||||
type: bool
|
|
||||||
default: true
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Create object store user (with access ID and key) foo in account bar
|
|
||||||
purefb_s3user:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug:
|
|
||||||
msg: "S3 User: {{ result['s3user_info'] }}"
|
|
||||||
|
|
||||||
- name: Delete object store user foo in account bar
|
|
||||||
purefb_s3user:
|
|
||||||
name: foo
|
|
||||||
account: bar
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import ObjectStoreAccessKey
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = '1.3'
|
|
||||||
|
|
||||||
|
|
||||||
def get_s3acc(module, blade):
|
|
||||||
"""Return Object Store Account or None"""
|
|
||||||
s3acc = None
|
|
||||||
accts = blade.object_store_accounts.list_object_store_accounts()
|
|
||||||
for acct in range(0, len(accts.items)):
|
|
||||||
if accts.items[acct].name == module.params['account']:
|
|
||||||
s3acc = accts.items[acct]
|
|
||||||
return s3acc
|
|
||||||
|
|
||||||
|
|
||||||
def get_s3user(module, blade):
|
|
||||||
"""Return Object Store Account or None"""
|
|
||||||
full_user = module.params['account'] + "/" + module.params['name']
|
|
||||||
s3user = None
|
|
||||||
s3users = blade.object_store_users.list_object_store_users()
|
|
||||||
for user in range(0, len(s3users.items)):
|
|
||||||
if s3users.items[user].name == full_user:
|
|
||||||
s3user = s3users.items[user]
|
|
||||||
return s3user
|
|
||||||
|
|
||||||
|
|
||||||
def update_s3user(module, blade):
|
|
||||||
"""Update Object Store User"""
|
|
||||||
changed = False
|
|
||||||
s3user_facts = {}
|
|
||||||
user = module.params['account'] + "/" + module.params['name']
|
|
||||||
if module.params['access_key']:
|
|
||||||
try:
|
|
||||||
result = blade.object_store_access_keys.create_object_store_access_keys(
|
|
||||||
object_store_access_key=ObjectStoreAccessKey(user={'name': user}))
|
|
||||||
s3user_facts['fb_s3user'] = {'user': user,
|
|
||||||
'access_key': result.items[0].secret_access_key,
|
|
||||||
'access_id': result.items[0].name}
|
|
||||||
except Exception:
|
|
||||||
delete_s3user(module, blade)
|
|
||||||
module.fail_json(msg='Object Store User {0}: Creation failed'.format(user))
|
|
||||||
changed = True
|
|
||||||
module.exit_json(changed=changed, s3user_info=s3user_facts)
|
|
||||||
|
|
||||||
|
|
||||||
def create_s3user(module, blade):
|
|
||||||
"""Create Object Store Account"""
|
|
||||||
s3user_facts = {}
|
|
||||||
changed = False
|
|
||||||
user = module.params['account'] + "/" + module.params['name']
|
|
||||||
try:
|
|
||||||
blade.object_store_users.create_object_store_users(names=[user])
|
|
||||||
if module.params['access_key']:
|
|
||||||
try:
|
|
||||||
result = blade.object_store_access_keys.create_object_store_access_keys(
|
|
||||||
object_store_access_key=ObjectStoreAccessKey(user={'name': user}))
|
|
||||||
s3user_facts['fb_s3user'] = {'user': user,
|
|
||||||
'access_key': result.items[0].secret_access_key,
|
|
||||||
'access_id': result.items[0].name}
|
|
||||||
except Exception:
|
|
||||||
delete_s3user(module, blade)
|
|
||||||
module.fail_json(msg='Object Store User {0}: Creation failed'.format(user))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Object Store User {0}: Creation failed'.format(user))
|
|
||||||
module.exit_json(changed=changed, s3user_info=s3user_facts)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_s3user(module, blade):
|
|
||||||
"""Delete Object Store Account"""
|
|
||||||
changed = False
|
|
||||||
user = module.params['account'] + "/" + module.params['name']
|
|
||||||
try:
|
|
||||||
blade.object_store_users.delete_object_store_users(names=[user])
|
|
||||||
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 = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
name=dict(required=True, type='str'),
|
|
||||||
account=dict(required=True, type='str'),
|
|
||||||
access_key=dict(default='true', type='bool'),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
))
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=False)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
versions = blade.api_version.list_versions().versions
|
|
||||||
|
|
||||||
if MIN_REQUIRED_API_VERSION not in versions:
|
|
||||||
module.fail_json(msg='FlashBlade REST version not supported. Minimum version required: {0}'.format(MIN_REQUIRED_API_VERSION))
|
|
||||||
|
|
||||||
s3acc = get_s3acc(module, blade)
|
|
||||||
if not s3acc:
|
|
||||||
module.fail_json(msg='Object Store Account {0} does not exist'.format(module.params['account']))
|
|
||||||
|
|
||||||
s3user = get_s3user(module, blade)
|
|
||||||
|
|
||||||
if state == 'absent' and s3user:
|
|
||||||
delete_s3user(module, blade)
|
|
||||||
elif state == 'present' and s3user:
|
|
||||||
update_s3user(module, blade)
|
|
||||||
elif not s3user and state == 'present':
|
|
||||||
create_s3user(module, blade)
|
|
||||||
else:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,112 +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: purefb_smtp
|
|
||||||
version_added: '2.9'
|
|
||||||
short_description: Configure SMTP for Pure Storage FlashBlade
|
|
||||||
description:
|
|
||||||
- Configure SMTP for a Pure Storage FlashBlade.
|
|
||||||
- Whilst there can be no relay host, a sender domain must be configured.
|
|
||||||
author:
|
|
||||||
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
host:
|
|
||||||
description: Relay server name
|
|
||||||
type: str
|
|
||||||
domain:
|
|
||||||
description: Domain name for alert messages
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Configure SMTP settings
|
|
||||||
purefb_smtp:
|
|
||||||
host: hostname
|
|
||||||
domain: xyz.com
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-9f276a18-50ab-446e-8a0c-666a3529a1b6
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import Smtp
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MIN_REQUIRED_API_VERSION = "1.6"
|
|
||||||
|
|
||||||
|
|
||||||
def set_smtp(module, blade):
|
|
||||||
"""Configure SMTP settings"""
|
|
||||||
changed = True
|
|
||||||
if not module.check_mode:
|
|
||||||
current_smtp = blade.smtp.list_smtp().items[0]
|
|
||||||
if module.params['host'] and module.params['host'] != current_smtp.relay_host:
|
|
||||||
smtp_settings = Smtp(relay_host=module.params['host'])
|
|
||||||
try:
|
|
||||||
blade.smtp.update_smtp(smtp_settings=smtp_settings)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Configuring SMTP relay host failed')
|
|
||||||
elif current_smtp.relay_host and not module.params['host']:
|
|
||||||
smtp_settings = Smtp(relay_host='')
|
|
||||||
try:
|
|
||||||
blade.smtp.update_smtp(smtp_settings=smtp_settings)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Configuring SMTP relay host failed')
|
|
||||||
if module.params['domain'] != current_smtp.sender_domain:
|
|
||||||
smtp_settings = Smtp(sender_domain=module.params['domain'])
|
|
||||||
try:
|
|
||||||
blade.smtp.update_smtp(smtp_settings=smtp_settings)
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Configuring SMTP sender domain failed')
|
|
||||||
else:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(dict(
|
|
||||||
host=dict(type='str'),
|
|
||||||
domain=dict(type='str', required=True),
|
|
||||||
))
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if MIN_REQUIRED_API_VERSION not in api_version:
|
|
||||||
module.fail_json(msg="Purity//FB must be upgraded to support this module.")
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb SDK is required for this module')
|
|
||||||
|
|
||||||
set_smtp(module, blade)
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,227 +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: purefb_snap
|
|
||||||
version_added: '2.6'
|
|
||||||
short_description: Manage filesystem snapshots on Pure Storage FlashBlades
|
|
||||||
description:
|
|
||||||
- Create or delete volumes and filesystem snapshots on Pure Storage FlashBlades.
|
|
||||||
author:
|
|
||||||
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- The name of the source filesystem.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
suffix:
|
|
||||||
description:
|
|
||||||
- Suffix of snapshot name.
|
|
||||||
type: str
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Define whether the filesystem snapshot should exist or not.
|
|
||||||
choices: [ absent, present ]
|
|
||||||
default: present
|
|
||||||
type: str
|
|
||||||
eradicate:
|
|
||||||
description:
|
|
||||||
- Define whether to eradicate the snapshot on delete or leave in trash.
|
|
||||||
type: bool
|
|
||||||
default: 'no'
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Create snapshot foo.ansible
|
|
||||||
purefb_snap:
|
|
||||||
name: foo
|
|
||||||
suffix: ansible
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
fb_api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Delete snapshot named foo.snap
|
|
||||||
purefb_snap:
|
|
||||||
name: foo
|
|
||||||
suffix: snap
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
fb_api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Recover deleted snapshot foo.ansible
|
|
||||||
purefb_snap:
|
|
||||||
name: foo
|
|
||||||
suffix: ansible
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
fb_api_token: e31060a7-21fc-e277-6240-25983c6c4592
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Eradicate snapshot named foo.snap
|
|
||||||
purefb_snap:
|
|
||||||
name: foo
|
|
||||||
suffix: snap
|
|
||||||
eradicate: true
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
fb_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_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import FileSystemSnapshot, SnapshotSuffix
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
|
|
||||||
def get_fs(module, blade):
|
|
||||||
"""Return Filesystem or None"""
|
|
||||||
fs = []
|
|
||||||
fs.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
res = blade.file_systems.list_file_systems(names=fs)
|
|
||||||
return res.items[0]
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_fssnapshot(module, blade):
|
|
||||||
"""Return Snapshot or None"""
|
|
||||||
try:
|
|
||||||
filt = 'source=\'' + module.params['name'] + '\' and suffix=\'' + module.params['suffix'] + '\''
|
|
||||||
res = blade.file_system_snapshots.list_file_system_snapshots(filter=filt)
|
|
||||||
return res.items[0]
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_snapshot(module, blade):
|
|
||||||
"""Create Snapshot"""
|
|
||||||
if not module.check_mode:
|
|
||||||
source = []
|
|
||||||
source.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
blade.file_system_snapshots.create_file_system_snapshots(sources=source, suffix=SnapshotSuffix(module.params['suffix']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def recover_snapshot(module, blade):
|
|
||||||
"""Recover deleted Snapshot"""
|
|
||||||
if not module.check_mode:
|
|
||||||
snapname = module.params['name'] + "." + module.params['suffix']
|
|
||||||
new_attr = FileSystemSnapshot(destroyed=False)
|
|
||||||
try:
|
|
||||||
blade.file_system_snapshots.update_file_system_snapshots(name=snapname, attributes=new_attr)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def update_snapshot(module, blade):
|
|
||||||
"""Update Snapshot"""
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_snapshot(module, blade):
|
|
||||||
""" Delete Snapshot"""
|
|
||||||
if not module.check_mode:
|
|
||||||
snapname = module.params['name'] + "." + module.params['suffix']
|
|
||||||
new_attr = FileSystemSnapshot(destroyed=True)
|
|
||||||
try:
|
|
||||||
blade.file_system_snapshots.update_file_system_snapshots(name=snapname, attributes=new_attr)
|
|
||||||
changed = True
|
|
||||||
if module.params['eradicate']:
|
|
||||||
try:
|
|
||||||
blade.file_system_snapshots.delete_file_system_snapshots(name=snapname)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def eradicate_snapshot(module, blade):
|
|
||||||
""" Eradicate Snapshot"""
|
|
||||||
if not module.check_mode:
|
|
||||||
snapname = module.params['name'] + "." + module.params['suffix']
|
|
||||||
try:
|
|
||||||
blade.file_system_snapshots.delete_file_system_snapshots(name=snapname)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(
|
|
||||||
dict(
|
|
||||||
name=dict(required=True),
|
|
||||||
suffix=dict(type='str'),
|
|
||||||
eradicate=dict(default='false', type='bool'),
|
|
||||||
state=dict(default='present', choices=['present', 'absent'])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
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']
|
|
||||||
blade = get_blade(module)
|
|
||||||
fs = get_fs(module, blade)
|
|
||||||
snap = get_fssnapshot(module, blade)
|
|
||||||
|
|
||||||
if state == 'present' and fs and not fs.destroyed and not snap:
|
|
||||||
create_snapshot(module, blade)
|
|
||||||
elif state == 'present' and fs and not fs.destroyed and snap and not snap.destroyed:
|
|
||||||
update_snapshot(module, blade)
|
|
||||||
elif state == 'present' and fs and not fs.destroyed and snap and snap.destroyed:
|
|
||||||
recover_snapshot(module, blade)
|
|
||||||
elif state == 'present' and fs and fs.destroyed:
|
|
||||||
update_snapshot(module, blade)
|
|
||||||
elif state == 'present' and not fs:
|
|
||||||
update_snapshot(module, blade)
|
|
||||||
elif state == 'absent' and snap and not snap.destroyed:
|
|
||||||
delete_snapshot(module, blade)
|
|
||||||
elif state == 'absent' and snap and snap.destroyed:
|
|
||||||
eradicate_snapshot(module, blade)
|
|
||||||
elif state == 'absent' and not snap:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,264 +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 = '''
|
|
||||||
---
|
|
||||||
module: purefb_subnet
|
|
||||||
version_added: "2.8"
|
|
||||||
short_description: Manage network subnets in a Pure Storage FlashBlade
|
|
||||||
description:
|
|
||||||
- This module manages network subnets on Pure Storage FlashBlade.
|
|
||||||
author: Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
|
|
||||||
options:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- Subnet Name.
|
|
||||||
required: true
|
|
||||||
type: str
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Create, delete or modifies a subnet.
|
|
||||||
required: false
|
|
||||||
default: present
|
|
||||||
choices: [ "present", "absent" ]
|
|
||||||
type: str
|
|
||||||
gateway:
|
|
||||||
description:
|
|
||||||
- IPv4 or IPv6 address of subnet gateway.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
mtu:
|
|
||||||
description:
|
|
||||||
- MTU size of the subnet. Range is 1280 to 9216.
|
|
||||||
required: false
|
|
||||||
default: 1500
|
|
||||||
type: int
|
|
||||||
prefix:
|
|
||||||
description:
|
|
||||||
- IPv4 or IPv6 address associated with the subnet.
|
|
||||||
- Supply the prefix length (CIDR) as well as the IP address.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
vlan:
|
|
||||||
description:
|
|
||||||
- VLAN ID of the subnet.
|
|
||||||
required: false
|
|
||||||
default: 0
|
|
||||||
type: int
|
|
||||||
extends_documentation_fragment:
|
|
||||||
- purestorage.fb
|
|
||||||
notes:
|
|
||||||
- Requires the netaddr Python package on the host.
|
|
||||||
requirements:
|
|
||||||
- netaddr
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
- name: Create new network subnet named foo
|
|
||||||
purefb_subnet:
|
|
||||||
name: foo
|
|
||||||
prefix: "10.21.200.3/24"
|
|
||||||
gateway: 10.21.200.1
|
|
||||||
mtu: 9000
|
|
||||||
vlan: 2200
|
|
||||||
state: present
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Change configuration of existing subnet foo
|
|
||||||
purefb_network:
|
|
||||||
name: foo
|
|
||||||
state: present
|
|
||||||
prefix: "10.21.100.3/24"
|
|
||||||
gateway: 10.21.100.1
|
|
||||||
mtu: 1500
|
|
||||||
address: 10.21.200.123
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641
|
|
||||||
|
|
||||||
- name: Delete network subnet named foo
|
|
||||||
purefb_subnet:
|
|
||||||
name: foo
|
|
||||||
state: absent
|
|
||||||
fb_url: 10.10.10.2
|
|
||||||
api_token: T-55a68eb5-c785-4720-a2ca-8b03903bf641'''
|
|
||||||
|
|
||||||
RETURN = '''
|
|
||||||
'''
|
|
||||||
|
|
||||||
HAS_PURITY_FB = True
|
|
||||||
try:
|
|
||||||
from purity_fb import Subnet
|
|
||||||
except ImportError:
|
|
||||||
HAS_PURITY_FB = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
import netaddr
|
|
||||||
HAS_NETADDR = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_NETADDR = False
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.pure import get_blade, purefb_argument_spec
|
|
||||||
|
|
||||||
|
|
||||||
MINIMUM_API_VERSION = '1.3'
|
|
||||||
|
|
||||||
|
|
||||||
def get_subnet(module, blade):
|
|
||||||
"""Return Subnet or None"""
|
|
||||||
subnet = []
|
|
||||||
subnet.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
res = blade.subnets.list_subnets(names=subnet)
|
|
||||||
return res.items[0]
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def create_subnet(module, blade):
|
|
||||||
"""Create Subnet"""
|
|
||||||
|
|
||||||
subnet = []
|
|
||||||
subnet.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
blade.subnets.create_subnets(names=subnet,
|
|
||||||
subnet=Subnet(prefix=module.params['prefix'],
|
|
||||||
vlan=module.params['vlan'],
|
|
||||||
mtu=module.params['mtu'],
|
|
||||||
gateway=module.params['gateway']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Failed to create subnet {0}. Confirm supplied parameters'.format(module.params['name']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def modify_subnet(module, blade):
|
|
||||||
"""Modify Subnet settings"""
|
|
||||||
changed = False
|
|
||||||
subnet = get_subnet(module, blade)
|
|
||||||
subnet_new = []
|
|
||||||
subnet_new.append(module.params['name'])
|
|
||||||
if module.params['prefix']:
|
|
||||||
if module.params['prefix'] != subnet.prefix:
|
|
||||||
try:
|
|
||||||
blade.subnets.update_subnets(names=subnet_new,
|
|
||||||
subnet=Subnet(prefix=module.params['prefix']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Failed to change subnet {0} prefix to {1}'.format(module.params['name'],
|
|
||||||
module.params['prefix']))
|
|
||||||
if module.params['vlan']:
|
|
||||||
if module.params['vlan'] != subnet.vlan:
|
|
||||||
try:
|
|
||||||
blade.subnets.update_subnets(names=subnet_new,
|
|
||||||
subnet=Subnet(vlan=module.params['vlan']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Failed to change subnet {0} VLAN to {1}'.format(module.params['name'],
|
|
||||||
module.params['vlan']))
|
|
||||||
if module.params['gateway']:
|
|
||||||
if module.params['gateway'] != subnet.gateway:
|
|
||||||
try:
|
|
||||||
blade.subnets.update_subnets(names=subnet_new,
|
|
||||||
subnet=Subnet(gateway=module.params['gateway']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Failed to change subnet {0} gateway to {1}'.format(module.params['name'],
|
|
||||||
module.params['gateway']))
|
|
||||||
if module.params['mtu']:
|
|
||||||
if module.params['mtu'] != subnet.mtu:
|
|
||||||
try:
|
|
||||||
blade.subnets.update_subnets(names=subnet_new,
|
|
||||||
subnet=Subnet(mtu=module.params['mtu']))
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
module.fail_json(msg='Failed to change subnet {0} MTU to {1}'.format(module.params['name'],
|
|
||||||
module.params['mtu']))
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_subnet(module, blade):
|
|
||||||
""" Delete Subnet"""
|
|
||||||
subnet = []
|
|
||||||
subnet.append(module.params['name'])
|
|
||||||
try:
|
|
||||||
blade.subnets.delete_subnets(names=subnet)
|
|
||||||
changed = True
|
|
||||||
except Exception:
|
|
||||||
changed = False
|
|
||||||
module.exit_json(changed=changed)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argument_spec = purefb_argument_spec()
|
|
||||||
argument_spec.update(
|
|
||||||
dict(
|
|
||||||
name=dict(required=True),
|
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
|
||||||
gateway=dict(),
|
|
||||||
mtu=dict(type='int', default=1500),
|
|
||||||
prefix=dict(),
|
|
||||||
vlan=dict(type='int', default=0),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
required_if = [["state", "present", ["gateway", 'prefix']]]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec,
|
|
||||||
required_if=required_if,
|
|
||||||
supports_check_mode=False)
|
|
||||||
|
|
||||||
if not HAS_PURITY_FB:
|
|
||||||
module.fail_json(msg='purity_fb sdk is required for this module')
|
|
||||||
|
|
||||||
if not HAS_NETADDR:
|
|
||||||
module.fail_json(msg='netaddr module is required')
|
|
||||||
|
|
||||||
state = module.params['state']
|
|
||||||
blade = get_blade(module)
|
|
||||||
api_version = blade.api_version.list_versions().versions
|
|
||||||
if MINIMUM_API_VERSION not in api_version:
|
|
||||||
module.fail_json(msg='Upgrade Purity//FB to enable this module')
|
|
||||||
subnet = get_subnet(module, blade)
|
|
||||||
if state == 'present':
|
|
||||||
if not (1280 <= module.params['mtu'] <= 9216):
|
|
||||||
module.fail_json(msg='MTU {0} is out of range (1280 to 9216)'.format(module.params['mtu']))
|
|
||||||
if not (0 <= module.params['vlan'] <= 4094):
|
|
||||||
module.fail_json(msg='VLAN ID {0} is out of range (0 to 4094)'.format(module.params['vlan']))
|
|
||||||
if netaddr.IPAddress(module.params['gateway']) not in netaddr.IPNetwork(module.params['prefix']):
|
|
||||||
module.fail_json(msg='Gateway and subnet are not compatible.')
|
|
||||||
subnets = blade.subnets.list_subnets()
|
|
||||||
nrange = netaddr.IPSet([module.params['prefix']])
|
|
||||||
for sub in range(0, len(subnets.items)):
|
|
||||||
if subnets.items[sub].vlan == module.params['vlan'] and subnets.items[sub].name != module.params['name']:
|
|
||||||
module.fail_json(msg='VLAN ID {0} is already in use.'.format(module.params['vlan']))
|
|
||||||
if nrange & netaddr.IPSet([subnets.items[sub].prefix]) and subnets.items[sub].name != module.params['name']:
|
|
||||||
module.fail_json(msg='Prefix CIDR overlaps with existing subnet.')
|
|
||||||
|
|
||||||
if state == 'present' and not subnet:
|
|
||||||
create_subnet(module, blade)
|
|
||||||
elif state == 'present' and subnet:
|
|
||||||
modify_subnet(module, blade)
|
|
||||||
elif state == 'absent' and subnet:
|
|
||||||
delete_subnet(module, blade)
|
|
||||||
elif state == 'absent' and not subnet:
|
|
||||||
module.exit_json(changed=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -993,14 +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: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:parameter-type-not-in-doc
|
||||||
lib/ansible/modules/source_control/subversion.py validate-modules:undocumented-parameter
|
lib/ansible/modules/source_control/subversion.py validate-modules:undocumented-parameter
|
||||||
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
|
|
||||||
lib/ansible/modules/storage/purestorage/purefb_fs.py validate-modules:doc-default-does-not-match-spec
|
|
||||||
lib/ansible/modules/storage/purestorage/purefb_info.py validate-modules:parameter-list-no-elements
|
|
||||||
lib/ansible/modules/storage/purestorage/purefb_info.py validate-modules:return-syntax-error
|
|
||||||
lib/ansible/modules/storage/purestorage/purefb_s3acc.py validate-modules:doc-required-mismatch
|
|
||||||
lib/ansible/modules/storage/purestorage/purefb_s3user.py validate-modules:doc-required-mismatch
|
|
||||||
lib/ansible/modules/system/getent.py validate-modules:parameter-type-not-in-doc
|
lib/ansible/modules/system/getent.py validate-modules:parameter-type-not-in-doc
|
||||||
lib/ansible/modules/system/hostname.py validate-modules:invalid-ansiblemodule-schema
|
lib/ansible/modules/system/hostname.py validate-modules:invalid-ansiblemodule-schema
|
||||||
lib/ansible/modules/system/hostname.py validate-modules:parameter-type-not-in-doc
|
lib/ansible/modules/system/hostname.py validate-modules:parameter-type-not-in-doc
|
||||||
|
|
Loading…
Reference in a new issue