def _fetch_file(self, key, url): try: # open the license file fp = util.urlopen(url) self._options[key] = ''.join(fp.readlines()).strip() except (urllib2.HTTPError, urllib2.URLError) as e: MODULE.warn('No information for %s available (%s): %s' % (key, e, url))
def install(self, package_manager, component_manager, add_component=True): try: # remove all existing component versions for iapp in self.versions: # dont remove yourself (if already added) if iapp is not self: component_manager.remove_app(iapp) # add the new repository component for the app ucr.load() is_master = ucr.get('server/role') in ('domaincontroller_master', 'domaincontroller_backup') # packages need to be installed on backup AND master systems to_install = self.get('defaultpackages') if is_master and self.get('defaultpackagesmaster'): to_install.extend(self.get('defaultpackagesmaster')) if add_component: component_manager.put_app(self) package_manager.update() # install + dist_upgrade package_manager.log('\n== INSTALLING %s AT %s ==\n' % (self.name, datetime.now())) package_manager.commit(install=to_install, dist_upgrade=True) # successful installation status = 200 except: MODULE.warn(traceback.format_exc()) status = 500 self._send_information('install', status) return status == 200
def init(self): MODULE.info("Initializing 'pkgdb' module with LANG = '%s'" % (self.locale, )) what = '' try: what = 'opening registry' self.ucr = univention.config_registry.ConfigRegistry() what = 'loading registry' self.ucr.load() # Create a suitable connect string what = 'building connect string' self.connection= updb.open_database_connection(self.ucr, pkgdbu=True) MODULE.info("Created database connection: %r" % (self.connection, )) self.cursor = self.connection.cursor() MODULE.info("Created database cursor: %r" % (self.cursor, )) what = 'checking variable lists' self._check_variable_lists() # initialize some member variables self._last_query = 0 self._last_result = [] except Exception, ex: MODULE.warn("[INIT] while %s: %s" % (what, ex, ))
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 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 _finished(thread, result): if self.__keep_alive_request: self.finished(self.__keep_alive_request.id, None) self.__keep_alive_request = None if isinstance(result, BaseException): msg = ''.join(thread.trace + traceback.format_exception_only(*thread.exc_info[:2])) MODULE.warn('Exception during saving the settings: %s' % (msg,)) self._progressParser.current.errors.append(_('Encountered unexpected error during setup process: %s') % (result,)) self._progressParser.current.critical = True self._finishedResult = True
def _finished(thread, result: Union[None, BaseException]) -> None: MODULE.info('Finished joining') self._unlock() self.progress_state.info = _('finished...') self.progress_state.finish() if isinstance(result, BaseException): msg = ''.join(thread.trace + traceback.format_exception_only( *thread.exc_info[:2])) MODULE.warn(f'Exception during domain join: {msg}') self.progress_state.error_handler( _('An unexpected error occurred: %s') % result)
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 guess_ad_domain_language(): '''AD Connector supports "en" and "de", this check detects a German AD Domain and returns "en" as fallback.''' p1, stdout, stderr = adsearch('sAMAccountName=Domänen-Admins') if stderr: MODULE.warn('adsearch "sAMAccountName=Domänen-Admins" stderr: %s' % stderr) for line in stdout.split('\n'): line = line.lower().strip() if line == 'samaccountname: domänen-admins': return 'de' return 'en'
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 = ''.join(thread.trace + traceback.format_exception_only( *thread.exc_info[:2])) MODULE.warn('Exception during running join scripts: %s' % (msg, )) self.progress_state.error_handler( _('An unexpected error occurred: %s') % result)
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)
def _test_for_docker_service(self): if docker_bridge_network_conflict(): msg = _('A conflict between the system network settings and the docker bridge default network has been detected.') + '\n\n' msg += _('Please either configure a different network for the docker bridge by setting the UCR variable docker/daemon/default/opts/bip to a different network and restart the system,') + ' ' msg += _('or disable the docker support in the AppCenter by setting appcenter/docker to false.') raise umcm.UMC_Error(msg) if not docker_is_running(): MODULE.warn('Docker is not running! Trying to start it now...') call_process(['invoke-rc.d', 'docker', 'start']) if not docker_is_running(): return False return True
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
def to_ucr(self): """Returns a dict of UCR variables to set or unset. Values which are None should be unset. """ name = self.name pattern = re.compile('^interfaces/%s(?:_[0-9]+)?/.*' % re.escape(name)) vals = dict((key, None) for key in ucr if pattern.match(key)) for key, val in self._leftover: vals[key] = val if self.start is not None: vals['interfaces/%s/start' % (name)] = str(bool(self.start)).lower() if self.type in ('static', 'manual', 'dhcp', 'dynamic', 'appliance-mode-temporary'): vals['interfaces/%s/type' % (name)] = self.type else: MODULE.warn('Unknown interfaces/%s/type: %r' % (self.name, self.type)) if isinstance(self.order, int): vals['interfaces/%s/order' % (name)] = str(self.order) vals['interfaces/%s/network' % (name)] = None vals['interfaces/%s/broadcast' % (name)] = None if not self.ip4dynamic: if self.ip4: address, netmask = self.ip4[0] vals['interfaces/%s/address' % (name)] = address vals['interfaces/%s/netmask' % (name)] = netmask network = ipaddr.IPv4Network('%s/%s' % (address, netmask)) vals['interfaces/%s/network' % (name)] = str(network.network) vals['interfaces/%s/broadcast' % (name)] = str(network.broadcast) for i, (address, netmask) in enumerate(self.ip4[1:]): vals['interfaces/%s_%s/address' % (name, i)] = address vals['interfaces/%s_%s/netmask' % (name, i)] = netmask if not self.ip6dynamic: for address, prefix, identifier in self.ip6: vals['interfaces/%s/ipv6/%s/address' % (name, identifier)] = address vals['interfaces/%s/ipv6/%s/prefix' % (name, identifier)] = prefix vals['interfaces/%s/ipv6/acceptRA' % (name)] = str(bool(self.ip6dynamic)).lower() options = sorted(self.get_options()) for i, option in enumerate(options): vals['interfaces/%s/options/%d' % (name, i)] = option return vals
def check_domain(self, username, password, ad_server_address, mode): ad_domain_info = {} try: if mode == 'admember': admember.check_server_role() ad_domain_info = admember.lookup_adds_dc(ad_server_address) ad_server_ip = ad_domain_info['DC IP'] if mode == 'admember': admember.check_domain(ad_domain_info) admember.check_connection(ad_domain_info, username, password) admember.check_ad_account(ad_domain_info, username, password) except admember.invalidUCSServerRole as exc: # check_server_role() MODULE.warn('Failure: %s' % exc) raise UMC_Error( _('The AD member mode can only be configured on a DC master server.' )) except admember.failedADConnect as exc: # lookup_adds_dc() MODULE.warn('Failure: %s' % exc) raise UMC_Error( _('Could not connect to AD Server %s. Please verify that the specified address is correct. (%s)' ) % (ad_server_address, 'check_domain: %s' % (exc, ))) except admember.domainnameMismatch as exc: # check_domain() MODULE.warn('Failure: %s' % exc) raise UMC_Error( _('The domain name of the AD Server (%(ad_domain)s) does not match the local UCS domain name (%(ucs_domain)s). For the AD member mode, it is necessary to setup a UCS system with the same domain name as the AD Server.' ) % { 'ad_domain': ad_domain_info.get("Domain"), 'ucs_domain': ucr['domainname'] }) except admember.connectionFailed as exc: # check_connection() MODULE.warn('Failure: %s' % exc) raise UMC_Error( _('Could not connect to AD Server %s. Please verify that username and password are correct. (Details:\n%s)' ) % (ad_domain_info.get('DC DNS Name'), exc)) except admember.notDomainAdminInAD as exc: # check_ad_account() MODULE.warn('Failure: %s' % exc) raise UMC_Error( _('The given user is not member of the Domain Admins group in Active Directory. This is a requirement for the Active Directory domain join.' )) # final info dict that is returned... replace spaces in the keys with '_' MODULE.info('Preparing info dict...') info = dict([(key.replace(' ', '_'), value) for key, value in ad_domain_info.iteritems()]) info['ssl_supported'] = admember.server_supports_ssl(ad_server_ip) # try to get binddn info['LDAP_BindDN'] = get_ad_binddn_from_name(info['LDAP_Base'], ad_server_ip, username, password) MODULE.info(str(info)) return info
def list_objects(container, object_type=None, ldap_connection=None, ldap_position=None): """Yields UDM objects""" try: result = ldap_connection.search(base=container, scope='one') except (LDAPError, udm_errors.ldapError): raise except udm_errors.noObject: raise ObjectDoesNotExist(container) except udm_errors.ldapTimeout: raise SearchTimeoutError() except udm_errors.ldapSizelimitExceeded: raise SearchLimitReached() except udm_errors.base as exc: UDM_Error(exc).reraise() for dn, attrs in result: modules = udm_modules.objectType(None, ldap_connection, dn, attrs) if not modules: MODULE.warn('Could not identify LDAP object %r' % (dn,)) continue if object_type == '$containers$' and not udm_modules.childs(modules[0]): continue if len(modules) > 1: MODULE.warn('Found multiple object types for %r: %r' % (dn, modules)) MODULE.info('dn: %r, attrs: %r' % (dn, attrs)) for mod in modules: module = UDM_Module(mod) if module.module: break if not module.module: MODULE.process('The UDM module %r could not be found. Ignoring LDAP object %r' % (modules[0], dn)) continue if module.superordinate_names: for superordinate in module.superordinate_names: so_module = UDM_Module(superordinate) so_obj = so_module.get(container) try: yield (module, module.get(dn, so_obj, attributes=attrs)) except BaseException: try: yield (module, module.get(dn, so_obj)) except (UDM_Error, udm_errors.base): MODULE.error('Could not load object %r (%r) exception: %s' % (dn, module.module, traceback.format_exc())) break else: try: yield (module, module.get(dn, attributes=attrs)) except BaseException: try: yield (module, module.get(dn)) except (UDM_Error, udm_errors.base): MODULE.error('Could not load object %r (%r) exception: %s' % (dn, module.module, traceback.format_exc()))
def remove(self, ldap_dn, cleanup=False, recursive=False, ldap_connection=None, ldap_position=None): """Removes an LDAP object""" superordinate = udm_objects.get_superordinate(self.module, None, ldap_connection, ldap_dn) obj = self.module.object(None, ldap_connection, ldap_position, dn=ldap_dn, superordinate=superordinate) try: obj.open() MODULE.info('Removing LDAP object %s' % ldap_dn) obj.remove(remove_childs=recursive) if cleanup: udm_objects.performCleanup(obj) except udm_errors.base as e: MODULE.warn('Failed to remove LDAP object %s: %s: %s' % (ldap_dn, e.__class__.__name__, str(e))) UDM_Error(e).reraise()
def get_class_for_udm_obj(cls, udm_obj, school): model = super(CSVUser, cls).get_class_for_udm_obj(udm_obj, school) if model is Student: return CSVStudent if model is Teacher: return CSVTeacher if model is TeachersAndStaff: return CSVTeachersAndStaff if model is Staff: return CSVStaff MODULE.warn('No mapping for %r, using %r' % (model.__name__, cls.__name__)) return cls
def _thread(_self, packages): MODULE.process('Starting package installation') with _self.package_manager.locked(reset_status=True, set_finished=True): with _self.package_manager.no_umc_restart(exclude_apache=True): _self.package_manager.update() if not _self.package_manager.install(*packages): raise SchoolInstallerError(_('Failed to install packages.')) if server_role != 'domaincontroller_backup' and not (server_role == 'domaincontroller_master' and setup == 'multiserver'): # create the school OU (not on backup and not on master w/multi server environment) MODULE.info('Starting creation of LDAP school OU structure...') progress_state.component = _('Creation of LDAP school structure') progress_state.info = '' try: if server_role == 'domaincontroller_slave': _educational_slave = ucr.get('hostname') if server_type == 'educational' else educational_slave administrative_slave = None if server_type == 'educational' else ucr.get('hostname') create_ou_remote(master, username, password, school_ou, ou_display_name, _educational_slave, administrative_slave) elif server_role == 'domaincontroller_master': create_ou_local(school_ou, ou_display_name) except SchoolInstallerError as exc: MODULE.error(str(exc)) raise SchoolInstallerError(_( 'The UCS@school software packages have been installed, however, a school OU could not be created and consequently a re-join of the system has not been performed. ' 'Please create a new school OU structure using the UMC module "Add school" on the master and perform a domain join on this machine via the UMC module "Domain join".' )) progress_state.add_steps(10) if server_role == 'domaincontroller_slave': # make sure that the slave is correctly moved below its OU MODULE.info('Trying to move the slave entry in the right OU structure...') result = umc(username, password, master, 'schoolwizards/schools/move_dc', {'schooldc': ucr.get('hostname'), 'schoolou': school_ou}, 'schoolwizards/schools').result if not result.get('success'): MODULE.warn('Could not successfully move the slave DC into its correct OU structure:\n%s' % result.get('message')) raise SchoolInstallerError(_('Validating the LDAP school OU structure failed. It seems that the current slave system has already been assigned to a different school or that the specified school OU name is already in use.')) # system join on a slave system progress_state.component = _('Domain join') if server_role == 'domaincontroller_slave': progress_state.info = _('Preparing domain join...') MODULE.process('Starting system join...') else: # run join scripts on DC backup/master progress_state.info = _('Executing join scripts...') MODULE.process('Running join scripts...') system_join( username, password, info_handler=self.progress_state.info_handler, step_handler=self.progress_state.add_steps, error_handler=self.progress_state.error_handler, )
def create(self, ldap_object, container=None, superordinate=None, ldap_connection=None, ldap_position=None): """Creates a LDAP object""" if superordinate == 'None': superordinate = None if container: try: ldap_position.setDn(container) except udm_errors.noObject: raise ObjectDoesNotExist(container) elif superordinate: try: ldap_position.setDn(superordinate) except udm_errors.noObject: raise SuperordinateDoesNotExist(superordinate) else: if hasattr(self.module, 'policy_position_dn_prefix'): container = '%s,cn=policies,%s' % (self.module.policy_position_dn_prefix, ldap_position.getBase()) elif hasattr(self.module, 'default_containers') and self.module.default_containers: container = '%s,%s' % (self.module.default_containers[0], ldap_position.getBase()) else: container = ldap_position.getBase() ldap_position.setDn(container) if superordinate: mod = get_module(self.name, superordinate) if not mod: MODULE.error('Superordinate module not found: %s' % (superordinate,)) raise SuperordinateDoesNotExist(superordinate) MODULE.info('Found UDM module for superordinate') superordinate = mod.get(superordinate) obj = self.module.object(None, ldap_connection, ldap_position, superordinate=superordinate) try: obj.open() MODULE.info('Creating LDAP object') if '$options$' in ldap_object: obj.options = filter(lambda option: ldap_object['$options$'][option] is True, ldap_object['$options$'].keys()) del ldap_object['$options$'] if '$policies$' in ldap_object: obj.policies = reduce(lambda x, y: x + y, ldap_object['$policies$'].values(), []) del ldap_object['$policies$'] self._map_properties(obj, ldap_object) obj.create() except udm_errors.base as e: MODULE.warn('Failed to create LDAP object: %s: %s' % (e.__class__.__name__, str(e))) UDM_Error(e, obj.dn).reraise() return obj.dn
def close_browser(self): try: with open('/var/cache/univention-system-setup/browser.pid', 'rb') as fd: pid = int(fd.readline().strip()) process = psutil.Process(pid) process.kill() return True except IOError as exc: MODULE.warn('cannot open browser PID file: %s' % (exc,)) except ValueError as exc: MODULE.error('browser PID is not a number: %s' % (exc,)) except psutil.NoSuchProcess as exc: MODULE.error('cannot kill process with PID: %s' % (exc,)) return False
def screenshot(self): if not self.connected(): MODULE.warn('%s: not connected - skipping screenshot' % (self.ipAddress, )) return None image = self._vnc.image() if not image.byteCount(): MODULE.info('%s: no screenshot available yet' % (self.ipAddress, )) return None tmpfile = tempfile.NamedTemporaryFile(delete=False) tmpfile.close() if image.save(tmpfile.name, 'JPG'): return tmpfile
def _finished(thread, result): MODULE.info('Finished installation') progress_state.finish() progress_state.info = _('finished...') self._installation_started = None if isinstance(result, SchoolInstallerError): MODULE.warn('Error during installation: %s' % (result,)) self.restore_original_certificate() progress_state.error_handler(str(result)) elif isinstance(result, BaseException): self.restore_original_certificate() msg = ''.join(traceback.format_exception(*thread.exc_info)) MODULE.error('Exception during installation: %s' % msg) progress_state.error_handler(_('An unexpected error occurred during installation: %s') % 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
def emit(self, record): try: from univention.management.console.log import MODULE except ImportError: pass else: msg = str(self.format(record)) if record.levelno <= logging.DEBUG: MODULE.info(msg) elif record.levelno <= logging.INFO: MODULE.process(msg) elif record.levelno <= logging.WARN: MODULE.warn(msg) else: MODULE.error(msg)
def _install_master_packages_on_host(self, app, function, host): client = Client(host, self.username, self.password) result = client.umc_command( 'appcenter/invoke', { 'function': function, 'application': app.id, 'force': True, 'dont_remote_install': True }).result if result['can_continue']: all_errors = self._query_remote_progress(client) return len(all_errors) == 0 else: MODULE.warn('%r' % result) return False
def reload(self, force=False): if self.uuid is not None and not force: # license with uuid has already been found return self.uuid = None # last time we checked, no uuid was found # but maybe the user installed a new license? try: _lo = uldap.getMachineConnection(ldap_master=False) data = _lo.search('objectClass=univentionLicense') del _lo self.uuid = data[0][1]['univentionLicenseKeyID'][0] except Exception as e: # no licensing available MODULE.warn('Failed to load license information: %s' % e)
def create_ou_local(ou, display_name): '''Calls create_ou locally as user root (only on master).''' if not display_name: MODULE.warn('create_ou_local(): display name is undefined - using OU name as display name') display_name = ou # call create_ou cmd = ['/usr/share/ucs-school-import/scripts/create_ou', '--displayName', display_name, ou] MODULE.info('Executing: %s' % ' '.join(cmd)) process = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = process.communicate() # check for errors if process.returncode != 0: raise SchoolInstallerError('Failed to execute create_ou: %s\n%s%s' % (cmd, stderr, stdout))
def move(self, ldap_dn, container, ldap_connection=None, ldap_position=None): """Moves an LDAP object""" superordinate = udm_objects.get_superordinate(self.module, None, ldap_connection, ldap_dn) obj = self.module.object(None, ldap_connection, ldap_position, dn=ldap_dn, superordinate=superordinate) try: obj.open() # build new dn rdn = udm.uldap.explodeDn(ldap_dn)[0] dest = '%s,%s' % (rdn, container) MODULE.info('Moving LDAP object %s to %s' % (ldap_dn, dest)) obj.move(dest) return dest except udm_errors.base as e: MODULE.warn('Failed to move LDAP object %s: %s: %s' % (ldap_dn, e.__class__.__name__, str(e))) UDM_Error(e).reraise()
def get_ucs_domaincontroller_master_query(nameserver, domain): if not nameserver or not domain: return # register nameserver resolver = _get_dns_resolver(nameserver) # perform a SRV lookup try: return resolver.query('_domaincontroller_master._tcp.%s.' % domain, 'SRV') except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers): MODULE.warn('No valid UCS domain (%s) at nameserver %s!' % (domain, nameserver)) except dns.exception.Timeout as exc: MODULE.warn('Lookup for DC master record at nameserver %s timed out: %s' % (nameserver, exc)) except dns.exception.DNSException as exc: MODULE.error('DNS Exception: %s' % (traceback.format_exc()))
def _finished(thread, result): if self.__keep_alive_request: self.finished(self.__keep_alive_request.id, None) self.__keep_alive_request = None 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 saving the settings: %s\n%s' % (result, msg)) self._progressParser.current.errors.append( _('Encountered unexpected error during setup process: %s') % result) self._progressParser.current.critical = True self._finishedResult = True
def reset_locale(self, locale): locale = Locale(locale) locale.codeset = self.locale.codeset MODULE.info('Switching language to: %s' % locale) os.putenv('LANG', str(self.locale)) try: _locale.setlocale(_locale.LC_ALL, str(locale)) except _locale.Error: MODULE.warn('Locale %s is not supported, using fallback locale "C" instead.' % locale) _locale.setlocale(_locale.LC_ALL, 'C') self.locale = locale # dynamically change the translation methods _translation.set_language(str(self.locale)) i18nXKeyboard.set_language(str(self.locale)) network._translation.set_language(str(self.locale)) AppCache().clear_cache()
def _enable_ssl_and_test_connection(self, certificate_fname=None): with ucr_rollback(ucr, ['connector/ad/ldap/ssl', 'connector/ad/ldap/certificate']): if certificate_fname: univention.config_registry.handler_set([u'connector/ad/ldap/certificate=%s' % certificate_fname]) server = ucr.get('connector/ad/ldap/host') if server: success = False if admember.server_supports_ssl(server): admember.enable_ssl() try: success = test_connection() except ADNotAvailable: success = False if not success: raise UMC_Error(_('Could not establish an encrypted connection. Either "%r" is not reachable or does not support encryption.') % server) else: MODULE.warn('connector is not configured yet, cannot test connection')
def storage_volume_remove( self, request ): """Removes a list of volumes located in the given pool. options: { 'nodeURI': <node uri>, 'volumes' : [ { 'pool' : <pool name>, 'volumeFilename' : <filename> }, ... ] } return: """ self.required_options( request, 'nodeURI', 'volumes' ) volume_list = [] node_uri = request.options[ 'nodeURI' ] for vol in request.options[ 'volumes' ]: path = self.get_pool_path( node_uri, vol[ 'pool' ] ) if not path: MODULE.warn( 'Could not remove volume %(volumeFilename)s. The pool %(pool)s is not known' % vol ) continue volume_list.append( os.path.join( path, vol[ 'volumeFilename' ] ) ) self.uvmm.send( 'STORAGE_VOLUMES_DESTROY', Callback( self._thread_finish, request ), uri = request.options[ 'nodeURI' ], volumes = volume_list )
def _create_project_dir(self, user, projectdir=None): umask = os.umask( 0) # set umask so that os.makedirs can set correct permissions try: owner = int(user.uidNumber) group = int(user.gidNumber) homedir = user.homedir # create home directory with correct permissions if not yet exsists (e.g. user never logged in via samba) if homedir and not os.path.exists(homedir): MODULE.warn('recreate homedir %r uidNumber=%r gidNumber=%r' % (homedir, owner, group)) os.makedirs(homedir, 0o711) os.chmod(homedir, 0o700) os.chown(homedir, owner, group) # create the project dir if projectdir and not os.path.exists(projectdir): MODULE.info("creating project dir in user's home: %s" % (projectdir, )) os.makedirs(projectdir, 0o700) os.chown(projectdir, owner, group) # set owner and permission if homedir and projectdir: startdir = os.path.normpath(homedir).rstrip('/') projectdir = os.path.normpath(projectdir).rstrip('/') if not projectdir.startswith(startdir): raise OSError( 'Projectdir is not underneath of homedir: %s %s' % (projectdir, startdir)) parts = projectdir[len(startdir):].lstrip('/').split('/') for part in parts: startdir = os.path.join(startdir, part) if os.path.isdir( startdir ): # prevent race conditions with symlink attacs os.chown(startdir, owner, group) except (OSError, IOError) as exc: import traceback MODULE.error(traceback.format_exc()) MODULE.error('failed to create/chown %r: %s' % (projectdir, exc)) finally: os.umask(umask)
def _send_information(self, action, status): ucr.load() server = self.get_server() url = 'http://%s/postinst' % (server, ) uuid = LICENSE.uuid or '00000000-0000-0000-0000-000000000000' try: values = {'uuid': uuid, 'app': self.id, 'version': self.version, 'action': action, 'status': status, 'role': ucr.get('server/role'), } request_data = urllib.urlencode(values) request = urllib2.Request(url, request_data) util.urlopen(request) except: MODULE.warn(traceback.format_exc())
def get( self, request ): """Returns the objects for the given IDs requests.options = [ <ID>, ... ] return: [ { 'id' : <unique identifier>, 'name' : <display name>, 'color' : <name of favorite color> }, ... ] """ MODULE.info( 'MODULEID.get: options: %s' % str( request.options ) ) ids = request.options result = [] if isinstance( ids, ( list, tuple ) ): ids = set(ids) result = filter(lambda x: x['id'] in ids, Instance.entries) else: MODULE.warn( 'MODULEID.get: wrong parameter, expected list of strings, but got: %s' % str( ids ) ) raise UMC_OptionTypeError( 'Expected list of strings, but got: %s' % str(ids) ) MODULE.info( 'MODULEID.get: results: %s' % str( result ) ) self.finished( request.id, result )
def domain_remove( self, request ): """Removes a domain. Optional a list of volumes can bes specified that should be removed options: { 'domainURI': <domain uri>, 'volumes' : [ { 'pool' : <pool name>, 'volumeFilename' : <filename> }, ... ] } return: """ self.required_options( request, 'domainURI', 'volumes' ) volume_list = [] node_uri, domain_uuid = urlparse.urldefrag( request.options[ 'domainURI' ] ) for vol in request.options[ 'volumes' ]: path = self.get_pool_path( node_uri, vol[ 'pool' ] ) if not path: MODULE.warn( 'Could not find volume %(volumeFilename)s. The pool %(pool)s is not known' % vol ) continue volume_list.append( os.path.join( path, vol[ 'volumeFilename' ] ) ) self.uvmm.send( 'DOMAIN_UNDEFINE', Callback( self._thread_finish, request ), uri = node_uri, domain = domain_uuid, volumes = volume_list )
def get_ad_binddn_from_name(base, server, username, password): lp = LoadParm() creds = Credentials() creds.guess(lp) creds.set_username(username) creds.set_password(password) binddn = 'cn=%s,cn=users,%s' % (ldap.dn.escape_dn_chars(username), base) try: samdb = SamDB(url='ldap://%s' % server, session_info=system_session(), credentials=creds, lp=lp) res = samdb.search( base, scope=ldb.SCOPE_SUBTREE, expression=ldap.filter.filter_format('(samAccountName=%s)', [username, ]), attrs=['samaccountname']) if res.count == 1: binddn = res.msgs[0].get('dn', idx=0).extended_str() except ldb.LdbError as ex: MODULE.warn('get_dn_from_name() could not get binddn for user %s: %s' % (username, ex)) return binddn
def init(self): try: if self.init_called: MODULE.warn("init() called multiple times!") return self.init_called = True MODULE.info("Initializing 'updater' module (PID = %d, LANG = '%s')" % (getpid(), self.locale)) self.uu = UniventionUpdater(False) self.ucr = univention.config_registry.ConfigRegistry() self.ucr.load() self._changes = {} # collects changed UCR vars, for committing the corresponding files self._current_job = {} # remembers last seen status of an installer job self._serial_file = Watched_File(COMPONENTS_SERIAL_FILE) self._updates_serial = Watched_Files(UPDATE_SERIAL_FILES) except Exception, ex: MODULE.error("init() ERROR: %s" % str(ex))
def _thread( request ): module = self._get_module_by_request( request ) superordinate = request.options.get( 'superordinate' ) if superordinate == 'None': superordinate = None elif superordinate is not None: MODULE.info( 'Query defines a superordinate %s' % superordinate ) mod = get_module( request.flavor, superordinate ) if mod is not None: MODULE.info( 'Found UDM module for superordinate' ) superordinate = mod.get( superordinate ) request.options[ 'container' ] = superordinate.dn else: raise UMC_OptionTypeError( _( 'Could not find an UDM module for the superordinate object %s' ) % superordinate ) result = module.search( request.options.get( 'container' ), request.options[ 'objectProperty' ], request.options[ 'objectPropertyValue' ], superordinate, scope = request.options.get( 'scope', 'sub' ) ) entries = [] object_type = request.options.get( 'objectType', request.flavor ) for obj in result: if obj is None: continue module = get_module( object_type, obj.dn ) if module.module is None: MODULE.warn( 'Could not identify LDAP object %s (flavor: %s). The object is ignored.' % ( obj.dn, request.flavor ) ) continue entry = { '$dn$' : obj.dn, '$childs$' : module.childs, 'objectType' : module.name, 'labelObjectType' : module.subtitle, 'name' : udm_objects.description( obj ), 'path' : ldap_dn2path( obj.dn, include_rdn = False ) } if request.options[ 'objectProperty' ] not in ( 'name', 'None' ): entry[ request.options[ 'objectProperty' ] ] = obj[ request.options[ 'objectProperty' ] ] entries.append( entry ) return entries
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 _check_variable_lists(self): """ checks if the variable lists (system roles and system versions) are already in the PROPOSALS dict, and if not -> fetches them. """ what = '' try: if not 'sysrole' in PROPOSALS: what = 'fetching system roles' sysroles = self._execute_query('sql_getall_systemroles') PROPOSALS['sysrole'] = sysroles MODULE.info(" ++ system roles: ['%s']" % "','".join(sysroles)) if not 'sysversion' in PROPOSALS: what = 'fetching system versions' sysversions = self._execute_query('sql_getall_systemversions') PROPOSALS['sysversion'] = sysversions MODULE.info(" ++ system versions: ['%s']" % "','".join(sysversions)) # make 'systems not updated' pattern to a selection too PROPOSALS['systems_not_updated'] = PROPOSALS['sysversion'] except Exception, ex: MODULE.warn("[check_variable_lists] while %s: %s" % (what, ex, ))
def _convert_to_grid(self, data, names): """ The queries here return arrays of values. But our grid only accepts dicts where the values are prefixed by the field names. This function converts one record. """ try: result = {} if isinstance(data, (list, tuple, )) and isinstance(names, (list, tuple, )): # find smaller length l = len(data) if len(names) < l: l = len(names) i = 0 while i < l: # This expression does the main work: # (1) assigns the field name to a value # (2) converts database representation into keyed values (_decoded_value) # (3) translates keyed values for display (_id_to_label) result[names[i]] = self._id_to_label(self._decoded_value(names[i], data[i])) i += 1 except Exception, ex: MODULE.warn("convert_to_grid: %s" % str(ex))
def install_dry_run(self, package_manager, component_manager, remove_component=True): MODULE.info('Invoke install_dry_run') result = None try: ucr.load() server_role = ucr.get('server/role') # packages to install to_install = self.get('defaultpackages') MODULE.info('defaultpackages: %s' % (to_install, )) if server_role in ('domaincontroller_master', 'domaincontroller_backup', ): MODULE.info('Running on DC master or DC backup') if self.get('defaultpackagesmaster'): to_install.extend(self.get('defaultpackagesmaster')) # add the new component component_manager.put_app(self) package_manager.update() # get package objects to_install = package_manager.get_packages(to_install) # determine the changes result = package_manager.mark(to_install, [], dry_run=True) result = dict(zip(['install', 'remove', 'broken'], result)) MODULE.info('Package changes: %s' % (result, )) if remove_component: # remove the newly added component MODULE.info('Remove component: %s' % (self.component_id, )) component_manager.remove_app(self) package_manager.update() except: MODULE.warn(traceback.format_exc()) return result
def settings_put(self, iterator, object): # FIXME: returns values although it should yield (multi_response) changed = False # Set values into our UCR copy. try: with util.set_save_commit_load(self.ucr) as super_ucr: for (object,) in iterator: for key, value in object.iteritems(): MODULE.info(" ++ Setting new value for '%s' to '%s'" % (key, value)) super_ucr.set_registry_var("%s/%s" % (constants.ONLINE_BASE, key), value) changed = super_ucr.changed() except Exception as e: MODULE.warn(" !! Writing UCR failed: %s" % str(e)) return [{"message": str(e), "status": constants.PUT_WRITE_ERROR}] self.package_manager.update() # Bug #24878: emit a warning if repository is not reachable try: updater = self.uu for line in updater.print_version_repositories().split("\n"): if line.strip(): break else: raise ConfigurationError() except ConfigurationError: msg = _("There is no repository at this server (or at least none for the current UCS version)") MODULE.warn(" !! Updater error: %s" % msg) response = {"message": msg, "status": constants.PUT_UPDATER_ERROR} # if nothing was committed, we want a different type of error code, # just to appropriately inform the user if changed: response["status"] = constants.PUT_UPDATER_NOREPOS return [response] except: info = sys.exc_info() emsg = "%s: %s" % info[:2] MODULE.warn(" !! Updater error [%s]: %s" % (emsg)) return [{"message": str(info[1]), "status": constants.PUT_UPDATER_ERROR}] return [{"status": constants.PUT_SUCCESS}]
def run_installer(self, request): """ This is the function that invokes any kind of installer. Arguments accepted: job ..... the main thing to do. can be one of: 'release' ...... perform a release update 'component' .... install a component by installing its default package(s) 'distupgrade' .. update all currently installed packages (distupgrade) 'check' ........ check what would be done for 'update' ... do we need this? detail ....... an argument that specifies the subject of the installer: for 'release' .... the target release number, for 'component' .. the component name, for all other subjects: detail has no meaning. Setup for this function is contained in the INSTALLERS structure at the top of the file. """ # ----------- DEBUG ----------------- MODULE.info("updater/installer/execute invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- # Clean up any stored job details ... they're now obsolete. self._current_job = {} result = {} result["status"] = 0 # successful. If not: set result['message'] too. subject = request.options.get("job", "") detail = request.options.get("detail", "") if not subject in INSTALLERS: result["message"] = "Unknown installer job type '%s'" % subject result["status"] = RUN_PARAMETER_ERROR MODULE.warn(result["message"]) self.finished(request.id, result) return MODULE.info(" ++ starting function '%s'" % subject) if not "command" in INSTALLERS[subject]: result["message"] = "Function '%s' has no command" % subject result["status"] = RUN_PARAMETER_ERROR MODULE.warn(result["message"]) self.finished(request.id, result) return # initial values of current job self._current_job = {"job": subject, "detail": detail, "logfile": "", "lines": 0} # We want to limit the amount of logfile data being transferred # to the frontend. So we remember the line count of the associated # log file. if "logfile" in INSTALLERS[subject]: fname = INSTALLERS[subject]["logfile"] count = 0 try: file = open(fname, "r") count = 0 for line in file: count += 1 finally: if file is not None: file.close() self._current_job["lines"] = count self._current_job["logfile"] = fname try: # Assemble the command line, now somewhat complicated: # # (1) take the 'command' entry from the INSTALLERS entry of this subject # (2) if it doesn't contain a percent sign -> ready. # (3) if it contains a percent sign: we must format something: # (4) if the subject is about 'component' we must get the 'defaultpackages' # entry from the UCR tuple named by 'detail' and use that. # (5) if not, we can format the 'detail' field into the command. # # cmd = '%s' % INSTALLERS[subject]['command'] # I need a copy of this string! # cmd = INSTALLERS[subject]["command"] if cmd.find("%") != -1: if subject == "component": pkgs = " ".join(self.uu.get_component_defaultpackage(detail)) cmd = cmd % pkgs MODULE.info(" Resolution of default packages of the '%s' component:" % detail) MODULE.info(" PKGS = '%s'" % pkgs) MODULE.info(" CMD = '%s'" % cmd) else: cmd = cmd % request.options.get("detail", "") MODULE.info(" ++ Creating job: '%s'" % cmd) self.__create_at_job(cmd, detail) except Exception, ex: MODULE.warn(" ERROR: %s" % str(ex))
def _finished(thread, result): if isinstance(result, BaseException): MODULE.warn("Exception during %s %s: %s" % (function, application_id, str(result)))
if query == '': query = None args = None if 'args' in desc: args = desc['args'] temp = self._execute_query(desc['function'], query, args) MODULE.info(" ++ Start converting %d entries" % len(temp)) for record in temp: dbf = desc['columns'] if 'db_fields' in desc: dbf = desc['db_fields'] result.append(self._convert_to_grid(record, dbf)) MODULE.info(" ++ Conversion finished.") except Exception, ex: MODULE.warn(" !! execute query: %s" % str(ex)) request.status = SUCCESS # Remember result for repeated invocation of the same query # (e.g. click on any sort header) self._last_result = result # ---------- DEBUG -------------- MODULE.info("pkgdb/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")
def _finished( thread, result ): if isinstance( result, BaseException ): MODULE.warn( 'Exception during saving the settings: %s' % str( result ) )
def _execute_query(self, function, query=None, args=None): """ Executes a pkgdb query """ what = 'starting' MODULE.info("Executing query (function='%s',query='%s',args='%s'):" % (function, query, args, )) try: moreargs = '' kwargs = {} if query is not None: kwargs['query'] = query if args is not None: kwargs.update(args) if function == 'sql_getall_systems': function = updb.sql_getall_systems elif function == 'sql_getall_systemroles': function = updb.sql_getall_systemroles elif function == 'sql_getall_systemversions': function = updb.sql_getall_systemversions elif function == 'sql_getall_packages_in_systems': function = updb.sql_getall_packages_in_systems elif function == 'sql_get_systems_by_query': function = updb.sql_get_systems_by_query elif function == 'sql_get_packages_in_systems_by_query': function = updb.sql_get_packages_in_systems_by_query else: assert False what = 'evaluating cmdstr' result = function(self.cursor, **kwargs) MODULE.info("-> result: %r" % (result, )) # Uuh, and sometimes it returns None, not telling why... if result is None: result = [] # DEBUG for #22896: the fetchall() call can return different data types. # Usually we expect an array of dictionaries: # # result = [ # { 'field1':'value1', 'field2':'value2' }, # { ... } # ] # # but depending on the type of query, the fields are sometimes returned without names, as in: # # result = [ # ['one', 'two'], # ['three', 'four'] # ] # # For Grid-driven queries, this is not relevant. But for 'distinct' queries that are meant # for ComboBox data, we need one array containing all those values, so converting them here: # what = 'checking result type' if (len(result) > 0) and ("'list'" in str(type(result[0]))) and (len(result[0]) == 1): MODULE.info(" ++ Converting %d entries from single-element arrays to strings" % (len(result), )) tmp = [] for element in result: tmp.append(element[0]) result = tmp # Marshaler isn't able to handle too much data, so we limit the record count. Better SQL # execution should avoid returning too much data, but in the meantime, we work around here. what = 'checking for record limit' if len(result) > RECORD_LIMIT: what = 'limiting record count' MODULE.warn(" >> QUERY returned %d entries -> showing only first %d" % (len(result), RECORD_LIMIT, )) del result[RECORD_LIMIT:] return result except Exception, ex: MODULE.warn(" !! Query (function='%s',query='%s',args='%s') failed:" % (function, query, args, )) MODULE.warn(' !! [while %s]: %s' % (what, ex, ))
def change(self, request): '''Return a dict with all necessary values for ipchange read from the current status of the system.''' result = {'success' : True} message = None MODULE.info('IP Change') if self._username.endswith('$'): server_name='%s' % self._username[:-1] MODULE.info('Server Name: %s' % server_name) lo, position = univention.admin.uldap.getAdminConnection() co = univention.admin.config.config() cmodule = univention.admin.modules.get('computers/%s' % request.options.get('role')) filter='(cn=%s)' % server_name cobject = univention.admin.modules.lookup(cmodule, co, lo, scope='sub', superordinate=None, filter=filter) if cobject: server = cobject[0] # do we have a forward zone for this IP address? if request.options.get('oldip') and request.options.get('oldip') != request.options.get('ip'): fmodule = univention.admin.modules.get('dns/forward_zone') filter='(aRecord=%s)' % (request.options.get('oldip')) forwardobjects = univention.admin.modules.lookup(fmodule, co, lo, scope='sub', superordinate=None, filter=filter) for forwardobject in forwardobjects: forwardobject.open() forwardobject['a'].remove(request.options.get('oldip')) forwardobject['a'].append(request.options.get('ip')) forwardobject.modify() # remove old DNS reverse entries with old IP server.open() old_ip = server['ip'] for e in server['dnsEntryZoneReverse']: if e[1] == old_ip: server['dnsEntryZoneReverse'].remove(e) # change IP server['ip'] = request.options.get('ip') MODULE.info('Change IP to %s' % request.options.get('ip')) try: server.modify() except Exception, err: MODULE.warn('Failed to change IP: %s' % traceback.format_exc()) result['success'] = False message = 'Failed to change IP' # do we have a new reverse zone for this IP address? rmodule = univention.admin.modules.get('dns/reverse_zone') # ignore all netmask values != 255 c = request.options.get('netmask').split('.').count('255') filter='(subnet=%s)' % (string.join(request.options.get('ip').split('.')[0:c], '.') ) reverseobject = univention.admin.modules.lookup(rmodule, co, lo, scope='sub', superordinate=None, filter=filter) if reverseobject: server.open() server['dnsEntryZoneReverse'].append([reverseobject[0].dn, request.options.get('ip')]) try: server.modify() except Exception, err: MODULE.warn('Failed to change DNS reverse zone: %s' % traceback.format_exc()) result['success'] = False message = 'Failed to change DNS reverse zone'
def _finished(thread, result): if isinstance(result, BaseException): MODULE.warn("Exception during %s %s: %r" % (function, packages, str(result)))
def all(cls, force_reread=False): # reload ucr variables ucr.load() # load the first time the category translations cls._get_category_translations() if force_reread: cls._all_applications = None if cls._all_applications is None: # query all applications from the server ucr.load() url = cls.get_metainf_url() parser = HTMLParser() try: cls._all_applications = [] threads = [] for iline in util.urlopen(url): # parse the server's directory listing m = cls._reg_dir_listing.match(iline) if m: # try to load and parse application's .ini file ifilename = m.group('name') # 'foo%20&%20bar.ini' -> 'foo%20&%20bar.ini' ifilename = parser.unescape(ifilename) iurl = url + '/' + ifilename # thread function def _append_app(myurl): try: cls._all_applications.append(Application(myurl)) except (ConfigParser.Error, urllib2.HTTPError, urllib2.URLError, ValueError, KeyError) as e: MODULE.warn('Could not open application file: %s\n%s' % (myurl, e)) # start a new thread for fetching the application information thread = threading.Thread(target=_append_app, args=(iurl,)) thread.start() threads.append(thread) # wait until all threads are finished for ithread in threads: ithread.join() except (urllib2.HTTPError, urllib2.URLError) as e: MODULE.warn('Could not query App Center host at: %s\n%s' % (url, e)) raise # filter function def _included(the_list, app): if the_list == '*': return True the_list = map(str.lower, cls._reg_comma.split(the_list)) if app.name.lower() in the_list: return True for category in app.get('categories'): if category.lower() in the_list: return True return False # filter blacklisted apps (by name and by category) filtered_applications = cls._all_applications blacklist = ucr.get('repository/app_center/blacklist') if blacklist: filtered_applications = [app for app in filtered_applications if not _included(blacklist, app)] # filter whitelisted apps (by name and by category) whitelist = ucr.get('repository/app_center/whitelist') if whitelist: # whitelist is stronger than blacklist: iterate over all_applications filtered_applications = [app for app in cls._all_applications if _included(whitelist, app) or app in filtered_applications] # group app entries by their ID app_map = {} for iapp in filtered_applications: if iapp.id not in app_map: app_map[iapp.id] = [] app_map[iapp.id].append(iapp) # version string comparison def _version_cmp(iapp, japp): iver = LooseVersion(iapp.version) jver = LooseVersion(japp.version) return cmp(iver, jver) # pick the latest version of each app final_applications = [] for iid, iapps in app_map.iteritems(): # sort apps after their version (latest first) iapps.sort(cmp=_version_cmp, reverse=True) # store all versions iapps[0].versions = iapps final_applications.append(iapps[0]) return final_applications
def _append_app(myurl): try: cls._all_applications.append(Application(myurl)) except (ConfigParser.Error, urllib2.HTTPError, urllib2.URLError, ValueError, KeyError) as e: MODULE.warn('Could not open application file: %s\n%s' % (myurl, e))
def updater_log_file(self, request): """ returns the content of the log file associated with the job. Argument 'count' has the same meaning as already known: <0 ...... return timestamp of file (for polling) 0 ....... return whole file as a string list >0 ...... ignore this many lines, return the rest of the file *** NOTE *** As soon as we have looked for a running job at least once, we know the job key and can associate it here. TODO: honor a given 'job' argument """ # ----------- DEBUG ----------------- MODULE.info("updater/installer/logfile invoked with:") pp = pprint.PrettyPrinter(indent=4) st = pp.pformat(request.options).split("\n") for s in st: MODULE.info(" << %s" % s) # ----------------------------------- result = None job = "" if self._current_job and "job" in self._current_job: job = self._current_job["job"] else: job = request.options.get("job", "") count = request.options.get("count", 0) if count < 0: result = 0 else: result = [] if not job in INSTALLERS: # job empty: this is the first call I can't avoid if job != "": MODULE.warn(" ?? Don't know a '%s' job" % job) else: if not "logfile" in INSTALLERS[job]: MODULE.warn(" ?? Job '%s' has no associated log file" % job) else: fname = INSTALLERS[job]["logfile"] if count < 0: result = self._logstamp(fname) else: # don't read complete file if we have an 'ignore' count if ("lines" in self._current_job) and (self._current_job["lines"]): count += int(self._current_job["lines"]) result = self._logview(fname, -count) # again debug, shortened if isinstance(result, int): MODULE.info(" >> %d" % result) else: MODULE.info(" >> %d lines" % len(result)) # ----------- DEBUG ----------------- MODULE.info("updater/installer/logfile 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 _finished( thread, result, request ): if self._check_thread_error( thread, result, request ): return success, data = result if not success: self.finished( request.id, None, message = str( data ), status = MODULE_ERR_COMMAND_FAILED ) return node_uri = urlparse.urlsplit( request.options[ 'domainURI' ] ) uri, uuid = urlparse.urldefrag( request.options[ 'domainURI' ] ) json = object2dict( data ) ## re-arrange a few attributes for the frontend # annotations for key in json[ 'annotations' ]: if key == 'uuid': continue json[ key ] = json[ 'annotations' ][ key ] # type json[ 'type' ] = '%(domain_type)s-%(os_type)s' % json # STOP here if domain is not available if not json[ 'available' ]: MODULE.info( 'Domain is not available: %s' % str( json ) ) self.finished( request.id, json ) return # RAM json[ 'maxMem' ] = MemorySize.num2str( json[ 'maxMem' ] ) # interfaces (fake the special type network:<source>) for iface in json[ 'interfaces' ]: if iface[ 'type' ] == Interface.TYPE_NETWORK: iface[ 'type' ] = 'network:' + iface[ 'source' ] # disks for disk in json[ 'disks' ]: if disk[ 'type' ] == Disk.TYPE_FILE: disk[ 'volumeFilename' ] = os.path.basename( disk[ 'source' ] ) disk[ 'pool' ] = self.get_pool_name( uri, os.path.dirname( disk[ 'source' ] ) ) else: disk[ 'volumeFilename' ] = disk[ 'source' ] disk[ 'pool' ] = None disk[ 'paravirtual' ] = disk[ 'target_bus' ] in ( 'virtio', 'xen' ) disk[ 'volumeType' ] = disk[ 'type' ] if isinstance( disk[ 'size' ], ( int, long ) ): disk[ 'size' ] = MemorySize.num2str( disk[ 'size' ] ) # graphics if json['graphics']: try: gfx = json[ 'graphics' ][ 0 ] json[ 'vnc' ] = True json[ 'vnc_host' ] = None json[ 'vnc_port' ] = None json[ 'kblayout' ] = gfx[ 'keymap' ] json[ 'vnc_remote' ] = gfx[ 'listen' ] == '0.0.0.0' json[ 'vnc_password' ] = gfx[ 'passwd' ] # vnc_password will not be send to frontend port = int( json[ 'graphics' ][ 0 ][ 'port' ] ) if port == -1: raise ValueError() host = node_uri.netloc vnc_link_format = ucr.get('uvmm/umc/vnc/host', 'IPv4') or '' match = Domains.RE_VNC.match(vnc_link_format) if match: family, pattern, substs = match.groups() if family: # IPvX family = Domains.SOCKET_FAMILIES[family] regex = re.compile(pattern or '.*') addrs = socket.getaddrinfo(host, port, family, socket.SOCK_STREAM, socket.SOL_TCP) for (family, _socktype, _proto, _canonname, sockaddr) in addrs: host, port = sockaddr[:2] if regex.search(host): break else: raise LookupError(pattern) host = Domains.SOCKET_FORMATS[family] % (host,) elif substs: # NAME for subst in substs.split(): old, new = subst.split('=', 1) host = host.replace(old, new) elif vnc_link_format: # overwrite all hosts with fixed host host = vnc_link_format json[ 'vnc_host' ] = host json[ 'vnc_port' ] = port except re.error, ex: # port is not valid MODULE.warn('Invalid VNC regex: %s' % (ex,)) except socket.gaierror, ex: MODULE.warn('Invalid VNC host: %s' % (ex,))