Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

View File

@@ -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.
'''

View File

@@ -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))

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()