Пример #1
0
 def _run(self, *args, **kwargs):
     stime = time.time()
     log.debug(u'Running wrapped plugin {}'.format(self.__class__.__name__))
     if u'stderr' in kwargs:
         sys.stderr = kwargs[u'stderr']
     r = self.run(self, *args, **kwargs)
     rtime = time.time() - stime
     log.info(u'Time running wrapped plugin {} = {}'.format(
         self.__class__.__name__, rtime))
     return r
Пример #2
0
 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]))
Пример #3
0
 def __init__(self, *args, **kwargs):
     log.debug(u'HwDetector initialization: initiating plugin manager')
     self.pm = PluginManager()
     self.all_plugins_are_needed = False
     os.path.dirname(os.path.abspath(__file__)) + u'/modules'
     log.debug(u'HwDetector initialization: adding path to plugin manager')
     self.pm.add_path(
         os.path.dirname(os.path.abspath(__file__)) + u'/modules', Detector)
     self.aborting = False
     self.MAX_RUNNING_TIME = None
     self.MAX_PROCESSES = None
     self.START_RUNNING_TIME = None
     self.RUNNING_TIME = None
     self.order = []
     self.capabilities = {}
     self.mapping = {}
     self.fake_capabilities = {}
     self.capabilities_stored = []
     self.helpers = {}
     self.is_classified = False
     self.nproc = 0
     self.nproc_started = 0
Пример #4
0
    def run(self,*args,**kwargs):
        msg=[]
        status = False
        msg_debug=[]
        mounts_info=kwargs[u'MOUNTS_INFO']
        user_test=kwargs[u'USER_TEST']

        for u in sorted(user_test.keys()):
            status=True
            if user_test[u][u'HAS_HOME']:
                msg_debug.append(u'\n{}\n'.format(u.upper()))
                for k in user_test[u]:
                    if k != u'MOUNTS_OK':
                        msg_debug.append(u'{} {}\n'.format(k,user_test[u][k]))
                        if user_test[u][k] == False:
                            msg_debug.append(u'Home of user {} has wrong permission,owners or acl\'s\n'.format(u))
                            msg.append(self.make_result(result=[u'Home of user {} has wrong permission,owners or acl\'su'.format(u)],msg='Nok !'))
                            status = False
                    else:
                        msg_debug.append(u'{} {}\nMESSAGES:\n{}\n'.format(k,user_test[u][k][0],u'\n'.join(user_test[u][k][1])))
                        if user_test[u][k][0] == False:
                            msg.append(self.make_result(result=[u'User {} has wrong mounts, detection says'.format(u)],msg=u''))
                            msg.append(self.make_result(result=user_test[u][u'MOUNTS_OK'][1],msg=u''))
                            status = False
                if status:
                    msg.append(self.make_result(result=[u'Home of user {} seems with good permission,owners and acl\'su'.format(u)],msg='Ok!'))
                if u'NOT_LOGGED_IN' in user_test[u][u'MOUNTS_OK'][1]:
                    msg.append(self.make_result(result=u'User {} not logged in, so i can\'t expect to analyze any mountsu'.format(u),msg=''))
                else:
                    msg.append(self.make_result(result=[u'User {} has correct mounts, detection says'.format(u)],msg=u''))
                    msg.append(self.make_result(result=user_test[u][u'MOUNTS_OK'][1],msg=u'Ok!'))

        msg=u''.join(msg)
        msg_debug=u''.join(msg_debug)
        log.debug(msg_debug)
        return {u'LLXUSERS_TEST':{u'status':status,u'msg':msg}}
Пример #5
0
#!/usr/bin/env python3
import hwdetector.Detector as Detector
import hwdetector.utils.log as log

log.debug(u'File '+__name__+u' loaded')

class LlxSystemTest(Detector):
    _NEEDS=[u'LLIUREX_RELEASE',u'SYSTEMCTL_INFO',u'DPKG_INFO',u'APACHE_INFO',u'EPOPTES_INFO',u'DNSMASQ_INFO',u'SQUID_INFO',u'PROCESS_INFO',u'VARLOG_INFO',u'HELPER_SEARCH_PROCESS']
    _PROVIDES=[u'LLXSYSTEM_TEST']

    def make_result(self,*args,**kwargs):
        ret=u''
        if not (u'result' in kwargs and u'msg' in kwargs):
            return
        if isinstance(kwargs[u'result'],list):
            result=kwargs[u'result']
        else:
            result=[str(kwargs[u'result'])]

        for x in result:
            ret+=u'{}> {}: {}\n'.format(self.__class__.__name__,x,kwargs[u'msg'])
        return ret

    def run(self,*args,**kwargs):

        release=str(kwargs[u'LLIUREX_RELEASE'])
        status=True
        msg=[]

        systemctl=kwargs[u'SYSTEMCTL_INFO']
        needed_services={}
Пример #6
0
 def toString(self):
     log.debug(u'Calling toString base class')
     log.debug(u'My name is: {}'.format(__name__))
     log.debug(u'My needs are: {}'.format(self._NEEDS))
     log.debug(u'My provides are: {}'.format(self._PROVIDES))
Пример #7
0
 def __init__(self):
     log.debug(u'Init detector base class')
Пример #8
0
    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
Пример #9
0
    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