diff --git a/univention/udm_share.py b/univention/udm_share.py new file mode 100644 index 00000000000..8831c3d79f3 --- /dev/null +++ b/univention/udm_share.py @@ -0,0 +1,617 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +# Copyright (c) 2016, Adfinis SyGroup AG +# Tobias Rueetschi +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.univention_umc import ( + umc_module_for_add, + umc_module_for_edit, + ldap_search, + base_dn, +) + + +DOCUMENTATION = ''' +--- +module: udm_share +version_added: "2.2" +author: "Tobias Rueetschi (@2-B)" +short_description: Manage samba shares on a univention corporate server +description: + - "This module allows to manage samba shares on a univention corporate + server (UCS). + It uses the python API of the UCS to create a new object or edit it." +requirements: + - Python >= 2.6 +options: + state: + required: false + default: "present" + choices: [ present, absent ] + description: + - Whether the share is present or not. + name: + required: true + description: + - Name + host: + required: false + default: None + description: + - Host FQDN (server which provides the share), e.g. C({{ + ansible_fqdn }}). Required if C(state=present). + path: + required: false + default: None + description: + - Directory on the providing server, e.g. C(/home). Required if C(state=present). + samba_name: + required: false + default: None + description: + - Windows name. Required if C(state=present). + aliases: [ sambaName ] + ou: + required: true + description: + - Organisational unit, inside the LDAP Base DN. + owner: + required: false + default: 0 + description: + - Directory owner of the share's root directory. + group: + required: false + default: '0' + description: + - Directory owner group of the share's root directory. + directorymode: + required: false + default: '00755' + description: + - Permissions for the share's root directory. + root_squash: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Modify user ID for root user (root squashing). + subtree_checking: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Subtree checking. + sync: + required: false + default: 'sync' + description: + - NFS synchronisation. + writeable: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - NFS write access. + samba_block_size: + required: false + default: None + description: + - Blocking size. + aliases: [ sambaBlockSize ] + samba_blocking_locks: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Blocking locks. + aliases: [ sambaBlockingLocks ] + samba_browseable: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Show in Windows network environment. + aliases: [ sambaBrowseable ] + samba_create_mode: + required: false + default: '0744' + description: + - File mode. + aliases: [ sambaCreateMode ] + samba_csc_policy: + required: false + default: 'manual' + description: + - Client-side caching policy. + aliases: [ sambaCscPolicy ] + samba_custom_settings: + required: false + default: [] + description: + - Option name in smb.conf and its value. + aliases: [ sambaCustomSettings ] + samba_directory_mode: + required: false + default: '0755' + description: + - Directory mode. + aliases: [ sambaDirectoryMode ] + samba_directory_security_mode: + required: false + default: '0777' + description: + - Directory security mode. + aliases: [ sambaDirectorySecurityMode ] + samba_dos_filemode: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Users with write access may modify permissions. + aliases: [ sambaDosFilemode ] + samba_fake_oplocks: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Fake oplocks. + aliases: [ sambaFakeOplocks ] + samba_force_create_mode: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Force file mode. + aliases: [ sambaForceCreateMode ] + samba_force_directory_mode: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Force directory mode. + aliases: [ sambaForceDirectoryMode ] + samba_force_directory_security_mode: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Force directory security mode. + aliases: [ sambaForceDirectorySecurityMode ] + samba_force_group: + required: false + default: None + description: + - Force group. + aliases: [ sambaForceGroup ] + samba_force_security_mode: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Force security mode. + aliases: [ sambaForceSecurityMode ] + samba_force_user: + required: false + default: None + description: + - Force user. + aliases: [ sambaForceUser ] + samba_hide_files: + required: false + default: None + description: + - Hide files. + aliases: [ sambaHideFiles ] + samba_hide_unreadable: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Hide unreadable files/directories. + aliases: [ sambaHideUnreadable ] + samba_hosts_allow: + required: false + default: [] + description: + - Allowed host/network. + aliases: [ sambaHostsAllow ] + samba_hosts_deny: + required: false + default: [] + description: + - Denied host/network. + aliases: [ sambaHostsDeny ] + samba_inherit_acls: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Inherit ACLs. + aliases: [ sambaInheritAcls ] + samba_inherit_owner: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Create files/directories with the owner of the parent directory. + aliases: [ sambaInheritOwner ] + samba_inherit_permissions: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Create files/directories with permissions of the parent directory. + aliases: [ sambaInheritPermissions ] + samba_invalid_users: + required: false + default: None + description: + - Invalid users or groups. + aliases: [ sambaInvalidUsers ] + samba_level_2_oplocks: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Level 2 oplocks. + aliases: [ sambaLevel2Oplocks ] + samba_locking: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Locking. + aliases: [ sambaLocking ] + samba_msdfs_root: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - MSDFS root. + aliases: [ sambaMSDFSRoot ] + samba_nt_acl_support: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - NT ACL support. + aliases: [ sambaNtAclSupport ] + samba_oplocks: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Oplocks. + aliases: [ sambaOplocks ] + samba_postexec: + required: false + default: None + description: + - Postexec script. + aliases: [ sambaPostexec ] + samba_preexec: + required: false + default: None + description: + - Preexec script. + aliases: [ sambaPreexec ] + samba_public: + required: false + default: '0' + choices: [ '0', '1' ] + description: + - Allow anonymous read-only access with a guest user. + aliases: [ sambaPublic ] + samba_security_mode: + required: false + default: '0777' + description: + - Security mode. + aliases: [ sambaSecurityMode ] + samba_strict_locking: + required: false + default: 'Auto' + description: + - Strict locking. + aliases: [ sambaStrictLocking ] + samba_vfs_objects: + required: false + default: None + description: + - VFS objects. + aliases: [ sambaVFSObjects ] + samba_valid_users: + required: false + default: None + description: + - Valid users or groups. + aliases: [ sambaValidUsers ] + samba_write_list: + required: false + default: None + description: + - Restrict write access to these users/groups. + aliases: [ sambaWriteList ] + samba_writeable: + required: false + default: '1' + choices: [ '0', '1' ] + description: + - Samba write access. + aliases: [ sambaWriteable ] + nfs_hosts: + required: false + default: [] + description: + - Only allow access for this host, IP address or network. + nfs_custom_settings: + required: false + default: [] + description: + - Option name in exports file. + aliases: [ nfsCustomSettings ] +''' + + +EXAMPLES = ''' +# Create a share named home on the server ucs.example.com with the path /home. +- udm_sahre: name=home + path=/home + host=ucs.example.com + sambaName=Home +''' + + +RETURN = '''# ''' + + +def main(): + module = AnsibleModule( + argument_spec = dict( + name = dict(required=True, + type='str'), + ou = dict(required=True, + type='str'), + owner = dict(type='str', + default='0'), + group = dict(type='str', + default='0'), + path = dict(type='path', + default=None), + directorymode = dict(type='str', + default='00755'), + host = dict(type='str', + default=None), + root_squash = dict(type='bool', + default=True), + subtree_checking = dict(type='bool', + default=True), + sync = dict(type='str', + default='sync'), + writeable = dict(type='bool', + default=True), + sambaBlockSize = dict(type='str', + aliases=['samba_block_size'], + default=None), + sambaBlockingLocks = dict(type='bool', + aliases=['samba_blocking_locks'], + default=True), + sambaBrowseable = dict(type='bool', + aliases=['samba_browsable'], + default=True), + sambaCreateMode = dict(type='str', + aliases=['samba_create_mode'], + default='0744'), + sambaCscPolicy = dict(type='str', + aliases=['samba_csc_policy'], + default='manual'), + sambaCustomSettings = dict(type='list', + aliases=['samba_custom_settings'], + default=[]), + sambaDirectoryMode = dict(type='str', + aliases=['samba_directory_mode'], + default='0755'), + sambaDirectorySecurityMode = dict(type='str', + aliases=['samba_directory_security_mode'], + default='0777'), + sambaDosFilemode = dict(type='bool', + aliases=['samba_dos_filemode'], + default=False), + sambaFakeOplocks = dict(type='bool', + aliases=['samba_fake_oplocks'], + default=False), + sambaForceCreateMode = dict(type='bool', + aliases=['samba_force_create_mode'], + default=False), + sambaForceDirectoryMode = dict(type='bool', + aliases=['samba_force_directory_mode'], + default=False), + sambaForceDirectorySecurityMode = dict(type='bool', + aliases=['samba_force_directory_security_mode'], + default=False), + sambaForceGroup = dict(type='str', + aliases=['samba_force_group'], + default=None), + sambaForceSecurityMode = dict(type='bool', + aliases=['samba_force_security_mode'], + default=False), + sambaForceUser = dict(type='str', + aliases=['samba_force_user'], + default=None), + sambaHideFiles = dict(type='str', + aliases=['samba_hide_files'], + default=None), + sambaHideUnreadable = dict(type='bool', + aliases=['samba_hide_unreadable'], + default=False), + sambaHostsAllow = dict(type='list', + aliases=['samba_hosts_allow'], + default=[]), + sambaHostsDeny = dict(type='list', + aliases=['samba_hosts_deny'], + default=[]), + sambaInheritAcls = dict(type='bool', + aliases=['samba_inherit_acls'], + default=True), + sambaInheritOwner = dict(type='bool', + aliases=['samba_inherit_owner'], + default=False), + sambaInheritPermissions = dict(type='bool', + aliases=['samba_inherit_permissions'], + default=False), + sambaInvalidUsers = dict(type='str', + aliases=['samba_invalid_users'], + default=None), + sambaLevel2Oplocks = dict(type='bool', + aliases=['samba_level_2_oplocks'], + default=True), + sambaLocking = dict(type='bool', + aliases=['samba_locking'], + default=True), + sambaMSDFSRoot = dict(type='bool', + aliases=['samba_msdfs_root'], + default=False), + sambaName = dict(type='str', + aliases=['samba_name'], + default=None), + sambaNtAclSupport = dict(type='bool', + aliases=['samba_nt_acl_support'], + default=True), + sambaOplocks = dict(type='bool', + aliases=['samba_oplocks'], + default=True), + sambaPostexec = dict(type='str', + aliases=['samba_postexec'], + default=None), + sambaPreexec = dict(type='str', + aliases=['samba_preexec'], + default=None), + sambaPublic = dict(type='bool', + aliases=['samba_public'], + default=False), + sambaSecurityMode = dict(type='str', + aliases=['samba_security_mode'], + default='0777'), + sambaStrictLocking = dict(type='str', + aliases=['samba_strict_locking'], + default='Auto'), + sambaVFSObjects = dict(type='str', + aliases=['samba_vfs_objects'], + default=None), + sambaValidUsers = dict(type='str', + aliases=['samba_valid_users'], + default=None), + sambaWriteList = dict(type='str', + aliases=['samba_write_list'], + default=None), + sambaWriteable = dict(type='bool', + aliases=['samba_writeable'], + default=True), + nfs_hosts = dict(type='list', + default=[]), + nfsCustomSettings = dict(type='list', + aliases=['nfs_custom_settings'], + default=[]), + state = dict(default='present', + choices=['present', 'absent'], + type='str') + ), + supports_check_mode=True, + required_if = ([ + ('state', 'present', ['path', 'host', 'sambaName']) + ]) + ) + name = module.params['name'] + state = module.params['state'] + changed = False + + obj = list(ldap_search( + '(&(objectClass=univentionShare)(cn={}))'.format(name), + attr=['cn'] + )) + + exists = bool(len(obj)) + container = 'cn=shares,ou={},{}'.format(module.params['ou'], base_dn()) + dn = 'cn={},{}'.format(name, container) + + if state == 'present': + try: + if not exists: + obj = umc_module_for_add('shares/share', container) + else: + obj = umc_module_for_edit('shares/share', dn) + + module.params['printablename'] = '{} ({})'.format(name, module.params['host']) + for k in obj.keys(): + if module.params[k] is True: + module.params[k] = '1' + elif module.params[k] is False: + module.params[k] = '0' + obj[k] = module.params[k] + + diff = obj.diff() + if exists: + for k in obj.keys(): + if obj.hasChanged(k): + changed = True + else: + changed = True + if not module.check_mode: + if not exists: + obj.create() + elif changed: + obj.modify() + except BaseException as err: + module.fail_json( + msg='Creating/editing share {} in {} failed: {}'.format( + name, + container, + err, + ) + ) + + if state == 'absent' and exists: + try: + obj = umc_module_for_edit('shares/share', dn) + if not module.check_mode: + obj.remove() + changed = True + except BaseException as err: + module.fail_json( + msg='Removing share {} in {} failed: {}'.format( + name, + container, + err, + ) + ) + + module.exit_json( + changed=changed, + name=name, + diff=diff, + container=container + ) + + +if __name__ == '__main__': + main()