diff --git a/OSAPIChecker.py b/OSAPIChecker.py index 406ad62d95baf583cae83abd6bedd4d661487bba..489a5e0367d408307ee4d2dfc5f5562fdb2e23f9 100644 --- a/OSAPIChecker.py +++ b/OSAPIChecker.py @@ -9,6 +9,7 @@ import logging import time import getpass from os_api_checker.constants import PROJECT_PATH, STD_PATH, LOG_PATH, OUTPUT_PATH +from os_api_checker.utils.tool import get_os_info from os_api_checker.utils.arg_parser import create_main_parser from os_api_checker.checkers.LibChecker.lib_checker import LibChecker @@ -49,6 +50,9 @@ def input_valid_check(): # 2. Check Environment Info def gen_envinfo_json(): + basic_iso = os.path.basename(args.iso_path) if args.iso_path else None + expand_repo = args.repository + l_organize = args.organize l_osname = platform.system() l_osversion = platform.version() @@ -63,8 +67,36 @@ def gen_envinfo_json(): l_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp)) l_disk = os.popen("lsblk -d -n | awk '{print $4}'").read().rstrip("\n") - #l_envinfodict = {"测试对象" : {"系统名称" : l_osname, "版本" : l_osversion}, "送测单位" : l_organize , "系统环境" : {"内核版本" : l_kernel , "编译器版本" : l_compver , "Python版本" : l_pythonver} , "环境配置" : {"机器型号" : l_osmachine , "CPU指令集" : l_osmachine , "CPU型号" : l_osprocessor , "内存" : l_meminfo , "硬盘" : l_disk, "固件" : l_firmwareinfo} , "测试工具" : {"名称" : "OSAPIChecker", "版本" : "1.0.0" } , "测试时间" : l_time } - l_envinfodict = {"测试对象" : {"系统名称" : l_osname, "版本" : l_osversion}, "送测单位" : l_organize , "系统环境" : {"内核版本" : l_kernel , "编译器版本" : l_compver , "Python版本" : l_pythonver} , "环境配置" : {"CPU指令集" : l_osmachine , "CPU型号" : l_osprocessor , "内存" : l_meminfo , "硬盘" : l_disk, "固件" : l_firmwareinfo} , "测试工具" : {"名称" : "OSAPIChecker", "版本" : "1.0.0" } , "测试时间" : l_time } + # 获取详细的OS发行版信息 + os_info = get_os_info() + + l_envinfodict = { + "测试时间" : l_time, + "送测单位" : l_organize , + "检测标准" : args.baseline, + "测试对象" : { + "系统名称" : os_info["name"], + "版本" : os_info["version"], + "基础镜像" : basic_iso, + "扩展仓库" : expand_repo + }, + "系统环境" : { + "内核版本" : l_kernel , + "编译器版本" : l_compver , + "Python版本" : l_pythonver + } , + "环境配置" : { + "CPU指令集" : l_osmachine , + "CPU型号" : l_osprocessor , + "内存" : l_meminfo , + "硬盘" : l_disk, + "固件" : l_firmwareinfo + } , + "测试工具" : { + "名称" : "OSAPIChecker", + "版本" : "1.0.0" + } , + } env_file_name = os.path.join(OUTPUT_PATH, 'environments-info_%s.json' %(l_file_time)) #with open("Outputs/environments-info.json","w+") as fw: diff --git "a/docs/OSAPIChecker\344\275\277\347\224\250\350\257\264\346\230\216.MD" "b/docs/OSAPIChecker\344\275\277\347\224\250\350\257\264\346\230\216.MD" index 3c85293c5fc333aed4d48fa992685cfcab7a8d63..a3a927ca0640f72501c4ae35b94d50edeb15de94 100644 --- "a/docs/OSAPIChecker\344\275\277\347\224\250\350\257\264\346\230\216.MD" +++ "b/docs/OSAPIChecker\344\275\277\347\224\250\350\257\264\346\230\216.MD" @@ -1,40 +1,35 @@ # OSAPIChecker(主程序) -OSAPIChecker是测试工具的主程序,将各个子模块进行汇总处理。 +OSAPIChecker是操作系统API符合性检查工具的主程序,将各个子模块进行汇总处理。 ## 环境要求 -python 3.7+ -golang 1.13+ -python3-reportlab +- python 3.7+ +- python3-reportlab(或使用pip install reportlab) +- RPM系统需安装rpmdevtools +- DEB系统需启用/etc/apt/sources.list中的deb-src并执行sudo apt update ## 完整目录结构 ``` os-api-checker/ -├── .git/ -├── .gitignore ├── OSAPIChecker.py # 主入口程序 ├── README.en.md # 英文项目说明 ├── README.md # 中文项目说明 ├── docs/ # 文档目录 -│ ├── 01-GUIs/ # GUI相关文档 -│ │ └── GUI说明.MD # GUI功能说明 │ ├── CmdChecker使用说明.MD # 命令检测模块使用说明 │ ├── FsChecker使用说明.MD # 文件系统检测模块使用说明 │ ├── LibChecker使用说明.MD # 动态库检测模块使用说明 │ ├── OSAPIChecker使用说明.MD # 主程序使用说明 -│ ├── UserGroupChecker使用说明.MD # 用户组检测模块使用说明 -│ └── ... +│ └── UserGroupChecker使用说明.MD # 用户组检测模块使用说明 ├── os_api_checker/ # 核心代码目录 │ ├── checkers/ # 检查器模块目录 │ │ ├── CmdChecker/ # 命令检测模块 -│ │ │ ├── Config/ # 配置文件目录 +│ │ │ ├── config/ # 配置文件目录 │ │ │ │ ├── cmd_config.json # 命令检测配置文件 │ │ │ │ └── cmd_result_tmp.json # 命令检测临时结果文件 │ │ │ ├── testfiles/ # 测试文件目录 -│ │ │ │ ├── test.sh # 测试脚本 -│ │ │ │ └── ... +│ │ │ │ └── test.sh # 测试脚本 │ │ │ ├── __init__.py # 模块初始化文件 │ │ │ ├── cmd_checker.py # 命令检测主程序 │ │ │ └── utils.py # 命令检测工具函数 @@ -42,152 +37,204 @@ os-api-checker/ │ │ │ ├── __init__.py # 模块初始化文件 │ │ │ └── fs_checker.py # 文件系统检测主程序 │ │ ├── LibChecker/ # 动态库检测模块 +│ │ │ ├── server/ # 服务器版检测器 +│ │ │ │ └── lib_checker_server.py # 服务器版主程序 +│ │ │ ├── utils/ # 工具目录 +│ │ │ │ ├── baseline.py # 基线数据处理 +│ │ │ │ └── logger.py # 日志工具 │ │ │ ├── graphical_test.py # 图形化测试文件 -│ │ │ ├── lib_checker.py # 动态库检测主程序 -│ │ │ ├── lib_checker-01-JA.py # 动态库检测程序版本1 -│ │ │ ├── lib_checker-06-JA.py # 动态库检测程序版本2 -│ │ │ ├── lib_checker-322-JA.py # 动态库检测程序版本3 -│ │ │ ├── lib_checker-version-01-only-apt.py # 仅APT版动态库检测 -│ │ │ ├── lib_checker-version-02-with-color.py # 彩色输出版动态库检测 -│ │ │ ├── lib_checker-version-03-english.py # 英文版动态库检测 -│ │ │ ├── lib_checker-version-04-zh.py # 中文版动态库检测 -│ │ │ ├── lib_checker-version-05-xiangyu.py # 详述版动态库检测 -│ │ │ └── ... +│ │ │ └── lib_checker.py # 动态库检测主程序 │ │ ├── ServiceChecker/ # systemd服务检测模块 -│ │ │ ├── __init__.py # 模块初始化文件 │ │ │ ├── checkers/ # 服务检测子模块目录 │ │ │ │ ├── __init__.py -│ │ │ │ ├── dbus_checker.py # D-Bus检测器 -│ │ │ │ ├── standard_checker.py # 标准检测器 -│ │ │ │ ├── standard_loader.py # 标准加载器 -│ │ │ │ ├── systemctl_checker.py # systemctl命令检测器 -│ │ │ │ ├── unit_file_checker.py # 单元文件检测器 │ │ │ │ └── unit_state_checker.py # 单元状态检测器 -│ │ │ ├── config/ # 服务检测配置目录 +│ │ │ ├── config/ # 配置目录 │ │ │ │ ├── lib.sh # Shell库文件 │ │ │ │ ├── logger.conf # 日志配置文件 │ │ │ │ └── verify_result.json # 验证结果配置文件 -│ │ │ ├── constants.py # 服务检测常量定义 -│ │ │ ├── path/ # 路径相关检测目录 -│ │ │ │ ├── __init__.py -│ │ │ │ └── path_checker.py -│ │ │ ├── service/ # 服务检测目录 -│ │ │ │ └── service_checker.py -│ │ │ ├── service_checker.py # 服务检测主程序 -│ │ │ ├── service_verify.sh # 服务验证Shell脚本 -│ │ │ ├── socket/ # Socket通信目录(Go实现) -│ │ │ │ ├── service_client.go # Socket客户端(Go) -│ │ │ │ └── service_server.go # Socket服务端(Go) -│ │ │ ├── swap/ # Swap检测目录 -│ │ │ │ └── swap_checker.py -│ │ │ ├── systemd_std.json # systemd标准配置文件 -│ │ │ ├── timer/ # Timer检测目录 -│ │ │ │ ├── timer_checker.py -│ │ │ │ └── __init__.py -│ │ │ ├── utils/ # 服务检测工具目录 +│ │ │ ├── socket/ # Socket通信目录 +│ │ │ │ ├── service_client.py # Socket客户端 +│ │ │ │ └── service_server.py # Socket服务端 +│ │ │ ├── utils/ # 工具目录 │ │ │ │ ├── logger.py # 日志工具 -│ │ │ │ ├── shell.py # Shell工具 -│ │ │ │ └── __init__.py -│ │ │ └── 标准检测说明文档.md # 服务检测说明文档(中文) +│ │ │ │ └── shell.py # Shell工具 +│ │ │ └── constants.py # 常量定义 │ │ └── UserGroupChecker/ # 用户组检测模块 │ │ ├── __init__.py # 模块初始化文件 │ │ └── user_group_checker.py # 用户组检测主程序 -│ ├── config/ # 各模块配置文件存放目录 -│ ├── constants.py # 全局常量定义 -│ ├── data/ # 数据目录 -│ │ ├── std_data/ # 标准数据目录 -│ │ │ ├── GB_25656/ # GB 25656标准数据 -│ │ │ │ ├── common/ # 通用标准数据 -│ │ │ │ │ ├── cmd_list.json # 命令列表标准数据 -│ │ │ │ │ ├── fs_list.json # 文件系统列表标准数据 -│ │ │ │ │ ├── lib_list.json # 库列表标准数据 -│ │ │ │ │ └── user_group_list.json # 用户组列表标准数据 -│ │ │ │ ├── desktop/ # 桌面版标准数据 -│ │ │ │ └── server/ # 服务器版标准数据 -│ │ │ └── TB_YYY/ # TB YYY标准数据(空目录) -│ │ └── test_data/ # 测试数据目录(空目录) -│ ├── genreport/ # 报告生成目录 -│ │ ├── NotoSansSCRegular.ttf # 中文字体文件 +│ ├── data/std_data/GB_25656/common/ # 国家标准数据 +│ │ ├── cmd_list.json # 命令列表标准数据 +│ │ ├── fs_list.json # 文件系统列表标准数据 +│ │ └── user_group_list.json # 用户组列表标准数据 +│ ├── genreport/ # PDF报告生成工具 │ │ ├── README.md # 报告生成模块说明 -│ │ ├── pdf.py # PDF报告生成主程序(超大文件,约200MB) +│ │ ├── pdf.py # PDF报告生成主程序 │ │ └── pdfmaker.py # PDF制作工具 -│ ├── outputs/ # 输出目录(用于存储检测结果) -│ │ └── (可能包含各模块的检测结果JSON文件) -│ └── reports/ # 报告脚本目录 -│ ├── reboot-pdf.sh # 重启后生成PDF报告脚本 -│ └── report-pdf.sh # 生成PDF报告脚本 -└── tests/ # 测试目录(目前为空) +│ ├── reports/ # 报告脚本目录 +│ │ ├── reboot-pdf.sh # 重启后生成PDF报告脚本 +│ │ └── report-pdf.sh # 生成PDF报告脚本 +│ ├── std_convert/ # 标准数据转换工具 +│ │ ├── java_versions.json # Java版本映射 +│ │ ├── libconvert.py # 库转换工具 +│ │ └── requirements.txt # 依赖文件 +│ ├── utils/ # 通用工具目录 +│ │ ├── arg_parser.py # 参数解析器 +│ │ ├── exceptions.py # 异常处理 +│ │ └── shell.py # Shell执行工具 +│ └── constants.py # 全局常量定义 +├── outputs/ # 检测结果输出目录 +└── Logs/ # 日志文件目录 ``` ## 使用方法 -1. 进入OSChecker主目录 +### 1. 基本运行 +进入项目根目录后直接运行主程序: + +```bash python3 OSAPIChecker.py +``` + +默认参数:`--channel=all --strategy=basic --level=l1l2 --ostype=desktop --pkgmngr=apt-deb --baseline=GB_25656` + +### 2. 完整参数说明 + +``` +usage: OSChecker [-h] [-c CHANNEL] [-b BASELINE] [-s STRATEGY] [-i ISO_PATH] + [-r REPOSITORY] [-l LEVEL] [-t OSTYPE] [-p PKGMNGR] + [-o ORGANIZE] [-R] + +optional arguments: + -h, --help 显示帮助信息 + -c CHANNEL, --channel CHANNEL + 选择要测试的子模块: + libchecker, cmdchecker, fschecker, usergroupchecker, + servicechecker, all + 默认: all (全部测试) + -b BASELINE, --baseline BASELINE + 选择检查标准线: + GB_25656, TB_YYY 等 + 默认: GB_25656 + -s STRATEGY, --strategy STRATEGY + 选择LibChecker测试策略: + basic, expansion, with-expand + 默认: basic + -i ISO_PATH, --iso-path ISO_PATH + 指定要检查的系统镜像地址 + 默认: None + -r REPOSITORY, --repository REPOSITORY + 指定要检查的仓库源 + 默认: None + -l LEVEL, --level LEVEL + 选择LibChecker测试级别: + l1, l2, l3, l1l2, l1l2l3 + 默认: l1l2 + -t OSTYPE, --ostype OSTYPE + 操作系统类型: + desktop, server + 默认: desktop + -p PKGMNGR, --pkgmngr PKGMNGR + 软件包管理器类型: + apt-deb, yum-rpm + 默认: apt-deb + -o ORGANIZE, --organize ORGANIZE + 送测单位名称 + 默认: 空 + -R, --reports 生成PDF报告 + 默认: 不生成报告 +``` + +### 3. 参数详细说明 + +**-h, --help**: 显示帮助信息 + +**-c CHANNEL, --channel CHANNEL**: +- 选择要测试的子模块 +- 可选值:`libchecker`, `cmdchecker`, `fschecker`, `usergroupchecker`, `servicechecker`, `all` +- 默认值:`all`(全部测试) + +**-b BASELINE, --baseline BASELINE**: +- 选择检查标准线 +- 可选值:`GB_25656`, `TB_YYY` 等 +- 默认值:`GB_25656` +- 注意:必须指定存在的标准线目录 + +**-s STRATEGY, --strategy STRATEGY**: +- 选择LibChecker测试的库类型 +- 可选值:`basic`(基础库), `expansion`(扩展库), `with-expand`(基础+扩展) +- 默认值:`basic` +- 仅对LibChecker模块生效 + +**-i ISO_PATH, --iso-path ISO_PATH**: +- 指定要检查的系统镜像地址 +- 用于离线检查场景 +- 默认值:`None` +- 仅当strategy为`with-expand`时必需 + +**-r REPOSITORY, --repository REPOSITORY**: +- 指定要检查的仓库源 +- 用于在线检查场景 +- 默认值:`None` +- 仅当strategy为`with-expand`时必需 + +**-l LEVEL, --level LEVEL**: +- 选择LibChecker测试的级别 +- 可选值:`l1`, `l2`, `l3`, `l1l2`, `l1l2l3` +- 默认值:`l1l2` +- 仅对LibChecker模块生效 + +**-t OSTYPE, --ostype OSTYPE**: +- 选择LibChecker测试的操作系统类型 +- 可选值:`desktop`(桌面版), `server`(服务器版) +- 默认值:`desktop` +- 仅对LibChecker模块生效 + +**-p PKGMNGR, --pkgmngr PKGMNGR**: +- 选择LibChecker测试的软件包管理器类型 +- 可选值:`apt-deb`(DEB包系统), `yum-rpm`(RPM包系统) +- 默认值:`apt-deb` +- 仅对LibChecker模块生效 + +**-o ORGANIZE, --organize ORGANIZE**: +- 指定送测单位名称 +- 用于在报告中标识测试单位 +- 默认值:空字符串 + +**-R, --reports**: +- 是否生成PDF报告 +- 设置后会在检测完成后自动生成PDF报告 +- 默认不生成报告 + +### 4. 使用示例 + +**示例1:完整检测并生成报告** +```bash +python3 OSAPIChecker.py -R +``` + +**示例2:指定检测标准和配置** +```bash +python3 OSAPIChecker.py --channel=all --baseline=GB_25656 --strategy=basic --level=l1l2 --ostype=desktop --pkgmngr=apt-deb -R +``` + +**示例3:仅检测LibChecker模块** +```bash +python3 OSAPIChecker.py --channel=libchecker --strategy=with-expand --level=l1l2l3 --ostype=server --pkgmngr=yum-rpm -i /path/to/iso -r http://repo.example.com -R +``` + +**示例4:检测服务器环境** +```bash +python3 OSAPIChecker.py --channel=all --ostype=server --pkgmngr=yum-rpm --reports +``` + +### 5. 注意事项 -2. 常用参数 - -  usage: OSChecker [-h] [-c CHANNEL] [-s STRATEGY] [-l LEVEL] [-t OSTYPE] [-p PKGMNGR] [-o ORGANIZE] [-R] - -  optional arguments: -   -h, --help -     show this help message and exit - -   -c CHANNEL, --channel CHANNEL -     Choice OSAPIChecker channels: -      libchecker,cmdchecker,fschecker,servicechecker,all - -   -s STRATEGY, --strategy STRATEGY -     Choice OSAPIChecker strategy: basic,expansion,with-expand - -   -l LEVEL, --level LEVEL -     Choice OSAPIChecker level like: l1,l2,l3,l1l2,l1l2l3 - -   -t OSTYPE, --ostype OSTYPE -     OSType of current OS: desktop, server - -   -p PKGMNGR, --pkgmngr PKGMNGR -     Package Manager of current OS: apt-deb, yum-rpm - -   -o ORGANIZE, --organize ORGANIZE -     Choice Organize - -   -R, --reports -     Generate Reports - -  参数解析: - -   -h, --help: -     显示帮助信息 - -   -c CHANNEL, --channel CHANNEL: -     选择要测试子模块(libchecker,cmdchecker,fschecker,servicechecker) -     默认是all--全部测试 - -   -s STRATEGY, --strategy STRATEGY: -     选择libchecker测试的库的类型(basic、expansion、with-expand) -     其中,with-expand是(basic+expansion) -     默认是basic - -   -l LEVEL, --level LEVEL: -     选择libchecker测试的级别(l1、l2、l3或者是三者组合) -     默认是l1l2 - -   -t OSTYPE, --ostype OSTYPE: -     选择libchecker测试的OS类型(desktop、server) -     默认是desktop - -   -p PKGMNGR, --pkgmngr PKGMNGR: -     选择libchecker测试的软件包类别(apt-deb、yum-rpm) -     默认是apt-deb - -   -o ORGANIZE, --organize ORGANIZE -     送测单位名称,默认是空 - -   -R, --reports -     生成报告,默认不生成报告 - -3. 注意 - 1) 在进行测试时,请根据需要填写必要的参数信息 - 2) 当前除libchecker外,其他子模块使用的默认配置,当前主程序不做单独配置处理(部分工具存在参数冲突), 若有需要, 请单独运行子模块程序 +1. **权限要求**:ServiceChecker模块需要root权限运行 +2. **环境准备**: + - DEB系统需要启用`/etc/apt/sources.list`中的`deb-src`并执行`sudo apt update` + - RPM系统需要安装`rpmdevtools` +3. **标准线目录**:`-b/--baseline`参数指定的标准线目录必须存在 +4. **报告生成**:使用`-R/--reports`参数时,需要确保`reportlab`库已安装 +5. **模块独立性**:除LibChecker外,其他子模块使用默认配置,如需特殊配置请单独运行子模块程序 diff --git a/os_api_checker/checkers/LibChecker/server/sql_data_manager.py b/os_api_checker/checkers/LibChecker/server/sql_data_manager.py index 8efe5d6fbdaba69b5e6001c3838732cc8ae2b2cf..da2b8d0793e80b6bc90b3af5b12b0233754eb356 100644 --- a/os_api_checker/checkers/LibChecker/server/sql_data_manager.py +++ b/os_api_checker/checkers/LibChecker/server/sql_data_manager.py @@ -26,7 +26,7 @@ import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) import requests from xml.dom.minidom import parseString -from os_api_checker.utils.shell import exec_system_command +from os_api_checker.utils.tool import exec_system_command from os_api_checker.utils.exceptions import NetworkException from os_api_checker.constants import PROJECT_PATH from ..utils.logger import logger diff --git a/os_api_checker/checkers/LibChecker/utils/logger.py b/os_api_checker/checkers/LibChecker/utils/logger.py index 6a5fac6148e4564f469c36f481189aeac2344a16..50a3898ec2107949606331512c8e115acd4a791b 100644 --- a/os_api_checker/checkers/LibChecker/utils/logger.py +++ b/os_api_checker/checkers/LibChecker/utils/logger.py @@ -192,8 +192,8 @@ class LibCheckerLogger: indent_level3 = self._get_indent('level3') indent_level4 = self._get_indent('level4') - self.logger.warning(f"{indent_level3}库: {library_name}") - self.logger.warning(f"{indent_level4}位置 -> {location}, 结论 -> {desc}") + self.logger.info(f"{indent_level3}库: {library_name}") + self.logger.info(f"{indent_level4}位置 -> {location}, 结论 -> {desc}") self.logger.info(f"") def log_strategy_info(self, strategy, iso_path=None, repository=None): diff --git a/os_api_checker/genreport/pdf.py b/os_api_checker/genreport/pdf.py index b3dac07b976e465c726967cbe89eec91d3606d10..f0a055b3f60d277b443f97534cccf287b3c3be88 100644 --- a/os_api_checker/genreport/pdf.py +++ b/os_api_checker/genreport/pdf.py @@ -155,7 +155,7 @@ def make_pdf_cover(content): def make_pdf_test_env(content): # 添加小标题 - content.append(PdfMaker.draw_little_title('一、测试环境')) + content.append(PdfMaker.draw_little_title('一、基础信息')) if not os.path.exists(g_env): print("未发现测试环境结果文件") @@ -168,21 +168,24 @@ def make_pdf_test_env(content): with open(g_env, 'r', encoding='utf8') as fp: json_data = json.load(fp) data = [ - ['测试对象', '系统名称', json_data["测试对象"]["系统名称"]], - ['测试对象', '版本', json_data["测试对象"]["版本"]], - ['送测单位', '送测单位', json_data["送测单位"]], - ['系统环境', '内核版本', json_data["系统环境"]["内核版本"]], + ['送测单位', '送测单位', json_data["送测单位"]], + ['检测时间', '检测时间', json_data["测试时间"]], + ['检测标准', '检测标准', json_data["检测标准"]], + ['送测对象', '产品名称', json_data["测试对象"]["系统名称"]], + ['送测对象', '产品版本', json_data["测试对象"]["版本"]], + ['送测对象', '基础镜像', json_data["测试对象"]["基础镜像"]], + ['送测对象', '扩展仓库', json_data["测试对象"]["扩展仓库"]], + ['系统环境', '内核版本', json_data["系统环境"]["内核版本"]], ['系统环境', '编译器版本', json_data["系统环境"]["编译器版本"]], ['系统环境', 'Python版本', json_data["系统环境"]["Python版本"]], - ['环境配置', '机器型号', json_data["环境配置"]["CPU型号"]], - ['环境配置', 'CPU指令集', json_data["环境配置"]["CPU指令集"]], - ['环境配置', 'CPU型号', json_data["环境配置"]["CPU型号"]], - ['环境配置', '内存', json_data["环境配置"]["内存"]], - ['环境配置', '硬盘', json_data["环境配置"]["硬盘"]], - ['环境配置', '固件', json_data["环境配置"]["固件"]], - ['测试工具', '名称', json_data["测试工具"]["名称"]], - ['测试工具', '版本', json_data["测试工具"]["版本"]], - ['测试时间', '测试时间', json_data["测试时间"]], + ['环境配置', '机器型号', json_data["环境配置"]["CPU型号"]], + ['环境配置', 'CPU指令集', json_data["环境配置"]["CPU指令集"]], + ['环境配置', 'CPU型号', json_data["环境配置"]["CPU型号"]], + ['环境配置', '内存', json_data["环境配置"]["内存"]], + ['环境配置', '硬盘', json_data["环境配置"]["硬盘"]], + ['环境配置', '固件', json_data["环境配置"]["固件"]], + ['测试工具', '名称', json_data["测试工具"]["名称"]], + ['测试工具', '版本', json_data["测试工具"]["版本"]] ] for i, row in enumerate(data): @@ -190,11 +193,13 @@ def make_pdf_test_env(content): data[i][j] = Paragraph(str(cell), default_para_style) extra_style = default_table_style + [ - ['SPAN', (0, 0), (0, 1)], + ['SPAN', (0, 0), (1, 0)], + ['SPAN', (0, 1), (1, 1)], ['SPAN', (0, 2), (1, 2)], - ['SPAN', (0, 3), (0, 5)], - ['SPAN', (0, 6), (0, 11)], - ['SPAN', (0, 12), (0, 13)], + ['SPAN', (0, 3), (0, 6)], + ['SPAN', (0, 7), (0, 9)], + ['SPAN', (0, 10), (0, 15)], + ['SPAN', (0, 16), (0, 17)], ] content.append( @@ -207,123 +212,19 @@ def make_pdf_test_env(content): def make_pdf_lib(content): content.append(Spacer(1, 10)) - # 1.运行库 - content.append(PdfMaker.draw_little_title('1.运行库', 15)) + # 1.系统库 + content.append(PdfMaker.draw_little_title('1.系统库', 15)) content.append(Spacer(1, 10)) if not os.path.exists(g_lib): - print("未发现运行库检查结果文件") + print("未发现系统库检查结果文件") content.append( PdfMaker.draw_little_title( - '未发现运行库检查结果文件', 12, colors.red)) + '未发现系统库检查结果文件', 12, colors.red)) return - # (1)库包检查 - content.append(PdfMaker.draw_little_title('(1)库包检查', 12)) - # 添加表格 - data = [ - ['包名', '检测信息', '--', '--', '--'], - ] - - with open(g_lib, 'r', encoding='utf8') as fp: - json_data = json.load(fp) - for r in json_data: - - require_version = json_data[r]["Required version"] - level = json_data[r]["Level"] - data.append([r, '版本要求', '级别', '--', '--']) - data.append([r, require_version, level, '--', '--']) - data.append([r, '二进制包名', '当前版本', '--', '测试结果']) - - # local_version = "-" - # status = "" - for pack in json_data[r]["Binary package"]: - if isinstance(json_data[r]["Binary package"][pack], dict): - if not json_data[r]["Binary package"][pack]: - data.append([r, "--", '--', '--', "不通过-未找到"]) - for lib in json_data[r]["Binary package"][pack]: - local_version = json_data[r]["Binary package"][pack][lib]["version"] - status = json_data[r]["Binary package"][pack][lib]["status"] - - if status == "compatible": - status = "通过" - elif status == "not installed": - continue - else: - status = "不通过" - data.append([r, lib, local_version, '--', status]) - - data.append([r, '共享对象名', '存储路径', '归属包名', '测试结果']) - if isinstance(json_data[r]["Shared library"], dict): - for shared in json_data[r]["Shared library"]: - result = json_data[r]["Shared library"][shared]["status"] - if result == "compatible": - result = "通过" - else: - result = "不通过" - - belongs = "-" - - if json_data[r]["Shared library"][shared]["belongs"] != "None": - belongs = json_data[r]["Shared library"][shared]["belongs"] - path = json_data[r]["Shared library"][shared]["path"] - if len(path) > 65: - path_list = list(path) - path_list.insert(60, '\n') - path = ''.join(path_list) - data.append([r, shared, path, belongs, result]) - - lib_table_style = default_table_style + [ - ['BACKGROUND', (0, 0), (-1, 0), table_background_color], # 设置第一行背景颜色 - ['SPAN', (1, 0), (-1, 0)], # 合并第一行后几列 - ] - - is_merge = False - - for i, r in enumerate(data): - if data[i][1] == "版本要求": - lib_table_style.append( - ['BACKGROUND', (1, i), (-1, i), table_background_color]) - lib_table_style.append(['SPAN', (2, i), (-1, i)]) - lib_table_style.append(['SPAN', (2, i + 1), (-1, i + 1)]) - if data[i][1] == "二进制包名": - lib_table_style.append( - ['BACKGROUND', (1, i), (-1, i), table_background_color]) - is_merge = True - - if data[i][1] == "共享对象名": - lib_table_style.append( - ['BACKGROUND', (1, i), (-1, i), table_background_color]) - is_merge = False - - if is_merge: - lib_table_style.append(['SPAN', (2, i), (3, i)]) - - if data[i][-1] == "不通过" or data[i][-1] == "不通过-未找到": - c = default_para_style.textColor - default_para_style.textColor = colors.red - data[i][-1] = Paragraph(str(data[i][-1]), - default_para_style) - default_para_style.textColor = c - - for j, cell in enumerate(r): - if not isinstance(data[i][j], Paragraph): - s = default_para_style.fontSize - if i == 0: - default_para_style.fontSize = 12 - data[i][j] = Paragraph(str(cell), default_para_style) - default_para_style.fontSize = s - - content.append( - PdfMaker.draw_table( - lib_table_style, - data, - totalWidth=total_width, - rates=[2, 3, 7, 2, 1.2])) - content.append(PageBreak()) - # (2)小计 - content.append(PdfMaker.draw_little_title('(2)小计', 12)) + content.append(PdfMaker.draw_little_title('(1)系统库检查结论', 12)) with open(g_lib, 'r', encoding='utf8') as fp: json_data = json.load(fp) @@ -430,6 +331,112 @@ def make_pdf_lib(content): )) + # (1)库包检查 + content.append(Spacer(1, 10)) + content.append(PdfMaker.draw_little_title('(2)库包检查详情', 12)) + # 添加表格 + data = [ + ['包名', '检测信息', '--', '--', '--'], + ] + + with open(g_lib, 'r', encoding='utf8') as fp: + json_data = json.load(fp) + for r in json_data: + + require_version = json_data[r]["Required version"] + level = json_data[r]["Level"] + data.append([r, '版本要求', '级别', '--', '--']) + data.append([r, require_version, level, '--', '--']) + data.append([r, '二进制包名', '当前版本', '--', '测试结果']) + + # local_version = "-" + # status = "" + for pack in json_data[r]["Binary package"]: + if isinstance(json_data[r]["Binary package"][pack], dict): + if not json_data[r]["Binary package"][pack]: + data.append([r, "--", '--', '--', "不通过-未找到"]) + for lib in json_data[r]["Binary package"][pack]: + local_version = json_data[r]["Binary package"][pack][lib]["version"] + status = json_data[r]["Binary package"][pack][lib]["status"] + + if status == "compatible": + status = "通过" + elif status == "not installed": + continue + else: + status = "不通过" + data.append([r, lib, local_version, '--', status]) + + data.append([r, '共享对象名', '存储路径', '归属包名', '测试结果']) + if isinstance(json_data[r]["Shared library"], dict): + for shared in json_data[r]["Shared library"]: + result = json_data[r]["Shared library"][shared]["status"] + if result == "compatible": + result = "通过" + else: + result = "不通过" + + belongs = "-" + + if json_data[r]["Shared library"][shared]["belongs"] != "None": + belongs = json_data[r]["Shared library"][shared]["belongs"] + path = json_data[r]["Shared library"][shared]["path"] + if len(path) > 65: + path_list = list(path) + path_list.insert(60, '\n') + path = ''.join(path_list) + data.append([r, shared, path, belongs, result]) + + lib_table_style = default_table_style + [ + ['BACKGROUND', (0, 0), (-1, 0), table_background_color], # 设置第一行背景颜色 + ['SPAN', (1, 0), (-1, 0)], # 合并第一行后几列 + ] + + is_merge = False + + for i, r in enumerate(data): + if data[i][1] == "版本要求": + lib_table_style.append( + ['BACKGROUND', (1, i), (-1, i), table_background_color]) + lib_table_style.append(['SPAN', (2, i), (-1, i)]) + lib_table_style.append(['SPAN', (2, i + 1), (-1, i + 1)]) + if data[i][1] == "二进制包名": + lib_table_style.append( + ['BACKGROUND', (1, i), (-1, i), table_background_color]) + is_merge = True + + if data[i][1] == "共享对象名": + lib_table_style.append( + ['BACKGROUND', (1, i), (-1, i), table_background_color]) + is_merge = False + + if is_merge: + lib_table_style.append(['SPAN', (2, i), (3, i)]) + + if data[i][-1] == "不通过" or data[i][-1] == "不通过-未找到": + c = default_para_style.textColor + default_para_style.textColor = colors.red + data[i][-1] = Paragraph(str(data[i][-1]), + default_para_style) + default_para_style.textColor = c + + for j, cell in enumerate(r): + if not isinstance(data[i][j], Paragraph): + s = default_para_style.fontSize + if i == 0: + default_para_style.fontSize = 12 + data[i][j] = Paragraph(str(cell), default_para_style) + default_para_style.fontSize = s + + content.append( + PdfMaker.draw_table( + lib_table_style, + data, + totalWidth=total_width, + rates=[2, 3, 7, 2, 1.2])) + content.append(PageBreak()) + + def make_pdf_fs(content): content.append(Spacer(1, 10)) # 2.文件系统层次结构 @@ -3782,7 +3789,7 @@ def make_pdf_service(content): def make_pdf_result(content): # 添加小标题 - content.append(PdfMaker.draw_little_title('二、测试结果')) + content.append(PdfMaker.draw_little_title('三、检测维度')) make_pdf_lib(content) content.append(PageBreak()) make_pdf_fs(content) @@ -3796,7 +3803,38 @@ def make_pdf_result(content): def make_pdf_conclusion(content): # 添加小标题 - content.append(PdfMaker.draw_little_title('三、测试结论')) + content.append(PdfMaker.draw_little_title('二、检测结论')) + # 添加检测项统计表格 + conclusion_data = [ + ['检测项', '检测数', '通过数', '通过率', '结论'], + ['系统库', '', '', '', ''], + ['系统命令', '', '', '', ''], + ['文件系统', '', '', '', ''], + ['系统服务', '', '', '', ''], + ['用户和组', '', '', '', ''], + ] + + conclusion_style = default_table_style + [ + ['BACKGROUND', (0, 0), (-1, 0), table_background_color], + ] + + for i, row in enumerate(conclusion_data): + for j, cell in enumerate(row): + s = default_para_style.fontSize + if i == 0: # 表头使用较大字体 + default_para_style.fontSize = 12 + conclusion_data[i][j] = Paragraph(str(cell), default_para_style) + default_para_style.fontSize = s + + content.append( + PdfMaker.draw_table( + conclusion_style, + conclusion_data, + totalWidth=total_width, + rates=[1.5, 1, 1, 1, 1])) + + # 添加间距 + content.append(Spacer(1, 20)) if not os.path.exists(g_env): content.append( @@ -3816,6 +3854,8 @@ def make_pdf_conclusion(content): content.append(PdfMaker.draw_text(text, 12)) + + def make_api_pdf(pdfName): # 创建内容对应的空列表 content = list() @@ -3824,9 +3864,9 @@ def make_api_pdf(pdfName): content.append(PageBreak()) make_pdf_test_env(content) content.append(PageBreak()) - make_pdf_result(content) - content.append(PageBreak()) make_pdf_conclusion(content) + content.append(PageBreak()) + make_pdf_result(content) PdfMaker.create_pdf(pdfName, content) print("pdf生成完成, 路径: {}".format(os.path.abspath(g_result))) diff --git a/os_api_checker/utils/shell.py b/os_api_checker/utils/tool.py similarity index 45% rename from os_api_checker/utils/shell.py rename to os_api_checker/utils/tool.py index 79e01aee995f19ec60d52023e92ed5750ed7ffa5..5975156ca1508c9781443ff2b9975d8857c4fd8b 100644 --- a/os_api_checker/utils/shell.py +++ b/os_api_checker/utils/tool.py @@ -6,6 +6,7 @@ @Author : zengliwen@kylinos.cn @Desc : 命令执行封装工具函数 """ +import os import subprocess @@ -42,3 +43,43 @@ def exec_system_command(cmd, timeout=30, shell=False, cwd=None, env=None): return -1, "", f"Command timed out after {timeout} seconds" except Exception as e: return -1, "", str(e) + +def get_os_info(): + """ + 获取操作系统信息/etc/os-release文件信息 + + Returns: + dict: 包含简化操作系统信息的字典 + + Example: + { + 'name': 'Ubuntu', + 'version': '20.04', + 'id': 'ubuntu', + 'pretty_name': 'Ubuntu 20.04.6 LTS' + } + """ + os_release_path = '/etc/os-release' + os_release = {} + if os.path.exists(os_release_path): + try: + with open(os_release_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line and not line.startswith('#') and '=' in line: + key, value = line.split('=', 1) + # 移除引号 + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] + elif value.startswith("\'") and value.endswith("\'"): + value = value[1:-1] + os_release[key] = value + except Exception as e: + print(f"Error reading {os_release_path}: {str(e)}") + + return { + 'name': os_release.get('NAME', 'Unknown'), + 'version': os_release.get('VERSION_ID', 'Unknown'), + 'id': os_release.get('ID', 'unknown'), + 'pretty_name': os_release.get('PRETTY_NAME', 'Unknown OS') + }