From b150f491871693fa9db5f8eaf360cacf2bb57d20 Mon Sep 17 00:00:00 2001 From: Simon Dodsley Date: Mon, 21 Aug 2017 18:15:51 -0400 Subject: [PATCH] purefa_volume: Add volume copy, aka clone (#28376) --- .../storage/purestorage/purefa_volume.py | 92 ++++++++++++++++--- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/lib/ansible/modules/storage/purestorage/purefa_volume.py b/lib/ansible/modules/storage/purestorage/purefa_volume.py index 69679cb98f9..1c5bb232258 100644 --- a/lib/ansible/modules/storage/purestorage/purefa_volume.py +++ b/lib/ansible/modules/storage/purestorage/purefa_volume.py @@ -17,7 +17,7 @@ DOCUMENTATION = ''' --- module: purefa_volume version_added: "2.4" -short_description: Create, Delete or Extend a volume on Pure Storage FlashArray +short_description: Create, Delete, Copy or Extend a volume on Pure Storage FlashArray description: - This module creates, deletes or extends the capacity of a volume on Pure Storage FlashArray. author: Simon Dodsley (@sdodsley) @@ -26,9 +26,13 @@ options: description: - Volume Name. required: true + target: + description: + - Target Volume Name if copying. + required: false state: description: - - Create, delete or extend capacity of a volume. + - Create, delete, copy or extend capacity of a volume. required: false default: present choices: [ "present", "absent" ] @@ -38,10 +42,16 @@ options: required: false type: bool default: false + overwrite: + description: + - Define whether to overwrite a target volume if it already exisits. + required: false + type: bool + default: false size: description: - Volume size in M, G, T or P units. See examples. - required: true + required: false extends_documentation_fragment: - purestorage ''' @@ -69,6 +79,23 @@ EXAMPLES = ''' eradicate: true state: absent fa_url: 10.10.10.2 + api_token: e31060a7-21fc-e277-6240-25983c6c4592 + +- name: Create clone of volume bar named foo + purefa_volume: + name: foo + target: bar + state: present + fa_url: 10.10.10.2 + api_token: e31060a7-21fc-e277-6240-25983c6c4592 + +- name: Overwrite volume bar with volume foo + purefa_volume: + name: foo + target: bar + overwrite: true + state: present + fa_url: 10.10.10.2 api_token: e31060a7-21fc-e277-6240-25983c6c4592''' RETURN = ''' @@ -91,15 +118,15 @@ def human_to_bytes(size): """ bytes = size[:-1] unit = size[-1] - if (bytes.isdigit()): + if bytes.isdigit(): bytes = int(bytes) - if (unit == 'P'): + if unit == 'P': bytes *= 1125899906842624 - elif (unit == 'T'): + elif unit == 'T': bytes *= 1099511627776 - elif (unit == 'G'): + elif unit == 'G': bytes *= 1073741824 - elif (unit == 'M'): + elif unit == 'M': bytes *= 1048576 else: bytes = 0 @@ -116,6 +143,14 @@ def get_volume(module, array): return None +def get_target(module, array): + """Return Volume or None""" + try: + return array.get_volume(module.params['target']) + except: + return None + + def create_volume(module, array): """Create Volume""" size = module.params['size'] @@ -125,6 +160,27 @@ def create_volume(module, array): module.exit_json(changed=True) +def copy_from_volume(module, array): + """Create Volume Clone""" + changed = False + + tgt = get_target(module, array) + + if tgt is None: + changed = True + if not module.check_mode: + array.copy_volume(module.params['name'], + module.params['target']) + elif tgt is not None and module.params['overwrite']: + changed = True + if not module.check_mode: + array.copy_volume(module.params['name'], + module.params['target'], + overwrite=module.params['overwrite']) + + module.exit_json(changed=changed) + + def update_volume(module, array): """Update Volume""" changed = True @@ -151,31 +207,41 @@ def main(): argument_spec.update( dict( name=dict(required=True), - eradicate=dict(default='false', type='bool'), + target=dict(), + overwrite=dict(default=False, type='bool'), + eradicate=dict(default=False, type='bool'), state=dict(default='present', choices=['present', 'absent']), size=dict() ) ) - required_if = [('state', 'present', ['size'])] + mutually_exclusive = [['size', 'target']] module = AnsibleModule(argument_spec, - required_if=required_if, + mutually_exclusive=mutually_exclusive, supports_check_mode=True) if not HAS_PURESTORAGE: module.fail_json(msg='purestorage sdk is required for this module in volume') + size = module.params['size'] state = module.params['state'] array = get_system(module) volume = get_volume(module, array) + target = get_target(module, array) - if state == 'present' and not volume: + if state == 'present' and not volume and size: create_volume(module, array) - elif state == 'present' and volume: + elif state == 'present' and volume and size: update_volume(module, array) + elif state == 'present' and volume and target: + copy_from_volume(module, array) + elif state == 'present' and volume and not target: + copy_from_volume(module, array) elif state == 'absent' and volume: delete_volume(module, array) + elif state == 'present' and not volume or not size: + module.exit_json(changed=False) elif state == 'absent' and not volume: module.exit_json(changed=False)