def get_cls(self, import_str): log.debug("instantiating class %s", import_str) mod = import_str.rpartition('.')[0] class_name = import_str.rpartition('.')[2] try: return getattr(importlib.import_module(mod), class_name) except Exception: log.exception("failed to import class %s from %s", class_name, mod) raise
def result(self): """ Assert whether the requirement is met. Returns True if met otherwise False. """ try: return self.handler() except Exception: # display traceback here before it gets swallowed up. log.exception("requires.%s.result raised the following", self.__class__.__name__) raise
def get_method(self, import_str): log.debug("calling method %s", import_str) mod = import_str.rpartition('.')[0] property = import_str.rpartition('.')[2] class_name = mod.rpartition('.')[2] mod = mod.rpartition('.')[0] cls = getattr(importlib.import_module(mod), class_name) try: ret = getattr(cls(), property)() except Exception: log.exception("failed to import and call method %s", import_str) raise return ret
def get_attribute(self, import_str): log.debug("fetching attribute %s", import_str) mod = import_str.rpartition('.')[0] attr = import_str.rpartition('.')[2] try: ret = getattr(importlib.import_module(mod), attr) except Exception as exc: log.exception("failed to get module attribute %s", import_str) # ystruct.YAMLDefOverrideBase swallows AttributeError so need to # convert to something else. if type(exc) == AttributeError: raise ImportError from exc raise return ret
def run_parts(self, parts, debug_mode=False): failed_parts = [] # The following are executed as part of each plugin run (but not last). ALWAYS_RUN = {'auto_scenario_check': YScenarioChecker} for name, always_parts in ALWAYS_RUN.items(): # update current env to reflect actual part being run setup_config(PART_NAME=name) try: always_parts()() except Exception as exc: failed_parts.append(name) log.exception("part '%s' raised exception: %s", name, exc) if debug_mode: raise # NOTE: we don't expect these parts to produce any output # for the summary so we wont check for it (the only raise # issues and bugs which are handled independently). for name, part_info in parts.items(): # update current env to reflect actual part being run setup_config(PART_NAME=name) for cls in part_info['objects']: inst = cls() # Only run plugin if it delares itself runnable. if not inst.plugin_runnable: log.debug("%s.%s.%s not runnable - skipping", HotSOSConfig.PLUGIN_NAME, name, cls.__name__) continue log.debug("running %s.%s.%s", HotSOSConfig.PLUGIN_NAME, name, cls.__name__) try: inst() # NOTE: since all parts are expected to be implementations # of PluginPartBase we expect them to always define an # output property. output = inst.output subkey = inst.summary_subkey except Exception as exc: failed_parts.append(name) log.exception("part '%s' raised exception: %s", name, exc) output = None if debug_mode: raise if output: for key, entry in output.items(): out = {key: entry.data} if subkey: out = {subkey: out} part_max = PluginPartBase.PLUGIN_PART_OFFSET_MAX part_offset = part_info['part_yaml_offset'] offset = ((part_offset * part_max) + entry.offset) save_part(out, offset=offset) if failed_parts: # always put these at the top save_part({'failed-parts': failed_parts}, offset=0) imgr = IssuesManager() bugs = imgr.load_bugs() raised_issues = imgr.load_issues() summary_end_offset = PluginPartBase.PLUGIN_PART_OFFSET_MAX ** 2 # Add detected known_bugs and raised issues to end summary. if bugs: save_part(bugs, offset=summary_end_offset) # Add raised issues to summary. if raised_issues: save_part(raised_issues, offset=summary_end_offset) return dump_all_parts()