def _commit_files(files, result, module): result['changed'] = len(files) > 0 if not result['changed']: result['message'] = "No files need to be unset" if module.check_mode: if len(files) > 0: result['message'] = "These files will be commited: {}".format(" ".join(files)) return if not result['changed']: return startd = datetime.datetime.now() ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, files) endd = datetime.datetime.now() result['start'] = str(startd) result['end'] = str(endd) result['delta'] = str(endd - startd) result['meta']['commited_templates'] = files result['message'] = "These files were be commited: {}".format(" ".join(files)) result['failed'] = 0
# GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # <http://www.gnu.org/licenses/>. __package__='' # workaround for PEP 366 import listener import os import time import univention.debug as ud import univention.config_registry ## for the ucr commit below in postrun we need ucr configHandlers from univention.config_registry import configHandlers ucr_handlers = configHandlers() ucr_handlers.load() from univention.config_registry.interfaces import Interfaces interfaces = Interfaces(listener.configRegistry) hostname = listener.baseConfig['hostname'] domainname = listener.baseConfig['domainname'] ip = str(interfaces.get_default_ip_address().ip) ldap_base = listener.baseConfig['ldap/base'] name='cups-printers' description='Manage CUPS printer configuration' filter='(|(objectClass=univentionPrinter)(objectClass=univentionPrinterGroup))' attributes=['univentionPrinterSpoolHost', 'univentionPrinterModel', 'univentionPrinterURI', 'univentionPrinterLocation', 'description', 'univentionPrinterSambaName','univentionPrinterPricePerPage','univentionPrinterPricePerJob','univentionPrinterQuotaSupport','univentionPrinterGroupMember', 'univentionPrinterACLUsers', 'univentionPrinterACLGroups', 'univentionPrinterACLtype', 'univentionPrinterUseClientDriver',] EMPTY = ('',)
# License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # <https://www.gnu.org/licenses/>. from __future__ import absolute_import from __future__ import print_function import listener import os import univention.debug import univention.lib.listenerSharePath import cPickle import urllib # for the ucr commit below in postrun we need ucr configHandlers from univention.config_registry import configHandlers, ConfigRegistry from univention.config_registry.interfaces import Interfaces ucr_handlers = configHandlers() ucr_handlers.load() domainname = listener.baseConfig['domainname'] name = 'samba-shares' description = 'Create configuration for Samba shares' filter = '(&(objectClass=univentionShare)(objectClass=univentionShareSamba))' # filter fqdn/ip in handler attributes = [] modrdn = '1' tmpFile = '/var/cache/univention-directory-listener/samba-shares.oldObject' def _validate_smb_share_name(name): if not name or len(name) > 80:
def handler(self, dn, new, old, name=None): """Handle LDAP ACL extensions on Master, Backup and Slave""" if not listener.configRegistry.get('ldap/server/type'): return if not listener.configRegistry.get('server/role') in ('domaincontroller_master'): # new, ignore first *inactive* appearance, has to be activated on master first if new and not old and new.get('univentionLDAPACLActive', ['FALSE'])[0] != 'TRUE': ud.debug(ud.LISTENER, ud.PROCESS, '%s: ignore first appearance of %s, not yet activated' % (name, dn)) return # ignore change unless (re) activated if new and old: if not new.get('univentionLDAPACLActive', ['FALSE'])[0] == 'TRUE': ud.debug(ud.LISTENER, ud.PROCESS, '%s: ignore modify of %s, not yet activated' % (name, dn)) return # Check UCS version requirements first and skip new if they are not met. if new: univentionUCSVersionStart = new.get('univentionUCSVersionStart', [None])[0] univentionUCSVersionEnd = new.get('univentionUCSVersionEnd', [None])[0] current_UCS_version = "%s-%s" % (listener.configRegistry.get('version/version'), listener.configRegistry.get('version/patchlevel')) if univentionUCSVersionStart and UCS_Version(current_UCS_version) < UCS_Version(univentionUCSVersionStart): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s requires at least UCR version %s.' % (name, new['cn'][0], univentionUCSVersionStart)) new = None elif univentionUCSVersionEnd and UCS_Version(current_UCS_version) > UCS_Version(univentionUCSVersionEnd): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s specifies compatibility only up to and including UCR version %s.' % (name, new['cn'][0], univentionUCSVersionEnd)) new = None if new: new_version = new.get('univentionOwnedByPackageVersion', [None])[0] if not new_version: return new_pkgname = new.get('univentionOwnedByPackage', [None])[0] if not new_pkgname: return ud.debug(ud.LISTENER, ud.PROCESS, '%s: %s active? %s' % (name, dn, new.get('univentionLDAPACLActive'))) if old: # check for trivial changes diff_keys = [key for key in new.keys() if new.get(key) != old.get(key) and key not in ('entryCSN', 'modifyTimestamp', 'modifiersName')] if diff_keys == ['univentionLDAPACLActive'] and new.get('univentionLDAPACLActive')[0] == 'TRUE': # ignore status change on master, already activated if listener.configRegistry.get('server/role') in ('domaincontroller_master'): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: activation status changed.' % (name, new['cn'][0])) return elif diff_keys == ['univentionAppIdentifier']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: App identifier changed.' % (name, new['cn'][0])) return ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: changed attributes: %s' % (name, new['cn'][0], diff_keys)) if new_pkgname == old.get('univentionOwnedByPackage', [None])[0]: old_version = old.get('univentionOwnedByPackageVersion', ['0'])[0] rc = apt.apt_pkg.version_compare(new_version, old_version) if not rc > -1: ud.debug(ud.LISTENER, ud.WARN, '%s: New version is lower than version of old object (%s), skipping update.' % (name, old_version)) return try: new_object_data = bz2.decompress(new.get('univentionLDAPACLData')[0]) except TypeError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error uncompressing data of object %s.' % (name, dn)) return new_basename = new.get('univentionLDAPACLFilename')[0] new_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, new_basename) listener.setuid(0) try: backup_filename = None backup_ucrinfo_filename = None backup_backlink_filename = None if old: old_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, old.get('univentionLDAPACLFilename')[0]) if os.path.exists(old_filename): backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, removing it.' % (name, old_filename)) os.unlink(old_filename) backup_filename = None os.close(backup_fd) # plus the old backlink file old_backlink_filename = "%s.info" % old_filename if os.path.exists(old_backlink_filename): backup_backlink_fd, backup_backlink_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old backlink file %s to %s.' % (name, old_backlink_filename, backup_backlink_filename)) try: shutil.move(old_backlink_filename, backup_backlink_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old backlink file %s, removing it.' % (name, old_backlink_filename)) os.unlink(old_backlink_filename) backup_backlink_filename = None os.close(backup_backlink_fd) # and the old UCR registration old_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, old.get('univentionLDAPACLFilename')[0])) if os.path.exists(old_ucrinfo_filename): backup_ucrinfo_fd, backup_ucrinfo_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old UCR info file %s to %s.' % (name, old_ucrinfo_filename, backup_ucrinfo_filename)) try: shutil.move(old_ucrinfo_filename, backup_ucrinfo_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old UCR info file %s, removing it.' % (name, old_ucrinfo_filename)) os.unlink(old_ucrinfo_filename) backup_ucrinfo_filename = None os.close(backup_ucrinfo_fd) if not os.path.isdir(self.ucr_slapd_conf_subfile_dir): if os.path.exists(self.ucr_slapd_conf_subfile_dir): ud.debug(ud.LISTENER, ud.WARN, '%s: Directory name %s occupied, renaming blocking file.' % (name, self.ucr_slapd_conf_subfile_dir)) shutil.move(self.ucr_slapd_conf_subfile_dir, "%s.bak" % self.ucr_slapd_conf_subfile_dir) ud.debug(ud.LISTENER, ud.INFO, '%s: Create directory %s.' % (name, self.ucr_slapd_conf_subfile_dir)) os.makedirs(self.ucr_slapd_conf_subfile_dir, 0o755) # Create new extension file try: ud.debug(ud.LISTENER, ud.INFO, '%s: Writing new extension file %s.' % (name, new_filename)) with open(new_filename, 'w') as f: f.write(new_object_data) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing file %s.' % (name, new_filename)) return # plus backlink file try: new_backlink_filename = "%s.info" % new_filename ud.debug(ud.LISTENER, ud.INFO, '%s: Writing backlink file %s.' % (name, new_backlink_filename)) with open(new_backlink_filename, 'w') as f: f.write("%s\n" % dn) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing backlink file %s.' % (name, new_backlink_filename)) return # and UCR registration try: new_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, new.get('univentionLDAPACLFilename')[0])) ud.debug(ud.LISTENER, ud.INFO, '%s: Writing UCR info file %s.' % (name, new_ucrinfo_filename)) with open(new_ucrinfo_filename, 'w') as f: f.write("Type: multifile\nMultifile: etc/ldap/slapd.conf\n\nType: subfile\nMultifile: etc/ldap/slapd.conf\nSubfile: etc/ldap/slapd.conf.d/%s\n" % new_basename) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing UCR info file %s.' % (name, new_ucrinfo_filename)) return # Commit to slapd.conf ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # validate p = subprocess.Popen(['/usr/sbin/slaptest', '-u'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0: ud.debug(ud.LISTENER, ud.ERROR, '%s: slapd.conf validation failed:\n%s.' % (name, stdout)) # Revert changes ud.debug(ud.LISTENER, ud.ERROR, '%s: Removing new file %s.' % (name, new_filename)) os.unlink(new_filename) os.unlink(new_backlink_filename) os.unlink(new_ucrinfo_filename) if backup_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous file %s.' % (name, old_filename)) try: shutil.move(backup_filename, old_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old file %s.' % (name, old_filename)) # plus backlink file if backup_backlink_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous backlink file %s.' % (name, old_backlink_filename)) try: shutil.move(backup_backlink_filename, old_backlink_filename) os.close(backup_backlink_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old backlink file %s.' % (name, old_backlink_filename)) # and the old UCR registration if backup_ucrinfo_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous UCR info file %s.' % (name, old_ucrinfo_filename)) try: shutil.move(backup_ucrinfo_filename, old_ucrinfo_filename) os.close(backup_ucrinfo_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old UCR info file %s.' % (name, old_ucrinfo_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful.' % (name,)) # cleanup backup if backup_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) # plus backlink file if backup_backlink_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old backlink file %s.' % (name, backup_backlink_filename)) os.unlink(backup_backlink_filename) os.close(backup_backlink_fd) # and the old UCR registration if backup_ucrinfo_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old UCR info file %s.' % (name, backup_ucrinfo_filename)) os.unlink(backup_ucrinfo_filename) os.close(backup_ucrinfo_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() elif old: old_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, old.get('univentionLDAPACLFilename')[0]) # plus backlink file old_backlink_filename = "%s.info" % old_filename # and the old UCR registration old_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, old.get('univentionLDAPACLFilename')[0])) if os.path.exists(old_filename): listener.setuid(0) try: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing extension %s.' % (name, old['cn'][0])) if os.path.exists(old_ucrinfo_filename): os.unlink(old_ucrinfo_filename) if os.path.exists(old_backlink_filename): os.unlink(old_backlink_filename) os.unlink(old_filename) ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid()
def handler(self, dn, new, old, name=None): """Handle LDAP schema extensions on Master and Backup""" if not listener.configRegistry.get('server/role') in ('domaincontroller_master', 'domaincontroller_backup'): return if new: new_version = new.get('univentionOwnedByPackageVersion', [None])[0] if not new_version: return new_pkgname = new.get('univentionOwnedByPackage', [None])[0] if not new_pkgname: return if old: # check for trivial changes diff_keys = [key for key in new.keys() if new.get(key) != old.get(key) and key not in ('entryCSN', 'modifyTimestamp', 'modifiersName')] if diff_keys == ['univentionLDAPSchemaActive'] and new.get('univentionLDAPSchemaActive') == ['TRUE']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: activation status changed.' % (name, new['cn'][0])) return elif diff_keys == ['univentionAppIdentifier']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: App identifier changed.' % (name, new['cn'][0])) return ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: changed attributes: %s' % (name, new['cn'][0], diff_keys)) if new_pkgname == old.get('univentionOwnedByPackage', [None])[0]: old_version = old.get('univentionOwnedByPackageVersion', ['0'])[0] rc = apt.apt_pkg.version_compare(new_version, old_version) if not rc > -1: ud.debug(ud.LISTENER, ud.WARN, '%s: New version is lower than version of old object (%s), skipping update.' % (name, old_version)) return try: new_object_data = bz2.decompress(new.get('univentionLDAPSchemaData')[0]) except TypeError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error uncompressing data of object %s.' % (name, dn)) return new_filename = os.path.join(self.basedir, new.get('univentionLDAPSchemaFilename')[0]) listener.setuid(0) try: backup_filename = None if old: old_filename = os.path.join(self.basedir, old.get('univentionLDAPSchemaFilename')[0]) if os.path.exists(old_filename): backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, removing it.' % (name, old_filename)) os.unlink(old_filename) # no choice backup_filename = None os.close(backup_fd) if not os.path.isdir(self.basedir): if os.path.exists(self.basedir): ud.debug(ud.LISTENER, ud.WARN, '%s: Directory name %s occupied, renaming blocking file.' % (name, self.basedir)) shutil.move(self.basedir, "%s.bak" % self.basedir) ud.debug(ud.LISTENER, ud.INFO, '%s: Create directory %s.' % (name, self.basedir)) os.makedirs(self.basedir, 0o755) # Create new extension file try: ud.debug(ud.LISTENER, ud.INFO, '%s: Writing new extension file %s.' % (name, new_filename)) with open(new_filename, 'w') as f: f.write(new_object_data) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing file %s.' % (name, new_filename)) return ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # validate # Slapschema doesn't fail on schema errors, errors are printed to stdout (Bug #45571) p = subprocess.Popen(['/usr/sbin/slapschema', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0 or stdout: ud.debug(ud.LISTENER, ud.ERROR, '%s: validation failed:\n%s.' % (name, stdout)) # Revert changes ud.debug(ud.LISTENER, ud.ERROR, '%s: Removing new file %s.' % (name, new_filename)) os.unlink(new_filename) if backup_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous file %s.' % (name, old_filename)) try: shutil.move(backup_filename, old_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old file %s.' % (name, old_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful.' % (name,)) # cleanup backup if backup_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() elif old: old_filename = os.path.join(self.basedir, old.get('univentionLDAPSchemaFilename')[0]) if os.path.exists(old_filename): listener.setuid(0) try: backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, leaving it untouched.' % (name, old_filename)) os.close(backup_fd) return ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # Slapschema doesn't fail on schema errors, errors are printed to stdout (Bug #45571) p = subprocess.Popen(['/usr/sbin/slapschema', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0 or stdout: ud.debug(ud.LISTENER, ud.WARN, '%s: validation fails without %s:\n%s.' % (name, old_filename, stdout)) ud.debug(ud.LISTENER, ud.WARN, '%s: Restoring %s.' % (name, old_filename)) # Revert changes try: with open(backup_filename, 'r') as original: file_data = original.read() with open(old_filename, 'w') as target_file: target_file.write("### %s: Leftover of removed settings/ldapschema\n" % (datetime.datetime.now(), ) + file_data) os.unlink(backup_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting removal of %s.' % (name, old_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful, removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() return