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 <ziheng.li@intel.com>
This commit is contained in:
Ziheng Li 2022-05-06 19:45:18 +08:00 committed by acrnsi-robot
parent 019ae24c94
commit 8bdbedd6cf

View File

@ -8,6 +8,7 @@
import sys, os import sys, os
import re import re
import logging import logging
import tempfile
import subprocess # nosec import subprocess # nosec
import lxml.etree import lxml.etree
import argparse import argparse
@ -46,7 +47,7 @@ def check_deps():
line = res.stdout.readline().decode('ascii') line = res.stdout.readline().decode('ascii')
if not line: 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 had_error = True
if execute == 'cpuid': if execute == 'cpuid':
@ -56,7 +57,7 @@ def check_deps():
line = res.stdout.readline().decode('ascii') line = res.stdout.readline().decode('ascii')
version = line.split()[2] version = line.split()[2]
if int(version) < cpuid_min_ver: 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" \ "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)) "from https://github.com/tycho/cpuid.".format(cpuid_min_ver))
had_error = True had_error = True
@ -65,26 +66,26 @@ def check_deps():
# Try updating pci.ids for latest PCI device descriptions # Try updating pci.ids for latest PCI device descriptions
try: 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"]) res = subprocess.Popen(["update-pciids", "-q"])
if res.wait() != 0: 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: 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(): def native_check():
cpu_ids = get_online_cpu_ids() cpu_ids = get_online_cpu_ids()
cpu_id = cpu_ids.pop(0) cpu_id = cpu_ids.pop(0)
leaf_1 = parse_cpuid(1, 0, cpu_id) leaf_1 = parse_cpuid(1, 0, cpu_id)
if leaf_1.hypervisor != 0: 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.") "Only KVM or QEMU is supported. Unexpected results may occur.")
def check_pci_domains(): def check_pci_domains():
root_buses = filter(lambda x: x.startswith("pci"), os.listdir("/sys/devices")) 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)) domain_ids = set(map(lambda x: x.split(":")[0].replace("pci", ""), root_buses))
if len(domain_ids) > 1: 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) sys.exit(1)
def bring_up_cores(): 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: with open("/sys/devices/system/cpu/cpu{}/online".format(id), "w") as f:
f.write("1") f.write("1")
except : 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): def main(board_name, board_xml, args):
# Check that the dependencies are met # Check that the dependencies are met
@ -144,7 +197,10 @@ def main(board_name, board_xml, args):
# Validate the XML against XSD assertions # Validate the XML against XSD assertions
count = validator.validate_board(os.path.join(script_dir, 'schema', 'boardchecks.xsd'), board_etree) count = validator.validate_board(os.path.join(script_dir, 'schema', 'boardchecks.xsd'), board_etree)
if count == 0: 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 # Finally overwrite the output with the updated XML
board_etree.write(board_xml, pretty_print=True) 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)))) .format(board_xml, os.path.dirname(os.path.abspath(board_xml))))
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
logging.critical(e) logger.critical(e)
sys.exit(1) sys.exit(1)
if __name__ == "__main__": 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("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("--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("--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("--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, parser.add_argument("--add-llc-cat", default=None, action=AddLLCCATAction,
metavar="<capacity_mask_length:int>,<clos_number:int>,<has_CDP:bool>", help="manually set the Cache Allocation Technology capability of the last level cache") metavar="<capacity_mask_length:int>,<clos_number:int>,<has_CDP:bool>", help="manually set the Cache Allocation Technology capability of the last level cache")
args = parser.parse_args() args = parser.parse_args()
try: 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: except ValueError:
print(f"{args.loglevel} is not a valid log level") print(f"{args.loglevel} is not a valid log level")
print(f"Valid log levels (non case-sensitive): critical, error, warning, info, debug") print(f"Valid log levels (non case-sensitive): critical, error, warning, info, debug")