def _get_all(self, klass, school, filter_str, lo): if school: schools = [School.cache(school)] else: schools = School.from_binddn(lo) objs = [] for school in schools: try: objs.extend(klass.get_all(lo, school.name, filter_str=filter_str, easy_filter=True)) except noObject as exc: MODULE.error('Could not get all objects of %r: %r' % (klass.__name__, exc)) return [obj.to_dict() for obj in objs]
def printers(self, request, ldap_user_read=None): """List all available printers except PDF printers return: [{'id': <spool host>://<printer name>, 'label': <display name>}, ...] """ try: printers = udm_modules.lookup( 'shares/printer', None, ldap_user_read, scope='sub', base=School.get_search_base( request.options['school']).printers) except udm_errors.noObject: printers = [] result = [] for prt in printers: # ignore PDF printers uri = prt.info.get('uri', []) if uri and uri[0].startswith('cups-pdf'): continue name = prt.info['name'] spool_host = prt.info['spoolHost'][0] # allways prefer myself if self.fqdn in prt.info['spoolHost']: spool_host = self.fqdn result.append({ 'id': '%s://%s' % (spool_host, name), 'label': name }) self.finished(request.id, result)
def examUserContainerDN(self, ldap_admin_write, ldap_position, school): '''lookup examUserContainerDN, create it if missing''' if not self._examUserContainerDN: search_base = School.get_search_base(school) examUsers = search_base.examUsers examUserContainerName = search_base._examUserContainerName try: ldap_admin_write.searchDn('(objectClass=organizationalRole)', examUsers, scope='base') except univention.admin.uexceptions.noObject: try: module_containers_cn = univention.admin.modules.get( 'container/cn') univention.admin.modules.init(ldap_admin_write, ldap_position, module_containers_cn) position = univention.admin.uldap.position( ldap_position.getBase()) position.setDn(ldap_admin_write.parentDn(examUsers)) exam_user_container = module_containers_cn.object( None, ldap_admin_write, position) exam_user_container.open() exam_user_container['name'] = examUserContainerName exam_user_container.create() except univention.admin.uexceptions.base: raise UMC_Error( _('Failed to create exam container\n%s') % traceback.format_exc()) self._examUserContainerDN = examUsers return self._examUserContainerDN
def _run_import_via_python_api(self): # reload UCR ucsschool.lib.models.utils.ucr.load() lo = univention.admin.uldap.getAdminConnection()[0] # get school from first group school = self.group_import.groups[0].school school_obj = SchoolLib.cache(school, display_name=school) if not school_obj.exists(lo): school_obj.dc_name = uts.random_name() school_obj.create(lo) for grp in self.group_import.groups: kwargs = { 'school': grp.school, 'name': grp.name, 'description': grp.description } if grp.mode == 'A': GroupLib(**kwargs).create(lo) elif grp.mode == 'M': GroupLib(**kwargs).modify(lo) elif grp.mode == 'D': GroupLib(**kwargs).remove(lo)
def fileservers_for_school(school_id, ldap_machine_read=None, ldap_position=None): school_obj = School(name=school_id).get_udm_object(ldap_machine_read) server_dn_list = [] server_dn = school_obj.get('ucsschoolHomeShareFileServer') if server_dn: server_dn_list.append(server_dn) server_list = [] for server_dn in server_dn_list: try: fqdn = fqdn_from_serverdn(server_dn) except univention.admin.uexceptions.noObject: print 'Ignoring non-existant ucsschoolHomeShareFileServer "%s"' % ( server_dn, ) continue if fqdn: server_list.append(fqdn) return set(server_list)
def create_ou_python_api(ou, dc, dc_administrative, sharefileserver, ou_displayname): kwargs = {'name': ou, 'dc_name': dc} if dc_administrative: kwargs['dc_name_administrative'] = dc_administrative if sharefileserver: kwargs['class_share_file_server'] = sharefileserver kwargs['home_share_file_server'] = sharefileserver if ou_displayname: kwargs['display_name'] = ou_displayname # invalidate caches and reload UCR ucsschool.lib.models.utils.ucr.load() ucsschool.lib.models.utils._pw_length_cache.clear() # UCSSchoolHelperAbstractClass._search_base_cache.clear() User._profile_path_cache.clear() User._samba_home_path_cache.clear() lo = univention.admin.uldap.getAdminConnection()[0] School.init_udm_module( lo ) # TODO FIXME has to be fixed in ucs-school-lib - should be done automatically School(**kwargs).create(lo)
def guess_room(self, request, ldap_user_read=None): ipaddress = request.options['ipaddress'] host_filter = self._get_host_filter(ipaddress) computers = ldap_user_read.searchDn(host_filter) if computers: room_filter = self._get_room_filter(computers) for school in School.get_all(ldap_user_read): school = school.name for room in ComputerRoom.get_all(ldap_user_read, school, room_filter): self.finished(request.id, dict(school=school, room=room.dn)) return self.finished(request.id, dict(school=None, room=None))
def get_schoolinfo_master(self, school): """ Fetches LDAP information from master about specified OU. This function assumes that the given arguments have already been validated! """ school_name = school try: lo, po = get_machine_connection(write=True) school = School.from_dn(School(name=school_name).dn, None, lo) except noObject: exists = False class_share_server = None home_share_server = None educational_slaves = [] administrative_slaves = [] except ldap.SERVER_DOWN: raise # handled via UMC except ldap.LDAPError as exc: MODULE.warn('LDAP error during receiving school info: %s' % (exc,)) raise UMC_Error(_('The LDAP connection to the master system failed.')) else: exists = True class_share_server = school.class_share_file_server home_share_server = school.home_share_file_server educational_slaves = [SchoolDCSlave.from_dn(dn, None, lo).name for dn in school.educational_servers] administrative_slaves = [SchoolDCSlave.from_dn(dn, None, lo).name for dn in school.administrative_servers] return { 'exists': exists, 'school': school_name, 'classShareServer': class_share_server, 'homeShareServer': home_share_server, 'educational_slaves': educational_slaves, 'administrative_slaves': administrative_slaves, }
def update_local_school_list(): global all_local_schools listener.setuid(0) univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'pupilgroups: update_local_school_list()') try: lo, po = univention.admin.uldap.getMachineConnection(ldap_master=False) all_local_schools = [school.dn for school in School.get_all(lo)] except ldap.LDAPError: all_local_schools = None return finally: univention.debug.debug( univention.debug.LISTENER, univention.debug.PROCESS, 'pupilgroups: all_local_schools=%r' % (all_local_schools, )) listener.unsetuid()
def examGroup(self, ldap_admin_write, ldap_position, school): '''fetch the examGroup object, create it if missing''' if not self._examGroup: search_base = School.get_search_base(school) examGroup = search_base.examGroup examGroupName = search_base.examGroupName if 'groups/group' in self._udm_modules: module_groups_group = self._udm_modules['groups/group'] else: module_groups_group = univention.admin.modules.get( 'groups/group') univention.admin.modules.init(ldap_admin_write, ldap_position, module_groups_group) self._udm_modules['groups/group'] = module_groups_group # Determine exam_group_dn try: ldap_filter = '(objectClass=univentionGroup)' ldap_admin_write.searchDn(ldap_filter, examGroup, scope='base') self._examGroup = module_groups_group.object( None, ldap_admin_write, ldap_position, examGroup) # self._examGroup.create() # currently not necessary except univention.admin.uexceptions.noObject: try: position = univention.admin.uldap.position( ldap_position.getBase()) position.setDn(ldap_admin_write.parentDn(examGroup)) self._examGroup = module_groups_group.object( None, ldap_admin_write, position) self._examGroup.open() self._examGroup['name'] = examGroupName self._examGroup[ 'sambaGroupType'] = self._examGroup.descriptions[ 'sambaGroupType'].base_default[0] self._examGroup.create() except univention.admin.uexceptions.base: raise UMC_Error( _('Failed to create exam group\n%s') % traceback.format_exc()) return self._examGroup
def _run_import_via_python_api(self): # reload UCR ucsschool.lib.models.utils.ucr.load() lo = univention.admin.uldap.getAdminConnection()[0] # get school from first computer school = self.computer_import.windows[0].school school_obj = SchoolLib.cache(school, display_name=school) if not school_obj.exists(lo): school_obj.dc_name = uts.random_name() school_obj.create(lo) def _set_kwargs(computer): kwargs = { 'school': computer.school, 'name': computer.name, 'ip_address': computer.ip, 'mac_address': computer.mac, 'type_name': computer.ctype, 'inventory_number': computer.inventorynumbers, 'zone': computer.zone, } return kwargs for computer in self.computer_import.windows: kwargs = _set_kwargs(computer) WindowsComputerLib(**kwargs).create(lo) # for computer in self.computer_import.memberservers: # kwargs = _set_kwargs(computer) # IPComputerLib(**kwargs).create(lo) for computer in self.computer_import.macos: kwargs = _set_kwargs(computer) MacComputerLib(**kwargs).create(lo) for computer in self.computer_import.ipmanagedclients: kwargs = _set_kwargs(computer) IPComputerLib(**kwargs).create(lo)
def create_roleshares(role_list, school_list=None, ucr=None, ldap_machine_read=None): if not ucr: ucr = univention.config_registry.ConfigRegistry() ucr.load() supported_roles = (role_pupil, role_teacher, role_staff) supported_role_aliases = {'student': 'pupil'} roles = [] for name in role_list: if name in supported_role_aliases: name = supported_role_aliases[name] if name not in supported_roles: print 'Given role is not supported. Only supported roles are %s' % ( supported_roles, ) sys.exit(1) roles.append(name) schools = School.get_all(ldap_machine_read) if not school_list: school_list = [] all_visible_schools = [x.name for x in schools] for school_ou in school_list: if school_ou not in all_visible_schools: print 'School not found: %s' (school_ou, ) for school in schools: if school_list and school.name not in school_list: continue for role in roles: create_roleshare_for_searchbase(role, school, ucr)
def _run_import_via_python_api(self): # reload UCR ucsschool.lib.models.utils.ucr.load() lo = univention.admin.uldap.getAdminConnection()[0] # get school from first user school = self.user_import.students[0].school school_obj = SchoolLib.cache(school, display_name=school) if not school_obj.exists(lo): school_obj.dc_name = uts.random_name() school_obj.create(lo) def _set_kwargs(user): kwargs = { 'school': user.school, 'schools': [user.school], 'name': user.username, 'firstname': user.firstname, 'lastname': user.lastname, 'school_classes': user.school_classes, 'email': user.mail, 'password': user.password, 'disabled': 'none' if user.is_active() else 'all', 'birthday': user.birthday, } return kwargs for user in self.user_import.students: kwargs = _set_kwargs(user) print '* student username=%r mode=%r kwargs=%r' % (user.username, user.mode, kwargs) if user.mode == 'A': StudentLib(**kwargs).create(lo) elif user.mode == 'M': StudentLib(**kwargs).modify(lo) elif user.mode == 'D': StudentLib(**kwargs).remove(lo) for user in self.user_import.teachers: kwargs = _set_kwargs(user) print '* teacher username=%r mode=%r kwargs=%r' % (user.username, user.mode, kwargs) if user.mode == 'A': TeacherLib(**kwargs).create(lo) elif user.mode == 'M': TeacherLib(**kwargs).modify(lo) elif user.mode == 'D': TeacherLib(**kwargs).remove(lo) for user in self.user_import.staff: kwargs = _set_kwargs(user) print '* staff username=%r mode=%r kwargs=%r' % (user.username, user.mode, kwargs) if user.mode == 'A': StaffLib(**kwargs).create(lo) elif user.mode == 'M': StaffLib(**kwargs).modify(lo) elif user.mode == 'D': StaffLib(**kwargs).remove(lo) for user in self.user_import.teacher_staff: kwargs = _set_kwargs(user) print '* teacher_staff username=%r mode=%r kwargs=%r' % (user.username, user.mode, kwargs) if user.mode == 'A': TeachersAndStaffLib(**kwargs).create(lo) elif user.mode == 'M': TeachersAndStaffLib(**kwargs).modify(lo) elif user.mode == 'D': TeachersAndStaffLib(**kwargs).remove(lo)
def send(self, request, ldap_user_read=None, ldap_position=None): ucr.load() if not ucr.get('ucsschool/helpdesk/recipient'): raise UMC_Error(_( 'The message could not be send to the helpdesk team: The email address for the helpdesk team is not configured. It must be configured by an administrator via the UCR variable "ucsschool/helpdesk/recipient".' ), status=500) def _send_thread(sender, recipients, subject, message): MODULE.info('sending mail: thread running') msg = u'From: %s\r\n' % (sanitize_header(sender), ) msg += u'To: %s\r\n' % (sanitize_header(', '.join(recipients)), ) msg += u'Subject: =?UTF-8?Q?%s?=\r\n' % ( sanitize_header(subject).encode('quopri'), ) msg += u'Content-Type: text/plain; charset="UTF-8"\r\n' msg += u'\r\n' msg += message msg += u'\r\n' msg = msg.encode('UTF-8') server = smtplib.SMTP('localhost') server.set_debuglevel(0) server.sendmail(sender, recipients, msg) server.quit() return True recipients = ucr['ucsschool/helpdesk/recipient'].split(' ') school = School.from_dn( School(name=request.options['school']).dn, None, ldap_user_read).display_name category = request.options['category'] message = request.options['message'] subject = u'%s (%s: %s)' % (category, _('School'), school) try: user = User(None, ldap_user_read, ldap_position, self.user_dn) user.open() except ldap.LDAPError: MODULE.error('Errror receiving user information: %s' % (traceback.format_exception(), )) user = { 'displayName': self.username, 'mailPrimaryAddress': '', 'mailAlternativeAddress': [], 'e-mail': [], 'phone': [] } mails = set([user['mailPrimaryAddress']]) | set( user['mailAlternativeAddress']) | set(user['e-mail']) sender = user['mailPrimaryAddress'] if not sender: if ucr.get('hostname') and ucr.get('domainname'): sender = 'ucsschool-helpdesk@%s.%s' % (ucr['hostname'], ucr['domainname']) else: sender = 'ucsschool-helpdesk@localhost' data = [ (_('Sender'), u'%s (%s)' % (user['displayName'], self.username)), (_('School'), school), (_('Mail address'), u', '.join(mails)), (_('Phone number'), u', '.join(user['phone'])), (_('Category'), category), (_('Message'), u'\r\n%s' % (message, )), ] msg = u'\r\n'.join(u'%s: %s' % (key, value) for key, value in data) MODULE.info( 'sending message: %s' % ('\n'.join(map(lambda x: repr(x.strip()), msg.splitlines()))), ) func = notifier.Callback(_send_thread, sender, recipients, subject, msg) MODULE.info('sending mail: starting thread') thread = notifier.threads.Simple( 'HelpdeskMessage', func, notifier.Callback(self.thread_finished_callback, request)) thread.run()
def get_schools(self, request, ldap_user_read=None): schools = School.get_all(ldap_user_read, filter_str=request.options.get('filter'), easy_filter=True) return [school.to_dict() for school in schools]
def create_ou(self, ou_name=None, name_edudc=None, name_admindc=None, displayName='', name_share_file_server=None, use_cli=False, wait_for_replication=True): """ Creates a new OU with random or specified name. The function may also set a specified displayName. If "displayName" is None, a random displayName will be set. If "displayName" equals to the empty string (''), the displayName won't be set. "name_edudc" may contain the optional name for an educational dc slave. "name_admindc" may contain the optional name for an administrative dc slave. If name_share_file_server is set, the class share file server and the home share file server will be set. If use_cli is set to True, the old CLI interface is used. Otherwise the UCS@school python library is used. PLEASE NOTE: if name_edudc is set to the hostname of the master or backup, name_edudc will be unset automatically, because it's not allowed to specify the hostname of the master or any backup in any situation! Return value: (ou_name, ou_dn) ou_name: name of the created OU ou_dn: DN of the created OU object """ # create random display name for OU charset = uts.STR_ALPHANUMDOTDASH + uts.STR_ALPHA.upper() + '()[]/,;:_#"+*@<>~ßöäüÖÄÜ$%&! ' if displayName is None: displayName = uts.random_string(length=random.randint(5, 50), charset=charset) # it is not allowed to set the master as name_edudc ==> resetting name_edudc if isinstance(name_edudc, str): if name_edudc.lower() == self._ucr.get('ldap/master', '').split('.', 1)[0].lower(): print '*** It is not allowed to set the master as name_edudc ==> resetting name_edudc' name_edudc = None elif any([name_edudc.lower() == backup.split('.', 1)[0].lower() for backup in self._ucr.get('ldap/backup', '').split(' ')]): print '*** It is not allowed to set any backup as name_edudc ==> resetting name_edudc' name_edudc = None # create random OU name if not ou_name: ou_name = uts.random_string(length=random.randint(3, 12)) # remember OU name for cleanup self._cleanup_ou_names.add(ou_name) if not use_cli: kwargs = { 'name': ou_name, 'dc_name': name_edudc } if name_admindc: kwargs['dc_name_administrative'] = name_admindc if name_share_file_server: kwargs['class_share_file_server'] = name_share_file_server kwargs['home_share_file_server'] = name_share_file_server if displayName: kwargs['display_name'] = displayName print '' print '*** Creating new OU %r' % (ou_name,) lo = self.open_ldap_connection() School.invalidate_all_caches() School.init_udm_module(lo) # TODO FIXME has to be fixed in ucs-school-lib - should be done automatically result = School(**kwargs).create(lo) print '*** Result of School(...).create(): %r' % (result,) print '\n\n' else: # build command line cmd = [self.PATH_CMD_CREATE_OU] if displayName: cmd += ['--displayName', displayName] cmd += [ou_name] if name_edudc: cmd += [name_edudc] print '*** Calling following command: %r' % cmd retval = subprocess.call(cmd) if retval: utils.fail('create_ou failed with exitcode %s' % retval) if wait_for_replication: utils.wait_for_replication() ou_dn = 'ou=%s,%s' % (ou_name, self.LDAP_BASE) return ou_name, ou_dn
def get_all_school_names(cls, lo): if not cls._all_school_names: cls._all_school_names = [s.name for s in School.get_all(lo)] return cls._all_school_names