From 3fa3c3044301cad3aff11caf3c80da17320640c4 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Fri, 23 Sep 2022 16:34:22 +0800 Subject: [PATCH 1/8] show all the values of "supported" flag --- src/soliddriver_checks/config/soliddriver-checks.conf | 3 +++ src/soliddriver_checks/utils/data_reader.py | 3 ++- tests/Dockerfile | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/soliddriver_checks/config/soliddriver-checks.conf b/src/soliddriver_checks/config/soliddriver-checks.conf index 7df9af0..d2e8cdd 100644 --- a/src/soliddriver_checks/config/soliddriver-checks.conf +++ b/src/soliddriver_checks/config/soliddriver-checks.conf @@ -12,6 +12,9 @@ { "name":"GPLv2" }, + { + "name":"GPL v2 only" + }, { "name":"GPL-2.0" }, diff --git a/src/soliddriver_checks/utils/data_reader.py b/src/soliddriver_checks/utils/data_reader.py index e701ea4..037e477 100644 --- a/src/soliddriver_checks/utils/data_reader.py +++ b/src/soliddriver_checks/utils/data_reader.py @@ -147,7 +147,8 @@ def _get_driver_supported(self, driver): if values[0].strip() == "supported": if supported != "": # only allow appears once. - return "Multiple" + supported = supported + ", " + ":".join(values[1:]).strip() + # return "Multiple" else: supported = ":".join(values[1:]).strip() diff --git a/tests/Dockerfile b/tests/Dockerfile index 48faff1..5f2c6d2 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -5,5 +5,5 @@ WORKDIR /root RUN zypper --non-interactive in python3-pip kmod RUN pip3 install rich pdfkit pandas \ -openpyxl click paramiko dominate +openpyxl click paramiko dominate build From 576396b7985d2d8f95dc406b93f72b982ac6133a Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Tue, 1 Nov 2022 11:10:00 +0800 Subject: [PATCH 2/8] add modalias for html summary table. --- src/soliddriver_checks/utils/data_exporter.py | 42 +++++++----- src/soliddriver_checks/utils/data_reader.py | 66 ++++++++++++++++++- 2 files changed, 90 insertions(+), 18 deletions(-) diff --git a/src/soliddriver_checks/utils/data_exporter.py b/src/soliddriver_checks/utils/data_exporter.py index b6b43dc..126385d 100644 --- a/src/soliddriver_checks/utils/data_exporter.py +++ b/src/soliddriver_checks/utils/data_exporter.py @@ -168,20 +168,9 @@ def _summary_symbol_result(self, val): result = "" if unfound_no > 0: - # result = "Can not find symbols like {} ... in RPM! ".format( - # val["unfound"][0] - # ) - result = f"Number of symbols can not be found in KMP: {unfound_no}" if cs_mm_no > 0: - # result = ( - # result - # + "Symbols check sum like {} ... does not match in RPM!".format( - # val["checksum-mismatch"][0] - # ) - # ) - result = result + f" Number of symbols checksum does not match: {cs_mm_no}" return result @@ -236,10 +225,20 @@ def _get_summary_table(self, rpm_table): "Signature", "Weak Module Invoked", "Symbols Check Failed", + "Modalias Check Failed", ] ) + + def alias_check(alias): + num = 0 + + for i in range(len(alias)): + if len(alias.iat[i]["unmatched_km_alias"]) > 0 and len(alias.iat[i]["unmatched_kmp_alias"]) > 0: + num != 1 + + return num - def drivers_check(rpms_sf, rpms_is): + def supported_check(rpms_sf, rpms_is): """ rpms_sf: RPMs' driver supported flag rpm_is : RPMs' is_signed column @@ -279,8 +278,8 @@ def license_check(vld_lics, rpm_licenses, driver_license): for v in vendors: df_vendor = df.loc[df["vendor"] == v] total = len(df_vendor.index) - dc = drivers_check(df_vendor["df-supported"], df_vendor["is-signed"]) - failed = len( + spc = supported_check(df_vendor["df-supported"], df_vendor["is-signed"]) + symc = len( df_vendor.loc[df_vendor["sym-check"] == "failed", "sym-check"].index ) lic_check = license_check( @@ -294,16 +293,18 @@ def license_check(vld_lics, rpm_licenses, driver_license): ].index ) wm_invoked = len(df_vendor.loc[df_vendor["wm-invoked"], "wm-invoked"].index) + aliasc = alias_check(df_vendor["modalias"]) df_summary = df_summary.append( { "Vendor": v, "Total KMPs": total, - "Driver Checks": f"{dc} ({dc/total * 100:.2f}%)", + "Driver Checks": f"{spc} ({spc/total * 100:.2f}%)", "License": f"{lic_check} ({lic_check/total * 100:.2f}%)", "Signature": f"{no_sig} ({no_sig/total * 100:.2f}%)", "Weak Module Invoked": f"{wm_invoked} ({wm_invoked/total * 100:.2f}%)", - "Symbols Check Failed": f"{failed} ({failed/total * 100:.2f}%)", + "Symbols Check Failed": f"{symc} ({symc/total * 100:.2f}%)", + "Modalias Check Failed": f"{aliasc} ({aliasc/total * 100:.2f}%)", }, ignore_index=True, ) @@ -332,6 +333,7 @@ def _get_summary_table_html(self, rpm_table): signature = row["Signature"] wm_invoked = row["Weak Module Invoked"] sym_failed = row["Symbols Check Failed"] + alias_failed = row["Modalias Check Failed"] row_passed = False if ( @@ -341,6 +343,7 @@ def _get_summary_table_html(self, rpm_table): and int(signature.split(" ")[0]) == total_rpms and int(wm_invoked.split(" ")[0]) == total_rpms and int(sym_failed.split(" ")[0]) == 0 + and int(alias_failed.split(" ")[0]) == 0 ): row_passed = True with tr() as r: @@ -388,6 +391,13 @@ def _get_summary_table_html(self, rpm_table): ) else: t.set_attribute("class", "summary_number") + with td(alias_failed) as t: + if int(alias_failed.split(" ")[0]) > 0: + t.set_attribute( + "class", "important_falied summary_number" + ) + else: + t.set_attribute("class", "summary_number") return tb diff --git a/src/soliddriver_checks/utils/data_reader.py b/src/soliddriver_checks/utils/data_reader.py index 037e477..4023d0a 100644 --- a/src/soliddriver_checks/utils/data_reader.py +++ b/src/soliddriver_checks/utils/data_reader.py @@ -7,6 +7,7 @@ import re from collections import namedtuple import tempfile +import fnmatch import json from scp import SCPClient from paramiko.ssh_exception import NoValidConnectionsError, SSHException @@ -90,8 +91,41 @@ def __init__(self, progress): "sym-check", "dv-licenses", "is-signed", + "modalias", ] + def _get_driver_alias(self, driver): + alias = run_cmd("/usr/sbin/modinfo --field=alias %s" % driver) + return alias.splitlines() + + def _get_rpm_modalias(self, rpm): + modalias = namedtuple("modalias", "kernel_flavor pci_re") + ml_pci_re = re.compile(r"modalias\((.*):(.*\:.*)\)") # example: modalias(kernel-default:pci:v000019A2d00000712sv*sd*bc*sc*i*) + ml_all_re = re.compile(r"modalias\((.*):(.*)\)") # example: packageand(kernel-default:primergy-be2iscsi) + raw_modalias = run_cmd("rpm -q --supplements %s" %rpm) + + mod_sup = {} #TODO We should only need the alias regex, will simply this code after discussed with Scott. + alias_re = [] + for line in raw_modalias.splitlines(): + line = str(line, "utf-8").strip() + pci_rst = ml_pci_re.match(line) + all_rst = ml_all_re.match(line) + if pci_rst: + ker_flavor, pci = pci_rst.groups() + mod_sup[pci] = modalias( + kernel_flavor=ker_flavor, pci_re=pci + ) + alias_re.append(pci) + elif all_rst: # match all (*) should not be allowed + ker_flavor, rst = all_rst.groups() + mod_sup[rst] = modalias( + kernel_flavor=ker_flavor, pci_re=rst + ) + alias_re.append(rst) + + return alias_re + # return mod_sup + def _driver_symbols_check(self, rpm_symbols, driver): symvers = run_cmd("/usr/sbin/modprobe --dump-modversions %s" % driver) @@ -148,7 +182,6 @@ def _get_driver_supported(self, driver): if values[0].strip() == "supported": if supported != "": # only allow appears once. supported = supported + ", " + ":".join(values[1:]).strip() - # return "Multiple" else: supported = ":".join(values[1:]).strip() @@ -204,6 +237,31 @@ def _fmt_driver_symbol(self, drivers): symbols[d] = d_info return symbols + + def _fmt_driver_modalias(self, kmp_alias, drivers): + # for a in kmp_alias: + # if a == "*": + # return "RPM intend to match all the hardware which is not recommended!" + + unmatched_ker_alias = [] + unmatched_kmp_alias = kmp_alias.copy() + + for d in drivers: + for ker_a in drivers[d]["alias"]: + ker_a = str(ker_a, "utf-8").strip() + found = False + for kmp_a in kmp_alias: + if fnmatch.fnmatch(ker_a.strip(), kmp_a.strip()): + found = True + for uk in unmatched_kmp_alias: + if uk.strip() == kmp_a.strip(): + unmatched_kmp_alias.remove(uk) + break + break + if not found: + unmatched_ker_alias.append(ker_a) + + return {'unmatched_km_alias':unmatched_ker_alias, 'unmatched_kmp_alias':unmatched_kmp_alias} def _is_driver_signed(self, driver): raw_info = run_cmd("/usr/sbin/modinfo %s" % driver) @@ -243,6 +301,7 @@ def _driver_checks(self, rpm: str): item["supported"] = self._get_driver_supported(driver) item["license"] = self._get_driver_license(driver) item["is_signed"] = self._is_driver_signed(driver) + item["alias"] = self._get_driver_alias(driver) dpath = str(driver) dpath = dpath[dpath.startswith(tmp.name) + len(tmp.name) - 1 :] @@ -294,11 +353,13 @@ def _format_rpm_info(self, rpm_files, raw_output, row_handlers, query="all"): symbols = dict() d_licenses = dict() is_signed = dict() + km_modalias = dict() if driver_checks is not None: supported = self._fmt_driver_supported(driver_checks) symbols = self._fmt_driver_symbol(driver_checks) d_licenses = self._fmt_driver_license(driver_checks) is_signed = self._fmt_driver_is_signed(driver_checks) + km_modalias = self._fmt_driver_modalias(self._get_rpm_modalias(rpm), driver_checks) if not self._query_filter(supported, query): continue @@ -316,7 +377,8 @@ def _format_rpm_info(self, rpm_files, raw_output, row_handlers, query="all"): supported, symbols, d_licenses, - is_signed + is_signed, + km_modalias ] ) From 05169209b24f63aa591372a686cdb56d94efff23 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Tue, 1 Nov 2022 11:31:47 +0800 Subject: [PATCH 3/8] fix summary table show wrong supported flag/signature check result --- .../config/templates/kmp-checks.html.jinja | 7 +++- src/soliddriver_checks/utils/data_exporter.py | 35 ++++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/soliddriver_checks/config/templates/kmp-checks.html.jinja b/src/soliddriver_checks/config/templates/kmp-checks.html.jinja index 7d14dfb..42de2b2 100644 --- a/src/soliddriver_checks/config/templates/kmp-checks.html.jinja +++ b/src/soliddriver_checks/config/templates/kmp-checks.html.jinja @@ -54,10 +54,15 @@ th.detail_6{ width:240px; background-color:#90EBCD; - }th.detail_7{ + } + th.detail_7{ width:240px; background-color:#90EBCD; } + th.detail_8{ + width:240px; + background-color:#90EBCD; + } td{ text-align:left; vertical-align: top; diff --git a/src/soliddriver_checks/utils/data_exporter.py b/src/soliddriver_checks/utils/data_exporter.py index 126385d..024a2d0 100644 --- a/src/soliddriver_checks/utils/data_exporter.py +++ b/src/soliddriver_checks/utils/data_exporter.py @@ -220,10 +220,10 @@ def _get_summary_table(self, rpm_table): columns=[ "Vendor", "Total KMPs", - "Driver Checks", "License", "Signature", "Weak Module Invoked", + "Supported Flag/Signature Checks Failed", "Symbols Check Failed", "Modalias Check Failed", ] @@ -238,7 +238,7 @@ def alias_check(alias): return num - def supported_check(rpms_sf, rpms_is): + def supported_sig_check(rpms_sf, rpms_is): """ rpms_sf: RPMs' driver supported flag rpm_is : RPMs' is_signed column @@ -257,7 +257,7 @@ def supported_check(rpms_sf, rpms_is): if not found_issues: num += 1 - return num + return rpms - num def license_check(vld_lics, rpm_licenses, driver_license): count = 0 @@ -278,7 +278,7 @@ def license_check(vld_lics, rpm_licenses, driver_license): for v in vendors: df_vendor = df.loc[df["vendor"] == v] total = len(df_vendor.index) - spc = supported_check(df_vendor["df-supported"], df_vendor["is-signed"]) + spc = supported_sig_check(df_vendor["df-supported"], df_vendor["is-signed"]) symc = len( df_vendor.loc[df_vendor["sym-check"] == "failed", "sym-check"].index ) @@ -299,10 +299,10 @@ def license_check(vld_lics, rpm_licenses, driver_license): { "Vendor": v, "Total KMPs": total, - "Driver Checks": f"{spc} ({spc/total * 100:.2f}%)", "License": f"{lic_check} ({lic_check/total * 100:.2f}%)", "Signature": f"{no_sig} ({no_sig/total * 100:.2f}%)", "Weak Module Invoked": f"{wm_invoked} ({wm_invoked/total * 100:.2f}%)", + "Supported Flag/Signature Checks Failed": f"{spc} ({spc/total * 100:.2f}%)", "Symbols Check Failed": f"{symc} ({symc/total * 100:.2f}%)", "Modalias Check Failed": f"{aliasc} ({aliasc/total * 100:.2f}%)", }, @@ -328,7 +328,7 @@ def _get_summary_table_html(self, rpm_table): for i, row in df_summary.iterrows(): vendor = row["Vendor"] total_rpms = row["Total KMPs"] - dc = row["Driver Checks"] + ssc = row["Supported Flag/Signature Checks Failed"] lic_check = row["License"] signature = row["Signature"] wm_invoked = row["Weak Module Invoked"] @@ -338,7 +338,7 @@ def _get_summary_table_html(self, rpm_table): row_passed = False if ( vendor != "" - and int(dc.split(" ")[0]) == total_rpms + and int(ssc.split(" ")[0]) == 0 and int(lic_check.split(" ")[0]) == total_rpms and int(signature.split(" ")[0]) == total_rpms and int(wm_invoked.split(" ")[0]) == total_rpms @@ -356,13 +356,6 @@ def _get_summary_table_html(self, rpm_table): tv.set_attribute("class", "important_failed") with td(total_rpms) as t: t.set_attribute("class", "summary_total") - with td(dc) as t: - if int(dc.split(" ")[0]) != total_rpms: - t.set_attribute( - "class", "critical_failed summary_number" - ) - else: - t.set_attribute("class", "summary_number") with td(lic_check) as t: if int(lic_check.split(" ")[0]) != total_rpms: t.set_attribute( @@ -384,6 +377,13 @@ def _get_summary_table_html(self, rpm_table): ) else: t.set_attribute("class", "summary_number") + with td(ssc) as t: + if int(ssc.split(" ")[0]) != 0: + t.set_attribute( + "class", "critical_failed summary_number" + ) + else: + t.set_attribute("class", "summary_number") with td(sym_failed) as t: if int(sym_failed.split(" ")[0]) != 0: t.set_attribute( @@ -409,11 +409,11 @@ def _rename_rpm_detail_columns(self, rpm_table): "path": "Path", "vendor": "Vendor", "signature": "Signature", - # "distribution": "Distribution", "license": "License", "wm-invoked": "Weak Module Invoked", "df-supported": "Driver Checks", "sym-check": "Symbols Check", + "modalias": "Modalias Check", "dv-licenses": "Driver Licenses", "is-signed": "is-signed", } @@ -454,7 +454,7 @@ def _get_table_detail_html(self, rpm_table): tb.set_attribute("class", "table_center") with tr(): th("KMP Checks", colspan=6).set_attribute("class", f"detail_rpm") - th("Kernel Module Checks", colspan=2).set_attribute("class", f"detail_kernel_module") + th("Kernel Module Checks", colspan=3).set_attribute("class", f"detail_kernel_module") with tr(): th("Name").set_attribute("class", f"detail_0") th("Path").set_attribute("class", f"detail_1") @@ -463,7 +463,8 @@ def _get_table_detail_html(self, rpm_table): th(raw("LicenseKMP and it's kernel modules should use open source licenses.")).set_attribute("class", f"detail_4 tooltip") th(raw("Weak Module InvokedWeak Module is necessary to make 3rd party kernel modules installed for one kernel available to KABI-compatible kernels. ")).set_attribute("class", f"detail_5 tooltip") th(raw("Supported Flag/Signature\"supported\" flag:
\"yes\": Only supported by SUSE
\"external\": supported by both SUSE and vendor
")).set_attribute("class", f"detail_6 tooltip") - th(raw("Symbolssymbols check is to check whether the symbols in kernel modules matches the symbols in its package.")).set_attribute("class", f"detail_7 tooltip") + th(raw("SymbolsSymbols check is to check whether the symbols in kernel modules matches the symbols in its package.")).set_attribute("class", f"detail_7 tooltip") + th(raw("ModaliasModalias check is to check whether the modalias in kernel modules matches the modalias in its package.")).set_attribute("class", f"detail_8 tooltip") for i, row in df.iterrows(): with tr() as r: From 6c91bd7f948ec750b3eba4196b2158d95da8fdda Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Tue, 1 Nov 2022 15:14:55 +0800 Subject: [PATCH 4/8] add modalias to the html detail table --- src/soliddriver_checks/utils/data_exporter.py | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/soliddriver_checks/utils/data_exporter.py b/src/soliddriver_checks/utils/data_exporter.py index 024a2d0..62a917e 100644 --- a/src/soliddriver_checks/utils/data_exporter.py +++ b/src/soliddriver_checks/utils/data_exporter.py @@ -411,7 +411,7 @@ def _rename_rpm_detail_columns(self, rpm_table): "signature": "Signature", "license": "License", "wm-invoked": "Weak Module Invoked", - "df-supported": "Driver Checks", + "df-supported": "Supported Flag Check", "sym-check": "Symbols Check", "modalias": "Modalias Check", "dv-licenses": "Driver Licenses", @@ -445,6 +445,26 @@ def _fmt_driver_license_check(self, rpm_license, driver_licenses, vld_lics): ) return chk_result + + def _fmt_modalias_check(self, alias): + km_unmatched = len(alias["unmatched_km_alias"]) + kmp_unmatched = len(alias["unmatched_kmp_alias"]) + + message = "" + + if km_unmatched > 0: + message += "Alias found in kernel module but no match in it's package: " + for kmu in alias["unmatched_km_alias"]: + message += kmu + ", " + message += "\n" + + if kmp_unmatched > 0: + message += "Alias found in the package but no match in it's kernel module: " + for kmpu in alias["unmatched_kmp_alias"]: + message += kmpu + ", " + + return message + def _get_table_detail_html(self, rpm_table): df = self._rename_rpm_detail_columns(rpm_table) @@ -478,9 +498,11 @@ def _get_table_detail_html(self, rpm_table): sym_check = self._get_sym_check_failed( row["Symbols Check"] ).replace("\n", "
") - supported = row["Driver Checks"] + supported = row["Supported Flag Check"] is_signed = row["is-signed"] - dc_err = self._combine_driver_check_errs(supported, is_signed) + alias = row["Modalias Check"] + alias_chk = self._fmt_modalias_check(alias) + dc_err = self._supported_sig_errs(supported, is_signed) dv_license = row["Driver Licenses"] lcs_chk = self._fmt_driver_license_check( license, dv_license, vld_lic @@ -501,7 +523,6 @@ def _get_table_detail_html(self, rpm_table): else: ts = td(signature) ts.set_attribute("class", "important_failed") - # td(distribution) if lcs_chk == "": # license check if license == "": tl = td("No License") @@ -536,10 +557,17 @@ def _get_table_detail_html(self, rpm_table): t_w = td(raw(sym_check)) t_w.set_attribute("class", "critical_failed") r.set_attribute("class", "critical_failed_row") + if alias_chk == "": + t = td("All passed!") + t.set_attribute("class", "detail_pass") + else: + t_w = td(raw(alias_chk.replace("\n", "
"))) + t_w.set_attribute("class", "important_failed") + r.set_attribute("class", "important_failed_row") return tb - def _combine_driver_check_errs(self, sffds, nsds): + def _supported_sig_errs(self, sffds, nsds): sfds_l = self._get_supported_driver_failed(sffds) nsds_l = self._get_no_signed_driver(nsds) @@ -752,8 +780,8 @@ def _xlsx_create_rpm_details(self, wb, rpm_table): ws_rd[cell_no].font = ctc_font ws_rd[cell_no].fill = ctc_fill ws_rd[cell_no].border = ctc_border - elif cols[col_idx] == "Driver Checks": - val = self._combine_driver_check_errs(val, row["is-signed"]) + elif cols[col_idx] == "Supported Flag Check": + val = self._supported_sig_errs(val, row["is-signed"]) if len(val) > 0: ws_rd[cell_no] = '\n'.join(val) ws_rd[cell_no].font = ctc_font From e9dc21b82ed3555ab5e491d78ff10757d6efcc62 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Mon, 14 Nov 2022 14:22:40 +0800 Subject: [PATCH 5/8] Remove useless codes --- src/soliddriver_checks/utils/data_reader.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/soliddriver_checks/utils/data_reader.py b/src/soliddriver_checks/utils/data_reader.py index 4023d0a..062b095 100644 --- a/src/soliddriver_checks/utils/data_reader.py +++ b/src/soliddriver_checks/utils/data_reader.py @@ -104,7 +104,6 @@ def _get_rpm_modalias(self, rpm): ml_all_re = re.compile(r"modalias\((.*):(.*)\)") # example: packageand(kernel-default:primergy-be2iscsi) raw_modalias = run_cmd("rpm -q --supplements %s" %rpm) - mod_sup = {} #TODO We should only need the alias regex, will simply this code after discussed with Scott. alias_re = [] for line in raw_modalias.splitlines(): line = str(line, "utf-8").strip() @@ -112,15 +111,9 @@ def _get_rpm_modalias(self, rpm): all_rst = ml_all_re.match(line) if pci_rst: ker_flavor, pci = pci_rst.groups() - mod_sup[pci] = modalias( - kernel_flavor=ker_flavor, pci_re=pci - ) alias_re.append(pci) elif all_rst: # match all (*) should not be allowed ker_flavor, rst = all_rst.groups() - mod_sup[rst] = modalias( - kernel_flavor=ker_flavor, pci_re=rst - ) alias_re.append(rst) return alias_re From 4596359e8e2ad62978075cb28c5c192c7b71b158 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Mon, 21 Nov 2022 11:12:44 +0800 Subject: [PATCH 6/8] enhancement: only check pci devices for modalias check support python3.9 test --- src/soliddriver_checks/cli.py | 2 +- src/soliddriver_checks/utils/data_exporter.py | 14 +++++--- src/soliddriver_checks/utils/data_reader.py | 36 ++++++++++++++----- tests/Dockerfile | 5 +-- tests/create_container_mac.sh | 2 +- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/soliddriver_checks/cli.py b/src/soliddriver_checks/cli.py index 67b5c94..d364d5f 100644 --- a/src/soliddriver_checks/cli.py +++ b/src/soliddriver_checks/cli.py @@ -114,7 +114,7 @@ def check(dst): "out_format", type=click.Choice(FORMAT_TYPES), default="json", - help="Specify output format", + help="Specify output format (PDF is in Beta)", ) @click.option( "--query", diff --git a/src/soliddriver_checks/utils/data_exporter.py b/src/soliddriver_checks/utils/data_exporter.py index 62a917e..847f48e 100644 --- a/src/soliddriver_checks/utils/data_exporter.py +++ b/src/soliddriver_checks/utils/data_exporter.py @@ -228,14 +228,14 @@ def _get_summary_table(self, rpm_table): "Modalias Check Failed", ] ) - + def alias_check(alias): num = 0 - + for i in range(len(alias)): - if len(alias.iat[i]["unmatched_km_alias"]) > 0 and len(alias.iat[i]["unmatched_kmp_alias"]) > 0: - num != 1 - + if alias.iat[i]["match_all"] or len(alias.iat[i]["unmatched_km_alias"]) > 0 or len(alias.iat[i]["unmatched_kmp_alias"]) > 0: + num += 1 + return num def supported_sig_check(rpms_sf, rpms_is): @@ -447,9 +447,13 @@ def _fmt_driver_license_check(self, rpm_license, driver_licenses, vld_lics): return chk_result def _fmt_modalias_check(self, alias): + match_all = alias["match_all"] km_unmatched = len(alias["unmatched_km_alias"]) kmp_unmatched = len(alias["unmatched_kmp_alias"]) + if match_all: + return "KMP can match all the devices! Highly not recommended!" + message = "" if km_unmatched > 0: diff --git a/src/soliddriver_checks/utils/data_reader.py b/src/soliddriver_checks/utils/data_reader.py index 062b095..656eb55 100644 --- a/src/soliddriver_checks/utils/data_reader.py +++ b/src/soliddriver_checks/utils/data_reader.py @@ -95,7 +95,7 @@ def __init__(self, progress): ] def _get_driver_alias(self, driver): - alias = run_cmd("/usr/sbin/modinfo --field=alias %s" % driver) + alias = run_cmd("/usr/sbin/modinfo --field=alias %s | grep pci:" % driver) return alias.splitlines() def _get_rpm_modalias(self, rpm): @@ -111,13 +111,14 @@ def _get_rpm_modalias(self, rpm): all_rst = ml_all_re.match(line) if pci_rst: ker_flavor, pci = pci_rst.groups() - alias_re.append(pci) + if "pci:" in pci: # only check PCI devices + alias_re.append(pci) elif all_rst: # match all (*) should not be allowed ker_flavor, rst = all_rst.groups() - alias_re.append(rst) + if rst == "*": + alias_re.append(rst) return alias_re - # return mod_sup def _driver_symbols_check(self, rpm_symbols, driver): symvers = run_cmd("/usr/sbin/modprobe --dump-modversions %s" % driver) @@ -232,9 +233,14 @@ def _fmt_driver_symbol(self, drivers): return symbols def _fmt_driver_modalias(self, kmp_alias, drivers): - # for a in kmp_alias: - # if a == "*": - # return "RPM intend to match all the hardware which is not recommended!" + key_match_all = 'match_all' + key_unmatched_km_alias = 'unmatched_km_alias' + key_unmatched_kmp_alias = 'unmatched_kmp_alias' + for a in kmp_alias: + if a == "*": # "use default-kernel:* to match all the devices is always a bad idea." + return {key_match_all:True, + key_unmatched_km_alias:[], + key_unmatched_kmp_alias:[]} unmatched_ker_alias = [] unmatched_kmp_alias = kmp_alias.copy() @@ -253,8 +259,22 @@ def _fmt_driver_modalias(self, kmp_alias, drivers): break if not found: unmatched_ker_alias.append(ker_a) + + # There has some packages have "%5" in the package but use "_" in the kernel module + # So we have to match it again, but equal is enough. + r_ukmpalias = [v.replace("_", "%5F").replace("-", "%2D").replace(".", "%2E") for v in unmatched_ker_alias] + for i in range(len(unmatched_kmp_alias) - 1, -1, -1): + found_match = False + for j in range(len(unmatched_ker_alias) - 1, -1, -1): + if r_ukmpalias[j] == unmatched_kmp_alias[i]: + unmatched_ker_alias.pop(j) + found_match = True + if found_match: + unmatched_kmp_alias.pop(i) - return {'unmatched_km_alias':unmatched_ker_alias, 'unmatched_kmp_alias':unmatched_kmp_alias} + return {key_match_all:False, + key_unmatched_km_alias:unmatched_ker_alias, + key_unmatched_kmp_alias:unmatched_kmp_alias} def _is_driver_signed(self, driver): raw_info = run_cmd("/usr/sbin/modinfo %s" % driver) diff --git a/tests/Dockerfile b/tests/Dockerfile index 5f2c6d2..49212b8 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -2,8 +2,9 @@ FROM opensuse/leap:latest WORKDIR /root -RUN zypper --non-interactive in python3-pip kmod +RUN zypper --non-interactive in python39 python39-pip kmod +RUN zypper --non-interactive dup -RUN pip3 install rich pdfkit pandas \ +RUN pip3.9 install rich pdfkit pandas \ openpyxl click paramiko dominate build diff --git a/tests/create_container_mac.sh b/tests/create_container_mac.sh index 5e49fb2..afbc0af 100755 --- a/tests/create_container_mac.sh +++ b/tests/create_container_mac.sh @@ -1,6 +1,6 @@ docker run \ -it --rm \ --mount type=bind,source=/Users/$USER/projects/github.com/SUSE/soliddriver-checks,target=/root/source_codes \ ---mount type=bind,source=/Users/$USER/projects/Lenovo/SSDP/01-Apr-2022,target=/root/rpms \ +--mount type=bind,source=/Users/$USER/projects/fujitsu/kmps-15-sp2,target=/root/rpms \ --mount type=bind,source=/Users/$USER/codes/tmp,target=/root/output_dir \ opensuse-leap-soliddriver-checks:latest /bin/bash From d1e6e274a092118de683e372efd79c6a8124ffc0 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Mon, 21 Nov 2022 14:55:39 +0800 Subject: [PATCH 7/8] add modalias support in excel --- src/soliddriver_checks/utils/data_exporter.py | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/soliddriver_checks/utils/data_exporter.py b/src/soliddriver_checks/utils/data_exporter.py index 847f48e..dce2a26 100644 --- a/src/soliddriver_checks/utils/data_exporter.py +++ b/src/soliddriver_checks/utils/data_exporter.py @@ -155,6 +155,7 @@ def _copy_work_sheep(self, title, ws): ws["A5"].value = _get_version() ws["A6"].value = _generate_timestamp() + ws.column_dimensions['A'].width = 200 class RPMsExporter: def __init__(self): @@ -701,7 +702,16 @@ def _xlsx_create_vendor_summary(self, wb, rpm_table): sym_failed = Rule(type="expression", dxf=ctc_style) sym_failed.formula = ['VALUE(LEFT($G2, FIND(" ", $G2) - 1)) <> 0'] ws_vs.conditional_formatting.add(f"G2:G{last_record_row_no}", sym_failed) - + + ws_vs.column_dimensions['A'].width = 30 + ws_vs.column_dimensions['B'].width = 15 + ws_vs.column_dimensions['C'].width = 15 + ws_vs.column_dimensions['D'].width = 15 + ws_vs.column_dimensions['E'].width = 15 + ws_vs.column_dimensions['F'].width = 15 + ws_vs.column_dimensions['G'].width = 15 + ws_vs.column_dimensions['H'].width = 15 + def _xlsx_create_rpm_details(self, wb, rpm_table): df = self._rename_rpm_detail_columns(rpm_table) ws_rd = wb.create_sheet("KMPs details") @@ -738,7 +748,7 @@ def _xlsx_create_rpm_details(self, wb, rpm_table): ws_rd['A1'].border = header_border ws_rd['A1'].alignment = center_align - ws_rd.merge_cells('H1:I1') + ws_rd.merge_cells('H1:L1') ws_rd['H1'] = "Kernel Module Checks" ws_rd['H1'].font = header_font ws_rd['H1'].fill = header_fill @@ -812,6 +822,18 @@ def _xlsx_create_rpm_details(self, wb, rpm_table): ws_rd[cell_no].font = imt_font ws_rd[cell_no].fill = imt_fill ws_rd[cell_no].border = imt_border + elif cols[col_idx] == "Modalias Check": + alias_check = self._fmt_modalias_check(row["Modalias Check"]) + if alias_check != "": + ws_rd[cell_no] = alias_check + ws_rd[cell_no].font = imt_font + ws_rd[cell_no].fill = imt_fill + ws_rd[cell_no].border = imt_border + else: + val = "All passed!" + ws_rd[cell_no] = val + ws_rd[cell_no].alignment = center_align + else: # no format needed. ws_rd[cell_no] = str(val) @@ -826,6 +848,16 @@ def _xlsx_create_rpm_details(self, wb, rpm_table): sig_rule = Rule(type="expression", dxf=ctc_style) sig_rule.formula = ['=OR($D2 = "", $D2 = "(none)")'] ws_rd.conditional_formatting.add(f"D2:D{records}", sig_rule) + + ws_rd.column_dimensions['A'].width = 30 + ws_rd.column_dimensions['B'].width = 40 + ws_rd.column_dimensions['C'].width = 30 + ws_rd.column_dimensions['D'].width = 30 + ws_rd.column_dimensions['F'].width = 20 + ws_rd.column_dimensions['G'].width = 15 + ws_rd.column_dimensions['H'].width = 40 + ws_rd.column_dimensions['I'].width = 40 + ws_rd.column_dimensions['L'].width = 40 def _xlsx_create_report_workbook(self): wb = Workbook() From 2cc1f6d003eda8890a297c5d2f153732fd25c3a5 Mon Sep 17 00:00:00 2001 From: Hui-Zhi Date: Mon, 21 Nov 2022 14:57:09 +0800 Subject: [PATCH 8/8] update version to 2.0.8-beta --- src/soliddriver_checks/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soliddriver_checks/version.py b/src/soliddriver_checks/version.py index af218a2..1847ab2 100644 --- a/src/soliddriver_checks/version.py +++ b/src/soliddriver_checks/version.py @@ -2,4 +2,4 @@ Global version information used in soliddriver-checks and the package """ -__VERSION__ = "2.0.7" +__VERSION__ = "2.0.8-beta"