From 8bdbedd6cfe67afc981bc434d8fc70a9a9358e3f Mon Sep 17 00:00:00 2001 From: Ziheng Li Date: Fri, 6 May 2022 19:45:18 +0800 Subject: [PATCH] config-tools:Board Inspector Behaviors Improvement 1.Temporarily store the log in the form of tempfile, and the temporary file will be deleted after the summary log information is displayed. 2.Now, the logs will be printed when they generated as well. Tracked-On: #6689 Signed-off-by: Ziheng Li --- .../board_inspector/board_inspector.py | 94 ++++++++++++++++--- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/misc/config_tools/board_inspector/board_inspector.py b/misc/config_tools/board_inspector/board_inspector.py index 666ff349a..5b9e3eecd 100755 --- a/misc/config_tools/board_inspector/board_inspector.py +++ b/misc/config_tools/board_inspector/board_inspector.py @@ -8,6 +8,7 @@ import sys, os import re import logging +import tempfile import subprocess # nosec import lxml.etree import argparse @@ -46,7 +47,7 @@ def check_deps(): line = res.stdout.readline().decode('ascii') if not line: - logging.critical("'{}' cannot be found. Please install it and run the Board Inspector again.".format(execute)) + logger.critical("'{}' cannot be found. Please install it and run the Board Inspector again.".format(execute)) had_error = True if execute == 'cpuid': @@ -56,7 +57,7 @@ def check_deps(): line = res.stdout.readline().decode('ascii') version = line.split()[2] if int(version) < cpuid_min_ver: - logging.critical("This tool requires CPUID version >= {}. Try updating and upgrading the OS" \ + logger.critical("This tool requires CPUID version >= {}. Try updating and upgrading the OS" \ "on this system and reruning the Board Inspector. If that fails, install a newer CPUID tool" \ "from https://github.com/tycho/cpuid.".format(cpuid_min_ver)) had_error = True @@ -65,26 +66,26 @@ def check_deps(): # Try updating pci.ids for latest PCI device descriptions try: - logging.info("Updating pci.ids for latest PCI device descriptions.") + logger.info("Updating pci.ids for latest PCI device descriptions.") res = subprocess.Popen(["update-pciids", "-q"]) if res.wait() != 0: - logging.warning(f"Failed to invoke update-pciids. No functional impact is foreseen, but descriptions of PCI devices may be inaccurate.") + logger.warning(f"Failed to invoke update-pciids. No functional impact is foreseen, but descriptions of PCI devices may be inaccurate.") except Exception as e: - logging.warning(f"Failed to invoke update-pciids: {e}. No functional impact is foreseen, but descriptions of PCI devices may be unavailable.") + logger.warning(f"Failed to invoke update-pciids: {e}. No functional impact is foreseen, but descriptions of PCI devices may be unavailable.") def native_check(): cpu_ids = get_online_cpu_ids() cpu_id = cpu_ids.pop(0) leaf_1 = parse_cpuid(1, 0, cpu_id) if leaf_1.hypervisor != 0: - logging.error("Board inspector is running inside an unsupported Virtual Machine (VM). " \ + logger.error("Board inspector is running inside an unsupported Virtual Machine (VM). " \ "Only KVM or QEMU is supported. Unexpected results may occur.") def check_pci_domains(): root_buses = filter(lambda x: x.startswith("pci"), os.listdir("/sys/devices")) domain_ids = set(map(lambda x: x.split(":")[0].replace("pci", ""), root_buses)) if len(domain_ids) > 1: - logging.fatal(f"ACRN does not support platforms with multiple PCI domains {domain_ids}. Check if the BIOS has any configuration that consolidates those domains into one.") + logger.fatal(f"ACRN does not support platforms with multiple PCI domains {domain_ids}. Check if the BIOS has any configuration that consolidates those domains into one.") sys.exit(1) def bring_up_cores(): @@ -94,7 +95,59 @@ def bring_up_cores(): with open("/sys/devices/system/cpu/cpu{}/online".format(id), "w") as f: f.write("1") except : - logging.warning("Cannot bring up core with cpu id {}.".format(id)) + logger.warning("Cannot bring up core with cpu id {}.".format(id)) + +def summary_loginfo(board_xml): + length = 120 + warning_list = [] + error_list = [] + critical_list = [] + log_line = open(str(tmpfile.name), "r", encoding='UTF-8') + for line in log_line: + if "DEBUG" in line: + warning_list.append(line) + elif "ERROR" in line: + error_list.append(line) + elif "CRITICAL" in line: + critical_list.append(line) + + print("="*length) + print("\033[1;37mWARNING\033[0m") + print("These issues affect optional features. You can ignore them if they don't apply to you.\n") + if len(warning_list) != 0: + for warning in warning_list: + print("\033[1;33m{0}\033[0m".format(warning.strip('\n'))) + else: + print("None") + + print("="*length) + print("\033[1;37mERROR\033[0m") + print("You must resolve these issues to generate a VALID board configuration file for building and boot ACRN.\n") + if len(error_list) != 0: + for error in error_list: + print("\033[1;31m{0}\033[0m".format(error.strip('\n'))) + else: + print("None") + + print("="*length) + print("\033[1;37mCRITICAL\033[0m") + print("You must resolve these issues to generate a board configuration file.\n") + if len(critical_list) != 0: + for critical in critical_list: + print("\033[1;31m{0}\033[0m".format(critical.strip('\n'))) + else: + print("None") + + print("="*length) + if len(error_list) != 0 and len(critical_list) == 0: + print( + f"\033[1;32mSUCCESS: Board configuration file {board_xml} generated successfully and saved to {os.path.dirname(os.path.abspath(board_xml))}\033[0m\n") + print("\033[1;36mNOTE: Board configuration file lacks important features, which will cause ACRN to fail build or boot. Resolve ERROR messages then run the tool again.\033[0m") + + elif len(warning_list) != 0 and len(error_list) == 0 and len(critical_list) == 0: + print( + f"\033[1;32mSUCCESS: Board configuration file {board_xml} generated successfully and saved to {os.path.dirname(os.path.abspath(board_xml))}\033[0m\n") + tmpfile.close() def main(board_name, board_xml, args): # Check that the dependencies are met @@ -144,7 +197,10 @@ def main(board_name, board_xml, args): # Validate the XML against XSD assertions count = validator.validate_board(os.path.join(script_dir, 'schema', 'boardchecks.xsd'), board_etree) if count == 0: - logging.info("All board checks passed.") + logger.info("All board checks passed.") + + #Format and out put the log info + summary_loginfo(board_xml) # Finally overwrite the output with the updated XML board_etree.write(board_xml, pretty_print=True) @@ -152,7 +208,7 @@ def main(board_name, board_xml, args): .format(board_xml, os.path.dirname(os.path.abspath(board_xml)))) except subprocess.CalledProcessError as e: - logging.critical(e) + logger.critical(e) sys.exit(1) if __name__ == "__main__": @@ -160,13 +216,27 @@ if __name__ == "__main__": parser.add_argument("board_name", help="the name of the board that runs the ACRN hypervisor") parser.add_argument("--out", help="the name of board info file") parser.add_argument("--basic", action="store_true", default=False, help="do not extract advanced information such as ACPI namespace") - parser.add_argument("--loglevel", default="warning", help="choose log level, e.g. info, warning or error") + parser.add_argument("--loglevel", default="info", help="choose log level, e.g. info, warning or error") parser.add_argument("--check-device-status", action="store_true", default=False, help="filter out devices whose _STA object evaluates to 0") parser.add_argument("--add-llc-cat", default=None, action=AddLLCCATAction, metavar=",,", help="manually set the Cache Allocation Technology capability of the last level cache") args = parser.parse_args() try: - logging.basicConfig(level=args.loglevel.upper()) + tmpfile = tempfile.NamedTemporaryFile(delete=True) + logger = logging.getLogger() + logger.setLevel(args.loglevel.upper()) + formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s:-%(message)s', datefmt='%Y-%m-%d %H:%M:%S') + fh = logging.FileHandler(str(tmpfile.name)) + fh.setLevel(args.loglevel.upper()) + fh.setFormatter(formatter) + + sh = logging.StreamHandler() + sh.setLevel(args.loglevel.upper()) + + sh.setFormatter(formatter) + logger.addHandler(fh) + logger.addHandler(sh) + except ValueError: print(f"{args.loglevel} is not a valid log level") print(f"Valid log levels (non case-sensitive): critical, error, warning, info, debug")