Repository URL to install this package:
|
Version:
6.0.0 ▾
|
#!/usr/bin/python
""" this is cifs_server module
(c) 2018-2022, 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
DOCUMENTATION = '''
---
module: na_ontap_cifs_server
short_description: NetApp ONTAP CIFS server configuration
extends_documentation_fragment:
- netapp.ontap.netapp.na_ontap
version_added: 2.6.0
author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com>
description:
- Creating / deleting and modifying the CIFS server .
options:
state:
description:
- Whether the specified cifs_server should exist or not.
default: present
choices: ['present', 'absent']
type: str
service_state:
description:
- CIFS Server Administrative Status.
choices: ['stopped', 'started']
type: str
name:
description:
- Specifies the cifs_server name.
required: true
aliases: ['cifs_server_name']
type: str
admin_user_name:
description:
- Specifies the cifs server admin username.
- When used with absent, the account will be deleted if admin_password is also provided.
type: str
admin_password:
description:
- Specifies the cifs server admin password.
- When used with absent, the account will be deleted if admin_user_name is also provided.
type: str
domain:
description:
- The Fully Qualified Domain Name of the Windows Active Directory this CIFS server belongs to.
type: str
workgroup:
description:
- The NetBIOS name of the domain or workgroup this CIFS server belongs to.
type: str
ou:
description:
- The Organizational Unit (OU) within the Windows Active Directory
this CIFS server belongs to.
version_added: 2.7.0
type: str
force:
type: bool
description:
- When state is present, if this is set and a machine account with the same name as
specified in 'name' exists in the Active Directory, it
will be overwritten and reused.
- When state is absent, if this is set, the local CIFS configuration is deleted regardless of communication errors.
- For REST, it requires ontap version 9.11.
version_added: 2.7.0
vserver:
description:
- The name of the vserver to use.
required: true
type: str
from_name:
description:
- Specifies the existing cifs_server name.
- This option is used to rename cifs_server.
- Supported only in REST and requires force to be set to True.
- Requires ontap version 9.11.0.
- if the service is running, it will be stopped to perform the rename action, and automatically restarts.
- if the service is stopped, it will be briefly restarted after the rename action, and stopped again.
type: str
version_added: 21.19.0
'''
EXAMPLES = '''
- name: Create cifs_server
netapp.ontap.na_ontap_cifs_server:
state: present
name: data2
vserver: svm1
service_state: stopped
domain: "{{ id_domain }}"
admin_user_name: "{{ domain_login }}"
admin_password: "{{ domain_pwd }}"
hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}"
password: "{{ netapp_password }}"
- name: Delete cifs_server
netapp.ontap.na_ontap_cifs_server:
state: absent
name: data2
vserver: svm1
admin_user_name: "{{ domain_login }}"
admin_password: "{{ domain_pwd }}"
hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}"
password: "{{ netapp_password }}"
- name: Start cifs_server
netapp.ontap.na_ontap_cifs_server:
state: present
name: data2
vserver: svm1
service_state: started
hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}"
password: "{{ netapp_password }}"
- name: Stop cifs_server
netapp.ontap.na_ontap_cifs_server:
state: present
name: data2
vserver: svm1
service_state: stopped
hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}"
password: "{{ netapp_password }}"
- name: Rename cifs_server - REST
netapp.ontap.na_ontap_cifs_server:
state: present
from_name: data2
name: cifs
vserver: svm1
force: True
hostname: "{{ netapp_hostname }}"
username: "{{ netapp_username }}"
password: "{{ netapp_password }}"
'''
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.netapp_module import NetAppModule
from ansible_collections.netapp.ontap.plugins.module_utils.netapp import OntapRestAPI
from ansible_collections.netapp.ontap.plugins.module_utils import rest_generic
class NetAppOntapcifsServer:
"""
object to describe cifs_server info
"""
def __init__(self):
self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
self.argument_spec.update(dict(
state=dict(required=False, choices=['present', 'absent'], default='present'),
service_state=dict(required=False, choices=['stopped', 'started']),
name=dict(required=True, type='str', aliases=['cifs_server_name']),
workgroup=dict(required=False, type='str', default=None),
domain=dict(required=False, type='str'),
admin_user_name=dict(required=False, type='str'),
admin_password=dict(required=False, type='str', no_log=True),
ou=dict(required=False, type='str'),
force=dict(required=False, type='bool'),
vserver=dict(required=True, type='str'),
from_name=dict(required=False, 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.parameters['cifs_server_name'] = self.parameters['name']
# Set up Rest API
self.rest_api = OntapRestAPI(self.module)
unsupported_rest_properties = ['workgroup']
partially_supported_rest_properties = [['force', (9, 11)]]
self.use_rest = self.rest_api.is_rest_supported_properties(self.parameters, unsupported_rest_properties, partially_supported_rest_properties)
if not self.use_rest:
if not netapp_utils.has_netapp_lib():
self.module.fail_json(msg=netapp_utils.netapp_lib_is_required())
self.server = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=self.parameters['vserver'])
def get_cifs_server(self):
"""
Return details about the CIFS-server
:param:
name : Name of the name of the cifs_server
:return: Details about the cifs_server. None if not found.
:rtype: dict
"""
cifs_server_info = netapp_utils.zapi.NaElement('cifs-server-get-iter')
cifs_server_attributes = netapp_utils.zapi.NaElement('cifs-server-config')
cifs_server_attributes.add_new_child('cifs-server', self.parameters['cifs_server_name'])
cifs_server_attributes.add_new_child('vserver', self.parameters['vserver'])
query = netapp_utils.zapi.NaElement('query')
query.add_child_elem(cifs_server_attributes)
cifs_server_info.add_child_elem(query)
result = self.server.invoke_successfully(cifs_server_info, True)
return_value = None
if result.get_child_by_name('num-records') and \
int(result.get_child_content('num-records')) >= 1:
cifs_server_attributes = result.get_child_by_name('attributes-list').\
get_child_by_name('cifs-server-config')
return_value = {
'cifs_server_name': self.parameters['cifs_server_name'],
'administrative-status': cifs_server_attributes.get_child_content('administrative-status')
}
return return_value
def create_cifs_server(self):
"""
calling zapi to create cifs_server
"""
options = {'cifs-server': self.parameters['cifs_server_name'], 'administrative-status': 'up'
if self.parameters.get('service_state') == 'started' else 'down'}
if 'workgroup' in self.parameters:
options['workgroup'] = self.parameters['workgroup']
if 'domain' in self.parameters:
options['domain'] = self.parameters['domain']
if 'admin_user_name' in self.parameters:
options['admin-username'] = self.parameters['admin_user_name']
if 'admin_password' in self.parameters:
options['admin-password'] = self.parameters['admin_password']
if 'ou' in self.parameters:
options['organizational-unit'] = self.parameters['ou']
if 'force' in self.parameters:
options['force-account-overwrite'] = str(self.parameters['force']).lower()
cifs_server_create = netapp_utils.zapi.NaElement.create_node_with_children(
'cifs-server-create', **options)
try:
self.server.invoke_successfully(cifs_server_create,
enable_tunneling=True)
except netapp_utils.zapi.NaApiError as exc:
self.module.fail_json(msg='Error Creating cifs_server %s: %s' %
(self.parameters['cifs_server_name'], to_native(exc)), exception=traceback.format_exc())
def delete_cifs_server(self):
"""
calling zapi to create cifs_server
"""
options = {}
if 'admin_user_name' in self.parameters:
options['admin-username'] = self.parameters['admin_user_name']
if 'admin_password' in self.parameters:
options['admin-password'] = self.parameters['admin_password']
if 'force' in self.parameters:
options['force-account-delete'] = str(self.parameters['force']).lower()
if options:
cifs_server_delete = netapp_utils.zapi.NaElement.create_node_with_children('cifs-server-delete', **options)
else:
cifs_server_delete = netapp_utils.zapi.NaElement.create_node_with_children('cifs-server-delete')
try:
self.server.invoke_successfully(cifs_server_delete,
enable_tunneling=True)
except netapp_utils.zapi.NaApiError as exc:
self.module.fail_json(msg='Error deleting cifs_server %s: %s' % (self.parameters['cifs_server_name'], to_native(exc)),
exception=traceback.format_exc())
def start_cifs_server(self):
"""
RModify the cifs_server.
"""
cifs_server_modify = netapp_utils.zapi.NaElement.create_node_with_children(
'cifs-server-start')
try:
self.server.invoke_successfully(cifs_server_modify,
enable_tunneling=True)
except netapp_utils.zapi.NaApiError as e:
self.module.fail_json(msg='Error modifying cifs_server %s: %s' % (self.parameters['cifs_server_name'], to_native(e)),
exception=traceback.format_exc())
def stop_cifs_server(self):
"""
RModify the cifs_server.
"""
cifs_server_modify = netapp_utils.zapi.NaElement.create_node_with_children(
'cifs-server-stop')
try:
self.server.invoke_successfully(cifs_server_modify,
enable_tunneling=True)
except netapp_utils.zapi.NaApiError as e:
self.module.fail_json(msg='Error modifying cifs_server %s: %s' % (self.parameters['cifs_server_name'], to_native(e)),
exception=traceback.format_exc())
def get_cifs_server_rest(self, from_name=None):
"""
get details of the cifs_server.
"""
options = {'svm.name': self.parameters['vserver']}
options['name'] = from_name or self.parameters['cifs_server_name']
api = 'protocols/cifs/services'
fields = 'svm.uuid,enabled'
record, error = rest_generic.get_one_record(self.rest_api, api, options, fields)
if error:
self.module.fail_json(msg="Error on fetching cifs: %s" % error)
if record:
record['service_state'] = 'started' if record.pop('enabled') else 'stopped'
return record
def service_state_to_bool(self, modify=None):
if modify and 'service_state' in modify:
return modify['service_state'] == 'started'
else:
return self.parameters.get('service_state') == 'started'
def build_ad_domain(self):
ad_domain = {}
if 'admin_user_name' in self.parameters:
ad_domain['user'] = self.parameters['admin_user_name']
if 'admin_password' in self.parameters:
ad_domain['password'] = self.parameters['admin_password']
if 'ou' in self.parameters:
ad_domain['organizational_unit'] = self.parameters['ou']
if 'domain' in self.parameters:
ad_domain['fqdn'] = self.parameters['domain']
return ad_domain
def create_cifs_server_rest(self):
"""
create the cifs_server.
"""
body = {'svm.name': self.parameters['vserver'],
'name': self.parameters['cifs_server_name'],
'enabled': self.service_state_to_bool()}
ad_domain = self.build_ad_domain()
if 'force' in self.parameters:
body['force'] = self.parameters['force']
if ad_domain:
body['ad_domain'] = ad_domain
api = 'protocols/cifs/services'
dummy, error = rest_generic.post_async(self.rest_api, api, body)
if error is not None:
self.module.fail_json(msg="Error on creating cifs: %s" % error)
def delete_cifs_server_rest(self, current):
"""
delete the cifs_server.
"""
ad_domain = self.build_ad_domain()
body = {'ad_domain': ad_domain} if ad_domain else None
if 'force' in self.parameters:
body['force'] = self.parameters['force']
api = 'protocols/cifs/services'
dummy, error = rest_generic.delete_async(self.rest_api, api, current['svm']['uuid'], body=body)
if error is not None:
self.module.fail_json(msg="Error on deleting cifs server: %s" % error)
def modify_cifs_server_rest(self, current, modify):
"""
Modify the state of CIFS server.
rename: cifs server should be in stopped state
"""
body = {}
query = {}
if 'force' in self.parameters:
query['force'] = self.parameters['force']
body['enabled'] = self.service_state_to_bool(modify)
if 'name' in modify:
body['name'] = self.parameters['name']
ad_domain = self.build_ad_domain()
if ad_domain:
body['ad_domain'] = ad_domain
api = 'protocols/cifs/services'
dummy, error = rest_generic.patch_async(self.rest_api, api, current['svm']['uuid'], body, query)
if error is not None:
self.module.fail_json(msg="Error on modifying cifs server: %s" % error)
def zapiapply(self):
"""
calling all cifs_server features
"""
changed = False
cifs_server_exists = False
netapp_utils.ems_log_event("na_ontap_cifs_server", self.server)
cifs_server_detail = self.get_cifs_server()
if cifs_server_detail:
cifs_server_exists = True
if self.parameters['state'] == 'present':
administrative_status = cifs_server_detail['administrative-status']
if self.parameters.get('service_state') == 'started' and administrative_status == 'down':
changed = True
if self.parameters.get('service_state') == 'stopped' and administrative_status == 'up':
changed = True
else:
# we will delete the CIFs server
changed = True
elif self.parameters['state'] == 'present':
changed = True
if changed and not self.module.check_mode:
if self.parameters['state'] == 'present':
if not cifs_server_exists:
self.create_cifs_server()
elif self.parameters.get('service_state') == 'stopped':
self.stop_cifs_server()
elif self.parameters.get('service_state') == 'started':
self.start_cifs_server()
elif self.parameters['state'] == 'absent':
self.delete_cifs_server()
self.module.exit_json(changed=changed)
def apply(self):
if not self.use_rest:
self.zapiapply()
current = self.get_cifs_server_rest()
cd_action, rename = None, None
modify = None
cd_action = self.na_helper.get_cd_action(current, self.parameters)
if cd_action == 'create' and 'from_name' in self.parameters:
cifs_info = self.get_cifs_server_rest(self.parameters['from_name'])
rename = self.na_helper.is_rename_action(cifs_info, current)
if rename is None:
self.module.fail_json(msg='Error renaming cifs server: %s - no cifs server with from_name: %s.'
% (self.parameters['name'], self.parameters['from_name']))
elif rename:
if 'force' in self.parameters and self.parameters.get('force') is True:
current = cifs_info
cd_action = None
else:
self.module.fail_json(msg='Error renaming cifs server from %s to %s without force.'
% (self.parameters['from_name'], self.parameters['name']))
modify = self.na_helper.get_modified_attributes(current, self.parameters) if cd_action is None else None
if self.na_helper.changed and not self.module.check_mode:
if rename:
current['name'] = self.parameters.get('name')
self.modify_cifs_server_rest(current, modify)
if cd_action == 'create':
self.create_cifs_server_rest()
elif cd_action == 'delete':
self.delete_cifs_server_rest(current)
if modify:
self.modify_cifs_server_rest(current, modify)
self.module.exit_json(changed=self.na_helper.changed)
def main():
cifs_server = NetAppOntapcifsServer()
cifs_server.apply()
if __name__ == '__main__':
main()