diff --git a/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py b/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py index 60c7aaf1af6..62ad8ed42e3 100644 --- a/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py +++ b/lib/ansible/modules/storage/purestorage/purefa_pgsnap.py @@ -15,10 +15,10 @@ DOCUMENTATION = r''' --- module: purefa_pgsnap version_added: '2.6' -short_description: Manage local protection group snapshots on Pure Storage FlashArrays +short_description: Manage protection group snapshots on Pure Storage FlashArrays description: -- Create or delete local protection group snapshots on Pure Storage FlashArray. -- This module only supports local protection groups. +- Create or delete protection group snapshots on Pure Storage FlashArray. +- Recovery of replicated snapshots on the replica target array is enabled. author: - Simon Dodsley (@sdodsley) options: @@ -32,8 +32,8 @@ options: state: description: - Define whether the protection group snapshot should exist or not. - Copy (added in 2.7) will force an overwrite of an exisitng volume - from a snapshot. + Copy (added in 2.7) will create a full read/write clone of the + snapshot. choices: [ absent, present, copy ] default: present eradicate: @@ -44,8 +44,18 @@ options: restore: description: - Restore a specific volume from a protection group snapshot. - This implies overwrite of the current full volume. USE WITH CARE!! version_added: 2.7 + overwrite: + description: + - Define whether to overwrite the target volume if it already exists. + type: bool + default: 'no' + version_added: 2.8 + target: + description: + - Volume to restore a specified volume to. + - If not supplied this will default to the volume defined in I(restore) + version_added: 2.8 extends_documentation_fragment: - purestorage.fa ''' @@ -68,12 +78,22 @@ EXAMPLES = r''' api_token: e31060a7-21fc-e277-6240-25983c6c4592 state: absent -- name: Restore volume data from protection group snapshot named foo.snap - USE WITH CARE! This will overwrite your existing volume +- name: Restore volume data from local protection group snapshot named foo.snap to volume data2 purefa_pgsnap: name: foo suffix: snap restore: data + target: data2 + overwrite: true + fa_url: 10.10.10.2 + api_token: e31060a7-21fc-e277-6240-25983c6c4592 + state: copy + +- name: Restore remote protection group snapshot arrayA:pgname.snap.data to local copy + purefa_pgsnap: + name: arrayA:pgname + suffix: snap + restore: data fa_url: 10.10.10.2 api_token: e31060a7-21fc-e277-6240-25983c6c4592 state: copy @@ -87,12 +107,6 @@ from ansible.module_utils.pure import get_system, purefa_argument_spec from datetime import datetime -try: - from purestorage import purestorage - HAS_PURESTORAGE = True -except ImportError: - HAS_PURESTORAGE = False - def get_pgroup(module, array): """Return Protection Group or None""" @@ -113,12 +127,23 @@ def get_pgroupvolume(module, array): return None +def get_rpgsnapshot(module, array): + """Return iReplicated Snapshot or None""" + try: + snapname = module.params['name'] + "." + module.params['suffix'] + "." + module.params['restore'] + for snap in array.list_volumes(snap='true'): + if snap['name'] == snapname: + return snapname + except: + return None + + def get_pgsnapshot(module, array): """Return Snapshot or None""" try: snapname = module.params['name'] + "." + module.params['suffix'] - for s in array.get_pgroup(module.params['name'], snap='true'): - if s['name'] == snapname: + for snap in array.get_pgroup(module.params['name'], snap='true'): + if snap['name'] == snapname: return snapname except: return None @@ -126,15 +151,14 @@ def get_pgsnapshot(module, array): def create_pgsnapshot(module, array): """Create Protection Group Snapshot""" - if not module.check_mode: - try: - array.create_pgroup_snapshot(source=module.params['name'], - suffix=module.params['suffix'], - snap=True, - apply_retention=True) - changed = True - except: - changed = False + try: + array.create_pgroup_snapshot(source=module.params['name'], + suffix=module.params['suffix'], + snap=True, + apply_retention=True) + changed = True + except: + changed = False module.exit_json(changed=changed) @@ -142,7 +166,7 @@ def restore_pgsnapvolume(module, array): """Restore a Protection Group Snapshot Volume""" volume = module.params['name'] + "." + module.params['suffix'] + "." + module.params['restore'] try: - array.copy_volume(volume, module.params['restore'], overwrite=True) + array.copy_volume(volume, module.params['target'], overwrite=module.params['overwrite']) changed = True except: changed = False @@ -157,19 +181,18 @@ def update_pgsnapshot(module, array): def delete_pgsnapshot(module, array): """ Delete Protection Group Snapshot""" - if not module.check_mode: - snapname = module.params['name'] + "." + module.params['suffix'] - try: - array.destroy_pgroup(snapname) - chaned = True - if module.params['eradicate']: - try: - array.eradicate_pgroup(snapname) - changed = True - except: - changed = False - except: - changed = False + snapname = module.params['name'] + "." + module.params['suffix'] + try: + array.destroy_pgroup(snapname) + changed = True + if module.params['eradicate']: + try: + array.eradicate_pgroup(snapname) + changed = True + except: + changed = False + except: + changed = False module.exit_json(changed=changed) @@ -179,6 +202,8 @@ def main(): name=dict(type='str', required=True), suffix=dict(type='str'), restore=dict(type='str'), + overwrite=dict(type='bool', default=False), + target=dict(type='str'), eradicate=dict(type='bool', default=False), state=dict(type='str', default='present', choices=['absent', 'present', 'copy']), )) @@ -187,20 +212,27 @@ def main(): module = AnsibleModule(argument_spec, required_if=required_if, - supports_check_mode=True) - - if not HAS_PURESTORAGE: - module.fail_json(msg='purestorage sdk is required for this module in volume') + supports_check_mode=False) if module.params['suffix'] is None: suffix = "snap-" + str((datetime.utcnow() - datetime(1970, 1, 1, 0, 0, 0, 0)).total_seconds()) module.params['suffix'] = suffix.replace(".", "") + if not module.params['target'] and module.params['restore']: + module.params['target'] = module.params['restore'] + state = module.params['state'] array = get_system(module) pgroup = get_pgroup(module, array) + if pgroup is None: + module.fail_json(msg="Protection Group {0} does not exist".format(module.params('pgroup'))) pgsnap = get_pgsnapshot(module, array) - rvolume = get_pgroupvolume(module, array) + if pgsnap is None: + module.fail_json(msg="Selected volume {0} does not exist in the Protection Group".format(module.params('name'))) + if ":" in module.params['name']: + rvolume = get_rpgsnapshot(module, array) + else: + rvolume = get_pgroupvolume(module, array) if state == 'copy' and rvolume: restore_pgsnapvolume(module, array)