From cdb5140adecc6859e27f0ef4f6a378e68fe67f45 Mon Sep 17 00:00:00 2001 From: Luca Lorenzetto Date: Thu, 9 Aug 2018 19:38:26 +0200 Subject: [PATCH] New module for managing EMC VNX Block storage (#42945) * New module for managing EMC VNX Block storage With the module emc_vnx_sg_member users can add or remove luns from existing storage groups. This module has been developed in couple with emc_vnx_mv_promote for disaster recovery process automation, but can be used by itself. --- lib/ansible/module_utils/storage/__init__.py | 0 .../module_utils/storage/emc/__init__.py | 0 .../module_utils/storage/emc/emc_vnx.py | 34 ++++ lib/ansible/modules/storage/emc/__init__.py | 0 .../modules/storage/emc/emc_vnx_sg_member.py | 173 ++++++++++++++++++ .../utils/module_docs_fragments/emc.py | 43 +++++ 6 files changed, 250 insertions(+) create mode 100644 lib/ansible/module_utils/storage/__init__.py create mode 100644 lib/ansible/module_utils/storage/emc/__init__.py create mode 100644 lib/ansible/module_utils/storage/emc/emc_vnx.py create mode 100644 lib/ansible/modules/storage/emc/__init__.py create mode 100644 lib/ansible/modules/storage/emc/emc_vnx_sg_member.py create mode 100644 lib/ansible/utils/module_docs_fragments/emc.py diff --git a/lib/ansible/module_utils/storage/__init__.py b/lib/ansible/module_utils/storage/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/storage/emc/__init__.py b/lib/ansible/module_utils/storage/emc/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/storage/emc/emc_vnx.py b/lib/ansible/module_utils/storage/emc/emc_vnx.py new file mode 100644 index 00000000000..c6177e53678 --- /dev/null +++ b/lib/ansible/module_utils/storage/emc/emc_vnx.py @@ -0,0 +1,34 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. +# +# (c) 2018 Luca 'remix_tj' Lorenzetto +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +emc_vnx_argument_spec = { + 'sp_address': dict(type='str', required=True), + 'sp_user': dict(type='str', required=False, default='sysadmin'), + 'sp_password': dict(type='str', required=False, default='sysadmin', + no_log=True), +} diff --git a/lib/ansible/modules/storage/emc/__init__.py b/lib/ansible/modules/storage/emc/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/modules/storage/emc/emc_vnx_sg_member.py b/lib/ansible/modules/storage/emc/emc_vnx_sg_member.py new file mode 100644 index 00000000000..540a7dac249 --- /dev/null +++ b/lib/ansible/modules/storage/emc/emc_vnx_sg_member.py @@ -0,0 +1,173 @@ +#!/usr/bin/python +# +# Copyright (c) 2018, Luca 'remix_tj' Lorenzetto +# +# 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: emc_vnx_sg_member + +short_description: Manage storage group member on EMC VNX + +version_added: "2.7" + +description: + - "This module manages the members of an existing storage group." + +extends_documentation_fragment: + - emc.emc_vnx + +options: + name: + description: + - Name of the Storage group to manage. + required: true + lunid: + description: + - Lun id to be added. + required: true + state: + description: + - Indicates the desired lunid state. + - C(present) ensures specified lunid is present in the Storage Group. + - C(absent) ensures specified lunid is absent from Storage Group. + default: present + choices: [ "present", "absent"] + + +author: + - Luca 'remix_tj' Lorenzetto (@remixtj) +''' + +EXAMPLES = ''' +- name: Add lun to storage group + emc_vnx_sg_member: + name: sg01 + sp_address: sp1a.fqdn + sp_user: sysadmin + sp_password: sysadmin + lunid: 100 + state: present + +- name: Remove lun from storage group + emc_vnx_sg_member: + name: sg01 + sp_address: sp1a.fqdn + sp_user: sysadmin + sp_password: sysadmin + lunid: 100 + state: absent +''' + +RETURN = ''' +hluid: + description: LUNID that hosts attached to the storage group will see. + type: int + returned: success +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible.module_utils.storage.emc.emc_vnx import emc_vnx_argument_spec + +try: + from storops import VNXSystem + from storops.exception import VNXCredentialError, VNXStorageGroupError, \ + VNXAluAlreadyAttachedError, VNXAttachAluError, VNXDetachAluNotFoundError + HAS_LIB = True +except: + HAS_LIB = False + + +def run_module(): + module_args = dict( + name=dict(type='str', required=True), + lunid=dict(type='int', required=True), + state=dict(default='present', choices=['present', 'absent']), + ) + + module_args.update(emc_vnx_argument_spec) + + result = dict( + changed=False, + hluid=None + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True + ) + + if not HAS_LIB: + module.fail_json(msg='storops library (0.5.10 or greater) is missing.' + 'Install with pip install storops' + ) + + sp_user = module.params['sp_user'] + sp_address = module.params['sp_address'] + sp_password = module.params['sp_password'] + alu = module.params['lunid'] + + # if the user is working with this module in only check mode we do not + # want to make any changes to the environment, just return the current + # state with no modifications + if module.check_mode: + return result + + try: + vnx = VNXSystem(sp_address, sp_user, sp_password) + sg = vnx.get_sg(module.params['name']) + if sg.existed: + if module.params['state'] == 'present': + if not sg.has_alu(alu): + try: + result['hluid'] = sg.attach_alu(alu) + result['changed'] = True + except VNXAluAlreadyAttachedError: + result['hluid'] = sg.get_hlu(alu) + except (VNXAttachAluError, VNXStorageGroupError) as e: + module.fail_json(msg='Error attaching {0}: ' + '{1} '.format(alu, to_native(e)), + **result) + else: + result['hluid'] = sg.get_hlu(alu) + if module.params['state'] == 'absent' and sg.has_alu(alu): + try: + sg.detach_alu(alu) + result['changed'] = True + except VNXDetachAluNotFoundError: + # being not attached when using absent is OK + pass + except VNXStorageGroupError as e: + module.fail_json(msg='Error detaching alu {0}: ' + '{1} '.format(alu, to_native(e)), + **result) + else: + module.fail_json(msg='No such storage group named ' + '{0}'.format(module.params['name']), + **result) + except VNXCredentialError as e: + module.fail_json(msg='{0}'.format(to_native(e)), **result) + + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/utils/module_docs_fragments/emc.py b/lib/ansible/utils/module_docs_fragments/emc.py new file mode 100644 index 00000000000..e072c160776 --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/emc.py @@ -0,0 +1,43 @@ +# +# Copyright (c) 2018, Luca 'remix_tj' Lorenzetto +# +# This file is part of Ansible +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + + +class ModuleDocFragment(object): + + DOCUMENTATION = """ +options: + - See respective platform section for more details +requirements: + - See respective platform section for more details +notes: + - Ansible modules are available for EMC VNX. +""" + + # Documentation fragment for VNX (emc_vnx) + EMC_VNX = """ +options: + sp_address: + description: + - Address of the SP of target/secondary storage. + required: true + sp_user: + description: + - Username for accessing SP. + default: sysadmin + required: false + sp_password: + description: + - password for accessing SP. + default: sysadmin + required: false +requirements: + - An EMC VNX Storage device. + - Ansible 2.7. + - storops (0.5.10 or greater). Install using 'pip install storops'. +notes: + - The modules prefixed with emc_vnx are built to support the ONTAP storage platform. + """