def set(self, request): # remove all lessons for lesson in self._lessons.lessons: self._lessons.remove(lesson) try: # add the new lessons for lesson in request.options.get('lessons', []): ( description, begin, end, ) = lesson if begin == end == '00:00' and not description: continue elif not description: raise ValueError( _('A description for a lesson is missing')) else: self._lessons.add(description, begin, end) self._lessons.save() except (ValueError, AttributeError), err: MODULE.info(str(err)) result = {'message': str(err)} self.finished(request.id, result)
def upload_certificate(self, request): def _return(pid, status, bufstdout, bufstderr, request, fn): bufstdout, bufstderr = bufstdout.decode('UTF-8', 'replace'), bufstderr.decode('UTF-8', 'replace') success = True if status == 0: message = _('Certificate has been uploaded successfully.') MODULE.info('Certificate has been uploaded successfully. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % (status, '\n'.join(bufstdout), '\n'.join(bufstderr))) try: self._enable_ssl_and_test_connection(fn) except UMC_Error: message = _('Could not establish connection. Either the certificate is wrong, the Active Directory server is unreachable or it does not support SSL.') success = False else: success = False message = _('Certificate upload or conversion failed.') MODULE.process('Certificate upload or conversion failed. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % (status, '\n'.join(bufstdout), '\n'.join(bufstderr))) self.finished(request.id, [{'success': success, 'message': message}]) upload = request.options[0]['tmpfile'] now = time.strftime('%Y%m%d_%H%M%S', time.localtime()) fn = '/etc/univention/connector/ad/ad_cert_%s.pem' % now cmd = '/usr/bin/openssl x509 -inform der -outform pem -in %s -out %s 2>&1' % (pipes.quote(upload), fn) MODULE.info('Converting certificate into correct format: %s' % cmd) proc = notifier.popen.Shell(cmd, stdout=True, stderr=True) cb = notifier.Callback(_return, request, fn) proc.signal_connect('finished', cb) proc.start()
def _get_category_translations(cls): if cls._category_translations == None: cls._category_translations = {} url = '%s/../categories.ini' % cls.get_metainf_url() try: # open .ini file MODULE.info('opening category translation file: %s' % url) fp = util.urlopen(url) config = ConfigParser.ConfigParser() config.readfp(fp) # get the translations for the current language loc = locale.getlocale()[0] if isinstance(loc, basestring): if not config.has_section(loc): loc = loc.split('_')[0] if config.has_section(loc): for k, v in config.items(loc): cls._category_translations[k] = v except (ConfigParser.Error, urllib2.HTTPError) as e: MODULE.warn( 'Could not load category translations from: %s\n%s' % (url, e)) MODULE.info('loaded category translations: %s' % cls._category_translations) return cls._category_translations
def send_verification_token(self, username): MODULE.info("send_verification_token(): username: {}".format(username)) ucr.load() if ucr.is_false('umc/self-service/account-verification/backend/enabled', True): msg = _('The account verification was disabled via the Univention Configuration Registry.') MODULE.error('send_verification_token(): {}'.format(msg)) raise UMC_Error(msg) invalid_information = { 'success': False, 'failType': 'INVALID_INFORMATION' } users_mod = UDM.machine().version(2).get('users/user') try: user = users_mod.get_by_id(username) except NoObject: return invalid_information try: email = user.props.PasswordRecoveryEmail except AttributeError: return invalid_information else: if not email: return invalid_information self.send_message(username, 'verify_email', email, raise_on_success=False) return { 'success': True, 'data': { 'username': username, } }
def identifies(self): """Property of the UDM module that identifies objects of this type""" for key, prop in getattr(self.module, 'property_descriptions', {}).items(): if prop.identifies: MODULE.info('The property %s identifies to module objects %s' % (key, self.name)) return key return None
def _writeRoomInfo(roomDN, user=None, cmd=None, exam=None, examDescription=None, examEndTime=None): '''Set infos for a room and lock the room.''' info = dict(room=roomDN, user=user, cmd=cmd, exam=exam, examDescription=examDescription, examEndTime=examEndTime, pid=os.getpid()) MODULE.info('Writing info file for room "%s": %s' % (roomDN, info)) try: # write user DN in the room file with open(_getRoomFile(roomDN), 'w') as fd: fcntl.lockf(fd, fcntl.LOCK_EX) try: for key, val in info.iteritems(): if val is not None: fd.write('%s=%s\n' % (key, val)) finally: # make sure that the file is unlocked fcntl.lockf(fd, fcntl.LOCK_UN) except EnvironmentError: MODULE.warn('Failed to write file: %s' % _getRoomFile(roomDN))
def enable_quota_in_kernel(activate): ucr.load() grub_append = ucr.get('grub/append', '') flags = [] option = 'usrquota' match = re.match(r'rootflags=([^\s]*)', grub_append) if match: flags = match.group(1).split(',') if activate and option not in flags: flags.append(option) elif not activate and option in flags: flags.remove(option) flags = ','.join(flags) if flags: flags = 'rootflags=%s' % (flags, ) new_grub_append = grub_append if 'rootflags=' not in grub_append: if flags: new_grub_append = '%s %s' % (grub_append, flags) else: new_grub_append = re.sub(r'rootflags=[^\s]*', flags, grub_append) if new_grub_append != grub_append: MODULE.info('Replacing grub/append from %s to %s' % (grub_append, new_grub_append)) handler_set(['grub/append=%s' % (new_grub_append, )]) status = _('enable') if activate else _('disable') raise QuotaActivationError( _('To %s quota support for the root filesystem the system has to be rebooted.' ) % (status, ))
def _check_usersid_join_permissions(self, lo, usersid): allowed_groups = ucr.get('ucsschool/windows/join/groups', 'Domain Admins').split(',') result = lo.searchDn( ldap.filter.filter_format('sambaSID=%s', [usersid])) if not result: raise UMC_Error('SID %s was not found.' % (usersid, )) user_dn = result[0] MODULE.info("Found user with DN %s" % (user_dn, )) result = lo.search(ldap.filter.filter_format('uniqueMember=%s', [user_dn]), attr=['cn']) if not result: raise UMC_Error('No group memberships for SID %s found.' % (usersid, )) for dn, attr in result: if attr.get('cn', [])[0] in allowed_groups: return raise UMC_Error( 'SID %s is not member of one of the following groups: %s. The allowed groups can be modified by setting the UCR variable ucsschool/windows/join/groups.' % (usersid, allowed_groups))
def get_fqdn(nameserver): # register nameserver resolver = _get_dns_resolver(nameserver) # perform a reverse lookup try: reverse_address = dns.reversename.from_address(nameserver) MODULE.info('Found reverse address: %s' % (reverse_address, )) reverse_lookup = resolver.query(reverse_address, 'PTR') if not len(reverse_lookup): return None fqdn = reverse_lookup[0] parts = [i for i in fqdn.target.labels if i] domain = '.'.join(parts) return domain except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers) as exc: MODULE.warn('Lookup for nameserver %s failed: %s %s' % (nameserver, type(exc).__name__, exc)) except dns.exception.Timeout as exc: MODULE.warn('Lookup for nameserver %s timed out: %s' % (nameserver, exc)) except dns.exception.DNSException as exc: MODULE.error('DNS Exception: %s' % (traceback.format_exc())) return None
def purge(self): """Remove project's cache directory, project file, and at job registrations.""" if not self.projectfile or not os.path.exists(self.projectfile): MODULE.error( 'cannot remove empty or non existing projectfile: %s' % self.projectfile) return self._unregister_at_jobs() # remove cachedir MODULE.info('trying to purge projectfile [%s] and cachedir [%s]' % (self.projectfile, self.cachedir)) if self.cachedir and os.path.exists(self.cachedir): try: shutil.rmtree(self.cachedir) except (OSError, IOError) as e: MODULE.error('failed to cleanup cache directory: %s [%s]' % (self.cachedir, str(e))) # remove projectfile try: os.remove(self.projectfile) except (OSError, IOError) as e: MODULE.error('cannot remove projectfile: %s [%s]' % (self.projectfile, str(e)))
def updates_available(self, request): """ Asks if there are package updates available. (don't get confused by the name of the UniventionUpdater function that is called here.) This is a seperate call since it can take an amount of time, thus being invoked by a seperate button (and not in the background) """ # ----------- DEBUG ----------------- MODULE.info("updater/updates/available invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- result = False what = 'starting' try: # be as current as possible. what = 'reinitializing UniventionUpdater' self.uu.ucr_reinit() what = 'reloading registry' self.ucr.load() what = 'checking update availability' result = self.uu.component_update_available() except Exception, ex: typ = str(type(ex)).strip('<>') msg = '[while %s] [%s] %s' % (what, typ, str(ex)) # result['message'] = msg # result['status'] = 1 MODULE.error(msg)
def set_registry_var(self, name, value): """ Sets a registry variable and tracks changedness in a private variable. This enables the set_save_commit_load() method to commit the files being affected by the changes we have made. Function handles boolean values properly. """ try: oldval = self.ucr.get(name) if isinstance(value, bool): value = self._bool_string(name, value) # Possibly useful: if the value is the empty string -> try to unset this variable. # FIXME Someone please confirm that there are no UCR variables that need # to be set to an empty string! if value == '': value = None # Don't do anything if the value being set is the same as # the value already found. if value == oldval: return MODULE.info('Setting registry variable %r to %r' % (name, value)) self._changes[name] = value except Exception as e: MODULE.warn("set_registry_var('%s', '%s') ERROR %s" % (name, value, str(e)))
def screenshot(self, request): """Returns a JPEG image containing a screenshot of the given computer.""" computer = request.options['computer'] tmpfile = computer.screenshot if computer.hide_screenshot: filename = FN_SCREENSHOT_DENIED elif tmpfile is None: filename = FN_SCREENSHOT_NOTREADY else: filename = tmpfile.name MODULE.info('screenshot(%s): hide screenshot = %r' % (computer.name, computer.hide_screenshot)) try: with open(filename, 'rb') as fd: response = fd.read() except EnvironmentError as exc: MODULE.error('Unable to load screenshot file %r: %s' % (filename, exc)) try: if tmpfile: os.unlink(tmpfile.name) except EnvironmentError as exc: MODULE.error('Unable to remove temporary screenshot file %r: %s' % (tmpfile.name, exc)) self.finished(request.id, response, mimetype='image/jpeg')
def _load_plugins(self): self._plugins = {} for module in os.listdir( os.path.join(os.path.dirname(__file__), 'plugins')): if module.endswith('.py'): try: module = importlib.import_module( 'univention.management.console.modules.computerroom.plugins.%s' % (module[:-3], )) except ImportError: MODULE.error(traceback.format_exc()) for name, plugin in inspect.getmembers(module, inspect.isclass): MODULE.info('Loading plugin %r from module %r' % ( plugin, module, )) if not name.startswith( '_') and plugin is not Plugin and issubclass( plugin, Plugin): try: plugin = plugin(self, self._italc) except Exception: MODULE.error(traceback.format_exc()) else: self._plugins[plugin.name] = plugin
def service(self, request): MODULE.info('State: options=%s' % request.options) self.required_options(request, 'action') self.__update_status() action = request.options['action'] MODULE.info('State: action=%s status_running=%s' % (action, self.status_running)) success = True message = None if self.status_running and action == 'start': message = _( 'Active Directory Connector is already running. Nothing to do.' ) elif not self.status_running and action == 'stop': message = _( 'Active Directory Connector is already stopped. Nothing to do.' ) elif action not in ('start', 'stop'): MODULE.process('State: unknown command: action=%s' % action) message = _( 'Unknown command ("%s") Please report error to your local administrator.' ) % action success = False if message is not None: self.finished(request.id, {'success': success, 'message': message}) return def _run_it(action): return subprocess.call( ('invoke-rc.d', 'univention-ad-connector', action)) def _return(thread, result, request): success = not result if result: message = _( 'Switching running state of Active Directory Connector failed.' ) MODULE.info( 'Switching running state of Active Directory Connector failed. exitcode=%s' % result) else: if request.options.get('action') == 'start': message = _( 'Active Directory connection service has been started.' ) else: message = _( 'Active Directory connection service has been stopped.' ) self.finished(request.id, {'success': success, 'message': message}) cb = notifier.Callback(_return, request) func = notifier.Callback(_run_it, action) thread = notifier.threads.Simple('service', func, cb) thread.run()
def _return(pid, status, bufstdout, bufstderr, request, fn): success = True if status == 0: message = _('Certificate has been uploaded successfully.') MODULE.info( 'Certificate has been uploaded successfully. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % (status, '\n'.join(bufstdout), '\n'.join(bufstderr))) try: self._enable_ssl_and_test_connection(fn) except UMC_Error: message = _( 'Could not establish connection. Either the certificate is wrong, the Active Directory server is unreachable or it does not support SSL.' ) success = False else: success = False message = _('Certificate upload or conversion failed.') MODULE.process( 'Certificate upload or conversion failed. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % (status, '\n'.join(bufstdout), '\n'.join(bufstderr))) self.finished(request.id, [{ 'success': success, 'message': message }])
def updates_serial(self): """ Watches the three sources.list snippets for changes """ result = self._updates_serial.timestamp() MODULE.info(" -> Serial for UPDATES is '%s'" % result) return result
def list_jobs(self,request): """ returns list of jobs for one printer. """ # ----------- DEBUG ----------------- MODULE.info("printers/jobs/query invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer','') result = self._job_list(printer) # ---------- DEBUG -------------- MODULE.info("printers/jobs/query returns:") pp = pprint.PrettyPrinter(indent=4) st = '' if len(result) > 5: tmp = result[0:5] MODULE.info(" >> %d entries, first 5 are:" % len(result)) st = pp.pformat(tmp).split("\n") else: st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id,result)
def updates_available(self, request): """ Asks if there are package updates available. (don't get confused by the name of the UniventionUpdater function that is called here.) This is a seperate call since it can take an amount of time, thus being invoked by a seperate button (and not in the background) """ # ----------- DEBUG ----------------- MODULE.info("updater/updates/available invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- result = False what = "starting" try: # be as current as possible. what = "reinitializing UniventionUpdater" self.uu.ucr_reinit() what = "reloading registry" self.ucr.load() what = "checking update availability" result = self.uu.component_update_available() except Exception, ex: typ = str(type(ex)).strip("<>") msg = "[while %s] [%s] %s" % (what, typ, str(ex)) # result['message'] = msg # result['status'] = 1 MODULE.error(msg)
def _thread(obj, username, password): # acquire the lock until the scripts have been executed self._finishedResult = False obj._finishedLock.acquire() try: self._progressParser.reset() # write the profile file and run setup scripts util.auto_complete_values_for_join(values) # on unjoined DC master the nameserver must be set to the external nameserver if newrole == 'domaincontroller_master' and not orgValues.get('joined'): for i in range(1, 4): # overwrite these values only if they are set, because the UMC module # will save only changed values if values.get('dns/forwarder%d' % i): values['nameserver%d' % i] = values.get('dns/forwarder%d' % i) MODULE.info('saving profile values') util.write_profile(values) # unjoined DC master (that is not being converted to a basesystem) -> run the join script MODULE.info('runnning system setup join script') util.run_joinscript(self._progressParser, values, username, password, dcname, lang=str(self.locale)) # done :) self._finishedResult = True return True finally: obj._finishedLock.release()
def _timed_out(self): # type: () -> NoReturn MODULE.info('Committing suicide') if self.__handler: self.__handler.destroy() self.exit() sys.exit(0)
def send(self, request): def _send_thread(sender, recipient, subject, message): MODULE.info('sending mail: thread running') # FIXME: contains header injection msg = u'From: ' + sender + u'\r\n' msg += u'To: ' + recipient + u'\r\n' msg += u'Subject: %s\r\n' % subject msg += u'\r\n' msg += message + u'\r\n' msg += u'\r\n' msg = msg.encode('latin1') server = smtplib.SMTP('localhost') server.set_debuglevel(0) server.sendmail(sender, recipient, msg) server.quit() return True func = notifier.Callback(_send_thread, request.options['sender'], request.options['recipient'], request.options['subject'], request.options['message']) MODULE.info('sending mail: starting thread') cb = notifier.Callback(self.thread_finished_callback, request) thread = notifier.threads.Simple('mailing', func, cb) thread.run()
def _thread(request, obj, username, password): # acquire the lock until the scripts have been executed self._finishedResult = False obj._finishedLock.acquire() try: self._progressParser.reset() # write the profile file and run setup scripts util.pre_save(values, orgValues) # on unjoined DC master the nameserver must be set to the external nameserver if newrole == 'domaincontroller_master' and not orgValues.get('joined'): for i in range(1,4): # overwrite these values only if they are set, because the UMC module # will save only changed values if values.get( 'dns/forwarder%d'%i ): values[ 'nameserver%d'%i ] = values.get( 'dns/forwarder%d'%i ) MODULE.info('saving profile values') util.write_profile(values) # unjoined DC master (that is not being converted to a basesystem) -> run the join script MODULE.info('runnning system setup join script') util.run_joinscript( self._progressParser, username, password ) # done :) self._finishedResult = True # we should do a cleanup now self._cleanup_required = True return True finally: obj._finishedLock.release()
def _register_at_jobs(self): '''Registers at-jobs for distributing and collecting files.''' # register the starting job # make sure that the startime, if given, lies in the future if self.starttime and self.starttime > datetime.now(): MODULE.info('register at-jobs: starttime = %s' % self.starttime) cmd = """'%s' --distribute %s""" % (DISTRIBUTION_CMD, quote(self.projectfile)) print 'register at-jobs: starttime = %s cmd = %s' % ( self.starttime, cmd) atJob = atjobs.add(cmd, self.starttime) if atJob and self.starttime: self.atJobNumDistribute = atJob.nr if not atJob: MODULE.warn('registration of at-job failed') print 'registration of at-job failed' # register the collecting job, only if a deadline is given if self.deadline and self.deadline > datetime.now(): MODULE.info('register at-jobs: deadline = %s' % self.deadline) print 'register at-jobs: deadline = %s' % self.deadline cmd = """'%s' --collect %s""" % (DISTRIBUTION_CMD, quote(self.projectfile)) atJob = atjobs.add(cmd, self.deadline) if atJob: self.atJobNumCollect = atJob.nr else: MODULE.warn('registration of at-job failed') print 'registration of at-job failed'
def send(self, request): def _send_thread(sender, recipient, subject, message): MODULE.info('sending mail: thread running') msg = MIMENonMultipart('text', 'plain', charset='utf-8') cs = email.charset.Charset("utf-8") cs.body_encoding = email.charset.QP msg["Subject"] = subject msg["From"] = sender msg["To"] = recipient msg.set_payload(message, charset=cs) server = smtplib.SMTP('localhost') server.set_debuglevel(0) server.sendmail(sender, recipient, msg.as_string()) server.quit() return True func = notifier.Callback(_send_thread, request.options['sender'], request.options['recipient'], request.options['subject'], request.options['message']) MODULE.info('sending mail: starting thread') cb = notifier.Callback(self.thread_finished_callback, request) thread = notifier.threads.Simple('mailing', func, cb) thread.run()
def _process_uvmm_response(self, thread, result, request, callback=None): # this is a notifier thread callback. If this raises an exception the whole module process crashes! if isinstance(result, BaseException): self.thread_finished_callback(thread, result, request) return success, data = result MODULE.info('Got result from UVMMd: success: %s, data: %r' % (success, data)) if not success: try: raise UMC_Error(str(data), status=500) except UMC_Error as result: thread._exc_info = sys.exc_info() self.thread_finished_callback(thread, result, request) return if callback: try: data = callback(data) except BaseException as result: thread._exc_info = sys.exc_info() self.thread_finished_callback(thread, result, request) return self.finished(request.id, data)
def query(self, request): """Searches for internet filter rules requests.options = {} 'pattern' -- pattern to match within the rule name or the list of domains """ MODULE.info('internetrules.query: options: %s' % str(request.options)) pattern = request.options.get('pattern', '').lower() def _matchDomain(domains): # helper function to match pattern within the list of domains matches = [idom for idom in domains if pattern in idom.lower()] return 0 < len(matches) # filter out all rules that match the given pattern result = [ dict( name=irule.name, type=_filterTypesInv[irule.type], domains=len(irule.domains), priority=irule.priority, wlan=irule.wlan, ) for irule in rules.list() if pattern in irule.name.lower() or _matchDomain(irule.domains) ] MODULE.info('internetrules.query: results: %s' % str(result)) self.finished(request.id, result)
def _cleanTmpDir(self): # copied from distribution module # clean up the temporary upload directory if self._tmpDir: MODULE.info('Clean up temporary directory: %s' % self._tmpDir) shutil.rmtree(self._tmpDir, ignore_errors=True) self._tmpDir = None
def execute(self, method, request, *args, **kwargs): self.__requests[request.id] = (request, method) try: function = getattr(self, method) except AttributeError: message = self._( 'Method %(method)r (%(path)r) in %(module)r does not exist.\n\n%(traceback)s' ) % { 'method': method, 'path': request.arguments, 'module': self.__class__.__module__, 'traceback': traceback.format_exc() } self.finished(request.id, None, message=message, status=500) return try: MODULE.info('Executing %r' % (request.arguments or request.command, )) self._parse_accept_language(request) if ucr.is_false('umc/server/disable-security-restrictions', True): self.security_checks(request, function) function.__func__(self, request, *args, **kwargs) except (KeyboardInterrupt, SystemExit): self.finished( request.id, None, self. _('The UMC service is currently shutting down or restarting. Please retry soon.' ), status=503) raise except: self.__error_handling(request, method, *sys.exc_info())
def list_jobs(self, request): """ returns list of jobs for one printer. """ # ----------- DEBUG ----------------- MODULE.info("printers/jobs/query invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer', '') result = self._job_list(printer) # ---------- DEBUG -------------- MODULE.info("printers/jobs/query returns:") pp = pprint.PrettyPrinter(indent=4) st = '' if len(result) > 5: tmp = result[0:5] MODULE.info(" >> %d entries, first 5 are:" % len(result)) st = pp.pformat(tmp).split("\n") else: st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def set_registry_var(self, name, value): """ Sets a registry variable and tracks changedness in a private variable. This enables the set_save_commit_load() method to commit the files being affected by the changes we have made. Function handles boolean values properly. """ try: oldval = self.ucr.get(name, '') if isinstance(value, bool): value = self._bool_string(name, value) # Don't do anything if the value being set is the same as # the value already found. if value == oldval: return # Possibly useful: if the value is the empty string -> try to unset this variable. # FIXME Someone please confirm that there are no UCR variables that need # to be set to an empty string! if value == '': if name in self.ucr: MODULE.info("Deleting registry variable '%s'" % name) del self.ucr[name] else: MODULE.info("Setting registry variable '%s' = '%s'" % (name, value)) self.ucr[name] = value if value != '' or oldval != '': self._changes[name] = (oldval, value) except Exception as e: MODULE.warn("set_registry_var('%s', '%s') ERROR %s" % (name, value, str(e)))
def _response(self, *args): arg_repr = _log(names, args) if arg_repr: MODULE.info('%s got: %s' % (name, ', '.join(arg_repr))) result = function(self, *args) MODULE.info('%s returned: %r' % (name, result)) return result
def send_message(self, username, method, address, raise_on_success=True): plugin = self._get_send_plugin(method) try: token_from_db = self.db.get_one(username=username) except MultipleTokensInDB as e: # this should not happen, delete all tokens MODULE.error("send_token(): {}".format(e)) self.db.delete_tokens(username=username) token_from_db = None token = self.create_token(plugin.token_length) if token_from_db: # replace with fresh token MODULE.info("send_token(): Updating token for user '{}'...".format(username)) self.db.update_token(username, method, token) else: # store a new token MODULE.info("send_token(): Adding new token for user '{}'...".format(username)) self.db.insert_token(username, method, token) try: self._call_send_msg_plugin(username, method, address, token) except Exception: MODULE.error("send_token(): Error sending token with via '{method}' to '{username}'.".format( method=method, username=username)) self.db.delete_tokens(username=username) raise if raise_on_success: raise UMC_Error(_("Successfully send token.").format(method), status=200) else: return True
def send_token(self, username, method): if ucr.is_false('umc/self-service/passwordreset/backend/enabled'): msg = _('The password reset was disabled via the Univention Configuration Registry.') MODULE.error('send_token(): {}'.format(msg)) raise UMC_Error(msg) MODULE.info("send_token(): username: '******' method: '{}'.".format(username, method)) try: plugin = self.password_reset_plugins[method] except KeyError: MODULE.error("send_token() method '{}' not in {}.".format(method, self.password_reset_plugins.keys())) raise UMC_Error(_("Unknown recovery method '{}'.").format(method)) if self.is_blacklisted(username, 'passwordreset'): raise MissingContactInformation() # check if the user has the required attribute set user = self.get_udm_user(username=username) username = user["username"] if len(user[plugin.udm_property]) > 0: # found contact info self.send_message(username, method, user[plugin.udm_property]) # no contact info raise MissingContactInformation()
def request( self, command, **kwargs ): MODULE.info( 'Sending request %s to UVMM daemon ...' % command ) try: request = eval( 'protocol.Request_%s()' % command ) except NameError, AttributeError: MODULE.error( 'Failed to create request %s' % command ) raise UVMM_Error( _( 'The given UVMM command is not known' ) )
def colors( self, request ): """Returns a list of all existing colors.""" MODULE.info( 'MODULEID.colors: options: %s' % str( request.options ) ) allColors = set(map(lambda x: x['color'], Instance.entries)) allColors = map(lambda x: { 'id': x, 'label': x }, allColors) allColors.append({ 'id': 'None', 'label': _('All colors') }) MODULE.info( 'MODULEID.colors: result: %s' % str( allColors ) ) self.finished(request.id, allColors)
def uninstall_dry_run(self, package_manager): MODULE.info('Invoke uninstall_dry_run') package_manager.reopen_cache() to_uninstall = package_manager.get_packages(self.get('defaultpackages')) for package in to_uninstall: package.mark_delete() packages = [pkg.name for pkg in package_manager.packages() if pkg.is_auto_removable] package_manager.reopen_cache() return packages
def _send_return( thread, result, request ): import traceback if not isinstance( result, BaseException ): MODULE.info( 'sending mail: completed successfully' ) self.finished( request.id, True ) else: msg = '%s\n%s: %s\n' % ( ''.join( traceback.format_tb( thread.exc_info[ 2 ] ) ), thread.exc_info[ 0 ].__name__, str( thread.exc_info[ 1 ] ) ) MODULE.process( 'sending mail:An internal error occurred: %s' % msg ) self.finished( request.id, False, msg, False )
def _thread_finish_success( self, thread, result, request ): """This method is invoked when a threaded request function is finished. The result is send back to the client. If the result is an instance of BaseException an error is returned.""" if self._check_thread_error( thread, result, request ): return success, data = result MODULE.info( 'Got result from UVMMd: success: %s, data: %s' % ( success, data ) ) self.finished( request.id, { 'success' : success, 'data' : data } )
def _logstamp(self, fname): """ Logfile timestamp. Now a seperate function. """ try: st = stat(fname) if st: MODULE.info(" >> log file stamp = '%s'" % st[9]) return st[9] return 0 except: return 0
def calculateFractions( self ): MODULE.info( 'Calculating maximum value for fractions ...' ) for category in filter( lambda x: os.path.isdir( os.path.join( PATH_SETUP_SCRIPTS, x ) ), os.listdir( PATH_SETUP_SCRIPTS ) ): cat_path = os.path.join( PATH_SETUP_SCRIPTS, category ) for script in filter( lambda x: os.path.isfile( os.path.join( cat_path, x ) ), os.listdir( cat_path ) ): name = '%s/%s' % ( category, script ) if not name in self.fractions: self.fractions[ name ] = 1 self.current.max = sum( self.fractions.values() ) MODULE.info( 'Calculated a maximum value of %d' % self.current.max )
def destroy(self): if self._cleanup_required: MODULE.info('Appliance mode: cleanup by timeout') # cleanup restarts umc, so MODULE.info will never # be called. but leave it that way, maybe it can # be called in the future. if util.cleanup(): MODULE.info('... cleanup successful') else: MODULE.warn('... cleanup operation failed') return super(Instance, self).destroy()
def restart(self, request): """Restart apache, UMC Web server, and UMC server. """ # send a response immediately as it won't be sent after the server restarts self.finished(request.id, True) # enable server restart and trigger restart # (disable first to make sure the services are restarted) subprocess.call(CMD_DISABLE_EXEC) p = subprocess.Popen(CMD_ENABLE_EXEC_WITH_RESTART, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, err = p.communicate() MODULE.info("enabling server restart:\n%s" % out)
def _return( thread, result, request ): success = not result if result: message = _('Switching running state of Active Directory Connector failed.') MODULE.info( 'Switching running state of Active Directory Connector failed. exitcode=%s' % result ) else: if request.options.get( 'action' ) == 'start': message = _( 'UCS Active Directory Connector has been started.' ) else: message = _( 'UCS Active Directory Connector has been stopped.' ) self.finished( request.id, { 'success' : success, 'message' : message } )
def cleanup(self, request): # shut down the browser in appliance mode # call finished() directly, so the browser will get the response in any case # (see Bug #27632) MODULE.info('Appliance mode: cleanup') self.finished(request.id, True) # put it here just in case destroy gets called during util self._cleanup_required = False if util.cleanup(): MODULE.info('... cleanup successful') else: MODULE.warn('... cleanup operation failed')
def _return( pid, status, bufstdout, bufstderr, request, fn ): success = True if status == 0: univention.config_registry.handler_set( [ u'connector/ad/ldap/certificate=%s' % fn ] ) message = _( 'Certificate has been uploaded successfully.' ) MODULE.info( 'Certificate has been uploaded successfully. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % ( status, '\n'.join( bufstdout ), '\n'.join( bufstderr ) ) ) else: success = False message = _( 'Certificate upload or conversion failed.' ) MODULE.process( 'Certificate upload or conversion failed. status=%s\nSTDOUT:\n%s\n\nSTDERR:\n%s' % ( status, '\n'.join( bufstdout ), '\n'.join( bufstderr ) ) ) self.finished( request.id, [ { 'success' : success, 'message' : message } ] )
def _finished( thread, result, request ): if self._check_thread_error( thread, result, request ): return success, data = result json = object2dict( data ) MODULE.info( 'New domain: success: %s, data: %s' % ( success, json ) ) if success: self.finished( request.id, json ) else: self.finished( request.id, None, message = str( data ), status = MODULE_ERR_COMMAND_FAILED )
def users_put(self, object): """ modify a local user """ response = [] errors = { # no information about returncodes, yet } try: success = True message = '' # Username username = object.get('$username$') new_username = object.get('username') pwoptions = {} cmd = ['/usr/sbin/usermod'] cmd += self._get_common_args( object, pwoptions ) # Change username if username != new_username: cmd += ['-l', new_username] # Account deactivation if pwoptions.get('lock'): cmd.append('-L') elif object.get('unlock'): cmd.append('-U') # Password password = object.get('password') self._change_user_password(username, password, pwoptions) # Execute if len(cmd) > 1: cmd.append(username) returncode = self.process(cmd) if returncode != 0: MODULE.error("cmd '%s' failed with returncode %d" % (' '.join(map(str, cmd)) returncode)) error = errors.get( returncode, _('unknown error with statuscode %d occurred') % (returncode) ) raise ValueError( error ) except ValueError as e: success = False message = '%s%s' % ('%s: ' % username if isinstance(username, basestring) else '', e,) MODULE.info( 'luga.users_edit: results: %s' % (message,) ) return {'message': message, 'success': success}
def users_add(self, object): """ add a local user """ errors = { 1: _('could not update password file'), 2: _('invalid command syntax'), 3: _('invalid argument to option'), 4: _('UID already in use (and no -o)'), 6: _('specified group doesnt exist'), 9: _('username already in use'), 10: _('could not update group file'), 12: _('could not create home directory'), 13: _('could not create mail spool'), } try: success = True message = '' # Username username = object.get('username') pwoptions = {} cmd = ['/usr/sbin/useradd', '-r'] if username == object.get('group'): object['create_usergroup'] = True cmd.append('-U') else: cmd.append('-N') cmd += self._get_common_args( object, pwoptions ) # Execute cmd.append(username) returncode = self.process(cmd) if 0 != returncode: MODULE.error("cmd '%s' failed with returncode %d" % (' '.join(map(str, cmd)), returncode)) error = errors.get( returncode, _('unknown error with statuscode %d occurred') % (returncode) ) raise ValueError( error ) # Change Password + options password = object.get('password') self._change_user_password(username, password, pwoptions) except ValueError as e: success = False message = '%s%s' % ('%s: ' % username if isinstance(username, basestring) else '', e,) MODULE.info( 'luga.users_add: results: %s' % (message,) ) return {'message': message, 'success': success}
def _thread_finish( self, thread, result, request ): """This method is invoked when a threaded request function is finished. The result is send back to the client. If the result is an instance of BaseException an error is returned.""" if self._check_thread_error( thread, result, request ): return success, data = result MODULE.info( 'Got result from UVMMd: success: %s, data: %s' % ( success, data ) ) if not success: self.finished( request.id, None, message = data, status = MODULE_ERR_COMMAND_FAILED ) else: self.finished( request.id, data )
def domain_state( self, request ): """Set the state a domain domainUUID on node nodeURI. options: { 'domainURI': <domain uri>, 'domainState': (RUN|SHUTDOWN|PAUSE|RESTART|SUSPEND) } return: """ self.required_options( request, 'domainURI', 'domainState' ) node_uri, domain_uuid = urlparse.urldefrag( request.options[ 'domainURI' ] ) MODULE.info( 'nodeURI: %s, domainUUID: %s' % ( node_uri, domain_uuid ) ) if request.options[ 'domainState' ] not in self.DOMAIN_STATES: raise UMC_OptionTypeError( _( 'Invalid domain state' ) ) self.uvmm.send( 'DOMAIN_STATE', Callback( self._thread_finish, request ), uri = node_uri, domain = domain_uuid, state = request.options[ 'domainState' ] )
def types( self, request, ldap_connection = None, ldap_position = None ): """Returns the list of object types matching the given flavor or container. requests.options = {} 'superordinate' -- if available only types for the given superordinate are returned (not for the navigation) 'container' -- if available only types suitable for the given container are returned (only for the navigation) return: [ { 'id' : <LDAP DN of container or None>, 'label' : <name> }, ... ] """ if request.flavor != 'navigation': module = UDM_Module( request.flavor ) superordinate = request.options.get( 'superordinate' ) if superordinate: self.finished( request.id, module.types4superordinate( request.flavor, superordinate ) ) else: self.finished( request.id, module.child_modules ) else: container = request.options.get( 'container' ) if not container: # no container is specified, return all existing object types MODULE.info('no container specified, returning all object types') self.finished( request.id, map( lambda module: { 'id' : module[ 0 ], 'label' : getattr( module[ 1 ], 'short_description', module[ 0 ] ) }, udm_modules.modules.items() ) ) return if 'None' == container: # if 'None' is given, use the LDAP base container = ucr.get( 'ldap/base' ) MODULE.info('no container == \'None\', set LDAP base as container') # create a list of modules that can be created # ... all container types except container/dc allowed_modules = set([m for m in udm_modules.containers if udm_modules.name(m) != 'container/dc']) # the container may be a superordinate or have one as its parent # (or grandparent, ....) superordinate = udm_modules.find_superordinate(container, None, ldap_connection) if superordinate: # there is a superordinate... add its subtypes to the list of allowed modules MODULE.info('container has a superordinate: %s' % superordinate) allowed_modules.update(udm_modules.subordinates(superordinate)) else: # add all types that do not have a superordinate MODULE.info('container has no superordinate') allowed_modules.update(filter(lambda mod: not udm_modules.superordinate(mod), udm_modules.modules.values())) # make sure that the object type can be created allowed_modules = filter(lambda mod: udm_modules.supports(mod, 'add'), allowed_modules) MODULE.info('all modules that are allowed: %s' % [udm_modules.name(mod) for mod in allowed_modules]) # return the final list of object types self.finished( request.id, map( lambda module: { 'id' : udm_modules.name(module), 'label' : getattr( module, 'short_description', udm_modules.name(module) ) }, allowed_modules ) )
def keys(self, request): """ returns the set of search criteria suitable for the given page. """ # ----------- DEBUG ----------------- MODULE.info("pkgdb/keys invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- page = request.options.get('page','') result = [] if page in CRITERIA: result = self._combobox_data(CRITERIA[page]) # ---------- DEBUG -------------- MODULE.info("pkgdb/keys returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def get_printer(self,request): """ gets detail data for one printer. """ # ----------- DEBUG ----------------- MODULE.info("printers/get invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer','') result = self._printer_details(printer) result['printer'] = printer result['status'] = self._printer_status(printer) result['quota'] = self._quota_enabled(printer) # ---------- DEBUG -------------- MODULE.info("printers/get returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id,result)
def columns(self, request): """ returns the structure of the results grid for a given page+key combination. Note that design properties (width etc) are added at the JS page (KeyTranslator.js) """ # ----------- DEBUG ----------------- MODULE.info("pkgdb/columns invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- page = request.options.get('page', '') key = request.options.get('key', '') result = None query = self._query_description(page, key) if query is not None: result = [] for col in query['columns']: # introduce exception fields: present in the returned result set # but not to be included into the grid if col != '': result.append(col) # ---------- DEBUG -------------- MODULE.info("pkgdb/columns returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def enable_printer(self,request): """ can enable or disable a printer, depending on args. returns empty string on success, else error message. """ # ----------- DEBUG ----------------- MODULE.info("printers/enable invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer','') on = request.options.get('on',False) result = self._enable_printer(printer,on) # ---------- DEBUG -------------- MODULE.info("printers/enable returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def cancel_jobs(self,request): """ cancels one or more print jobs. Job IDs are passed as an array that can be directly passed on to the _shell_command() method """ # ----------- DEBUG ----------------- MODULE.info("printers/jobs/cancel invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- jobs = request.options['jobs'] printer = request.options.get('printer','') result = self._cancel_jobs(printer,jobs) # ---------- DEBUG -------------- MODULE.info("printers/jobs/cancel returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def set_quota(self,request): """ sets quota limits for a (printer,user) combination. optionally tries to create the corresponding user entry. """ # ----------- DEBUG ----------------- MODULE.info("printers/quota/set invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer','') user = request.options.get('user','') soft = request.options.get('soft',0) hard = request.options.get('hard',0) if printer=='' or user=='': result = "Required parameter missing" else: result = self._set_quota(printer,user,soft,hard) # ---------- DEBUG -------------- MODULE.info("printers/quota/set returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def reset_quota(self,request): """ resets quota for a (printer,user) combination. """ # ----------- DEBUG ----------------- MODULE.info("printers/quota/reset invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- printer = request.options.get('printer','') users = request.options.get('users',[]) result = self._reset_quota(printer,users) # ---------- DEBUG -------------- MODULE.info("printers/quota/reset returns:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(result).split("\n") for s in st: MODULE.info(" >> %s" % s) # -------------------------------- self.finished(request.id, result)
def cleanup(): # write header before executing scripts f = open(LOG_FILE, 'a') f.write('\n\n=== Cleanup (%s) ===\n\n' % timestamp()) f.flush() ucr = univention.config_registry.ConfigRegistry() ucr.load() # The browser was only started, if system/setup/boot/start is true if ucr.is_true('system/setup/boot/start', False): MODULE.info('Appliance mode: try to shut down the browser') try: fpid = open(PATH_BROWSER_PID) strpid = fpid.readline().strip() pid = int(strpid) p = psutil.Process(pid) p.kill() except IOError: MODULE.warn('cannot open browser PID file: %s' % PATH_BROWSER_PID) except ValueError: MODULE.error('browser PID is not a number: "%s"' % strpid) except psutil.NoSuchProcess: MODULE.error('cannot kill process with PID: %s' % pid) # Maybe the system-setup CMD tool was started for p in psutil.process_iter(): if p.name == 'python2.6' and '/usr/share/univention-system-setup/univention-system-setup' in p.cmdline: p.kill() # unset the temporary interface if set for var in ucr.keys(): if RE_IPV4_TYPE.match(var) and ucr.get(var) == 'appliance-mode-temporary': f.write('unset %s' % var) keys = [var] for k in ['netmask', 'address', 'broadcast', 'network']: keys.append(var.replace('/type', '/%s' % k)) univention.config_registry.handler_unset(keys) # Shut down temporary interface subprocess.call(['ifconfig', var.split('/')[1].replace('_', ':'), 'down']) # force a restart of UMC servers and apache subprocess.call( CMD_DISABLE_EXEC, stdout = f, stderr = f ) subprocess.call( CMD_ENABLE_EXEC_WITH_RESTART, stdout = f, stderr = f ) f.write('\n=== DONE (%s) ===\n\n' % timestamp()) f.flush() f.close() return True