From d82446652fcac3d039bb4485865ce5f9a162e859 Mon Sep 17 00:00:00 2001 From: Simon Dodsley Date: Fri, 26 Jul 2019 10:06:08 +0200 Subject: [PATCH] Update FlashBlade filesystem module to support quotas and NFS v4.1 (#59559) --- .../59559-deprecate-nfs-param-purefb_fs.yml | 2 + .../modules/storage/purestorage/purefb_fs.py | 174 +++++++++++++----- 2 files changed, 133 insertions(+), 43 deletions(-) create mode 100644 changelogs/fragments/59559-deprecate-nfs-param-purefb_fs.yml diff --git a/changelogs/fragments/59559-deprecate-nfs-param-purefb_fs.yml b/changelogs/fragments/59559-deprecate-nfs-param-purefb_fs.yml new file mode 100644 index 00000000000..db008a3da62 --- /dev/null +++ b/changelogs/fragments/59559-deprecate-nfs-param-purefb_fs.yml @@ -0,0 +1,2 @@ +minor_changes: +- purefb_fs - Deprecate I(nfs) param and replace with I(nfsv3). Add params I(user_quota) and I(group_quota) (https://github.com/ansible/ansible/pull/59559) diff --git a/lib/ansible/modules/storage/purestorage/purefb_fs.py b/lib/ansible/modules/storage/purestorage/purefb_fs.py index 38c21c02de5..36f2d3eef8b 100644 --- a/lib/ansible/modules/storage/purestorage/purefb_fs.py +++ b/lib/ansible/modules/storage/purestorage/purefb_fs.py @@ -46,9 +46,24 @@ options: 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: description: - - Define whether to NFS protocol is enabled for the filesystem. + - (Deprecate) Define whether to NFSv3 protocol is enabled for the filesystem. + - This option will be deprecated in 2.10, use I(nfsv3) instead. required: false type: bool default: true @@ -91,6 +106,18 @@ options: 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 ''' @@ -129,9 +156,11 @@ EXAMPLES = ''' - name: Modify attributes of an existing filesystem named foo purefb_fs: name: foo - size: 2T - nfs : true + nfsv3 : false + nfsv4 : true + user_quota: 10K + group_quota: 25M nfs_rules: '*(ro)' snapshot: true fastremove: true @@ -155,14 +184,15 @@ 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""" - fs = [] - fs.append(module.params['name']) + fsys = [] + fsys.append(module.params['name']) try: - res = blade.file_systems.list_file_systems(names=fs) + res = blade.file_systems.list_file_systems(names=fsys) return res.items[0] except Exception: return None @@ -175,20 +205,41 @@ def create_fs(module, blade): module.params['size'] = '32G' size = human_to_bytes(module.params['size']) + nfsv3 = module.params['nfs'] if module.params['nfsv3'] is None else module.params['nfsv3'] + + 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']) if not module.check_mode: try: api_version = blade.api_version.list_versions().versions if HARD_LIMIT_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(enabled=module.params['nfs'], rules=module.params['nfs_rules']), - smb=ProtocolRule(enabled=module.params['smb']), - http=ProtocolRule(enabled=module.params['http']) - ) + 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=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=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, @@ -208,53 +259,83 @@ def create_fs(module, blade): def modify_fs(module, blade): """Modify Filesystem""" changed = False + nfsv3 = module.params['nfs'] if module.params['nfsv3'] is None else module.params['nfsv3'] 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']) if not module.check_mode: - fs = get_fs(module, blade) - if fs.destroyed: + api_version = blade.api_version.list_versions().versions + fsys = get_fs(module, blade) + if fsys.destroyed: attr['destroyed'] = False changed = True if module.params['size']: - if human_to_bytes(module.params['size']) > fs.provisioned: + if human_to_bytes(module.params['size']) > fsys.provisioned: attr['provisioned'] = human_to_bytes(module.params['size']) changed = True - if module.params['nfs'] and not fs.nfs.enabled: - attr['nfs'] = NfsRule(enabled=module.params['nfs']) - changed = True - if not module.params['nfs'] and fs.nfs.enabled: - attr['nfs'] = NfsRule(enabled=module.params['nfs']) - changed = True - if module.params['nfs'] and fs.nfs.enabled: - if fs.nfs.rules != module.params['nfs_rules']: - attr['nfs'] = NfsRule(rules=module.params['nfs_rules']) + if NFSV4_API_VERSION in api_version: + if nfsv3 and not fsys.nfs.v3_enabled: + attr['nfs'] = NfsRule(v3_enabled=nfsv3) + changed = True + if not nfsv3 and fsys.nfs.v3_enabled: + attr['nfs'] = NfsRule(v3_enabled=nfsv3) changed = True - if module.params['smb'] and not fs.smb.enabled: + if module.params['nfsv4'] and not fsys.nfs.v4_1_enabled: + attr['nfs'] = NfsRule(v4_1_enabled=module.params['nfsv4']) + changed = True + if not module.params['nfsv4'] and fsys.nfs.v4_1_enabled: + attr['nfs'] = NfsRule(v4_1_enabled=module.params['nfsv4']) + changed = True + if 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']) + changed = True + if module.params['user_quota'] and user_quota != fsys.default_user_quota: + attr['default_user_quota'] = user_quota + changed = True + if module.params['group_quota'] and group_quota != fsys.default_group_quota: + attr['default_group_quota'] = group_quota + changed = True + else: + if nfsv3 and not fsys.nfs.enabled: + attr['nfs'] = NfsRule(enabled=nfsv3) + changed = True + if not nfsv3 and fsys.nfs.enabled: + attr['nfs'] = NfsRule(enabled=nfsv3) + changed = True + if nfsv3 and fsys.nfs.enabled: + if fsys.nfs.rules != module.params['nfs_rules']: + attr['nfs'] = NfsRule(rules=module.params['nfs_rules']) + changed = True + if module.params['smb'] and not fsys.smb.enabled: attr['smb'] = ProtocolRule(enabled=module.params['smb']) changed = True - if not module.params['smb'] and fs.smb.enabled: + if not module.params['smb'] and fsys.smb.enabled: attr['smb'] = ProtocolRule(enabled=module.params['smb']) changed = True - if module.params['http'] and not fs.http.enabled: + if module.params['http'] and not fsys.http.enabled: attr['http'] = ProtocolRule(enabled=module.params['http']) changed = True - if not module.params['http'] and fs.http.enabled: + if not module.params['http'] and fsys.http.enabled: attr['http'] = ProtocolRule(enabled=module.params['http']) changed = True - if module.params['snapshot'] and not fs.snapshot_directory_enabled: + if module.params['snapshot'] and not fsys.snapshot_directory_enabled: attr['snapshot_directory_enabled'] = module.params['snapshot'] changed = True - if not module.params['snapshot'] and fs.snapshot_directory_enabled: + if not module.params['snapshot'] and fsys.snapshot_directory_enabled: attr['snapshot_directory_enabled'] = module.params['snapshot'] changed = True - if module.params['fastremove'] and not fs.fast_remove_directory_enabled: + if module.params['fastremove'] and not fsys.fast_remove_directory_enabled: attr['fast_remove_directory_enabled'] = module.params['fastremove'] changed = True - if not module.params['fastremove'] and fs.fast_remove_directory_enabled: + if not module.params['fastremove'] and fsys.fast_remove_directory_enabled: attr['fast_remove_directory_enabled'] = module.params['fastremove'] changed = True api_version = blade.api_version.list_versions().versions if HARD_LIMIT_API_VERSION in api_version: - if not module.params['hard_limit'] and fs.hard_limit_enabled: + if not module.params['hard_limit'] and fsys.hard_limit_enabled: attr['hard_limit_enabled'] = module.params['hard_limit'] changed = True if changed: @@ -305,19 +386,26 @@ def main(): dict( name=dict(required=True), eradicate=dict(default='false', type='bool'), - nfs=dict(default='true', type='bool'), + nfs=dict(removed_in_version='2.10', default='true', 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() ) ) + mutually_exclusive = [['nfs', 'nfsv3']] + module = AnsibleModule(argument_spec, + mutually_exclusive=mutually_exclusive, supports_check_mode=True) if not HAS_PURITY_FB: @@ -325,17 +413,17 @@ def main(): state = module.params['state'] blade = get_blade(module) - fs = get_fs(module, blade) + fsys = get_fs(module, blade) - if state == 'present' and not fs: + if state == 'present' and not fsys: create_fs(module, blade) - elif state == 'present' and fs: + elif state == 'present' and fsys: modify_fs(module, blade) - elif state == 'absent' and fs and not fs.destroyed: + elif state == 'absent' and fsys and not fsys.destroyed: delete_fs(module, blade) - elif state == 'absent' and fs and fs.destroyed and module.params['eradicate']: + elif state == 'absent' and fsys and fsys.destroyed and module.params['eradicate']: eradicate_fs(module, blade) - elif state == 'absent' and not fs: + elif state == 'absent' and not fsys: module.exit_json(changed=False)