Repository URL to install this package:
|
Version:
6.0.0 ▾
|
#!/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)
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
module: na_ontap_metrocluster_dr_group
short_description: NetApp ONTAP manage MetroCluster DR Group
extends_documentation_fragment:
- netapp.ontap.netapp.na_ontap
version_added: 20.11.0
author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com>
requirements:
- ONTAP >= 9.8
description:
- Create/Delete MetroCluster DR Group
- Create only supports MCC IP
- Delete supports both MCC IP and MCC FC
options:
state:
choices: ['present', 'absent']
description:
add or remove DR groups
default: present
type: str
dr_pairs:
description: disaster recovery pairs
type: list
required: true
elements: dict
suboptions:
node_name:
description:
- the name of the main node
required: true
type: str
partner_node_name:
description:
- the name of the main partner node
required: true
type: str
partner_cluster_name:
description:
- The name of the partner cluster
required: true
type: str
'''
EXAMPLES = '''
-
name: Manage MetroCluster DR group
hosts: localhost
collections:
- netapp.ontap
vars:
login: &login
hostname: "{{ hostname }}"
username: "{{ username }}"
password: "{{ password }}"
https: True
validate_certs: False
tasks:
- name: Create MetroCluster DR group
na_ontap_metrocluster_dr_group:
<<: *login
dr_pairs:
- partner_name: carchi_cluster3_01
node_name: carchi_cluster1_01
partner_cluster_name: carchi_cluster3
- name: Delete MetroCluster DR group
na_ontap_metrocluster_dr_group:
<<: *login
dr_pairs:
- partner_name: carchi_cluster3_01
node_name: carchi_cluster1_01
state: absent
partner_cluster_name: carchi_cluster3
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
import ansible_collections.netapp.ontap.plugins.module_utils.netapp as netapp_utils
from ansible_collections.netapp.ontap.plugins.module_utils.netapp_module import NetAppModule
from ansible_collections.netapp.ontap.plugins.module_utils.netapp import OntapRestAPI
class NetAppONTAPMetroClusterDRGroup(object):
def __init__(self):
self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
self.argument_spec.update(dict(
state=dict(choices=['present', 'absent'], default='present'),
dr_pairs=dict(required=True, type='list', elements='dict', options=dict(
node_name=dict(required=True, type='str'),
partner_node_name=dict(required=True, type='str')
)),
partner_cluster_name=dict(required=True, type='str')
))
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 = OntapRestAPI(self.module)
self.use_rest = self.rest_api.is_rest()
if not self.use_rest:
self.module.fail_json(msg=self.rest_api.requires_ontap_version('na_ontap_metrocluster_dr_group',
version='9.8'))
def get_dr_group(self):
return_attrs = None
for pair in self.parameters['dr_pairs']:
api = 'cluster/metrocluster/dr-groups'
options = {'fields': '*',
'dr_pairs.node.name': pair['node_name'],
'dr_pairs.partner.name': pair['partner_node_name'],
'partner_cluster.name': self.parameters['partner_cluster_name']}
message, error = self.rest_api.get(api, options)
if error:
self.module.fail_json(msg=error)
if 'records' in message and message['num_records'] == 0:
continue
elif 'records' not in message or message['num_records'] != 1:
error = "Unexpected response from %s: %s" % (api, repr(message))
self.module.fail_json(msg=error)
record = message['records'][0]
return_attrs = {
'partner_cluster_name': record['partner_cluster']['name'],
'dr_pairs': [],
'id': record['id']
}
for dr_pair in record['dr_pairs']:
return_attrs['dr_pairs'].append({'node_name': dr_pair['node']['name'], 'partner_node_name': dr_pair['partner']['name']})
# if we have an return_dr_id we don't need to loop anymore
break
return return_attrs
def get_dr_group_ids_from_nodes(self):
delete_ids = []
for pair in self.parameters['dr_pairs']:
api = 'cluster/metrocluster/nodes'
options = {'fields': '*',
'node.name': pair['node_name']}
message, error = self.rest_api.get(api, options)
if error:
self.module.fail_json(msg=error)
if 'records' in message and message['num_records'] == 0:
continue
elif 'records' not in message or message['num_records'] != 1:
error = "Unexpected response from %s: %s" % (api, repr(message))
self.module.fail_json(msg=error)
record = message['records'][0]
if int(record['dr_group_id']) not in delete_ids:
delete_ids.append(int(record['dr_group_id']))
return delete_ids
def create_dr_group(self):
api = 'cluster/metrocluster/dr-groups'
dr_pairs = []
for pair in self.parameters['dr_pairs']:
dr_pairs.append({'node': {'name': pair['node_name']},
'partner': {'name': pair['partner_node_name']}})
partner_cluster = {'name': self.parameters['partner_cluster_name']}
data = {'dr_pairs': dr_pairs, 'partner_cluster': partner_cluster}
message, error = self.rest_api.post(api, data)
if error is not None:
self.module.fail_json(msg="%s" % error)
message, error = self.rest_api.wait_on_job(message['job'])
if error:
self.module.fail_json(msg="%s" % error)
def delete_dr_groups(self, dr_ids):
for dr_id in dr_ids:
api = 'cluster/metrocluster/dr-groups/' + str(dr_id)
message, error = self.rest_api.delete(api)
if error:
self.module.fail_json(msg=error)
message, error = self.rest_api.wait_on_job(message['job'])
if error:
self.module.fail_json(msg="%s" % error)
def apply(self):
current = self.get_dr_group()
delete_ids = None
cd_action = self.na_helper.get_cd_action(current, self.parameters)
if cd_action is None and current is None and self.parameters['state'] == 'absent':
# check if there is some FC group to delete
delete_ids = self.get_dr_group_ids_from_nodes()
if delete_ids:
cd_action = 'delete'
self.na_helper.changed = True
elif cd_action == 'delete':
delete_ids = [current['id']]
if cd_action and not self.module.check_mode:
if cd_action == 'create':
self.create_dr_group()
if cd_action == 'delete':
self.delete_dr_groups(delete_ids)
self.module.exit_json(changed=self.na_helper.changed)
def main():
obj = NetAppONTAPMetroClusterDRGroup()
obj.apply()
if __name__ == '__main__':
main()