def check_ns(self, *args, **kwargs): if len(args) > 1: return None try: ip = socket.gethostbyname(str(args[0])) return ip except: log.warning(u'Fail checking dnsname {}'.format(args[0])) return False
def check_n4d(self, *args, **kwargs): output = {} output[u'N4D_STATUS'] = {u'online': str(self.check_open_port(u'9779'))} output[u'N4D_STATUS'].update( {u'resolvable': str(self.check_ns(u'server'))}) try: since = self.execute( run= 'systemctl show --value --property=ActiveEnterTimestamp n4d', stderr=None) status = '' status = self.execute(run=[ 'journalctl', '-u', 'n4d', '-o', 'cat', '--no-pager', '-S', since, '-q' ], stderr=None, asroot=True) if status: status = status.split('\n') output['N4D_LAST_LOG'] = status if status: available = [] failed = [] into_plugins = False for line in status: line = line.strip() if not into_plugins and re.search( '\[Core\] Initializing plugins', line): into_plugins = True if into_plugins: if re.search('\[Core\] Executing startups', line): break m = re.search( r'(?P<pluginname>\w+)\s+\.{3}\s+(?P<status>\w+)?$', line) if m: d = m.groupdict() if d[u'status'] and d[u'pluginname']: if d[u'status'].lower() == u'ok': available.append(d[u'pluginname']) else: failed.append(d[u'pluginname']) available = sorted(available) failed = sorted(failed) output[u'N4D_MODULES'] = { u'available': dict(zip(available, available)), u'failed': dict(zip(failed, failed)) } else: log.warning('Cannot get n4d journal') output['N4D_MODULES'] = '' except Exception as e: output[u'N4D_STATUS'].update({u'initlog': u'not available'}) output[u'N4D_STATUS'].update({u'initlog_error': str(e)}) return output
def run(self, *args, **kwargs): d = {} output = {} output.setdefault(u'LLIUREX_VERSION', None) output[u'ARCHITECTURE'] = self.execute(run=u'arch', stderr=None) try: os.stat('/usr/bin/lliurex-version') except: log.warning('/usr/bin/lliurex-version NOT INSTALLED') output.update({'LLIUREX_VERSION': 'Non lliurex'}) output.update({'LLIUREX_RELEASE': 'Non lliurex'}) output.update({'LLIUREX_SESSION_TYPE': 'Non lliurex'}) output.update({'HAS_MIRROR': False}) output.update({'LOGIN_TYPE': 'Unknown'}) return output output.update({ u'LLIUREX_VERSION': self.execute(run=u'lliurex-version -n', stderr=None) }) try: for k, v in [ x.split(u'=') for x in self.execute( run=u'lliurex-version -a -e', stderr=None).replace( u'\n', u' ').split(u' ') ]: d[k] = v except: pass output.setdefault(u'LLIUREX_RELEASE', None) for x in [ u'CLIENT', u'DESKTOP', u'SERVER', u'INFANTIL', u'MUSIC', u'PIME' ]: if x in d and d[x].lower() == u'yes': output[u'LLIUREX_RELEASE'] = x output.setdefault(u'LLIUREX_SESSION_TYPE', None) for x in [u'LIVE', u'SEMI', u'FAT', u'THIN']: if x in d and d[x].lower() == u'yes': output[u'LLIUREX_SESSION_TYPE'] = x if u'MIRROR' in d and d[u'MIRROR'].lower() == u'true': output[u'HAS_MIRROR'] = True else: output[u'HAS_MIRROR'] = False output.setdefault(u'LOGIN_TYPE', None) if u'LOGIN_TYPE' in d: output[u'LOGIN_TYPE'] = d[u'LOGIN_TYPE'] output[u'ARCHITECTURE'] = self.execute(run=u'arch', stderr=None) return output
def _kill_proc(self, *args, **kwargs): #self._close_stderr() try: while (args[0].is_alive()): args[0].terminate() time.sleep(0.01) self.nproc -= 1 log.debug(u'Killed {} remaning procs={}'.format( args[0].name, self.nproc)) except Exception as e: log.warning(u'Error while killing {}'.format(args[0]))
def check_exports(self, *args, **kwargs): files = [] if os.path.isfile(u'/etc/exports'): files.append(u'/etc/exports') if os.path.isdir(u'/etc/exports.d'): for file in os.listdir(u'/etc/exports.d/'): files.append(u'/etc/exports.d/' + file) content = [] for file in files: with open(file, u'r') as f: content.extend(self.uncomment(f.read())) if content: content = u'\n'.join(content) else: content = None needed_services = [ u'portmapper', u'mountd', u'nfs', u'nlockmgr', u'status' ] exitting = False try: os.stat('/usr/bin/rpcinfo') except: log.warning('/usr/bin/rpcinfo NOT INSTALLED') exported = None exitting = True if not exitting: services_running = self.execute(run=u'rpcinfo -p', stderr=None) if services_running: reg = re.compile(r'\s+\d+\s+\d+\s+\w+\s+\d+\s+(\w+)*', re.UNICODE) for s in services_running.split(u'\n'): m = re.findall(reg, s) if m: if m[0] in needed_services: needed_services.remove(m[0]) if needed_services: needed_services = None else: needed_services = True if needed_services: exported = self.execute(run=u'showmount -e --no-headers', stderr=None) if exported: exported = exported.split(u'\n') else: exported = None else: exported = None return {u'FILES': files, u'CONTENT': content, u'EXPORTED': exported}
def read_pass(self): self.pwd = None sfile = u'/etc/ldap.secret' try: if not os.path.exists(sfile): sfile = None else: with open(sfile, u'r') as f: self.pwd = f.read().strip() except: if sfile: log.warning( u'Running as user, secret file verification is not possible' ) pass
def compress_file(self, *args, **kwargs): file = kwargs.get(u'file') string = kwargs.get(u'string') if not (u'file' in kwargs or u'string' in kwargs): log.error( u'Compressing called without \'file\' or \'string\' keyparam') if file: if os.path.exists(file): try: with open(file, u'r') as f: try: content = f.read() except: return None try: return (u'__gz__', base64.b64encode( zlib.compress( content.encode(u'utf-8').strip()))) except: return (u'__gz__', base64.b64encode( zlib.compress(content.strip()))) except Exception as e: log.warning(u'Fail compressing file {} : {}'.format( file, str(e).decode('utf-8'))) return str(u'NOT_READABLE') if string: try: try: return (u'__gz__', base64.b64encode( zlib.compress( string.encode(u'utf-8').strip()))) except: return (u'__gz__', base64.b64encode(zlib.compress(string.strip()))) except Exception as e: log.warning(u'Fail compressing string {} : {}'.format( string, e)) return None
def uncomment(self, *args, **kwargs): r = u'' comments = kwargs.get(u'comments', [u'#']) creg = [] for c in comments: creg.append(c + u'.*') creg = u'|'.join(creg) try: is_file = os.path.isfile(args[0]) except: is_file = False if is_file: reg = re.compile(r'^(\s*|{})*$'.format(creg), re.UNICODE) try: with open(args[0], u'r') as f: for line in f.readlines(): #line=line.decode('utf-8') line = line m = re.match(reg, line) if not m: r += line except Exception as e: log.warning(u'Trying to read unreadable file {}'.format( args[0])) r += str(u'NOT_READABLE') else: if isinstance(args[0], list): string = u''.join(str(args[0])) else: string = str(args[0]) reg = re.compile(r'^(\s*|#.*)*$') for line in string.split(u'\n'): m = re.match(reg, line) if not m: r += line + u'\n' try: r = r.decode(u'utf-8') except: r = r.encode(u'utf-8').decode(u'utf-8') return r.strip()
def get_varlog(self,*args,**kwargs): varlog={} regexp=re.compile(r'^[^\.]+(\.log|(\.\d+)+)?$',re.UNICODE) #filter=lambda x: [ f for f in x if re.match(regexp,f)] try: #prefix=u'/var/log' #file_names=[] #for root,dirnames,filenames in os.walk(prefix): # for filename in filter(filenames): # file_names.append(os.path.join(root,filename)) file_names=self.list_files(path=u'/var/log',regexp=regexp) exceptions=[u'/var/log/lastlog',u'/var/log/wtmp',u'/var/log/wtmp.1'] file_names=[ x for x in file_names if x not in exceptions] for file in file_names: comp=self.compress_file(file=file) if comp: varlog[file]=comp else: log.warning(u'Fail compressing logfile {}'.format(file)) except Exception as e: pass return varlog
def parse_tree(self, *args, **kwargs): if not (isinstance(args[0], str) or isinstance(args[0], str)): return None output = {} lines = args[0].split(u'\n') path = output atrib = u'' value = u'' for line in lines: if line == u'': path = output else: if line.startswith(u'dn: '): hierarchy = line[4:].split(u',') hierarchy.reverse() for level in hierarchy: if level not in path: path[level] = {} path = path[level] elif line.startswith(u' '): value = value + line[1:] path[atrib][-1] = value else: parts = line.split(u' ') atrib = parts[0][:-1] value = u' '.join(parts[1:]) if atrib in path: path[atrib].append(value) else: path.update({atrib: [value]}) if output: output = self.make_alias(output) else: log.warning(u'Can\'t parse ldap tree') raise Exception(u'No_ldap_tree') return output
def check_open_port(self, *args, **kwargs): if len(args) > 2 or len(args) == 0: return if len(args) == 1: port = str(args[0]) host = u'127.0.0.1' m = re.search(r'^\d+$', port) if m: port = int(args[0]) else: log.warning( u'Trying to check open port with no numerical value host=\'{}\' port\'{}\'' .format(host, port)) return False else: host = str(args[0]) #split protocol if there is something host = re.findall(r'(?:[^/]+/+)?(.*)$', host)[0] m = re.search(r'^(\d+(?:\.\d+){3})$', host) if not m: if not self.check_ns(host): return False port = str(args[1]) m = re.search(r'^\d+$', port) if m: port = int(port) else: log.warning( u'Trying to check open port with no numerical value host=\'{}\' port\'{}\'' .format(host, port)) return False sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(3) try: res = sock.connect_ex((host, port)) except: log.warning(u'Timeout connection to {}:{}'.format(host, port)) return None finally: sock.close() if res == 0: return True else: return False
def run(self, *args, **kwargs): log.warning(u'Running fake run method from base class') pass
def run(self, *args, **kwargs): out = {u'LDAP_MASTER_IP': None} output = {} release = kwargs[u'LLIUREX_RELEASE'] vars = kwargs[u'N4D_VARS'] mapping = {u'CLIENT_LDAP_URI': u'SERVER_LDAP'} server = None localldap = None # Guess server ldap uri for search_var in mapping: if search_var in vars and u'value' in vars[search_var]: out.update({mapping[search_var]: vars[search_var][u'value']}) server = vars[search_var][u'value'] out.setdefault(u'LOCAL_LDAP', True) localldap = True if not server: ip_server = self.check_ns(u'server') try: ip_server2 = kwargs[u'NETINFO'][u'gw'][u'via'] except: ip_server2 = None if not ip_server: log.warning(u'\'server\' not resolvable') if ip_server2: server = ip_server2 log.warning( u'using gateway trying to guess \'server\' dnsname') else: log.warning(u'not detected any gateway') else: server = ip_server if ip_server != ip_server2: log.warning(u'\'server\' is not my gateway') if server: out.update({u'SERVER_LDAP': server}) out.update({u'LOCAL_LDAP': False}) localldap = False else: out.update({u'SERVER_LDAP': None}) out.update({u'LOCAL_LDAP': None}) localldap = None self.read_pass() output[u'PORTS'] = self.check_ports(server, localldap) mode = None if output[u'PORTS'][u'636']: output[u'CONFIG'] = self.get_ldap_config(release, server) mode = u'UNKNOWN' try: test = output[u'CONFIG'][u'INITIALIZED'] except: mode = u'UNNINITIALIZED' try: test = output[u'CONFIG'][u'CONFIG'][u'config'][u'{1}mdb'][ u'olcSyncrepl'] test = output[u'CONFIG'][u'CONFIG'][u'config'][u'{1}mdb'][ u'olcUpdateRef'] mode = u'SLAVE' if output[u'CONFIG'][u'CONFIG'][u'config'][u'{1}mdb'][ u'olcSyncrepl'][0]: m = re.search( r'provider=ldapi?://(?P<LDAP_MASTER_IP>\d+\.\d+\.\d+\.\d+)u', output['CONFIG']['CONFIG']['config']['{1}mdb'] ['olcSyncrepl'][0]) if m: out.update(m.groupdict()) except: # indep or (master/slave(running without permissions)) mode = u'INDEPENDENT' netinfo = kwargs[u'NETINFO'] if netinfo: aliased_interfaces = [ k for k in netinfo if isinstance(netinfo[k], dict) and u'nalias' in netinfo[k] and netinfo[k][u'nalias'] > 0 ] for i in aliased_interfaces: for n in range(netinfo[i][u'nalias']): if u'alias' + str(n + 1) + u'_ifaddr' in netinfo[i]: ip_alias = netinfo[i][ u'alias' + str(n + 1) + u'_ifaddr'].split(u'.')[3].split(u'/')[0] if ip_alias == u'1': mode = u'SLAVE' elif ip_alias == u'254': mode = u'MASTER' if not out['LDAP_MASTER_IP'] and mode in [ 'SLAVE', MASTER ]: out['LDAP_MASTER_IP'] = netinfo[i][ u'alias' + str(n + 1) + u'_ifaddr'].split('/')[0] if not aliased_interfaces: phys_ifaces = [ dev for dev in netinfo if isinstance(netinfo[dev], dict) and 'ifaddr' in netinfo[dev] and netinfo[dev]['ifaddr'] ] for dev in phys_ifaces: ip = netinfo[dev]['ifaddr'] ip = ip.split('/') octets = ip[0].split('.') if octets[0] == '10' and octets[1] == '3': if octets[3] == '1': mode = 'SLAVE' elif octets[3] == '254': mode = 'MASTER' if not out['LDAP_MASTER_IP'] and mode in [ 'SLAVE', 'MASTER' ]: out['LDAP_MASTER_IP'] = '.'.join(octets) output[u'FILES'] = self.check_files(release, mode, server) out.update({u'LDAP_INFO': output, u'LDAP_MODE': mode}) return out
def execute(self, timeout=3.0, shell=False, *args, **kwargs): params = {} if u'run' not in kwargs: log.error(u'Execute called without \'run\' key parameter') return None else: if not isinstance(kwargs[u'run'], list): runlist = kwargs[u'run'].split(u' ') else: runlist = kwargs[u'run'] timeout_remaning = float(timeout) #Ready for python3 #params.setdefault(u'timeout',int(timeout)) #Python 2 code delay = 0.1 if u'stderr' in kwargs: if kwargs[u'stderr'] == u'stdout': params.setdefault(u'stderr', subprocess.STDOUT) if kwargs[u'stderr'] == None or kwargs[u'stderr'] == u'no': params.setdefault(u'stderr', open(os.devnull, u'w')) else: params.setdefault(u'stderr', subprocess.PIPE) else: params.setdefault(u'stderr', subprocess.PIPE) params.setdefault(u'stdout', subprocess.PIPE) with_uncomment = False if u'nocomment' in kwargs: if kwargs[u'nocomment'] == True or kwargs[u'nocomment'] == u'yes': with_uncomment = True myinfo = pwd.getpwuid(os.geteuid()) user = myinfo.pw_name group = grp.getgrgid(myinfo.pw_gid).gr_name root_mode = False if self.check_root(): if u'asroot' in kwargs: if kwargs[u'asroot'] == True or kwargs[u'asroot'] == u'yes': root_mode = True if not root_mode: params.setdefault(u'preexec_fn', self.demote) user = u'nobody' group = u'nogroup' else: params.setdefault(u'preexec_fn', self.set_root_ids) else: if kwargs.get('asroot') == True: log.warning('Can\'t use rootmote execution for: \'{}\''.format( ' '.join(runlist))) params.setdefault(u'shell', shell) stdout = None stderr = None log.info(u'Executing command \'{}\' as {}:{}'.format( u' '.join(runlist), user, group)) try: start = time.time() p = subprocess.Popen(runlist, **params) ret = p.poll() while ret is None and timeout_remaning > 0: time.sleep(delay) timeout_remaning -= delay stdout, stderr = p.communicate() ret = p.poll() if stdout is None: stdout, stderr = p.communicate() if timeout_remaning <= 0: raise Exception( u'timeout({}) exceded while executing {}'.format( timeout, kwargs[u'run'])) if ret != 0: if stderr != u'': stderr = u'stderr={}'.format(stderr) log.warning( u'Execution with exit code {} (possible error) {}'.format( ret, stderr)) except Exception as e: log.error(u'Error executing: {}'.format(e)) return None if stdout != None: if with_uncomment: out = self.uncomment(stdout.strip()) else: out = stdout.strip() try: out = out.decode(u'utf-8') except UnicodeDecodeError: out = out.encode(u'utf-8') return out else: log.error( u'Execution of {} hasn\'t produced any result, returning None'. format(kwargs['run'])) return None
def run(self, *args, **kwargs): ret = True if not self.is_classified: if not self._classify(**kwargs): ret = False else: log.info(u'Running all plugins') if not self.START_RUNNING_TIME: self.START_RUNNING_TIME = time.time() procs = [None] * self.MAX_PROCESSES done = None remaning = copy.copy(self.order) started = [] self.capabilities_stored = [] if self.fake_capabilities: for x in self.fake_capabilities.keys(): self.capabilities_stored.append(x) while done == None and not self.aborting: #start processes for plug in self.order: if done == False: #recalculation in process break if procs[self.order.index(plug)] == None: can_start = False if self.pm.classes[plug]._NEEDS: for need in self.pm.classes[plug]._NEEDS: if need: if need in self.capabilities.keys( ) and need in self.capabilities_stored: can_start = True else: can_start = False break else: can_start = True if can_start: pipe_in, pipe_out = Pipe(duplex=False) #kw = {u'out': pipe_out,u'stderr':open(os.devnull,u'w')} kw = {u'out': pipe_out} args = (pipe_out, ) obj = self.pm.classes[plug]() for need in obj._NEEDS: if need and need in self.capabilities.keys(): if need.lower()[0:6] == u'helper': f = pickle.loads(self.helpers[need]) dummy_func = types.FunctionType( f[u'code'].__code__, f[u'glob'], f[u'code'].__code__.co_name) dummy_func.__globals__.update( {u'self': f[u'code'].__self__}) obj.__dict__[f[u'code'].__code__. co_name] = dummy_func setattr(obj, f[u'code'].__code__.co_name, f[u'code']) log.debug( u'Helper {} registered into {}'.format( need, obj.__class__.__name__)) else: if self.capabilities[need] == None: log.warning( u'Providing capability {} with an empty value to {} plugin' .format(need, obj.__class__.__name__)) kw.update({need: self.capabilities[need]}) args = args + (self.capabilities[need], ) procs[self.order.index(plug)] = { u'process': Process(target=obj._run, name=plug, args=args, kwargs=kw), u'name': plug, u'stime': None, u'rtime': None, u'pin': pipe_in, u'pout': pipe_out } if not self.aborting: procs[self.order.index(plug)][u'process'].start() procs[self.order.index( plug)][u'stime'] = time.time() started.append(plug) self.nproc += 1 self.nproc_started += 1 log.debug(u'Started process number={} ({})'.format( self.nproc_started, plug)) # check processes for pinfo in procs: if done == False: # recalculation in progress break if pinfo and pinfo[u'stime']: t = time.time() - pinfo[u'stime'] if self.MAX_RUNNING_TIME and t > self.MAX_RUNNING_TIME and not pinfo[ u'rtime']: self._kill_proc(pinfo[u'process']) pinfo[u'rtime'] = t log.error( u'Plugin {} aborted, maximun running time ({}) exceded' .format(pinfo[u'name'], self.MAX_RUNNING_TIME)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True del self.pm.classes[pinfo[u'name']] log.debug( u'Plugin {} deactivated, recalculating dependencies & rerunning' .format(pinfo[u'name'])) done = False ret = False break if pinfo[u'pin'].poll(): pinfo[u'rtime'] = t output = pinfo[u'pin'].recv() pinfo[u'process'].join() self.nproc -= 1 log.debug(u'Finished {}'.format(pinfo[u'name'])) for provide in self.pm.classes[ pinfo[u'name']]._PROVIDES: if provide: if output and type(output) == type( dict()) and provide in output.keys(): #out_stripped=str(output[provide]).upper().replace(u'NULL',u'null').strip() out_stripped = output[provide] if provide[0:6].lower() == u'helper': self.helpers[provide] = out_stripped out_stripped = u'STORED' if provide in self.capabilities.keys( ) and self.capabilities[provide] != None: log.warning( u'Plugin {} overwrite {} capability' .format(pinfo[u'name'], provide)) else: log.debug( u'Plugin {} set the capability \'{}\' with value \'{}\' in {}' .format(pinfo[u'name'], provide, out_stripped, pinfo[u'rtime'])) if out_stripped == None: log.warning( u'Capability {} was stored with and empty value of {}' .format(provide, str(out_stripped))) self.capabilities[provide] = out_stripped self.capabilities_stored.append(provide) else: # provide not in output if provide in self.capabilities_stored: log.info( u'Plugin {} was provided by unknown instead of {}, recalculate not needed' .format(provide, pinfo[u'name'])) else: log.error( u'Plugin {} mus\'t provide {} which wasn\'t available into result' .format(pinfo[u'name'], provide)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True del self.pm.classes[pinfo[u'name']] log.debug( u'Plugin {} deactivated, recalculating dependencies & rerunning' .format(pinfo[u'name'])) done = False ret = False break remaning.remove(pinfo[u'name']) elif not pinfo[u'rtime'] and not pinfo[ u'process'].is_alive(): log.error( u'Plugin {} dead without sending results'.format( pinfo[u'name'])) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True self.nproc -= 1 del self.pm.classes[pinfo[u'name']] log.debug( u'Plugin {} deactivated, recalculating dependencies & rerunning' .format(pinfo[u'name'])) done = False ret = False if done == False or self.aborting: for pinfo2 in procs: if pinfo2 and pinfo2[u'stime'] and pinfo2[ u'process'].is_alive(): self._kill_proc(pinfo2[u'process']) pinfo2[u'rtime'] = t if self.aborting: log.debug( u'Aborting... terminating process {}'. format(pinfo2[u'name'])) else: log.debug( u'Terminating process {} due recalculation in process' .format(pinfo2[u'name'])) if done != False: if len(remaning) > 0: still = [p for p in remaning if p in started] log.debug(u'Endloop plugins still running: {}'.format( u','.join(still))) else: log.debug(u'No more plugins to run!') #check all finished (done=True) or wait to next round for start & check (done=None) done = True for pinfo in procs: if not pinfo or pinfo[u'rtime'] == None: done = None timesleep = 0.01 if log.level < 20: timesleep = 0.5 time.sleep(timesleep) break if done == False: # kill all plugins currently running for p in procs: if p and p[u'stime'] and p[u'process'].is_alive(): self._kill_proc(p[u'process']) p[u'rtime'] = t log.debug( u'Terminating process {} before recalculation in process' .format(p[u'name'])) if not self.aborting: self._classify(**kwargs) self.run() else: # when loop start+check finish must have all process completed clasifying_success = [x for x in procs if x != None] if clasifying_success: for i in range(0, len(procs)): #if procs[i] == None: if not (procs[i] and procs[i][u'rtime']): log.error( u'Plugin {} can\'t be started, previous plugin fail providing dependencies' .format(self.order[i])) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True ret = False break if not self.RUNNING_TIME: self.RUNNING_TIME = time.time() - self.START_RUNNING_TIME return ret
def run(self, *args, **kwargs): output = {} LDAP_INFO = kwargs[u'LDAP_INFO'] LLIUREX_RELEASE = str(kwargs[u'LLIUREX_RELEASE']).lower() logged_users = self.users_logged() myinfo = self.who_i_am() try: people = LDAP_INFO[u'CONFIG'][u'DB'][u'net'][u'lliurex'][u'ma5'][ u'People'] users = [(x, people[u'Students'][x]) for x in people[u'Students'].keys() if isinstance(people[u'Students'][x], dict)] admins = [(x, people[u'Admins'][x]) for x in people[u'Admins'].keys() if isinstance(people[u'Admins'][x], dict)] teachers = [(x, people[u'Teachers'][x]) for x in people[u'Teachers'].keys() if isinstance(people[u'Teachers'][x], dict)] except Exception as e: log.warning( u'Fail getting needed ldap information, using fake information only for current user' ) people = None # NO LDAP ACCESS DO IT ONLY FOR ME fake_ldap_info = (myinfo[u'name'], { u'homeDirectory': [myinfo[u'user_info'][5]], u'uid': [myinfo[u'name']] }) users = [] admins = [] teachers = [] try: if str(kwargs[u'LOGIN_TYPE']).lower() == u'ldap': if u'students' in myinfo[u'groups']: users.append(fake_ldap_info) elif u'teachers' in myinfo[u'groups']: teachers.append(fake_ldap_info) elif u'admins' in myinfo[u'groups']: admins.append(fake_ldap_info) except Exception as e: log.error(e) # USER TEST FUNCTIONALITY homes = [u'/home/' + x for x in os.listdir(u'/home/')] cmd = [u'getfacl', u'-tp'] + homes perm_info = self.execute(run=cmd, stderr=None).split(u'\n') perm_dirs = {} i = -1 file = None while i < len(perm_info) - 1: i += 1 line = perm_info[i] if line.startswith(u'#'): # complete previous if exists if file: if perm_dirs[file][u'group'] or perm_dirs[file][u'user']: perm_dirs[file][u'USE_ACLS'] = True else: perm_dirs[file][u'USE_ACLS'] = False file = line[8:] perm_dirs[file] = { u'USER': {}, u'GROUP': {}, u'user': {}, u'group': {}, u'other': {}, u'mask': {} } continue if line != u'': field = [x for x in line.split(u' ') if x != u''] if field[0] in [u'other', u'mask']: perm_dirs[file][field[0]] = field[1] else: perm_dirs[file][field[0]][field[1]] = field[2] if users: for (u, udata) in users: #TEST HOME if os.path.exists(udata[u'homeDirectory'][0]): output[u] = {u'HAS_HOME': True} homedir = udata[u'homeDirectory'][0] user = udata[u'uid'][0] try: output[u][u'PERM_OK']=\ perm_dirs[homedir][u'USER'][user] == u'rwx' \ and perm_dirs[homedir][u'user'][user] == u'rwx' \ and perm_dirs[homedir][u'GROUP'][u'nogroup'] == u'r-x' \ and perm_dirs[homedir][u'group'][u'students'] == u'---' \ and perm_dirs[homedir][u'group'][u'teachers'] == u'rwx' \ and perm_dirs[homedir][u'group'][u'admins'] == u'rwx' \ and perm_dirs[homedir][u'other'] == u'---' except: output[u][u'PERM_OK'] = False if u in logged_users: output[u][u'MOUNTS_OK'] = self.check_mounts( u, u'student', **kwargs) else: output[u][u'MOUNTS_OK'] = (None, [u'NOT_LOGGED_IN']) else: output[u] = {u'HAS_HOME': False} # TEACHERS if teachers: for (u, udata) in teachers: #TEST HOME if os.path.exists(udata[u'homeDirectory'][0]): output[u] = {u'HAS_HOME': True} homedir = udata[u'homeDirectory'][0] user = udata[u'uid'][0] try: output[u][u'PERM_OK']=\ perm_dirs[homedir][u'USER'][user] == u'rwx' \ and perm_dirs[homedir][u'user'][user] == u'rwx' \ and perm_dirs[homedir][u'GROUP'][u'nogroup'] == u'r-x' \ and perm_dirs[homedir][u'group'][u'teachers'] == u'---' \ and perm_dirs[homedir][u'group'][u'admins'] == u'rwx' \ and perm_dirs[homedir][u'other'] == u'---' except: output[u][u'PERM_OK'] = False if u in logged_users: output[u][u'MOUNTS_OK'] = self.check_mounts( u, u'teacher', **kwargs) else: output[u][u'MOUNTS_OK'] = (None, [u'NOT_LOGGED_IN']) else: output[u] = {u'HAS_HOME': False} # ADMINS if admins: for (u, udata) in admins: #TEST HOME if os.path.exists(udata[u'homeDirectory'][0]): output[u] = {u'HAS_HOME': True} homedir = udata[u'homeDirectory'][0] user = udata[u'uid'][0] try: output[u][u'PERM_OK']=\ perm_dirs[homedir][u'USER'][user] == u'rwx' \ and perm_dirs[homedir][u'user'][user] == u'rwx' \ and perm_dirs[homedir][u'GROUP'][u'nogroup'] == u'r-x' \ and perm_dirs[homedir][u'group'][u'admins'] == u'rwx' \ and perm_dirs[homedir][u'other'] == u'---' except: output[u][u'PERM_OK'] = False if u in logged_users: output[u][u'MOUNTS_OK'] = self.check_mounts( u, u'admin', **kwargs) else: output[u][u'MOUNTS_OK'] = (None, [u'NOT_LOGGED_IN']) else: output[u] = {u'HAS_HOME': False} return {u'USERS_INFO': perm_dirs, u'USER_TEST': output}
def _classify(self, *args, **kwargs): run_needs = [] resolved_needs = [] free_add_plugins = [] self.all_needs = [] self.all_provides = [] if u'needs' in kwargs: run_needs = kwargs[u'needs'] need_run_plugin = [] self.capabilities = {} self.order = [] pending = [] empty_provides = [] for classname in self.pm.classes: class_provides = self.pm.classes[classname]._PROVIDES class_needs = self.pm.classes[classname]._NEEDS log.debug(u'Class: {} needs {}'.format(classname, class_needs)) log.debug(u'Class: {} provides {}'.format(classname, class_provides)) for x in class_provides: if x not in self.mapping: self.mapping[x] = {u'PROVIDED': [classname], u'NEEDED': []} else: self.mapping[x][u'PROVIDED'].append(classname) for x in class_needs: if x not in self.mapping: self.mapping[x] = {u'PROVIDED': [], u'NEEDED': [classname]} else: self.mapping[x][u'NEEDED'].append(classname) self.all_provides.extend( x for x in self.mapping if self.mapping[x][u'PROVIDED'] and x not in self.all_provides) self.all_needs.extend( x for x in self.mapping if self.mapping[x][u'NEEDED'] and x not in self.all_needs) #self.all_provides.extend([x for x in self.pm.classes[classname]._PROVIDES if x not in self.all_provides]) #self.all_needs.extend([x for x in self.pm.classes[classname]._NEEDS if x not in self.all_needs]) if class_provides == None or class_needs == None: log.warning( u'Plugin {} with empty provides and needs, maybe it\'s using base class attributes !!! disabling plugin...' .format(classname)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True empty_provides.append(classname) continue # Disable plugins that not provides nothing if not class_provides: log.warning( u'Plugin {} disabled because not providing anything!'. format(classname)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True empty_provides.append(classname) continue # Add plugins that only provides if not class_needs and class_provides: free_add_plugins.append(classname) if not run_needs: add = True else: add = False for x in run_needs: if x in class_provides: add = True break if add: self.order.append(classname) for x in class_provides: if x: self.capabilities[x] = None else: pending.append(classname) else: for x in run_needs: if x in class_provides: need_run_plugin.append(classname) resolved_needs.extend(class_needs) pending.append(classname) missing = [ x for x in self.all_needs if x not in [y for y in self.all_provides] ] not_necessary = [ x for x in self.all_provides if x not in [y for y in self.all_needs] ] if not_necessary: log.info(u'Provided {} not used by anybody'.format( u','.join(not_necessary))) for i in empty_provides: log.warning(u'Disabling class {} not providing anything'.format(i)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True del self.pm.classes[i] for x in missing: log.error(u'Need {} not provided by any plugin'.format(x)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True for pl in self.mapping[x][u'NEEDED']: if pl in self.pm.classes: del self.pm.classes[pl] self.mapping[x][u'NEEDED'].remove(pl) pending.remove(pl) if self.fake_capabilities: for x in self.fake_capabilities: self.capabilities[x] = self.fake_capabilities[x] if run_needs: for nr in need_run_plugin: add = False class_needs = self.pm.classes[nr]._NEEDS class_provides = self.pm.classes[nr]._PROVIDES for need in class_needs: if need not in self.capabilities: for fp in free_add_plugins: if fp not in self.order and need in class_provides: add = fp break if add and add not in self.order: self.order.append(add) resolved_needs.extend(class_needs) for x in class_provides: if x: self.capabilities[x] = None if add in pending: pending.remove(add) #Resolve other dependencies still_ordering = True if not run_needs: still_missing_for_run = True else: still_missing_for_run = False for x in resolved_needs: if x not in self.capabilities: still_missing_for_run = True break while pending != [] and still_ordering and still_missing_for_run and not self.aborting: still_ordering = False # Detect full loop without changing anything to_remove = [] more_needs = [] if not run_needs: for classname in pending: add = classname for need in self.pm.classes[classname]._NEEDS: if need: #avoid empty if need not in self.capabilities: add = None break if add: # class has resolved all needs #pending.remove(classname) to_remove.append(add) self.order.append(add) #resolved_needs.extend(self.pm.classes[classname]._PROVIDES) for x in self.pm.classes[add]._PROVIDES: if x: self.capabilities[x] = None else: for need in resolved_needs: if need not in self.capabilities: for classname in pending: add = classname if need in self.pm.classes[classname]._PROVIDES: for x in self.pm.classes[classname]._NEEDS: if x: if x not in self.capabilities: add = None more_needs.append(x) if add: to_remove.append(add) self.order.append(add) for x in self.pm.classes[add]._PROVIDES: if x: self.capabilities[x] = None log.debug(u'Endloop classifier') for r in to_remove: if r in pending: pending.remove(r) still_ordering = True for n in more_needs: if n not in resolved_needs: resolved_needs.append(n) still_ordering = True if still_ordering == False: # none of pending plugins can satisfy more dependencies if run_needs: not_found = [] for x in resolved_needs: if x not in self.capabilities: not_found.append(x) if not_found: if self.is_classified: str = u'couldn\'t satisfy all dependencies for needed plugin' else: if self.pm.found_duplicates: str = u'maybe missing dependency?' else: str = u'maybe ciclic dependency?' # Get plugins related to cycle related = [] for plug in self.pm.classes: for prov in self.pm.classes[plug]._PROVIDES: if prov in not_found and plug not in related: related.append(plug) str += u'\nPlugins related with cycle: {}'.format( u','.join(related)) log.error( u'Unable to continue, {} !!!\nNotFound providers for ({})' .format(str, u','.join(not_found))) self.aborting = True else: for pl in need_run_plugin: add = pl for need in self.pm.classes[pl]._NEEDS: if need not in self.capabilities: add = None break if not add: log.error( u'Disabling class {} needed to run due to unresolved dependencies' .format(pending_class)) self.aborting = True break else: self.order.append(add) else: for pending_class in pending: log.warning( u'Disabling class {} due to unresolved dependencies' .format(pending_class)) if self.all_plugins_are_needed: log.error( u'Unable to continue, all plugins are needed to run properly' ) self.aborting = True break del self.pm.classes[pending_class] self.MAX_PROCESSES = len(self.order) log.info(u'Plugin order calculated: {}'.format(u','.join(self.order))) self.is_classified = True if self.aborting: return False else: return True