def upload_archive(self, archive): ucr.load() url = ucr.get( 'umc/sysinfo/upload/url', 'https://forge.univention.org/cgi-bin/system-info-upload.py') SYSINFO_PATH = '/usr/share/univention-system-info/archives/' path = os.path.abspath(os.path.join(SYSINFO_PATH, archive)) if not path.startswith(SYSINFO_PATH): raise UMC_Error('Archive path invalid.') fd = open(os.path.join(SYSINFO_PATH, archive), 'r') data = { 'filename': fd, } req = urllib2.Request(url, data, {}) try: u = urllib2.urlopen(req) answer = u.read() except (urllib2.HTTPError, urllib2.URLError, httplib.HTTPException) as exc: raise UMC_Error('Archive upload failed: %s' % (exc, )) else: if answer.startswith('ERROR:'): raise UMC_Error(answer)
def add(self, request, ldap_user_write=None, ldap_user_read=None, ldap_position=None): for group in request.options: group = group['object'] break try: grp = {} grp['school'] = group['school'] grp['name'] = '%(school)s-%(name)s' % group grp['description'] = group['description'] grp['users'] = group['members'] grp = WorkGroup(**grp) success = grp.create(ldap_user_write) if not success and grp.exists(ldap_user_read): raise UMC_Error( _('The workgroup %r already exists!') % grp.name) except udm_exceptions.base as exc: MODULE.process( 'An error occurred while creating the group "%s": %s' % (group['name'], exc.message)) raise UMC_Error(_('Failed to create group (%s).') % exc.message) self.finished(request.id, success)
def send_message(self, username, method, address, token): MODULE.info( "send_message(): username: {} method: {} address: {}".format( username, method, address)) try: plugin = self.send_plugins[method] if not plugin.is_enabled: raise KeyError except KeyError: raise UMC_Error("Method not allowed!", status=403) plugin.set_data({ "username": username, "address": address, "token": token }) MODULE.info("send_message(): Running plugin of class {}...".format( plugin.__class__.__name__)) try: plugin.send() except Exception as exc: MODULE.error('Unknown error: %s' % (traceback.format_exc(), )) raise UMC_Error(_("Error sending token: {}").format(exc), status=500) return True
def list_quota(self, printer=''): """ lists all quota entries related to this printer. """ result = [] status = None try: from pykota.tool import PyKotaTool from pykota import reporter from pykota.storages.pgstorage import PGError except ImportError: raise UMC_Error( _('The print quota settings are currently disabled. Please install the package univention-printquota to enable them.' )) reportTool = PyKotaTool() try: reportTool.deferredInit() printers = reportTool.storage.getMatchingPrinters(printer) reportingtool = reporter.openReporter(reportTool, 'html', printers, '*', 0) status = reportingtool.generateReport() except PGError as exc: MODULE.error('Cannot connect to postgres: %s' % (exc, )) raise UMC_Error( _('The connection to the print quota postgres database failed. Please make sure the postgres service is running and reachable.' )) finally: reportTool.regainPriv() if status: tree = lxml.html.fromstring(status) table = tree.find_class('pykotatable') for i in table: for a in i.iterchildren(tag='tr'): data = list() for b in a.iterchildren(tag='td'): data.append(b.text_content().strip()) if data and len(data) >= 11: user = data[0] # limitby = data[1] # overcharge = data[2] used = data[3] soft = data[4] hard = data[5] # balance = data[6] # grace = data[7] total = data[8] # paid = data[9] # warn = data[10] result.append( dict( user=user, used=used, soft=soft, hard=hard, total=total, )) return result
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 _start_import(self, request): school = request.options['school'] filename = request.options['filename'] userrole = request.options['userrole'] import_file = os.path.join(CACHE_IMPORT_FILES, os.path.basename(filename)) try: job = self.client.userimportjob.create(filename=import_file, school=school, user_role=userrole, dryrun=False) except ConnectionError as exc: MODULE.error('ConnectionError during import: %s' % (exc, )) raise UMC_Error( _('The connection to the import server could not be established.' )) except PermissionError: raise UMC_Error( _('The permissions to perform a user import are not sufficient enough.' )) os.remove(import_file) return { 'id': job.id, 'school': job.school.displayName, 'userrole': self._parse_user_role(job.user_role) }
def run(self, request): """runs the given join scripts""" # Check if already a join process is running if self._running: raise UMC_Error(_('A join process is already running.')) # check for dpkg lock if self._dpkg_locked(): raise UMC_Error( _('Currently, software is being installed or uninstalled. Join scripts should not be run right now.' )) scripts, username, password, force = (request.options['scripts'], request.options.get('username'), request.options.get('password'), request.options.get( 'force', False)) # sort scripts scripts.sort(key=lambda i: int(re.match('^(\d+)', i).group())) def _thread(): # reset progress state and lock against other join processes self.progress_state.reset() self.progress_state.component = _('Authentication') self._lock() return run_join_scripts( scripts, force, username, password, info_handler=self.progress_state.info_handler, step_handler=self.progress_state.add_steps, error_handler=self.progress_state.error_handler, component_handler=self.progress_state.component_handler, critical_handler=self.progress_state.critical_handler, ) def _finished(thread, result): MODULE.info('Finished running join scripts') self._unlock() self.progress_state.info = _('finished...') self.progress_state.finish() if isinstance(result, BaseException): 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.warn('Exception during running join scripts: %s' % msg) self.progress_state.error_handler( _('An unexpected error occurred: %s') % result) # launch thread thread = notifier.threads.Simple('join', _thread, _finished) thread.run() # finish request request.status = 202 self.finished(request.id, True)
def join(self, request): username, password, hostname = (request.options['username'], request.options['password'], request.options['hostname']) # Check if already a join process is running if self._running: raise UMC_Error(_('A join process is already running.')) # check for valid server role if ucr.get('server/role') == 'domaincontroller_master': raise UMC_Error( _('Invalid server role! A master domain controller can not be joined.' )) # check for dpkg lock if self._dpkg_locked(): raise UMC_Error( _('Currently, software is being installed or uninstalled. Join scripts should not be run right now.' )) def _thread(): self.progress_state.reset() self.progress_state.component = _('Domain join') self._lock() return system_join( hostname, username, password, info_handler=self.progress_state.info_handler, step_handler=self.progress_state.add_steps, error_handler=self.progress_state.error_handler, component_handler=self.progress_state.component_handler, critical_handler=self.progress_state.critical_handler, ) def _finished(thread, result): MODULE.info('Finished joining') self._unlock() self.progress_state.info = _('finished...') self.progress_state.finish() if isinstance(result, BaseException): 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.warn('Exception during domain join: %s' % msg) self.progress_state.error_handler( _('An unexpected error occurred: %s') % result) # launch thread thread = notifier.threads.Simple('join', _thread, _finished) thread.run() request.status = 202 self.finished(request.id, True)
def set_contact(self, username, password, email=None, mobile=None): MODULE.info( "set_contact(): username: {} password: ***** email: {} mobile: {}". format(username, email, mobile)) dn, username = self.auth(username, password) if self.is_blacklisted(username): raise ServiceForbidden() if self.set_contact_data(dn, email, mobile): raise UMC_Error(_("Successfully changed your contact data."), status=200) raise UMC_Error(_('Changing contact data failed.'), status=500)
def send_token(self, username, method): MODULE.info("send_token(): username: '******' method: '{}'.".format( username, method)) try: plugin = self.send_plugins[method] except KeyError: MODULE.error("send_token() method '{}' not in {}.".format( method, self.send_plugins.keys())) raise UMC_Error(_("Unknown recovery method '{}'.").format(method)) if self.is_blacklisted(username): 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 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.send_message(username, method, user[plugin.udm_property], token) except: MODULE.error( "send_token(): Error sending token with via '{method}' to '{username}'." .format(method=method, username=username)) self.db.delete_tokens(username=username) raise raise UMC_Error(_("Successfully send token.").format(method), status=200) # no contact info raise MissingContactInformation()
def check_credentials_nonmaster(dns, nameserver, address, username, password): if dns: domain = get_ucs_domain(nameserver) else: domain = '.'.join(address.split('.')[1:]) if not domain: # Not checked... no UCS domain! raise UMC_Error(_('No UCS Primary Directory Node could be found at the address.')) with _temporary_password_file(password) as password_file: if subprocess.call(['univention-ssh', password_file, '%s@%s' % (username, address), '/bin/true']): raise UMC_Error(_('The connection to the UCS Primary Directory Node was refused. Please recheck the password.')) return domain
def set_contact(self, username, password, email=None, mobile=None): if ucr.is_false('umc/self-service/protect-account/backend/enabled'): msg = _('The account protection was disabled via the Univention Configuration Registry.') MODULE.error('set_contact(): {}'.format(msg)) raise UMC_Error(msg) MODULE.info("set_contact(): username: {} password: ***** email: {} mobile: {}".format(username, email, mobile)) dn, username = self.auth(username, password) if self.is_blacklisted(username, 'passwordreset'): raise ServiceForbidden() try: return self.set_contact_data(dn, email, mobile) except Exception: raise UMC_Error(_('Changing contact data failed.'), status=500)
def deregister_account(self, username, password): MODULE.info("deregister_account(): username: {} password: *****".format(username)) ucr.load() if ucr.is_false('umc/self-service/account-deregistration/enabled', True): msg = _('The account deregistration was disabled via the Univention Configuration Registry.') MODULE.error('deregister_account(): {}'.format(msg)) raise UMC_Error(msg) dn, username = self.auth(username, password) if self.is_blacklisted(username, 'account-deregistration'): raise ServiceForbidden() try: return self._deregister_account(username) except Exception: raise UMC_Error(_('Account could not be deleted'), status=500)
def printit(self, username, printjob, printer): """Print a given document on the given printer requests.options = {} 'username' -- owner of the print job 'printjob' -- relative filename of the print job 'printer' -- the printer to use (<hostname>://<printer>) return: <PDF document> """ path = self._get_path(username, printjob) try: spoolhost, printer = printer.split('://', 1) except ValueError: raise UMC_Error(_('Invalid printer URI')) if not os.path.exists(path): raise UMC_Error( _('File %r could not be printed as it does not exists (anymore).' ) % (printjob, )) MODULE.process('Printing: %s' % path) self.pw_callback_bad_password = False try: cups.setUser(self.username) cups.setEncryption(cups.HTTP_ENCRYPT_ALWAYS) cups.setPasswordCB(self.pw_callback) conn = cups.Connection(spoolhost) conn.printFile(printer, path, Printjob.filename2label(printjob), {}) except RuntimeError: raise UMC_Error( _('Failed to connect to print server %(printserver)s.') % {'printserver': spoolhost}) except cups.IPPError as (errno, description): IPP_AUTHENTICATION_CANCELED = 4096 description = { cups.IPP_NOT_AUTHORIZED: _('No permission to print'), IPP_AUTHENTICATION_CANCELED: _('Wrong password'), }.get(errno, description) raise UMC_Error( _('Failed to print on %(printer)s: %(stderr)s (error %(errno)d).' ) % { 'printer': printer, 'stderr': description, 'errno': errno })
def set_contact_data(self, dn, email, mobile): try: user = self.get_udm_user_by_dn(userdn=dn, admin=True) old_email = user['PasswordRecoveryEmail'] if email is not None and email.lower() != old_email.lower(): try: user["PasswordRecoveryEmail"] = email except udm_errors.valueInvalidSyntax as err: raise UMC_Error(err) else: user['PasswordRecoveryEmailVerified'] = 'FALSE' if mobile is not None and mobile.lower() != user["PasswordRecoveryMobile"].lower(): user["PasswordRecoveryMobile"] = mobile user.modify() verification_email_send = False if user['RegisteredThroughSelfService'] == 'TRUE': if old_email is not None and old_email.lower() != email.lower(): self._notify_about_email_change(user['username'], old_email, email) if email is not None and email.lower() != old_email.lower(): self.send_message(user['username'], 'verify_email', email, raise_on_success=False) verification_email_send = True return { 'verificationEmailSend': verification_email_send, 'email': email, } except Exception: MODULE.error("set_contact_data(): {}".format(traceback.format_exc())) raise
def admember_set_password(self, username, password): ldb_url = ucr.get('connector/ad/ldap/host') ldb_url = 'ldaps://%s' % (ldb_url, ) if ucr.is_true( 'connector/ad/ldap/ldaps') else 'ldap://%s' % (ldb_url, ) try: reset_username = dict(ucr)['ad/reset/username'] with open(dict(ucr)['ad/reset/password']) as fd: reset_password = fd.readline().strip() except (EnvironmentError, KeyError): raise UMC_Error(_( 'The configuration of the password reset service is not complete. The UCR variables "ad/reset/username" and "ad/reset/password" need to be set properly. Please inform an administration.' ), status=500) process = Popen([ 'samba-tool', 'user', 'setpassword', '--username', reset_username, '--password', reset_password, '--filter', filter_format('samaccountname=%s', (username, )), '--newpassword', password, '-H', ldb_url ], stdout=PIPE, stderr=STDOUT) stdouterr = process.communicate()[0] if stdouterr: MODULE.process('samba-tool user setpassword: %s' % (stdouterr, )) if process.returncode: MODULE.error( "admember_set_password(): failed to set password. Return code: %s" % (process.returncode, )) return False return True
def set_role_and_check_if_join_will_work(role, master_fqdn, admin_username, admin_password): orig_role = UCR.get('server/role') try: univention.config_registry.handler_set(['server/role=%s' % (role,)]) with _temporary_password_file(admin_password) as password_file: p1 = subprocess.Popen([ 'univention-join', '-dcname', master_fqdn, '-dcaccount', admin_username, '-dcpwd', password_file, '-checkPrerequisites' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) stdout, stderr = p1.communicate() if p1.returncode != 0: messages = [line[11:] for line in stdout.split('\n') if line.startswith("* Message: ")] raise UMC_Error(_( "univention-join -checkPrerequisites reported a problem. " "Output of check:\n\n" ) + "\n".join(messages)) finally: if orig_role: univention.config_registry.handler_set(['server/role=%s' % (orig_role,)]) else: univention.config_registry.handler_unset(['server/role'])
def get_general_info(self): DMIDECODE = '/usr/sbin/dmidecode' MANUFACTURER_CMD = ( DMIDECODE, '-s', 'system-manufacturer', ) MODEL_CMD = ( DMIDECODE, '-s', 'system-product-name', ) stdout_list = [] for command in ( MANUFACTURER_CMD, MODEL_CMD, ): ( exitcode, stdout, stderr, ) = self._call(command) if exitcode: MODULE.error('Command %r failed: %s %r %r' % (command, exitcode, stdout, stderr)) raise UMC_Error(_('Failed to execute command')) else: stdout = stdout[:-1] # remove newline character stdout_list.append(stdout) result = {} result['manufacturer'] = stdout_list[0] result['model'] = stdout_list[1] return 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 unset_computerroom_exammode(self, request, ldap_user_read=None, ldap_admin_write=None, ldap_position=None): '''Remove all member hosts of a given computer room from the special exam group.''' roomdn = request.options['roomdn'] try: room = ComputerRoom.from_dn(roomdn, None, ldap_user_read) except univention.admin.uexceptions.noObject: raise UMC_Error('Room %r not found.' % (roomdn, )) except univention.admin.uexceptions.ldapError: raise # Remove all host members of room from examGroup host_uid_list = [ univention.admin.uldap.explodeDn(uniqueMember, 1)[0] + '$' for uniqueMember in room.hosts ] examGroup = self.examGroup(ldap_admin_write, ldap_position, room.school) examGroup.fast_member_remove( room.hosts, host_uid_list ) # removes any uniqueMember and member listed if still present self.finished(request.id, {}, success=True)
def upload_traceback(self, traceback, remark, email): ucr.load() ucs_version = '%(version/version)s-%(version/patchlevel)s errata%(version/erratalevel)s' % ucr if ucr.get('appcenter/apps/ucsschool/version'): ucs_version = '%s - UCS@school %s' % ( ucs_version, ucr['appcenter/apps/ucsschool/version']) # anonymised id of localhost uuid_system = ucr.get('uuid/system', '') url = ucr.get( 'umc/sysinfo/traceback/url', 'https://forge.univention.org/cgi-bin/system-info-traceback.py') MODULE.process('Sending %s to %s' % (traceback, url)) request_data = { 'traceback': traceback, 'remark': remark, 'email': email, 'ucs_version': ucs_version, 'uuid_system': uuid_system, 'uuid_license': ucr.get('uuid/license', ''), 'server_role': ucr.get('server/role'), } try: response = requests.post(url, data=request_data) response.raise_for_status() except requests.exceptions.RequestException as exc: raise UMC_Error('Sending traceback failed: %s' % (exc, ))
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 _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 remove(self, request, ldap_user_write=None, ldap_user_read=None, ldap_position=None): """Deletes a workgroup""" for group_dn in request.options: group_dn = group_dn['object'][0] break group = WorkGroup.from_dn(group_dn, None, ldap_user_write) if not group.school: raise UMC_Error('Group must within the scope of a school OU: %s' % group_dn) try: success = group.remove(ldap_user_write) except udm_exceptions.base as exc: MODULE.error('Could not remove group "%s": %s' % (group.dn, exc)) self.finished(request.id, [{ 'success': False, 'message': str(exc) }]) return self.finished(request.id, [{'success': success}])
def collect_exam(self, exam): project = util.distribution.Project.load(exam) if not project: raise UMC_Error(_('No files have been distributed')) project.collect() return True
def get(self, request, ldap_user_read=None, ldap_position=None): klass = get_group_class(request) for group_dn in request.options: break try: group = klass.from_dn(group_dn, None, ldap_user_read) except udm_exceptions.noObject: raise UMC_Error('unknown object') school = group.school result = group.to_dict() if request.flavor == 'teacher': classes = SchoolClass.get_all(ldap_user_read, school, filter_str=filter_format( 'uniqueMember=%s', (group_dn, ))) result['classes'] = [{ 'id': class_.dn, 'label': class_.get_relative_name() } for class_ in classes] self.finished(request.id, [result]) return result['members'] = self._filter_members(request, group, result.pop('users', []), ldap_user_read) self.finished(request.id, [ result, ])
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 check_domain_has_activated_license(address, username, password): appliance_name = UCR.get("umc/web/appliance/name") if not appliance_name: return # the license must only be checked in an appliance scenario valid_license = True error = None with _temporary_password_file(password) as password_file: try: license_uuid = subprocess.check_output([ 'univention-ssh', password_file, '%s@%s' % (username, address), '/usr/sbin/ucr', 'get', 'uuid/license' ], stderr=subprocess.STDOUT).rstrip() except subprocess.CalledProcessError as exc: valid_license = False error = exc.output else: valid_license = len(license_uuid) == 36 error = _('The license %s is not valid.') % (license_uuid,) if not valid_license: raise UMC_Error( _('To install the {appliance_name} appliance it is necessary to have an activated UCS license on the Primary Directory Node.').format(appliance_name=appliance_name) + ' ' + _('During the check of the license status the following error occurred:\n{error}''').format(error=error) )
def _sanitize(self, value, name, further_args): value = super(ComputerSanitizer, self)._sanitize(value, name, further_args) try: return self.instance._italc.get(value) except KeyError: raise UMC_Error('Unknown computer')
def _request_license(self, request): try: urlopen(request) except (urllib2.HTTPError, urllib2.URLError, IOError) as exc: strerror = '' if hasattr(exc, 'read'): # try to parse an html error body = exc.read() match = re.search('<span id="details">(?P<details>.*?)</span>', body, flags=re.DOTALL) if match: strerror = match.group(1).replace('\n', '') if not strerror: if hasattr(exc, 'getcode') and exc.getcode() >= 400: strerror = _('This seems to be a problem with the license server. Please try again later.') while hasattr(exc, 'reason'): exc = exc.reason if hasattr(exc, 'errno'): version = ucr.get('version/version') errno = exc.errno strerror += getattr(exc, 'strerror', '') or '' if errno == 1: # gaierror(1, something like 'SSL Unknown protocol') link_to_doc = _('http://docs.univention.de/manual-%s.html#ip-config:Web_proxy_for_caching_and_policy_management__virus_scan') % version strerror += '. ' + _('This may be a problem with the proxy of your system. You may find help at %s.') % link_to_doc if errno == -2: # gaierror(-2, 'Name or service not known') link_to_doc = _('http://docs.univention.de/manual-%s.html#networks:dns') % version strerror += '. ' + _('This is probably due to the DNS settings of your server. You may find help at %s.') % link_to_doc if not strerror.strip(): strerror = str(exc) raise UMC_Error(_('An error occurred while contacting the license server: %s') % (strerror,), status=500)