Server IP : 85.214.239.14 / Your IP : 3.15.186.27 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /lib/python3/dist-packages/ansible_collections/netapp/ontap/plugins/modules/ |
Upload File : |
#!/usr/bin/python # (c) 2018-2023, NetApp, Inc # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ''' na_ontap_dns ''' from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' module: na_ontap_dns short_description: NetApp ONTAP Create, delete, modify DNS servers. extends_documentation_fragment: - netapp.ontap.netapp.na_ontap version_added: 2.7.0 author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> description: - Create, delete, modify DNS servers. - With REST, the module is currently limited to data vservers for delete or modify operations. options: state: description: - Whether the DNS servers should be enabled for the given vserver. choices: ['present', 'absent'] type: str default: present vserver: description: - The name of the vserver to use. - With REST, for cluster scoped DNS, omit this option or set it to NULL. - With ZAPI or REST, for cluster scoped DNS, this can also be set to the cluster vserver name. type: str domains: description: - List of DNS domains such as 'sales.bar.com'. The first domain is the one that the Vserver belongs to. type: list elements: str nameservers: description: - List of IPv4 addresses of name servers such as '123.123.123.123'. type: list elements: str skip_validation: type: bool description: - By default, all nameservers are checked to validate they are available to resolve. - If you DNS servers are not yet installed or momentarily not available, you can set this option to 'true' - to bypass the check for all servers specified in nameservers field. - With REST, requires ONTAP 9.9.1 or later and ignored for cluster DNS operations. version_added: 2.8.0 ''' EXAMPLES = """ - name: create or modify DNS netapp.ontap.na_ontap_dns: state: present hostname: "{{hostname}}" username: "{{username}}" password: "{{password}}" vserver: "{{vservername}}" domains: sales.bar.com nameservers: 10.193.0.250,10.192.0.250 skip_validation: true - name: create or modify cluster DNS with REST netapp.ontap.na_ontap_dns: state: present hostname: "{{hostname}}" username: "{{username}}" password: "{{password}}" domains: sales.bar.com nameservers: 10.193.0.250,10.192.0.250 """ RETURN = """ """ import traceback from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native import ansible_collections.netapp.ontap.plugins.module_utils.netapp as netapp_utils from ansible_collections.netapp.ontap.plugins.module_utils import rest_generic from ansible_collections.netapp.ontap.plugins.module_utils.netapp_module import NetAppModule class NetAppOntapDns: """ Enable and Disable dns """ def __init__(self): self.use_rest = False self.argument_spec = netapp_utils.na_ontap_host_argument_spec() self.argument_spec.update(dict( state=dict(required=False, type='str', choices=['present', 'absent'], default='present'), vserver=dict(required=False, type='str'), domains=dict(required=False, type='list', elements='str'), nameservers=dict(required=False, type='list', elements='str'), skip_validation=dict(required=False, type='bool') )) self.module = AnsibleModule( argument_spec=self.argument_spec, required_if=[('state', 'present', ['domains', 'nameservers'])], supports_check_mode=True ) self.na_helper = NetAppModule() self.parameters = self.na_helper.set_parameters(self.module.params) # Cluster vserver and data vserver use different REST API. self.is_cluster = False # REST API should be used for ONTAP 9.6 or higher, ZAPI for lower version self.rest_api = netapp_utils.OntapRestAPI(self.module) self.use_rest = self.rest_api.is_rest_supported_properties(self.parameters, None, [['skip_validation', (9, 9, 1)]]) if not self.use_rest: if not netapp_utils.has_netapp_lib(): self.module.fail_json(msg=netapp_utils.netapp_lib_is_required()) if not self.parameters.get('vserver'): self.module.fail_json(msg="Error: vserver is a required parameter with ZAPI.") self.server = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=self.parameters['vserver']) return def patch_cluster_dns(self): api = 'cluster' body = { 'dns_domains': self.parameters['domains'], 'name_servers': self.parameters['nameservers'] } if self.parameters.get('skip_validation'): self.module.warn("skip_validation is ignored for cluster DNS operations in REST.") dummy, error = rest_generic.patch_async(self.rest_api, api, None, body) if error: self.module.fail_json(msg="Error updating cluster DNS options: %s" % error) def create_dns_rest(self): """ Create DNS server :return: none """ if self.is_cluster or not self.parameters.get('vserver'): # with 9.13, using scope=cluster with POST on 'name-services/dns' does not work: # "svm.uuid" is a required field return self.patch_cluster_dns() api = 'name-services/dns' body = { 'domains': self.parameters['domains'], 'servers': self.parameters['nameservers'], 'svm': { 'name': self.parameters['vserver'] } } if 'skip_validation' in self.parameters: body['skip_config_validation'] = self.parameters['skip_validation'] dummy, error = rest_generic.post_async(self.rest_api, api, body) if error: self.module.fail_json(msg="Error creating DNS service: %s" % error) def create_dns(self): """ Create DNS server :return: none """ if self.use_rest: return self.create_dns_rest() dns = netapp_utils.zapi.NaElement('net-dns-create') nameservers = netapp_utils.zapi.NaElement('name-servers') domains = netapp_utils.zapi.NaElement('domains') for each in self.parameters['nameservers']: ip_address = netapp_utils.zapi.NaElement('ip-address') ip_address.set_content(each) nameservers.add_child_elem(ip_address) dns.add_child_elem(nameservers) for each in self.parameters['domains']: domain = netapp_utils.zapi.NaElement('string') domain.set_content(each) domains.add_child_elem(domain) dns.add_child_elem(domains) if self.parameters.get('skip_validation'): validation = netapp_utils.zapi.NaElement('skip-config-validation') validation.set_content(str(self.parameters['skip_validation'])) dns.add_child_elem(validation) try: self.server.invoke_successfully(dns, True) except netapp_utils.zapi.NaApiError as error: self.module.fail_json(msg='Error creating dns: %s' % to_native(error), exception=traceback.format_exc()) def destroy_dns_rest(self, dns_attrs): """ Destroys an already created dns :return: """ if self.is_cluster: error = 'Error: cluster scope when deleting DNS with REST requires ONTAP 9.9.1 or later.' self.module.fail_json(msg=error) api = 'name-services/dns' dummy, error = rest_generic.delete_async(self.rest_api, api, dns_attrs['uuid']) if error: self.module.fail_json(msg="Error deleting DNS service: %s" % error) def destroy_dns(self, dns_attrs): """ Destroys an already created dns :return: """ if self.use_rest: return self.destroy_dns_rest(dns_attrs) try: self.server.invoke_successfully(netapp_utils.zapi.NaElement('net-dns-destroy'), True) except netapp_utils.zapi.NaApiError as error: self.module.fail_json(msg='Error destroying dns: %s' % to_native(error), exception=traceback.format_exc()) def get_cluster(self): api = "cluster" record, error = rest_generic.get_one_record(self.rest_api, api) if error: self.module.fail_json(msg="Error getting cluster info: %s" % error) return record def get_cluster_dns(self): cluster_attrs = self.get_cluster() dns_attrs = None if not self.parameters.get('vserver') or self.parameters['vserver'] == cluster_attrs['name']: dns_attrs = { 'domains': cluster_attrs.get('dns_domains'), 'nameservers': cluster_attrs.get('name_servers'), 'uuid': cluster_attrs['uuid'], } self.is_cluster = True if dns_attrs['domains'] is None and dns_attrs['nameservers'] is None: dns_attrs = None return dns_attrs def get_dns_rest(self): if not self.parameters.get('vserver') and not self.rest_api.meets_rest_minimum_version(self.use_rest, 9, 9, 1): # scope requires 9.9, so revert to cluster API return self.get_cluster_dns() api = "name-services/dns" params = {'fields': 'domains,servers,svm'} if self.parameters.get('vserver'): # omit scope as vserver may be a cluster vserver params['svm.name'] = self.parameters['vserver'] else: params['scope'] = 'cluster' record, error = rest_generic.get_one_record(self.rest_api, api, params) if error: self.module.fail_json(msg="Error getting DNS service: %s" % error) if record: return { 'domains': record['domains'], 'nameservers': record['servers'], 'uuid': record['svm']['uuid'] } if self.parameters.get('vserver') and not self.rest_api.meets_rest_minimum_version(self.use_rest, 9, 9, 1): # There is a chance we are working at the cluster level return self.get_cluster_dns() return None def get_dns(self): if self.use_rest: return self.get_dns_rest() dns_obj = netapp_utils.zapi.NaElement('net-dns-get') try: result = self.server.invoke_successfully(dns_obj, True) except netapp_utils.zapi.NaApiError as error: if to_native(error.code) == "15661": # 15661 is object not found return None else: self.module.fail_json(msg="Error getting DNS info: %s." % to_native(error), exception=traceback.format_exc()) attributes = result.get_child_by_name('attributes') if attributes is None: return dns_info = attributes.get_child_by_name('net-dns-info') nameservers = dns_info.get_child_by_name('name-servers') attrs = { 'nameservers': [ each.get_content() for each in nameservers.get_children() ] } domains = dns_info.get_child_by_name('domains') attrs['domains'] = [each.get_content() for each in domains.get_children()] return attrs def modify_dns_rest(self, dns_attrs): if self.is_cluster: return self.patch_cluster_dns() body = {} if dns_attrs['nameservers'] != self.parameters['nameservers']: body['servers'] = self.parameters['nameservers'] if dns_attrs['domains'] != self.parameters['domains']: body['domains'] = self.parameters['domains'] if 'skip_validation' in self.parameters: body['skip_config_validation'] = self.parameters['skip_validation'] api = "name-services/dns" dummy, error = rest_generic.patch_async(self.rest_api, api, dns_attrs['uuid'], body) if error: self.module.fail_json(msg="Error modifying DNS configuration: %s" % error) def modify_dns(self, dns_attrs): if self.use_rest: return self.modify_dns_rest(dns_attrs) dns = netapp_utils.zapi.NaElement('net-dns-modify') if dns_attrs['nameservers'] != self.parameters['nameservers']: nameservers = netapp_utils.zapi.NaElement('name-servers') for each in self.parameters['nameservers']: ip_address = netapp_utils.zapi.NaElement('ip-address') ip_address.set_content(each) nameservers.add_child_elem(ip_address) dns.add_child_elem(nameservers) if dns_attrs['domains'] != self.parameters['domains']: domains = netapp_utils.zapi.NaElement('domains') for each in self.parameters['domains']: domain = netapp_utils.zapi.NaElement('string') domain.set_content(each) domains.add_child_elem(domain) dns.add_child_elem(domains) if self.parameters.get('skip_validation'): validation = netapp_utils.zapi.NaElement('skip-config-validation') validation.set_content(str(self.parameters['skip_validation'])) dns.add_child_elem(validation) try: self.server.invoke_successfully(dns, True) except netapp_utils.zapi.NaApiError as error: self.module.fail_json(msg='Error modifying dns: %s' % to_native(error), exception=traceback.format_exc()) def apply(self): dns_attrs = self.get_dns() cd_action = self.na_helper.get_cd_action(dns_attrs, self.parameters) modify = None if cd_action is None: modify = self.na_helper.get_modified_attributes(dns_attrs, self.parameters) if self.na_helper.changed and not self.module.check_mode: if cd_action == 'create': self.create_dns() elif cd_action == 'delete': self.destroy_dns(dns_attrs) else: self.modify_dns(dns_attrs) result = netapp_utils.generate_result(self.na_helper.changed, cd_action, modify) self.module.exit_json(**result) def main(): """ Create, Delete, Modify DNS servers. """ obj = NetAppOntapDns() obj.apply() if __name__ == '__main__': main()