diff options
Diffstat (limited to 'ansible_collections/netapp/um_info/plugins')
13 files changed, 1905 insertions, 0 deletions
diff --git a/ansible_collections/netapp/um_info/plugins/doc_fragments/netapp.py b/ansible_collections/netapp/um_info/plugins/doc_fragments/netapp.py new file mode 100644 index 000000000..0790f109a --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/doc_fragments/netapp.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Suhas Bangalore Shekar <bsuhas@netapp.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 + + +class ModuleDocFragment(object): + + DOCUMENTATION = r''' +options: + - See respective platform section for more details +requirements: + - See respective platform section for more details +notes: + - Ansible modules are available for the following NetApp Storage Management Platforms: AIQUM 9.7 +''' + + # Documentation fragment for AIQUM (um) + UM = r''' +options: + hostname: + description: + - The hostname or IP address of the Unified Manager instance. + type: str + required: true + username: + description: + - username of the Unified Manager instance. + type: str + required: true + password: + description: + - Password for the specified user. + type: str + required: true + validate_certs: + description: + - If set to C(False), the SSL certificates will not be validated. + - This should only set to C(False) used on personally controlled sites using self-signed certificates. + type: bool + default: True + http_port: + description: + - Override the default port (443) with this port + type: int + feature_flags: + description: + - Enable or disable a new feature. + - This can be used to enable an experimental feature or disable a new feature that breaks backward compatibility. + - Supported keys and values are subject to change without notice. Unknown keys are ignored. + - trace_apis can be set to true to enable tracing, data is written to /tmp/um_apis.log. + type: dict + version_added: 21.7.0 + max_records: + description: + - Maximum number of records retrieved in a single GET request. + - This module loops on GET requests until all available records are fetched. + - If absent, AIQUM uses 1000. + type: int + version_added: 21.7.0 + + +requirements: + - A AIQUM 9.7 system. + - Ansible 2.9 or later. + +notes: + - With the 21.6.0 release, all modules have been renamed to na_um_<module>_info. The old ones will continue to work but will be depecrated in the future. + - The modules prefixed with na_um are built to support the AIQUM 9.7 platform. + - Supports check_mode. +''' diff --git a/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py b/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py new file mode 100644 index 000000000..ba58f56e8 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py @@ -0,0 +1,246 @@ +# 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. +# +# Copyright (c) 2017, Sumit Kumar <sumit4@netapp.com> +# Copyright (c) 2017, Michael Price <michael.price@netapp.com> +# All rights reserved. +# +# 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. + +''' +common routines for um_info +''' + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import logging +from ansible.module_utils.basic import missing_required_lib +from ansible.module_utils._text import to_native + +try: + from ansible.module_utils.ansible_release import __version__ as ansible_version +except ImportError: + ansible_version = 'unknown' + +COLLECTION_VERSION = "21.8.0" + +try: + import requests + HAS_REQUESTS = True +except ImportError: + HAS_REQUESTS = False + +ERROR_MSG = dict( + no_cserver='This module is expected to run as cluster admin' +) + +LOG = logging.getLogger(__name__) +LOG_FILE = '/tmp/um_apis.log' + + +def na_um_host_argument_spec(): + + return dict( + hostname=dict(required=True, type='str'), + username=dict(required=True, type='str'), + password=dict(required=True, type='str', no_log=True), + validate_certs=dict(required=False, type='bool', default=True), + http_port=dict(required=False, type='int'), + feature_flags=dict(required=False, type='dict', default=dict()), + max_records=dict(required=False, type='int') + ) + + +def has_feature(module, feature_name): + feature = get_feature(module, feature_name) + if isinstance(feature, bool): + return feature + module.fail_json(msg="Error: expected bool type for feature flag: %s" % feature_name) + + +def get_feature(module, feature_name): + ''' if the user has configured the feature, use it + otherwise, use our default + ''' + default_flags = dict( + strict_json_check=True, # if true, fail if response.content in not empty and is not valid json + trace_apis=False, # if true, append REST requests/responses to LOG_FILE + + ) + + if module.params['feature_flags'] is not None and feature_name in module.params['feature_flags']: + return module.params['feature_flags'][feature_name] + if feature_name in default_flags: + return default_flags[feature_name] + module.fail_json(msg="Internal error: unexpected feature flag: %s" % feature_name) + + +class UMRestAPI(object): + ''' send REST request and process response ''' + def __init__(self, module, timeout=60): + self.module = module + self.username = self.module.params['username'] + self.password = self.module.params['password'] + self.hostname = self.module.params['hostname'] + self.verify = self.module.params['validate_certs'] + self.max_records = self.module.params['max_records'] + self.timeout = timeout + if self.module.params.get('http_port') is not None: + self.url = 'https://%s:%d' % (self.hostname, self.module.params['http_port']) + else: + self.url = 'https://%s' % self.hostname + self.errors = list() + self.debug_logs = list() + self.check_required_library() + if has_feature(module, 'trace_apis'): + logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s') + + def check_required_library(self): + if not HAS_REQUESTS: + self.module.fail_json(msg=missing_required_lib('requests')) + + def get_records(self, message, api): + records = list() + try: + if message['total_records'] > 0: + records = message['records'] + if message['total_records'] != len(records): + self.module.warn('Mismatch between received: %d and expected: %d records.' % (len(records), message['total_records'])) + except KeyError as exc: + self.module.fail_json(msg='Error: unexpected response from %s: %s - expecting key: %s' + % (api, message, to_native(exc))) + return records + + def send_request(self, method, api, params, json=None, accept=None): + ''' send http request and process response, including error conditions ''' + url = self.url + api + status_code = None + content = None + json_dict = None + json_error = None + error_details = None + headers = None + if accept is not None: + headers = dict() + # accept is used to turn on/off HAL linking + if accept is not None: + headers['accept'] = accept + + def check_contents(response): + '''json() may fail on an empty value, but it's OK if no response is expected. + To avoid false positives, only report an issue when we expect to read a value. + The first get will see it. + ''' + if method == 'GET' and has_feature(self.module, 'strict_json_check'): + contents = response.content + if len(contents) > 0: + raise ValueError("Expecting json, got: %s" % contents) + + def get_json(response): + ''' extract json, and error message if present ''' + try: + json = response.json() + except ValueError: + check_contents(response) + return None, None + error = json.get('error') + return json, error + + self.log_debug('sending', repr(dict(method=method, url=url, verify=self.verify, params=params, + timeout=self.timeout, json=json, headers=headers))) + try: + response = requests.request(method, url, verify=self.verify, auth=(self.username, self.password), + params=params, timeout=self.timeout, json=json, headers=headers) + content = response.content # for debug purposes + status_code = response.status_code + # If the response was successful, no Exception will be raised + response.raise_for_status() + json_dict, json_error = get_json(response) + except requests.exceptions.HTTPError as err: + __, json_error = get_json(response) + if json_error is None: + self.log_error(status_code, 'HTTP error: %s' % err) + error_details = str(err) + # If an error was reported in the json payload, it is handled below + except requests.exceptions.ConnectionError as err: + self.log_error(status_code, 'Connection error: %s' % err) + error_details = str(err) + except Exception as err: + self.log_error(status_code, 'Other error: %s' % err) + error_details = str(err) + if json_error is not None: + self.log_error(status_code, 'Endpoint error: %d: %s' % (status_code, json_error)) + error_details = json_error + self.log_debug(status_code, content) + return json_dict, error_details + + def get(self, api, params): + + def get_next_api(message): + '''make sure _links is present, and href is present if next is present + return api if next is present, None otherwise + return error if _links or href are missing + ''' + api, error = None, None + if message is None or '_links' not in message: + error = 'Expecting _links key in %s' % message + elif 'next' in message['_links']: + if 'href' in message['_links']['next']: + api = message['_links']['next']['href'] + else: + error = 'Expecting href key in %s' % message['_links']['next'] + return api, error + + method = 'GET' + records = list() + if self.max_records is not None: + if params and 'max_records' not in params: + params['max_records'] = self.max_records + else: + params = dict(max_records=self.max_records) + api = '/api/%s' % api + + while api: + message, error = self.send_request(method, api, params) + if error: + return message, error + api, error = get_next_api(message) + if error: + return message, error + if 'records' in message: + records.extend(message['records']) + params = None # already included in the next link + + if records: + message['records'] = records + return message, error + + def log_error(self, status_code, message): + LOG.error("%s: %s", status_code, message) + self.errors.append(message) + self.debug_logs.append((status_code, message)) + + def log_debug(self, status_code, content): + LOG.debug("%s: %s", status_code, content) + self.debug_logs.append((status_code, content)) diff --git a/ansible_collections/netapp/um_info/plugins/module_utils/netapp_module.py b/ansible_collections/netapp/um_info/plugins/module_utils/netapp_module.py new file mode 100644 index 000000000..f3b95800e --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/module_utils/netapp_module.py @@ -0,0 +1,51 @@ +# 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. +# +# Copyright (c) 2020, Laurent Nicolas <laurentn@netapp.com> +# All rights reserved. +# +# 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. + +''' Support class for NetApp ansible modules ''' + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class NetAppModule(object): + ''' + Common class for NetApp modules + set of support functions to derive actions based + on the current state of the system, and a desired state + ''' + + def __init__(self): + self.changed = False + self.parameters = {} + + def set_parameters(self, ansible_params): + self.parameters = dict() + for param in ansible_params: + if ansible_params[param] is not None: + self.parameters[param] = ansible_params[param] + return self.parameters diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_aggregates_info.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_aggregates_info.py new file mode 100644 index 000000000..10a34cfdf --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_aggregates_info.py @@ -0,0 +1,163 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_aggregates +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_aggregates_info +short_description: NetApp Unified Manager list aggregates. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Aggregates on AIQUM. +''' + +EXAMPLES = """ +- name: List Aggregates + netapp.um_info.na_um_aggregates_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Aggregates information + returned: always + type: list + sample: [{'node': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'snaplock_type': '...', + 'uuid': '...', + 'space': + {'block_storage': + {'available': ..., + 'used': ..., + 'size': ... + }, + 'efficiency': + {'savings': ..., + 'logical_used': ... + } + }, + 'block_storage': + {'hybrid_cache': + {'enabled': ..., + 'size': ... + }, + 'primary': + {'raid_size': ..., + 'raid_type': '...' + }, + 'mirror': + {'state': '...' + } + }, + 'data_encryption': + {'software_encryption_enabled': ... + }, + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'state': '...', + 'create_time': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'type': '...', + 'name': '...' + } + ] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMAggregate(object): + ''' aggregates initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_aggregates(self): + """ + Fetch details of aggregates. + :return: + Dictionary of current details if aggregates found + None if aggregates is not found + """ + data = {} + api = "datacenter/storage/aggregates?order_by=performance_capacity.used" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the aggregates listing + :return: None + """ + current = self.get_aggregates() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Aggregate class instance and invoke apply + :return: None + """ + list_aggregates_obj = NetAppUMAggregate() + list_aggregates_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_clusters_info.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_clusters_info.py new file mode 100644 index 000000000..60baa7a48 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_clusters_info.py @@ -0,0 +1,152 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_clusters +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_clusters_info +short_description: NetApp Unified Manager list cluster. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Cluster on AIQUM. +''' + +EXAMPLES = """ +- name: List Clusters + netapp.um_info.na_um_clusters_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Clusters information + returned: always + type: list + sample: [{ + 'name': '...', + 'version': + { + 'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + 'management_ip': '...', + 'contact': ..., + '_links': + { + 'self': + { + 'href': '...' + } + }, + 'location': '...', + 'key': '', + 'nodes': + [ + { + 'uptime': ..., + 'uuid': '...', + 'version': + { + 'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + '_links': + { + 'self': + { + 'href': '...' + } + }, + 'location': '...', + 'key': '...', + 'serial_number': '...', + 'model': '...', + 'name': '...' + } + ], + 'isSanOptimized': ..., + 'uuid': '...' + } + ] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMCluster(object): + ''' cluster initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_clusters(self): + """ + Fetch details of clusters. + :return: + Dictionary of current details if clusters found + None if clusters is not found + """ + data = {} + api = "datacenter/cluster/clusters" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the cluster listing + :return: None + """ + current = self.get_clusters() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Cluster class instance and invoke apply + :return: None + """ + list_cluster_obj = NetAppUMCluster() + list_cluster_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_list_aggregates.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_aggregates.py new file mode 100644 index 000000000..10a34cfdf --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_aggregates.py @@ -0,0 +1,163 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_aggregates +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_aggregates_info +short_description: NetApp Unified Manager list aggregates. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Aggregates on AIQUM. +''' + +EXAMPLES = """ +- name: List Aggregates + netapp.um_info.na_um_aggregates_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Aggregates information + returned: always + type: list + sample: [{'node': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'snaplock_type': '...', + 'uuid': '...', + 'space': + {'block_storage': + {'available': ..., + 'used': ..., + 'size': ... + }, + 'efficiency': + {'savings': ..., + 'logical_used': ... + } + }, + 'block_storage': + {'hybrid_cache': + {'enabled': ..., + 'size': ... + }, + 'primary': + {'raid_size': ..., + 'raid_type': '...' + }, + 'mirror': + {'state': '...' + } + }, + 'data_encryption': + {'software_encryption_enabled': ... + }, + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'state': '...', + 'create_time': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'type': '...', + 'name': '...' + } + ] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMAggregate(object): + ''' aggregates initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_aggregates(self): + """ + Fetch details of aggregates. + :return: + Dictionary of current details if aggregates found + None if aggregates is not found + """ + data = {} + api = "datacenter/storage/aggregates?order_by=performance_capacity.used" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the aggregates listing + :return: None + """ + current = self.get_aggregates() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Aggregate class instance and invoke apply + :return: None + """ + list_aggregates_obj = NetAppUMAggregate() + list_aggregates_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_list_clusters.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_clusters.py new file mode 100644 index 000000000..60baa7a48 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_clusters.py @@ -0,0 +1,152 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_clusters +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_clusters_info +short_description: NetApp Unified Manager list cluster. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Cluster on AIQUM. +''' + +EXAMPLES = """ +- name: List Clusters + netapp.um_info.na_um_clusters_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Clusters information + returned: always + type: list + sample: [{ + 'name': '...', + 'version': + { + 'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + 'management_ip': '...', + 'contact': ..., + '_links': + { + 'self': + { + 'href': '...' + } + }, + 'location': '...', + 'key': '', + 'nodes': + [ + { + 'uptime': ..., + 'uuid': '...', + 'version': + { + 'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + '_links': + { + 'self': + { + 'href': '...' + } + }, + 'location': '...', + 'key': '...', + 'serial_number': '...', + 'model': '...', + 'name': '...' + } + ], + 'isSanOptimized': ..., + 'uuid': '...' + } + ] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMCluster(object): + ''' cluster initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_clusters(self): + """ + Fetch details of clusters. + :return: + Dictionary of current details if clusters found + None if clusters is not found + """ + data = {} + api = "datacenter/cluster/clusters" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the cluster listing + :return: None + """ + current = self.get_clusters() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Cluster class instance and invoke apply + :return: None + """ + list_cluster_obj = NetAppUMCluster() + list_cluster_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_list_nodes.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_nodes.py new file mode 100644 index 000000000..27e81ec2e --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_nodes.py @@ -0,0 +1,145 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_nodes +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_nodes_info +short_description: NetApp Unified Manager list nodes. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Nodes on AIQUM. +''' + +EXAMPLES = """ +- name: List Nodes + netapp.um_info.na_um_nodes_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Nodes information + returned: always + type: list + sample: [{'allFlashOptimized': ..., + 'uptime': ..., + 'vendor': '...', + 'uuid': '...', + 'nvramid': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'version': + {'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + 'systemid': '...', + 'location': '...', + 'key': ...', + 'is_all_flash_optimized': ..., + 'serial_number': '...', + 'model': '...', + 'ha': + {'partners': + [{'_links': {}, + 'uuid': ..., + 'key': ..., + 'name': ... + }] + }, + 'health': ..., + 'name': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMNode(object): + ''' nodes initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_nodes(self): + """ + Fetch details of nodes. + :return: + Dictionary of current details if nodes found + None if nodes is not found + """ + data = {} + api = "datacenter/cluster/nodes?order_by=performance_capacity.used" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the nodes listing + :return: None + """ + current = self.get_nodes() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Node class instance and invoke apply + :return: None + """ + list_nodes_obj = NetAppUMNode() + list_nodes_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_list_svms.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_svms.py new file mode 100644 index 000000000..2722e9ef6 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_svms.py @@ -0,0 +1,174 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_svms +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_svms_info +short_description: NetApp Unified Manager list svms. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List SVMs on AIQUM. +''' + +EXAMPLES = """ +- name: List SVMs + netapp.um_info.na_um_svms_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of SVMs information + returned: always + type: list + sample: [{'fcp': + {'enabled': ... + }, + 'dns': ..., + 'snapshot_policy': + {'_links': {}, + 'uuid': ..., + 'key': '...', + 'name': '...' + }, + 'language': '...', + 'subtype': 'default', + 'aggregates': + [{'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }], + 'nvme': + {'enabled': ... + }, + 'ipspace': + {'_links': {}, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'uuid': '...', + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'state': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'ldap': + {'enabled': ... + }, + 'nis': + {'domain': ..., + 'enabled': ..., + 'servers': ... + }, + 'cifs': + {'enabled': ..., + 'name': ..., + 'ad_domain': + {'fqdn': ... + } + }, + 'iscsi': + {'enabled': ... + }, + 'nfs': + {'enabled': ... + }, + 'name': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMSVM(object): + ''' svms initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_svms(self): + """ + Fetch details of svms. + :return: + Dictionary of current details if svms found + None if svms is not found + """ + data = {} + api = "datacenter/svm/svms" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the svms listing + :return: None + """ + current = self.get_svms() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create SVM class instance and invoke apply + :return: None + """ + list_svms_obj = NetAppUMSVM() + list_svms_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_list_volumes.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_volumes.py new file mode 100644 index 000000000..099213226 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_list_volumes.py @@ -0,0 +1,133 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_volumes +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_volumes_info +short_description: NetApp Unified Manager list volumes. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.6.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Volumes on AIQUM. +''' + +EXAMPLES = """ +- name: List Volumes + netapp.um_info.na_um_volumes_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Volumes information + returned: always + type: list + sample: [{'style': '...', + 'svm': + {'_links': + {'self': {...} + }, + '...' + }, + 'qos': {...}, + 'name': '...', + 'language': '...', + 'space': {...}, + 'aggregates': + [ + {...} + ], + 'tiering': {...}, + 'autosize': {...}, + 'cluster': {...}, + 'state': '...', + 'create_time': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'snapmirror': {...}, + 'snapshot_policy': {...}, + 'type': '...', + 'uuid': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMVolume(object): + ''' volumes initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_volumes(self): + """ + Fetch details of volumes. + :return: + Dictionary of current details if volumes found + None if volumes is not found + """ + data = {} + api = "datacenter/storage/volumes" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the volumes listing + :return: None + """ + current = self.get_volumes() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Volume class instance and invoke apply + :return: None + """ + list_volumes_obj = NetAppUMVolume() + list_volumes_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_nodes_info.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_nodes_info.py new file mode 100644 index 000000000..27e81ec2e --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_nodes_info.py @@ -0,0 +1,145 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_nodes +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_nodes_info +short_description: NetApp Unified Manager list nodes. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Nodes on AIQUM. +''' + +EXAMPLES = """ +- name: List Nodes + netapp.um_info.na_um_nodes_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Nodes information + returned: always + type: list + sample: [{'allFlashOptimized': ..., + 'uptime': ..., + 'vendor': '...', + 'uuid': '...', + 'nvramid': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'version': + {'generation': ..., + 'major': ..., + 'full': '...', + 'minor': ... + }, + 'systemid': '...', + 'location': '...', + 'key': ...', + 'is_all_flash_optimized': ..., + 'serial_number': '...', + 'model': '...', + 'ha': + {'partners': + [{'_links': {}, + 'uuid': ..., + 'key': ..., + 'name': ... + }] + }, + 'health': ..., + 'name': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMNode(object): + ''' nodes initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_nodes(self): + """ + Fetch details of nodes. + :return: + Dictionary of current details if nodes found + None if nodes is not found + """ + data = {} + api = "datacenter/cluster/nodes?order_by=performance_capacity.used" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the nodes listing + :return: None + """ + current = self.get_nodes() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Node class instance and invoke apply + :return: None + """ + list_nodes_obj = NetAppUMNode() + list_nodes_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_svms_info.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_svms_info.py new file mode 100644 index 000000000..2722e9ef6 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_svms_info.py @@ -0,0 +1,174 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_svms +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_svms_info +short_description: NetApp Unified Manager list svms. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.5.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List SVMs on AIQUM. +''' + +EXAMPLES = """ +- name: List SVMs + netapp.um_info.na_um_svms_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of SVMs information + returned: always + type: list + sample: [{'fcp': + {'enabled': ... + }, + 'dns': ..., + 'snapshot_policy': + {'_links': {}, + 'uuid': ..., + 'key': '...', + 'name': '...' + }, + 'language': '...', + 'subtype': 'default', + 'aggregates': + [{'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }], + 'nvme': + {'enabled': ... + }, + 'ipspace': + {'_links': {}, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'uuid': '...', + 'cluster': + {'_links': + {'self': + {'href': '...' + } + }, + 'uuid': '...', + 'key': '...', + 'name': '...' + }, + 'state': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'ldap': + {'enabled': ... + }, + 'nis': + {'domain': ..., + 'enabled': ..., + 'servers': ... + }, + 'cifs': + {'enabled': ..., + 'name': ..., + 'ad_domain': + {'fqdn': ... + } + }, + 'iscsi': + {'enabled': ... + }, + 'nfs': + {'enabled': ... + }, + 'name': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMSVM(object): + ''' svms initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_svms(self): + """ + Fetch details of svms. + :return: + Dictionary of current details if svms found + None if svms is not found + """ + data = {} + api = "datacenter/svm/svms" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the svms listing + :return: None + """ + current = self.get_svms() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create SVM class instance and invoke apply + :return: None + """ + list_svms_obj = NetAppUMSVM() + list_svms_obj.apply() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/netapp/um_info/plugins/modules/na_um_volumes_info.py b/ansible_collections/netapp/um_info/plugins/modules/na_um_volumes_info.py new file mode 100644 index 000000000..099213226 --- /dev/null +++ b/ansible_collections/netapp/um_info/plugins/modules/na_um_volumes_info.py @@ -0,0 +1,133 @@ +#!/usr/bin/python + +# (c) 2020, NetApp, Inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +''' +na_um_list_volumes +''' + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'certified'} + + +DOCUMENTATION = ''' +module: na_um_volumes_info +short_description: NetApp Unified Manager list volumes. +extends_documentation_fragment: + - netapp.um_info.netapp.um +version_added: '20.6.0' +author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> + +description: +- List Volumes on AIQUM. +''' + +EXAMPLES = """ +- name: List Volumes + netapp.um_info.na_um_volumes_info: + hostname: "{{ hostname }}" + username: "{{ username }}" + password: "{{ password }}" +""" + +RETURN = """ +records: + description: Returns list of Volumes information + returned: always + type: list + sample: [{'style': '...', + 'svm': + {'_links': + {'self': {...} + }, + '...' + }, + 'qos': {...}, + 'name': '...', + 'language': '...', + 'space': {...}, + 'aggregates': + [ + {...} + ], + 'tiering': {...}, + 'autosize': {...}, + 'cluster': {...}, + 'state': '...', + 'create_time': '...', + '_links': + {'self': + {'href': '...' + } + }, + 'key': '...', + 'snapmirror': {...}, + 'snapshot_policy': {...}, + 'type': '...', + 'uuid': '...' + }] +""" + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils +from ansible_collections.netapp.um_info.plugins.module_utils.netapp_module import NetAppModule +from ansible_collections.netapp.um_info.plugins.module_utils.netapp import UMRestAPI + + +class NetAppUMVolume(object): + ''' volumes initialize and class methods ''' + + def __init__(self): + self.argument_spec = netapp_utils.na_um_host_argument_spec() + self.module = AnsibleModule( + argument_spec=self.argument_spec, + supports_check_mode=True + ) + + self.na_helper = NetAppModule() + self.parameters = self.na_helper.set_parameters(self.module.params) + + self.rest_api = UMRestAPI(self.module) + + def get_volumes(self): + """ + Fetch details of volumes. + :return: + Dictionary of current details if volumes found + None if volumes is not found + """ + data = {} + api = "datacenter/storage/volumes" + message, error = self.rest_api.get(api, data) + if error: + self.module.fail_json(msg=error) + return self.rest_api.get_records(message, api) + + def apply(self): + """ + Apply action to the volumes listing + :return: None + """ + current = self.get_volumes() + if current is not None: + self.na_helper.changed = True + self.module.exit_json(changed=self.na_helper.changed, msg=current) + + +def main(): + """ + Create Volume class instance and invoke apply + :return: None + """ + list_volumes_obj = NetAppUMVolume() + list_volumes_obj.apply() + + +if __name__ == '__main__': + main() |