From e3f26985e4cd755c98466c06000820ed0656ac7e Mon Sep 17 00:00:00 2001 From: cuixucui <350255958@qq.com> Date: Tue, 16 Apr 2024 18:40:39 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E5=92=8C=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oec-hardware-1.1.5-2-fix-bug.patch | 1598 ++++++++++++++++++++++++++++ oec-hardware.spec | 12 +- 2 files changed, 1609 insertions(+), 1 deletion(-) create mode 100644 oec-hardware-1.1.5-2-fix-bug.patch diff --git a/oec-hardware-1.1.5-2-fix-bug.patch b/oec-hardware-1.1.5-2-fix-bug.patch new file mode 100644 index 0000000..db67c81 --- /dev/null +++ b/oec-hardware-1.1.5-2-fix-bug.patch @@ -0,0 +1,1598 @@ +diff -Naur rpm/config/pci.ids oech/config/pci.ids +--- rpm/config/pci.ids 2023-10-24 22:25:50.000000000 +0800 ++++ oech/config/pci.ids 2024-04-16 18:08:37.752536721 +0800 +@@ -23904,6 +23904,8 @@ + 1af5 Netezza Corp. + 1afa J & W Electronics Co., Ltd. + 1b00 Montage Technology Co., Ltd. ++ d011 TSSE ++ d021 TSSE [VF] + 1b03 Magnum Semiconductor, Inc, + 6100 DXT/DXTPro Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder + 7000 D7 Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder +diff -Naur rpm/hwcompatible/cert_info.py oech/hwcompatible/cert_info.py +--- rpm/hwcompatible/cert_info.py 2024-04-16 18:17:05.010569180 +0800 ++++ oech/hwcompatible/cert_info.py 2024-04-16 18:08:37.756536769 +0800 +@@ -24,7 +24,8 @@ + self.cert_devices = [] + self.cert_quads = [] + self.infos = ["vendorID", "deviceID", "svID", "ssID", "architecture", "os", "driverName", "version", +- "type", "date", "sha256", "driverSize", "chipVendor", "boardModel", "chipModel", "downloadLink"] ++ "type", "date", "sha256", "driverSize", "chipVendor", "boardModel", "chipModel", "item", ++ "downloadLink"] + self.logger = logger + self.command = command + +@@ -64,6 +65,8 @@ + oec_json["boardModel"] = device.board + oec_json["chipModel"] = device.chip + oec_json["type"] = device_name.upper() ++ if oec_json["type"] == "ETHERNET": ++ oec_json["type"] = "NIC" + arch = self.command.run_cmd("uname -m", log_print=False) + oec_json["architecture"] = arch[0].strip("\n") + os_cmd = self.command.run_cmd( +@@ -80,6 +83,7 @@ + driver_size = self.command.run_cmd( + "ls -lh %s | awk '{print $5}'" % filename[0].strip("\n"), log_print=False) + oec_json["driverSize"] = driver_size[0].strip("\n") ++ oec_json["item"] = "" + oec_json["downloadLink"] = "inbox" + + self.cert_quads.append(device.quad) +diff -Naur rpm/hwcompatible/compatibility.py oech/hwcompatible/compatibility.py +--- rpm/hwcompatible/compatibility.py 2024-04-16 18:17:05.010569180 +0800 ++++ oech/hwcompatible/compatibility.py 2024-04-16 18:08:37.756536769 +0800 +@@ -147,7 +147,7 @@ + if not self.test_factory: + if self.category == "virtualization": + factory_doc = FactoryDocument(CertEnv.virtfactoryfile, self.logger) +- elif self.category == "compatible": ++ elif self.category == "compatible" or not self.category: + factory_doc = FactoryDocument(CertEnv.factoryfile, self.logger) + self.test_factory = factory_doc.get_factory() + +@@ -350,6 +350,12 @@ + sort_devices["fc"] = [device] + continue + driver = device.get_property("DRIVER") ++ if driver == "tsse": ++ if "keycard" in sort_devices.keys(): ++ sort_devices["keycard"].extend([device]) ++ else: ++ sort_devices["keycard"] = [device] ++ continue + if any([d in driver for d in GPU_DRIVER]): + if "gpu" in sort_devices.keys(): + sort_devices["gpu"].extend([device]) +diff -Naur rpm/hwcompatible/device.py oech/hwcompatible/device.py +--- rpm/hwcompatible/device.py 2023-10-24 22:25:50.000000000 +0800 ++++ oech/hwcompatible/device.py 2024-04-16 18:08:37.756536769 +0800 +@@ -209,11 +209,11 @@ + if re.match("\t" + self.quad[1], ln): + flag += 1 + if self.quad[0] == "8086": +- self.chip = self._search_info(r'\[(.*)\]', ln) ++ self.chip = self._search_info(r'\[(.*)\]', ln).strip() + elif self.quad[0] == "19e5": +- self.chip = re.sub(ln[0:7], "", ln).split(" ")[0] ++ self.chip = re.sub(ln[0:7], "", ln).split(" ")[0].strip() + else: +- self.chip = ln.split(" ")[-1] ++ self.chip = ln.split(" ")[-1].strip() + elif flag == 2: + if re.match("\t\t" + self.quad[2] + " " + self.quad[3], ln): + flag += 1 +diff -Naur rpm/README.en.md oech/README.en.md +--- rpm/README.en.md 1970-01-01 08:00:00.000000000 +0800 ++++ oech/README.en.md 2024-04-16 18:08:37.744536626 +0800 +@@ -0,0 +1,526 @@ ++ ++ ++- [Overview](#Overview) ++ - [tool describes](#tool describes) ++ - [Compatibility Conclusion Inheritance Description](#Compatibility Conclusion Inheritance Description) ++ - [Overall compatibility Conclusion Inheritance strategy](#Overall compatibility Conclusion Inheritance strategy) ++ - [Board Compatibility Conclusion Inheritance Strategy](#Board Compatibility Conclusion Inheritance Strategy) ++ - [version release](#version release) ++ - [Version Maintenance Statement](#Version Maintenance Statement) ++ - [tool uses](#tool uses) ++ - [use process](#use process) ++ - [User Usage Process](#User Usage Process) ++ - [operating environment](#operating environment) ++ - [environmental requirements](#environmental requirements) ++ - [Operating environment networking](#Operating environment networking) ++- [tool mounting](#tool mounting) ++ - [prerequisite](#prerequisite) ++ - [Get the installation package](#Get the installation package) ++ - [installation process](#installation process) ++ - [Client](#Client) ++ - [Server](#Server) ++- [use guidance](#use guidance) ++ - [prerequisite](#prerequisite-1) ++ - [using step](#using step) ++- [result acquisition](#result acquisition) ++ - [view results](#view results) ++ - [results show](#results show) ++ - [Review of test results](#Review of test results) ++- [Test item introduction](#Test item introduction) ++ - [Existing test items](#Existing test items) ++- [Community Developer Involvement Presentations](#Community Developer Involvement Presentations) ++ - [environment deployment](#environment deployment) ++ - [New test item](#New test item) ++- [FAQ](#FAQ) ++ ++ ++ ++# Overview ++ ++## tool describes ++ ++oec-hardware tool is a hardware compatibility test tool provided by openEuler community. oec-hardware provides compatibility verification test of server whole machine, board and openEuler. Verification is limited to basic function verification, excluding performance test and other tests. ++ ++Hardware manufacturers can use oec-hardware when they need to verify the compatibility of hardware products with openEuler. The community provides a hardware compatibility test process, and hardware manufacturers can refer to the community compatibility adaptation process to adapt to openEuler. ++ ++For hardware products tested by oec-hardware tools, openEuler will publish compatibility lists on the community website, and hardware manufacturers will publish corresponding compatibility information on the manufacturer's website. ++ ++# Compatibility Conclusion Inheritance Description ++ ++## Overall compatibility Conclusion Inheritance strategy ++ ++If the verification adapter has the same motherboard and CPU generation, the compatibility conclusion can be inherited. ++ ++## Board Compatibility Conclusion Inheritance Strategy ++ ++The card type is generally confirmed by quadruples. ++ ++``` ++Quadruple tuple information: ++ - vendorID: Chip manufacturer ID ++ - deviceID: Chip model ID ++ - svID: Board manufacturer ID ++ - ssID: Board model ID ++ ++Ways to view the quadruple tuple: ++ - View it through iBMC ++ - Run the command "lspci -nvv" in the system ++``` ++ ++The board compatibility conclusion inherits the following three points: ++ ++1. vendorID and deviceID are different ++ ++ Unable to inherit compatibility conclusions. ++ ++2. vendorID and deviceID, svID are different ++ ++ The chip model is the same but the board manufacturer is different, and the compatibility conclusion cannot be inherited. ++ ++3. Same vendorID, deviceID, svID ++ ++ Different boards made of the same chip can inherit the compatibility conclusion on behalf of the same board manufacturer. ++ ++4. Same vendorID, deviceID, svID, ssID ++ ++ Represents the same board manufacturer, the same series of boards made of the same chip, the same quadruple information, and can inherit the compatibility conclusion. The manufacturer evaluates this series of boards by himself, and can write representative board names. ++ ++The board manufacturer refers to the compatibility list of the community and the board being adapted. If the compatibility conclusion can be inherited, it needs to be explained in the corresponding adaptation issue. The compatibility sig group will conduct manual review, and the corresponding compatibility list will be issued after the review is passed. ++ ++# version release ++ ++Detailed release strategy and release plan see `docs/design_docs/oech_rpm_version_design.md` ++ ++## Version Maintenance Statement ++ ++oec-hardware-version 1.1.1 will no longer be updated and maintained. Please obtain the latest version of oec-hardware for installation and use. ++ ++# tool uses ++ ++## use process ++ ++### User Usage Process ++ ++![user-flow](docs/pictures/user-flow.png) ++ ++## operating environment ++ ++### environmental requirements ++ ++#### Environmental requirements for complete machine test ++ ++| Project | Requirements | ++| ------------------ | ------------------------------------------------------------ | ++| Number of machines | Two complete machines are required, and the service network interface is interconnected. | ++| Hardware | At least one RAID card and one NIC (including integrated motherboard hardware) | ++| Memory内存 | Recommended full | ++ ++#### Board test environment requirements ++ ++| Project | Requirements | ++| ------------- | ------------------------------------------------------------ | ++| server models | Taishan200(Model 2280), 2288H V5 or equivalent servers (see the community compatibility list for details). For x86_64 servers, you can choose one of icelake/cooperlake/cascade, preferably icelake. | ++| RAID Card | group raid is required, at least group raid 0 | ++| NIC/IB Card | The server and the test end need to insert a board of the same type respectively, configure the IP of the same network segment, and ensure direct connection and intercommunication. | ++| FC Card | Magnetic array needs to be connected, at least two luns | ++ ++**Note** ++ ++If you want to test external drivers, install the drivers in advance and configure the test environment. ++ ++GPU, VGPU, keycard and other test items need to install external drivers in advance to ensure that the environment deployment is completed, and then use this tool for testing. ++ ++### Operating environment networking ++ ++![test-network](docs/pictures/test-network.png) ++ ++# Offline Installation Environment Deployment Requirements ++ ++1. Download openEuler's official everything iso and mount the local repo source. ++ ++ If you cannot find a dependent package in everything iso, download the package manually from the openEuler repo and upload it to the tester for installation. ++ ++2. Root different test items, configure offline test dependencies ++ ++ | Test item | filename | path | ++ | --------- | ------------------------------------------------------------ | ------ | ++ | GPU | [https://github.com/wilicc/gpu-burn](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Fwilicc%2Fgpu-burn) | `/opt` | ++ | | [https://github.com/NVIDIA/cuda-samples/archive/refs/heads/master.zip](https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2FNVIDIA%2Fcuda-samples%2Farchive%2Frefs%2Fheads%2Fmaster.zip) | `/opt` | ++ | VGPU | NVIDIA vgpu client driver package | /root | ++ | | Download the virtual machine image file with the corresponding version and architecture, taking openEuler 22.03LTS and x86_64 as an example:[https://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/x86_64/openEuler-22.03-LTS-x86_64.qcow2.xz](https://gitee.com/link?target=https%3A%2F%2Frepo.openeuler.org%2FopenEuler-22.03-LTS%2Fvirtual_machine_img%2Fx86_64%2FopenEuler-22.03-LTS-x86_64.qcow2.xz) | `/opt` | ++ ++# tool mounting ++ ++## prerequisite ++ ++This tool supports openEuler 20.03 (LTS) or higher. For details of supported operating system versions, please see file `oec-hardware/scripts/kernelrelease.json` . ++ ++## Get the installation package ++ ++Configure the everything and update repo sources of the corresponding versions in the openEuler official repo, and use `dnf` to get the package for installation. ++ ++## installation process ++ ++### client ++ ++1. Install client oec-hardware using `dnf` . ++ ++ ``` ++ dnf install oec-hardware ++ ``` ++ ++2. Enter `oech` command, it can run normally, it means that the installation is successful. ++ ++### server ++ ++1. Install server-side oec-hardware-server using `dnf` . ++ ++ ``` ++ dnf install oec-hardware-server ++ ``` ++ ++2. Start the service. This service provides web services through nginx service. By default, port 80 is used. External ports can be modified through nginx service configuration files. Please ensure that these ports are not occupied before starting. ++ ++ ``` ++ systemctl start oech-server.service ++ systemctl start nginx.service ++ ``` ++ ++3. Turn off firewall and SElinux. ++ ++ ``` ++ systemctl stop firewalld ++ iptables -F ++ setenforce 0 ++ ``` ++ ++# use guidance ++ ++## prerequisite ++ ++- The `/usr/share/oech/kernelrelease.json` file lists all currently supported system versions. Use the `uname -a` command to confirm whether the current system kernel version belongs to the supported version of the framework. ++- By default, the framework scans all network cards. Before testing the network cards, please filter the tested network cards by yourself. The test port is required to be connected and the status is up. It is recommended not to use the service network interface for network card testing. ++- `/usr/share/oech/lib/config/test_config.yaml ` is the configuration file template of hardware test items. `fc` , `raid` , `disk` , `ethernet` and `infiniband` need to be configured according to the actual environment before hardware test. Other hardware tests do not need to be configured. For network card test, if the IP address is automatically added by the tool, after the test is completed, for security reasons, the IP of the server needs to be manually deleted. ++ ++## using step ++ ++1. Launch the test framework on the client side. The client starts `oech` , selects the test category, `compatible` indicates compatibility, `virtualization` indicates virtualization, and fills in the category number, i.e., enter `1` to indicate the selected compatibility category. ++ ++ ``` ++ # oech ++ Please select test category. ++ No. category ++ 1 compatible ++ 2 virtualization ++ Please select test category No:1 ++ ``` ++ ++2. Fill in configuration items `ID` , `URL` and `Server` ; `ID` is recommended to fill in the issue ID on gitee (note: `ID` cannot contain special characters); `URL` is recommended to fill in the product link; `Server` must be filled in as the server domain name or ip that the client can directly access, which is used to display the test report and the server for network testing. The default port number of server `nginx` is `80` . If the port is not modified after the server is installed, you only need to enter the service IP address of the server for the value `Compatibility Test Server` ; otherwise, you need to bring the port number, such as `172.167.145.2:90` . ++ ++ ``` ++ The openEuler Hardware Compatibility Test Suite ++ Please provide your Compatibility Test ID: ++ Please provide your Product URL: ++ Please provide the Compatibility Test Server (Hostname or Ipaddr): ++ ``` ++ ++3. Enter the test kit selection interface. In the case selection interface, the framework will automatically scan the hardware and select the test suite available for testing in the current environment. Enter `edit` to enter the test suite selection interface. ++ ++ ``` ++ These tests are recommended to complete the compatibility test: ++ No. Run-Now? status Class Device driverName driverVersion chipModel boardModel ++ 1 yes NotRun acpi ++ 2 yes NotRun clock ++ 3 yes NotRun cpufreq ++ 4 yes NotRun disk ++ 5 yes NotRun ethernet enp3s0 hinic 2.3.2.17 Hi1822 SP580 ++ 6 yes NotRun ethernet enp4s0 hinic 2.3.2.17 Hi1822 SP580 ++ 7 yes NotRun ethernet enp125s0f0 hns3 HNS GE/10GE/25GE TM210/TM280 ++ 8 yes NotRun ethernet enp125s0f1 hns3 HNS GE/10GE/25GE TM210/TM280 ++ 9 yes NotRun raid 0000:04:00.0 megaraid_sas 07.714.04.00-rc1 SAS3408 SR150-M ++ 10 yes NotRun gpu 0000:03:00.0 amdgpu Navi Radeon PRO W6800 ++ 11 yes NotRun ipmi ++ 12 yes NotRun kabi ++ 13 yes NotRun kdump ++ 14 yes NotRun memory ++ 15 yes NotRun perf ++ 16 yes NotRun system ++ 17 yes NotRun usb ++ 18 yes NotRun watchdog ++ Ready to begin testing? (run|edit|quit) ++ ``` ++ ++4. Select the test kit. `all|none` is used for `全选|全取消` respectively (the mandatory test item `system` cannot be cancelled, and the status of `system` will change to `Force` after repeated successful execution); the number number can be selected as the test set, and only one number can be selected at a time. After pressing the enter character, `no` changes to `yes` , indicating that the test set has been selected. ++ ++ ``` ++ Select tests to run: ++ No. Run-Now? status Class Device driverName driverVersion chipModel boardModel ++ 1 no NotRun acpi ++ 2 no NotRun clock ++ 3 no NotRun cpufreq ++ 4 no NotRun disk ++ 5 yes NotRun ethernet enp3s0 hinic 2.3.2.17 Hi1822 SP580 ++ 6 no NotRun ethernet enp4s0 hinic 2.3.2.17 Hi1822 SP580 ++ 7 no NotRun ethernet enp125s0f0 hns3 HNS GE/10GE/25GE TM210/TM280 ++ 8 no NotRun ethernet enp125s0f1 hns3 HNS GE/10GE/25GE TM210/TM280 ++ 9 yes NotRun raid 0000:04:00.0 megaraid_sas 07.714.04.00-rc1 SAS3408 SR150-M ++ 10 yes NotRun gpu 0000:03:00.0 amdgpu Navi Radeon PRO W6800 ++ 11 yes NotRun ipmi ++ 12 yes NotRun kabi ++ 13 yes NotRun kdump ++ 14 yes NotRun memory ++ 15 yes NotRun perf ++ 16 yes NotRun system ++ 17 yes NotRun usb ++ 18 yes NotRun watchdog ++ Selection (|all|none|quit|run): ++ ``` ++ ++5. Start testing. Enter `run` to start the test. ++ ++6. Upload test results. After the test is completed, you can upload the test results to the server for easy result display and log analysis. If the upload fails, check the network configuration and re-upload the test results. ++ ++ ``` ++ ... ++ ------------- Summary ------------- ++ ethernet-enp3s0 PASS ++ system PASS ++ Log saved to /usr/share/oech/logs/oech-20200228210118-TnvUJxFb50.tar succ. ++ Do you want to submit last result? (y|n) y ++ Uploading... ++ Successfully uploaded result to server X.X.X.X. ++ ``` ++ ++# result acquisition ++ ++## view results ++ ++1. Open the server IP address in the browser, click the navigation bar `Results` interface, and find the corresponding test id to enter. ++ ++ ![results](docs/pictures/results.png) ++ ++2. Enter a single task page to see specific test results, including environmental information and execution results. ++ ++ - `Summary` View all test results. ++ ++ - `Devices` View all hardware device information. ++ ++ - `Runtime` View test run times and total task execution logs. ++ ++ - `Attachment` Download Test Log Attachment. ++ ++ - `Submit` means upload the results to Euler's official authentication server (currently not open). ++ ++ ![result-qemu](docs/pictures/result-qemu.png) ++ ++## results show ++ ++The Result column displays the test results, which can be either PASS or FAIL. If the result is FAIL, you can click the result directly to view the execution log, and check the case code according to the error report. ++ ++## Review of test results ++ ++If the tested hardware and complete machine need to be published to the openEuler compatibility list, please upload all the following test results to the relevant adaptation issue: ++ ++- oec-hardware test log ++ ++- html test report generated by oec-hardware-server ++ ++- Compatibility manifest file ++ ++ After oec-hardware is executed, compatibility information file `hw_compatibility.json` will be automatically generated for the hardware passing the test. Please refer to this file to fill in templates under templates directory, and then upload the filled template file. ++ ++ The whole machine adaptation needs to test at least one RAID card and one network card, and provide corresponding information. ++ ++# Test item introduction ++ ++## Existing test items ++ ++### compatible ++ ++1. **system** ++ ++ - Check if this tool has been modified. ++ - Check if OS version and kernel version match. ++ - Check if the kernel is modified/infected. ++ - Check if selinux is enabled properly. ++ - Use the dmidecode tool to read hardware information. ++ ++2. **cpufreq** ++ ++ - Test whether cpu runs at the same frequency as expected under different fm strategies. ++ - Test whether the time required for cpu to calculate exactly the same specification at different frequencies is inversely related to the frequency value. ++ ++3. **clock** ++ ++ - Test time vectoricity, no backtracking. ++ - Test basic stability of RTC hardware clock. ++ ++4. **memory** ++ ++ - Use the memtester tool for memory read and write testing. ++ - mmap all available system memory, trigger swap, 120s read and write test. ++ - Test hugetlb. ++ - Memory hot plug test. ++ ++5. **network** ++ ++ - Use ethtool to get network card information and ifconfig to perform down/up tests on the network card. ++ ++ - Use qperf to test ethernet tcp/udp latency and bandwidth, as well as http upload and download rates. ++ ++ - Use perftest to test latency and bandwidth of infiniband(IB) or RoCE network protocols. ++ ++ **Note** ++ ++ When testing the network bandwidth, please confirm in advance that the network card speed of the server is not lower than that of the client, and ensure that there is no other traffic interference on the test network. ++ ++6. **disk** ++ ++ Sequential/random read-write testing of bare disks/file systems using fio tools. ++ ++7. **kdump** ++ ++ Trigger kdump to test whether the vmcore file can be generated and parsed normally. ++ ++8. **watchdog** ++ ++ Trigger watchdog to test whether the system can be reset normally. ++ ++9. **perf** ++ ++ - Collect events generated by hardware in the system. ++ - Collect sampling information and view statistical results. ++ ++10. **cdrom** ++ ++ Burn and read optical drives using mkisofs and cdrecord. ++ ++11. **ipmi** ++ ++ Query IPMI information using ipmitool. ++ ++12. **nvme** ++ ++ Use nvme-cli tool to format, read and write, query and test the disk. ++ ++13. **usb** ++ ++ Plug and unplug usb devices and test whether usb interfaces can be recognized normally. ++ ++14. **acpi** ++ ++ Use the acpidump tool to read the data. ++ ++15. **FC** ++ ++ Sequential/random read-write testing of FC storage servers using fio tools. ++ ++16. **RAID** ++ ++ Use fio tool for sequential/random read/write test of hard disk under RAID. ++ ++17. **keycard** ++ ++ Test whether the encryption card can be used normally. ++ ++18. **GPU** ++ ++ - NVIDIA GPU ++ ++ - Stress test GPU using gpu_burn tool. ++ - Use cuda_samples to test basic GPU functionality. ++ ++ - AMD GPU ++ ++ - Use the radeontop tool to view GPU usage. ++ ++ - Use the glmark2 tool to view GPU screen information. ++ ++ - Stress testing GPU using glmark2 tool. ++ ++ **Note** ++ ++ AMD GPU testing relies on a graphical interface, which needs to be deployed and switched to before testing. ++ ++19. **infiniband** ++ ++ - Use ethtool to get network card information. ++ ++ - Use perftest to test the latency and bandwidth of the infiniband(IB) network protocol. ++ ++ **Note** ++ ++ When testing the network bandwidth, please confirm in advance that the network card speed of the server is not lower than that of the client, and ensure that there is no other traffic interference on the test network. ++ ++20. **kabi** ++ ++ - Test whether the kernel kabi has changed compared to the standard system. ++ ++21. **VGPU** ++ ++ - Test NVIDIA VGPU server-side basics. ++ - Deploy NVIDIA VGPU client virtual machines, test driver installation, test client VGPU functionality. ++ - The VGPU server monitors the operation of the client. ++ ++22. **spdk** ++ ++ - Sequential and random read and write testing of SSDs using the spdk tool. ++ ++23. **dpdk** ++ ++ - Use dpdk-testpmd to connect two Ethernet ports in loopback mode. In the absence of an external traffic generator, the client uses Tx-only mode as the packet source, and the server uses Rx-only mode as the packet receiver to test the port transmission rate function. ++ ++### virtualization ++ ++``` ++Virtualization has use cases waiting for updates. ++``` ++ ++# Community Developer Involvement Presentations ++ ++## environment deployment ++ ++1. Fork oec-hardware source code repository to personal space; ++ ++2. clone repository source code; ++ ++ ``` ++ git clone https://gitee.com/${gitee_id}/oec-hardware.git ++ ``` ++ ++3. Enter the corresponding directory, compile and install; ++ ++ ``` ++ cd oec-hardware ++ make && make install ++ ``` ++ ++4. Package verification, here take version 1.0.0 as an example for packaging, the specific packaging version please refer to the version in the spec file. ++ ++ ``` ++ dnf install -y rpm-build ++ cd oec-hardware ++ tar jcvf oec-hardware-1.0.0.tar.bz2 * ++ mkdir -p /root/rpmbuild/SOURCES ++ cp oec-hardware-1.0.0.tar.bz2 /root/rpmbuild/SOURCES/ ++ rpmbuild -ba oec-hardware.spec ++ ``` ++ ++## New test item ++ ++1. If there is already a category of test items in the directory `tests/` , add test items directly under the category. The directory name of the test items should be the same as the name of the following entry function. For example, the entry file of acpi test items is acpi.py file, and inherit the framework `Test` to implement your own test class. Otherwise, add category catalog first, and then add test items under category. ++2. Important member variables or functions in the test class: ++ - Function `test` -Required to test the main flow. ++ - Function `setup` -environment preparation before test, mainly used to initialize the relevant information of the tested equipment, you can refer to network test. ++ - Function `teardown` -environment cleaning after test is completed, mainly used to ensure that the environment can be restored correctly regardless of test success or failure, you can refer to network test. ++ - Variable `requirements` -stores the rpm package names that the test depends on as an array, and the framework is automatically installed before the test starts. ++ - Variables `reboot` and `rebootup` -If `reboot = True` indicates that the test suite/test case will restart the system and continue to execute the function specified by `rebootup` after restart, refer to kdump test. ++3. Add identification display of corresponding test item in `hwcompatible/compatibility.py` file. Refer to https://gitee.com/openeuler/oec-hardware/blob/master/docs/develop_doc/get_board.md for card identification method. ++ ++# FAQ ++ ++ Kunpeng Xiaozhi provides solutions to problems that may be encountered during oec-hardware testing, and users can retrieve solutions to problems. In addition, the Kunpeng Forum provides complete oec-hardware installation and use questions, and users can obtain solutions according to scenarios. ++ ++If you encounter problems in the adaptation process, it is recommended that users first obtain support through Kunpeng Xiaozhi or Kunpeng Forum. ++ ++If Kunpeng Xiaozhi can't solve it, you can submit issue feedback under this repository or send an email to openEuler Community Compatibility SIG Group Email: oecompatibility@openeuler.org +\ No newline at end of file +diff -Naur rpm/README.md oech/README.md +--- rpm/README.md 2023-10-24 22:25:50.000000000 +0800 ++++ oech/README.md 2024-04-16 18:08:37.744536626 +0800 +@@ -204,18 +204,26 @@ + * `/usr/share/oech/lib/config/test_config.yaml ` 是硬件测试项配置文件模板,`fc`、`raid`、`disk`、`ethernet`、`infiniband`硬件测试前需先根据实际环境进行配置,其它硬件测试不需要配置。对于网卡测试,如果是工具自动添加的IP地址,测试完成后,为了安全,服务端的IP需手动删除。 + + ## 使用步骤 ++1. 在客户端启动测试框架。客户端启动 `oech`,选择测试类别,`compatible`表示兼容性,`virtualization`表示虚拟化,填写类别序号,即输入`1`表示选择的兼容性类别。 ++ ``` ++ # oech ++ Please select test category. ++ No. category ++ 1 compatible ++ 2 virtualization ++ Please select test category No:1 ++ ``` + +-1. 在客户端启动测试框架。在客户端启动 `oech`,填写`ID`、`URL`、`Server`配置项,`ID` 建议填写 gitee 上的 issue ID(注意:`ID`中不能带特殊字符);`URL`建议填写产品链接;`Server` 必须填写为客户端可以直接访问的服务器域名或 ip,用于展示测试报告和作网络测试的服务端。服务端`nginx`默认端口号是`80`,如果服务端安装完成后没有修改该端口,`Compatibility Test Server` 的值只需要输入服务端的业务IP地址;否则需要带上端口号,比如:`172.167.145.2:90`。 ++2. 填写`ID`、`URL`、`Server`配置项,`ID` 建议填写 gitee 上的 issue ID(注意:`ID`中不能带特殊字符);`URL`建议填写产品链接;`Server` 必须填写为客户端可以直接访问的服务器域名或 ip,用于展示测试报告和作网络测试的服务端。服务端`nginx`默认端口号是`80`,如果服务端安装完成后没有修改该端口,`Compatibility Test Server` 的值只需要输入服务端的业务IP地址;否则需要带上端口号,比如:`172.167.145.2:90`。 + + ``` +- # oech + The openEuler Hardware Compatibility Test Suite + Please provide your Compatibility Test ID: + Please provide your Product URL: + Please provide the Compatibility Test Server (Hostname or Ipaddr): + ``` + +-2. 进入测试套选择界面。在用例选择界面,框架将自动扫描硬件并选取当前环境可供测试的测试套,输入 `edit` 可以进入测试套选择界面。 ++3. 进入测试套选择界面。在用例选择界面,框架将自动扫描硬件并选取当前环境可供测试的测试套,输入 `edit` 可以进入测试套选择界面。 + + ``` + These tests are recommended to complete the compatibility test: +@@ -228,18 +236,20 @@ + 6 yes NotRun ethernet enp4s0 hinic 2.3.2.17 Hi1822 SP580 + 7 yes NotRun ethernet enp125s0f0 hns3 HNS GE/10GE/25GE TM210/TM280 + 8 yes NotRun ethernet enp125s0f1 hns3 HNS GE/10GE/25GE TM210/TM280 +- 9 yes NotRun ipmi +- 10 yes NotRun kabi +- 11 yes NotRun kdump +- 12 yes NotRun memory +- 13 yes NotRun perf +- 14 yes NotRun system +- 15 yes NotRun usb +- 16 yes NotRun watchdog ++ 9 yes NotRun raid 0000:04:00.0 megaraid_sas 07.714.04.00-rc1 SAS3408 SR150-M ++ 10 yes NotRun gpu 0000:03:00.0 amdgpu Navi Radeon PRO W6800 ++ 11 yes NotRun ipmi ++ 12 yes NotRun kabi ++ 13 yes NotRun kdump ++ 14 yes NotRun memory ++ 15 yes NotRun perf ++ 16 yes NotRun system ++ 17 yes NotRun usb ++ 18 yes NotRun watchdog + Ready to begin testing? (run|edit|quit) + ``` + +-3. 选择测试套。`all|none` 分别用于 `全选|全取消`(必测项 `system` 不可取消,多次执行成功后 `system` 的状态会变为`Force`);数字编号可选择测试套,每次只能选择一个数字,按回车符之后 `no` 变为 `yes`,表示已选择该测试套。 ++4. 选择测试套。`all|none` 分别用于 `全选|全取消`(必测项 `system` 不可取消,多次执行成功后 `system` 的状态会变为`Force`);数字编号可选择测试套,每次只能选择一个数字,按回车符之后 `no` 变为 `yes`,表示已选择该测试套。 + + ``` + Select tests to run: +@@ -252,20 +262,22 @@ + 6 no NotRun ethernet enp4s0 hinic 2.3.2.17 Hi1822 SP580 + 7 no NotRun ethernet enp125s0f0 hns3 HNS GE/10GE/25GE TM210/TM280 + 8 no NotRun ethernet enp125s0f1 hns3 HNS GE/10GE/25GE TM210/TM280 +- 9 no NotRun ipmi +- 10 no NotRun kabi +- 11 no NotRun kdump +- 12 no NotRun memory +- 13 no NotRun perf +- 14 yes NotRun system +- 15 no NotRun usb +- 16 no NotRun watchdog ++ 9 yes NotRun raid 0000:04:00.0 megaraid_sas 07.714.04.00-rc1 SAS3408 SR150-M ++ 10 yes NotRun gpu 0000:03:00.0 amdgpu Navi Radeon PRO W6800 ++ 11 yes NotRun ipmi ++ 12 yes NotRun kabi ++ 13 yes NotRun kdump ++ 14 yes NotRun memory ++ 15 yes NotRun perf ++ 16 yes NotRun system ++ 17 yes NotRun usb ++ 18 yes NotRun watchdog + Selection (|all|none|quit|run): + ``` + +-4. 开始测试。选择完成后输入 `run` 开始测试。 ++5. 开始测试。选择完成后输入 `run` 开始测试。 + +-5. 上传测试结果。测试完成后可以上传测试结果到服务器,便于结果展示和日志分析。如果上传失败,请检查网络配置,然后重新上传测试结果。 ++6. 上传测试结果。测试完成后可以上传测试结果到服务器,便于结果展示和日志分析。如果上传失败,请检查网络配置,然后重新上传测试结果。 + + ``` + ... +@@ -322,6 +334,7 @@ + # 测试项介绍 + + ## 已有测试项 ++### compatible + + 1. **system** + +@@ -453,6 +466,10 @@ + 客户端使用发包模式(Tx-only mode)作为数据包源,服务端使用收包模式(Rx-only mode) + 作为数据包接收器, 测试端口传输速率功能。 + ++### virtualization ++ ++ 虚拟化已有用例待更新 ++ + # 社区开发者参与介绍 + + ## 环境部署 +@@ -485,7 +502,7 @@ + + ## 新增测试项 + +-1. 在 `tests/` 目录下添加测试项模板,通过继承框架 `Test` 实现自己的测试类。 ++1. `tests/` 目录下如果已有测试项所在的类别,直接在类别下添加测试项,测试项的目录名称需和下面入口函数名称相同,比如acpi测试项的入口文件是acpi.py文件,并继承框架 `Test` 实现自己的测试类。否则先添加类别目录,在类别下面再添加测试项。 + + 2. 测试类中的重要成员变量或函数介绍: + +@@ -499,7 +516,7 @@ + + - 变量 `reboot` 和 `rebootup` - 若 `reboot = True` 表示该测试套/测试用例会重启系统,且在重启后继续执行 `rebootup` 指定的函数,可以参考 kdump 测试。 + +-3. 在 `hwcompatible/compatibility.py` 文件中添加对应测试项的识别显示。 ++3. 在 `hwcompatible/compatibility.py` 文件中添加对应测试项的识别显示,板卡识别方法可参考https://gitee.com/openeuler/oec-hardware/blob/master/docs/develop_doc/get_board.md 文档。 + + # FAQ + +diff -Naur rpm/scripts/kernelrelease.json oech/scripts/kernelrelease.json +--- rpm/scripts/kernelrelease.json 2023-10-24 22:25:50.000000000 +0800 ++++ oech/scripts/kernelrelease.json 2024-04-16 18:08:37.756536769 +0800 +@@ -9,12 +9,21 @@ + "openEuler 22.03 LTS": "5.10.0", + "openEuler 22.03 (LTS-SP1)": "5.10.0", + "openEuler 22.03 (LTS-SP2)": "5.10.0", +- "openEuler 22.03 (LTS-SP3)": "5.10.0" ++ "openEuler 22.03 (LTS-SP3)": "5.10.0", ++ "openEuler 22.03 (LTS-SP4)": "5.10.0", ++ "openEuler 24.03 (LTS)": "6.6.0" + }, + "KylinSec": { + "345": "openEuler-20.03-LTS-SP3/4.19.90-2112.8.0.0131.oe1", + "351": "openEuler-22.03-LTS/5.10.0-60.18.0.50.oe2203", + "352": "openEuler-22.03-LTS-SP2/5.10.0-153.12.0.92.oe2203sp2" +- } ++ }, ++ "Kylin": { ++ "V10": "openEuler-20.03-LTS-SP3/4.19.90-2112.8.0.0131.oe1" ++ }, ++ "UOS": { ++ "20": "openEuler-22.03-LTS/5.10.0-60.18.0.50.oe2203", ++ "20": "openEuler-22.03-LTS-SP2/5.10.0-153.12.0.92.oe2203sp2" ++ } + } + +diff -Naur rpm/server/oech-server-pre.sh oech/server/oech-server-pre.sh +--- rpm/server/oech-server-pre.sh 2023-10-24 22:25:50.000000000 +0800 ++++ oech/server/oech-server-pre.sh 2024-04-16 18:08:37.756536769 +0800 +@@ -15,3 +15,8 @@ + dir_cert=/usr/share/oech/lib/server + + test -f ${dir_nginx}/uwsgi.conf || cp -af ${dir_cert}/uwsgi.conf ${dir_nginx} ++ ++if [ ! -f /usr/bin/uwsgi ]; ++then ++ ln -s /usr/sbin/uwsgi /usr/bin/uwsgi ++fi +diff -Naur rpm/server/uwsgi.ini oech/server/uwsgi.ini +--- rpm/server/uwsgi.ini 2023-10-24 22:25:50.000000000 +0800 ++++ oech/server/uwsgi.ini 2024-04-16 18:08:37.756536769 +0800 +@@ -6,4 +6,5 @@ + processes = 4 + pidfile = /usr/share/oech/lib/server/uwsgi.pid + master = true +-buffer-size = 65536 +\ No newline at end of file ++buffer-size = 65536 ++plugins = python3 +\ No newline at end of file +diff -Naur rpm/tests/compatible/cpufreq/cpufreq.py oech/tests/compatible/cpufreq/cpufreq.py +--- rpm/tests/compatible/cpufreq/cpufreq.py 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/cpufreq/cpufreq.py 2024-04-16 18:08:37.760536817 +0800 +@@ -136,7 +136,7 @@ + :return: + """ + self.process = self.command.run_cmd( +- "taskset -c %s python -u %s/cpufreq/cal.py" % (self.cpu, CertEnv.testdirectoy), log_print=False) ++ "taskset -c %s python3 -u %s/compatible/cpufreq/cal.py" % (self.cpu, CertEnv.testdirectoy), log_print=False) + + def get_runtime(self): + """ +diff -Naur rpm/tests/compatible/disk/common.py oech/tests/compatible/disk/common.py +--- rpm/tests/compatible/disk/common.py 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/disk/common.py 2024-04-16 18:08:37.760536817 +0800 +@@ -106,17 +106,29 @@ + size = 1048576 + + logger.info("Starting sequential raw IO test...") +- opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" +- if not do_fio(logger, command, device, size, opts): +- logger.error("%s sequential raw IO test failed." % device) +- return False ++ # opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" ++ opts_list = ["-direct=1 -iodepth 32 -rw=write -group_reporting -name=file", ++ "-direct=1 -iodepth 32 -rw=read -group_reporting -name=file -runtime=300", ++ "-direct=1 -iodepth 32 -rw=write -group_reporting -name=file -runtime=300", ++ "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300", ++ ] ++ for opts in opts_list: ++ if not do_fio(logger, command, device, size, opts): ++ logger.error("%s sequential raw IO test failed." % device) ++ return False ++ logger.info("%s sequential raw IO test succeed." % device) + + logger.info("Starting rand raw IO test...") +- opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ +- "-group_reporting -name=file -runtime=300" +- if not do_fio(logger, command, device, size, opts): +- logger.error("%s rand raw IO test failed." % device) +- return False ++ # opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ ++ # "-group_reporting -name=file -runtime=300" ++ opts_list = ["-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 -group_reporting -name=file -runtime=300", ++ "-direct=1 -iodepth 32 -rw=randread -group_reporting -name=file -runtime=300", ++ "-direct=1 -iodepth 32 -rw=randwrite -group_reporting -name=file -runtime=300"] ++ for opts in opts_list: ++ if not do_fio(logger, command, device, size, opts): ++ logger.error("%s rand raw IO test failed." % device) ++ return False ++ logger.info("%s sequential rand raw IO test succeed." % device) + + return True + +@@ -189,7 +201,6 @@ + logger.error("%s fio failed." % filepath) + return False + a_bs = a_bs * 2 +- logger.info("%s fio succeed." % filepath) + return True + + +diff -Naur rpm/tests/compatible/dpdk/dpdk.py oech/tests/compatible/dpdk/dpdk.py +--- rpm/tests/compatible/dpdk/dpdk.py 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/dpdk/dpdk.py 2024-04-16 18:08:37.760536817 +0800 +@@ -348,7 +348,7 @@ + self.logger.error("Set speed of %s failed." % self.interface) + + count = 500 +- cmd = "ping -q -c %d -i 0 %s | grep 'packet loss' | awk '{print $6}'" % ( ++ cmd = "ping -q -c %d -i 0.001 %s | grep 'packet loss' | awk '{print $6}'" % ( + count, self.server_ip) + for _ in range(self.retries): + result = self.command.run_cmd(cmd, ignore_errors=True) +diff -Naur rpm/tests/compatible/dpdk/Makefile oech/tests/compatible/dpdk/Makefile +--- rpm/tests/compatible/dpdk/Makefile 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/dpdk/Makefile 2024-04-16 18:08:37.760536817 +0800 +@@ -17,7 +17,7 @@ + + install: + mkdir -p $(DEST) +- cp -a $(SUBDIR)/build *.py $(DEST) ++ cp -a *.py $(DEST) + chmod a+x $(DEST)/*.py + + clean: +diff -Naur rpm/tests/compatible/gpu/nvidia_gpu.py oech/tests/compatible/gpu/nvidia_gpu.py +--- rpm/tests/compatible/gpu/nvidia_gpu.py 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/gpu/nvidia_gpu.py 2024-04-16 18:08:37.760536817 +0800 +@@ -15,6 +15,7 @@ + import os + import re + import time ++import platform + from subprocess import getstatusoutput + gpu_dir = os.path.dirname(os.path.realpath(__file__)) + +@@ -27,6 +28,9 @@ + self.cuda_samples_log = os.path.join( + self.logger.logdir, 'cuda_samples.log') + self.gpu_burn = os.path.join(self.logger.logdir, 'gpu_burn.log') ++ self.gpu_clpeak_log = os.path.join(self.logger.logdir, 'gpu_clpeak.log') ++ self.gpu_nvidia_smi_log = os.path.join(self.logger.logdir, 'gpu_nvidia_smi.log') ++ self.gpu_vulkan_log = os.path.join(self.logger.logdir, 'gpu_vulkan.log') + self.smi_name = "nvidia-smi" + + def get_driver_info(self): +@@ -136,9 +140,21 @@ + self.logger.error("Test gpu pressure failed.") + result = False + ++ machine = platform.machine() ++ if machine == 'x86_64': ++ self.logger.info("Start to test clpeak.") ++ self.set_default_gpu() ++ code = self.command.run_cmd( ++ "bash %s/test_nvidia_gpu.sh test_clpeak '%s'" % (gpu_dir, self.gpu_clpeak_log)) ++ if code[2] == 0: ++ self.logger.info("Test clpeak succeed.") ++ else: ++ result = False ++ self.logger.error("Test clpeak failed.") ++ + self.logger.info("Start to test cuda samples.") + self.set_default_gpu() +- sample_case = "simpleOccupancy,bandwidthTest,p2pBandwidthLatencyTest,deviceQuery,clock" ++ sample_case = "simpleOccupancy,bandwidthTest,p2pBandwidthLatencyTest,deviceQuery,clock,cuda_maketest" + code = self.command.run_cmd( + "bash %s/test_nvidia_gpu.sh test_cuda_samples '%s %s'" % (gpu_dir, self.cuda_samples_log, sample_case)) + if code[2] == 0: +@@ -146,6 +162,29 @@ + else: + result = False + self.logger.error("Test cuda samples failed.") ++ ++ self.logger.info("Start to test nvidia driver using nvidia-smi tool.") ++ self.set_default_gpu() ++ code = self.command.run_cmd( ++ "bash %s/test_nvidia_gpu.sh test_nvidia_smi '%s'" % (gpu_dir, self.gpu_nvidia_smi_log)) ++ if code[2] == 0: ++ self.logger.info("Using nvidia-smi to test Drvier succeed.") ++ else: ++ result = False ++ self.logger.error("Using nvidia-smi to test Drvier failed.") ++ ++ env_display = os.getenv('DISPLAY') ++ if env_display != '': ++ self.logger.info("Start to test Vulkan.") ++ self.set_default_gpu() ++ code = self.command.run_cmd( ++ "bash %s/test_nvidia_gpu.sh test_VulkanSamples '%s'" % (gpu_dir, self.gpu_vulkan_log)) ++ if code[2] == 0: ++ self.logger.info("Test Vulkan succeed.") ++ else: ++ result = False ++ self.logger.error("Test Vulkan failed.") ++ + except Exception as e: + self.logger.error( + "Failed to run the script because compiling or setting variables: %s" % e) +diff -Naur rpm/tests/compatible/gpu/test_nvidia_gpu.sh oech/tests/compatible/gpu/test_nvidia_gpu.sh +--- rpm/tests/compatible/gpu/test_nvidia_gpu.sh 2024-04-16 18:17:05.014569227 +0800 ++++ oech/tests/compatible/gpu/test_nvidia_gpu.sh 2024-04-16 18:08:37.760536817 +0800 +@@ -15,6 +15,25 @@ + cuda_version=$(nvidia-smi -q | grep "CUDA Version" | awk '{print $4}') + cuda_name="cuda-samples-${cuda_version}" + ++function install_clpeak() { ++ cd /opt ++ res_code=0 ++ if [ ! -d clpeak ]; then ++ git clone https://gitee.com/shangbaogen/clpeak.git ++ fi ++ cd clpeak ++ git checkout 1.1.2 &>/dev/null ++ if [ ! -d build ]; then ++ mkdir build ++ fi ++ cd build ++ if [ ! -d sdk_install ]; then ++ cmake .. &>/dev/null || res_code=1 ++ fi ++ cmake --build . &>/dev/null || res_code=1 ++ return $res_code ++} ++ + function install_gpu_burn() { + cd /opt + res_code=0 +@@ -50,15 +69,40 @@ + return 0 + } + ++function install_VulkanSamples() { ++ cd /opt ++ res_code=0 ++ if [ ! -d VulkanSamples ]; then ++ git clone https://github.com/LunarG/VulkanSamples.git ++ fi ++ cd VulkanSamples ++ if [ ! -d build ]; then ++ mkdir build ++ cd build ++ sed -i 's/python/python3/g' ../scripts/update_deps.py ++ chmod +x ../scripts/update_deps.py ++ ../scripts/update_deps.py &>/dev/null || res_code=1 ++ cmake -C helper.cmake .. &>/dev/null || res_code=1 ++ cmake --build . &>/dev/null || res_code=1 ++ fi ++ return $res_code ++} ++ + function test_nvidia_case() { + casename=$1 + logfile=$2 + res_code=0 + cd /opt/${cuda_name} +- path=$(find ./ -name $casename -type d) +- cd $path + make &>/dev/null +- ./$casename &>>$logfile ++ ++ if [[ $casename == 'cuda_maketest' ]];then ++ make test &>>$logfile ++ else ++ path=$(find ./ -name $casename -type d) ++ cd $path ++ ./$casename &>>$logfile ++ fi ++ + if [[ $? -eq 0 ]]; then + echo "Test $casename succeed." >>$logfile + else +@@ -116,6 +160,98 @@ + return $res_code + } + ++function test_clpeak() { ++ logfile=$1 ++ res_code=0 ++ install_clpeak ++ if [[ $? -eq 1 ]]; then ++ echo "Install clpeak failed." ++ res_code=1 ++ return $res_code ++ fi ++ /opt/clpeak/build/clpeak &> $logfile ++ if [[ $? -eq 0 ]]; then ++ echo "Test clpeak succeed." ++ res_code=0 ++ else ++ echo "Test clpeak failed." ++ res_code=1 ++ fi ++ return $res_code ++} ++ ++sm_clock=`nvidia-smi -q|grep "SM "|head -n 1|cut -d ':' -f 2|awk '{print $1}'` ++memory_clock=`nvidia-smi -q -d SUPPORTED_CLOCKS|grep Memory|head -n 1|cut -d ':' -f 2|awk '{print $1}'` ++min_power_limit=`nvidia-smi -q|grep "Min Power Limit"|head -n 1|cut -d ':' -f 2|awk '{print $1}'` ++max_power_limit=`nvidia-smi -q|grep "Max Power Limit"|head -n 1|cut -d ':' -f 2|awk '{print $1}'` ++ ++allcases="nvidia-smi; \ ++ nvidia-smi -L; \ ++ nvidia-smi -q; \ ++ nvidia-smi -q -d SUPPORTED_CLOCKS; \ ++ nvidia-smi topo --matrix; \ ++ nvidia-smi -pm 0; \ ++ nvidia-smi -pm 1; \ ++ nvidia-smi -e 0; \ ++ nvidia-smi -e 1; \ ++ nvidia-smi -p 0; \ ++ nvidia-smi -p 1; \ ++ nvidia-smi -c 0; \ ++ nvidia-smi -c 2; \ ++ nvidia-smi -c 3; \ ++ nvidia-smi -pl $min_power_limit; \ ++ nvidia-smi -pl $max_power_limit; \ ++ nvidia-smi -ac $memory_clock,$sm_clock; \ ++ nvidia-smi -am 1; \ ++ nvidia-smi -am 0; \ ++ nvidia-smi -caa; \ ++ nvidia-smi -r; \ ++" ++ ++function test_nvidia_smi() { ++ logfile=$1 ++ IFS_OLD=$IFS ++ IFS=$';' ++ res_code=0 ++ for casename in ${allcases[@]}; do ++ eval $casename ++ if [[ $? -eq 1 ]]; then ++ res_code=1 ++ fi ++ done ++ IFS=${IFS_OLD} ++ return $res_code ++} ++ ++function test_VulkanSamples() { ++ logfile=$1 ++ res_code=0 ++ install_VulkanSamples ++ if [[ $? -eq 1 ]]; then ++ echo "Install VulkanSamples failed." ++ res_code=1 ++ return $res_code ++ fi ++ source ~/.bash_profile ++ if [ -n "$DISPLAY" ]; then ++ timeout 5s /opt/VulkanSamples/build/Sample-Programs/Hologram/Hologram &> $logfile ++ cd /opt/VulkanSamples/build/API-Samples/ ++ ./run_all_samples.sh &>> $logfile ++ if [[ $? -eq 0 ]]; then ++ echo "Test VulkanSamples succeed." ++ res_code=0 ++ else ++ echo "Test VulkanSamples failed." ++ res_code=1 ++ fi ++ else ++ echo "Please set the DISPLAY environment variables!" ++ res_code=1 ++ fi ++ return $res_code ++ ++} ++ + function main() { + func_name=$1 + param_list=$2 +@@ -126,6 +262,12 @@ + install_cuda_samples + elif [[ $func_name == "test_cuda_samples" ]]; then + test_cuda_samples $param_list ++ elif [[ $func_name == "test_clpeak" ]]; then ++ test_clpeak $param_list ++ elif [[ $func_name == "test_nvidia_smi" ]]; then ++ test_nvidia_smi $param_list ++ elif [[ $func_name == "test_VulkanSamples" ]]; then ++ test_VulkanSamples $param_list + else + echo "The function doesn't exist, please check!" + return 1 +diff -Naur rpm/tests/compatible/kabiwhitelist/kabi_check.sh oech/tests/compatible/kabiwhitelist/kabi_check.sh +--- rpm/tests/compatible/kabiwhitelist/kabi_check.sh 2024-04-16 18:17:05.018569275 +0800 ++++ oech/tests/compatible/kabiwhitelist/kabi_check.sh 2024-04-16 18:08:37.760536817 +0800 +@@ -11,8 +11,8 @@ + # Author: @liqiang1118 + # Create: 2023-05-15 + +-mkdir /usr/share/oech/lib/tests/kabiwhitelist/test_log +-testdir="/usr/share/oech/lib/tests/kabiwhitelist/test_log" ++mkdir /usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log ++testdir="/usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log" + cd $testdir + + os_version=`cat /etc/openEuler-latest|grep openeulerversion |awk -F = '{print $2}'` +@@ -21,8 +21,8 @@ + wget $url + kernel_version=`uname -r` + symvers_gz="symvers-"$kernel_version".gz" +-cp /boot/$symvers_gz /usr/share/oech/lib/tests/kabiwhitelist/test_log +-gunzip /usr/share/oech/lib/tests/kabiwhitelist/test_log/$symvers_gz ++cp /boot/$symvers_gz /usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log ++gunzip /usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log/$symvers_gz + + # Desc: Test kabi + # Input: xxx.ko or xxx.rpm +diff -Naur rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py oech/tests/compatible/kabiwhitelist/kabiwhitelist.py +--- rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py 2024-04-16 18:17:05.018569275 +0800 ++++ oech/tests/compatible/kabiwhitelist/kabiwhitelist.py 2024-04-16 18:08:37.760536817 +0800 +@@ -58,7 +58,7 @@ + """ + Clear temporary files + """ +- file_name = "/usr/share/oech/lib/tests/kabiwhitelist/test_log" ++ file_name = "/usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log" + if os.path.exists(file_name): + shutil.rmtree(file_name) + self.logger.info("Clearing temporary files is complete") +diff -Naur rpm/tests/compatible/kabiwhitelist/Makefile oech/tests/compatible/kabiwhitelist/Makefile +--- rpm/tests/compatible/kabiwhitelist/Makefile 2024-04-16 18:17:05.018569275 +0800 ++++ oech/tests/compatible/kabiwhitelist/Makefile 2024-04-16 18:08:37.760536817 +0800 +@@ -17,8 +17,8 @@ + + install: + mkdir -p $(DEST) +- cp -a $(SUBDIR)/build *.py $(DEST) +- cp -a $(SUBDIR)/build *.sh $(DEST) ++ cp -a *.py $(DEST) ++ cp -a *.sh $(DEST) + chmod a+x $(DEST)/*.py + chmod a+x $(DEST)/*.sh + +diff -Naur rpm/tests/compatible/keycard/keycard.py oech/tests/compatible/keycard/keycard.py +--- rpm/tests/compatible/keycard/keycard.py 2024-04-16 18:17:05.018569275 +0800 ++++ oech/tests/compatible/keycard/keycard.py 2024-04-16 18:08:37.760536817 +0800 +@@ -13,58 +13,40 @@ + # Create: 2022-03-28 + # Desc: Public key card test + +-import os +-import shutil ++import argparse ++from sds_keycard import SDSKeyCardTest ++from tsse_keycard import TSSEKeyCardTest + from hwcompatible.test import Test +-from hwcompatible.command_ui import CommandUI +- +-keycard_dir = os.path.dirname(os.path.realpath(__file__)) + + + class KeyCardTest(Test): + def __init__(self): + Test.__init__(self) +- self.com_ui = CommandUI() +- self.target_file = "/usr/lib64/libswsds.so" ++ self.device = None ++ self.keycard_test = None ++ ++ def setup(self, args=None): ++ """ ++ Initialization before test ++ """ ++ self.args = args or argparse.Namespace() ++ self.device = getattr(args, 'device', None) ++ if self.device.driver == "tsse": ++ self.keycard_test = TSSEKeyCardTest() ++ else: ++ self.keycard_test = SDSKeyCardTest() ++ self.keycard_test.setup(args) + + def test(self): + """ + Run key card test case + return: result + """ +- result = True +- original_file = os.path.join(keycard_dir, "libswsds.so") +- shutil.copy(original_file, self.target_file) +- ui_message_list = [ +- "Which test suite would you like to test: ", +- "1|基本函数测试", +- "2|RSA非对称密码运算函数测试", +- "3|ECC非对称密码运算函数测试", +- "4|对称密码运算函数测试", +- "5|杂凑运算函数测试", +- "6|用户文件操作函数测试", +- "Enter space to split(ex: 1 2 3)\n" +- ] +- ui_message = "\n".join(ui_message_list) +- execnum = self.com_ui.prompt(ui_message) +- self.logger.info("Start to test, please wait.") +- execnum = execnum.split(" ") +- for num in execnum: +- result = self.command.run_cmd( +- "echo %s | %s/TestSDS" % (num, keycard_dir)) +- if result[2] != 0: +- result = False ++ return self.keycard_test.test() + +- if result: +- self.logger.info("Test key card succeed.") +- else: +- self.logger.error("Test key card failed.") +- return result +- + def teardown(self): + """ + Environment recovery after test + :return: + """ +- if os.path.exists(self.target_file): +- os.remove(self.target_file) +\ No newline at end of file ++ self.keycard_test.teardown() +\ No newline at end of file +diff -Naur rpm/tests/compatible/keycard/Makefile oech/tests/compatible/keycard/Makefile +--- rpm/tests/compatible/keycard/Makefile 2024-04-16 18:17:05.030569417 +0800 ++++ oech/tests/compatible/keycard/Makefile 2024-04-16 18:08:37.760536817 +0800 +@@ -27,6 +27,8 @@ + cp -a *.py $(DEST) + cp $(APPS) $(DEST) + chmod a+x $(DEST)/*.py ++ cp -a *.sh $(DEST) ++ chmod a+x $(DEST)/*.sh + + %.o:%.c + $(CC) -O2 -c $(CFLAGS) $< -o $@ +diff -Naur rpm/tests/compatible/keycard/sds_keycard.py oech/tests/compatible/keycard/sds_keycard.py +--- rpm/tests/compatible/keycard/sds_keycard.py 1970-01-01 08:00:00.000000000 +0800 ++++ oech/tests/compatible/keycard/sds_keycard.py 2024-04-16 18:08:37.772536959 +0800 +@@ -0,0 +1,79 @@ ++#!/usr/bin/env python3 ++# coding: utf-8 ++# Copyright (c) 2022 Huawei Technologies Co., Ltd. ++# oec-hardware is licensed under the Mulan PSL v2.gica's ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++# Author: @meitingli ++# Create: 2022-03-28 ++# Desc: Public key card test ++ ++import argparse ++import os ++import shutil ++from hwcompatible.command import Command ++from hwcompatible.test import Test ++from hwcompatible.command_ui import CommandUI ++ ++keycard_dir = os.path.dirname(os.path.realpath(__file__)) ++ ++ ++class SDSKeyCardTest(Test): ++ def __init__(self): ++ Test.__init__(self) ++ self.com_ui = None ++ self.target_file = "" ++ ++ def setup(self, args=None): ++ self.args = args or argparse.Namespace() ++ self.logger = getattr(args, "test_logger", None) ++ self.command = Command(self.logger) ++ self.com_ui = CommandUI() ++ self.target_file = "/usr/lib64/libswsds.so" ++ ++ def test(self): ++ """ ++ Run key card test case ++ return: result ++ """ ++ ret_val = True ++ original_file = os.path.join(keycard_dir, "libswsds.so") ++ shutil.copy(original_file, self.target_file) ++ ui_message_list = [ ++ "Which test suite would you like to test: ", ++ "1|基本函数测试", ++ "2|RSA非对称密码运算函数测试", ++ "3|ECC非对称密码运算函数测试", ++ "4|对称密码运算函数测试", ++ "5|杂凑运算函数测试", ++ "6|用户文件操作函数测试", ++ "Enter space to split(ex: 1 2 3)\n" ++ ] ++ ui_message = "\n".join(ui_message_list) ++ execnum = self.com_ui.prompt(ui_message) ++ self.logger.info("Start to test, please wait.") ++ execnum = execnum.split(" ") ++ for num in execnum: ++ result = self.command.run_cmd( ++ "echo %s | %s/TestSDS" % (num, keycard_dir)) ++ if result[2] != 0: ++ ret_val = False ++ ++ if ret_val: ++ self.logger.info("Test key card succeed.") ++ else: ++ self.logger.error("Test key card failed.") ++ return ret_val ++ ++ def teardown(self): ++ """ ++ Environment recovery after test ++ :return: ++ """ ++ if os.path.exists(self.target_file): ++ os.remove(self.target_file) +\ No newline at end of file +diff -Naur rpm/tests/compatible/keycard/test_tsse_keycard.sh oech/tests/compatible/keycard/test_tsse_keycard.sh +--- rpm/tests/compatible/keycard/test_tsse_keycard.sh 1970-01-01 08:00:00.000000000 +0800 ++++ oech/tests/compatible/keycard/test_tsse_keycard.sh 2024-04-16 18:08:37.772536959 +0800 +@@ -0,0 +1,40 @@ ++#!/usr/bin/bash ++# Copyright (c) 2024 Montage Technology. ++# oec-hardware is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++# Create: 2024-03-20 ++# Desc: Shell script used for testing tsse keycard ++ ++function main() { ++ res_code=0 ++ cd /opt ++ if [ ! -f openssl-3.1.5.tar.gz ]; then ++ wget https://www.openssl.org/source/openssl-3.1.5.tar.gz ++ fi ++ if [ ! -d openssl-3.1.5 ]; then ++ tar -xvzf openssl-3.1.5.tar.gz -C . &>/dev/null ++ fi ++ if [ ! -d /opt/local/ssl ]; then ++ cd openssl-3.1.5 ++ ./Configure --prefix=/opt/local/ssl --openssldir=/opt/local/ssl ++ echo "doing make and make install ..." ++ make &>/dev/null || res_code=1 ++ make install &>/dev/null || res_code=1 ++ echo "make and make install completed" ++ fi ++ if [ ! -f /usr/lib64/libssl.so.3 ]; then ++ ln -s /opt/local/ssl/lib64/libssl.so.3 /usr/lib64/libssl.so.3 ++ fi ++ if [ ! -f /usr/lib64/libcrypto.so.3 ]; then ++ ln -s /opt/local/ssl/lib64/libcrypto.so.3 /usr/lib64/libcrypto.so.3 ++ fi ++ return $res_code ++} ++ ++main "$@" +\ No newline at end of file +diff -Naur rpm/tests/compatible/keycard/tsse_keycard.py oech/tests/compatible/keycard/tsse_keycard.py +--- rpm/tests/compatible/keycard/tsse_keycard.py 1970-01-01 08:00:00.000000000 +0800 ++++ oech/tests/compatible/keycard/tsse_keycard.py 2024-04-16 18:08:37.772536959 +0800 +@@ -0,0 +1,89 @@ ++#!/usr/bin/env python3 ++# coding: utf-8 ++ ++# Copyright (c) 2024 Montage Technology. ++# oec-hardware is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++# Create: 2024-03-20 ++ ++import argparse ++import ssl ++import os ++from hwcompatible.command import Command ++from hwcompatible.test import Test ++ ++local_openssl_dir = os.path.dirname(os.path.realpath(__file__)) ++ ++ ++class TSSEKeyCardTest(Test): ++ def __init__(self): ++ Test.__init__(self) ++ self.device = None ++ ++ def setup(self, args=None): ++ """ ++ Initialization before test ++ :return: ++ """ ++ self.args = args or argparse.Namespace() ++ self.logger = getattr(self.args, "test_logger", None) ++ self.command = Command(self.logger) ++ self.device = getattr(self.args, 'device', None) ++ self.show_driver_info() ++ ++ def test(self): ++ """ ++ Run openssl ++ return: result ++ """ ++ ret = True ++ version = ssl.OPENSSL_VERSION_INFO ++ system_openssl = True ++ ++ if version < (3, 0): ++ self.logger.info("System openssl version is less than 3.0, will install a new one.") ++ system_openssl = False ++ result = self.command.run_cmd( ++ "bash {}/test_tsse_keycard.sh".format(local_openssl_dir)) ++ if result[2] != 0: ++ self.logger.error("failed to install new openssl.") ++ return False ++ else: ++ out = self.command.run_cmd("/opt/local/ssl/bin/openssl version -m") ++ self.logger.info(out[0]) ++ else: ++ out = self.command.run_cmd("openssl version -m") ++ self.logger.info(out[0]) ++ self.logger.info("Please make sure the provider shared object file of Mont-TSSE exists in MODULESDIR") ++ ++ algorithms = ["aes-128-gcm", "aes-256-gcm", "sha256", "sha384", "sha512", ++ "sm3", "sm4-cbc", "sm4-gcm", "sm2"] ++ if system_openssl: ++ cmd_format = "openssl speed -provider {} -elapsed {}{}" ++ else: ++ cmd_format = "/opt/local/ssl/bin/openssl speed -provider {} -elapsed {}{}" ++ ++ for alg in algorithms: ++ if (alg == "sm2"): ++ cmd = cmd_format.format("mcpprovider", "", alg) ++ else: ++ cmd = cmd_format.format("mcpprovider", "-evp ", alg) ++ result = self.command.run_cmd(cmd) ++ if result[2] != 0: ++ self.logger.error("openssl {} failed.".format(alg)) ++ self.logger.error(result[1]) ++ ret = False ++ else: ++ self.logger.info("openssl {} succeed.".format(alg)) ++ ++ if ret: ++ self.logger.info("Test OpenSSL succeed.") ++ else: ++ self.logger.error("Test OpenSSL failed.") ++ return ret +\ No newline at end of file +diff -Naur rpm/tests/compatible/memory/memory.py oech/tests/compatible/memory/memory.py +--- rpm/tests/compatible/memory/memory.py 2024-04-16 18:17:05.030569417 +0800 ++++ oech/tests/compatible/memory/memory.py 2024-04-16 18:08:37.772536959 +0800 +@@ -131,7 +131,7 @@ + self.command.run_cmd("sysctl -w vm.panic_on_oom=1") + self.logger.info("set the system not to restart.") + if self.swap_memory < 4096: +- self.logger.error("Swap memory of %s MB is too small. Suggest configuring to 4G." ++ self.logger.error("Swap memory of %s MB is too small. Suggest configuring to 10G." + % self.swap_memory) + return False + extra_mem = self.free_memory/100 +diff -Naur rpm/tests/compatible/network/network.py oech/tests/compatible/network/network.py +--- rpm/tests/compatible/network/network.py 2024-04-16 18:17:05.030569417 +0800 ++++ oech/tests/compatible/network/network.py 2024-04-16 18:08:37.772536959 +0800 +@@ -196,7 +196,7 @@ + :return: + """ + count = 500 +- cmd = "ping -q -c %d -i 0 %s | grep 'packet loss' | awk '{print $6}'" % ( ++ cmd = "ping -q -c %d -i 0.001 %s | grep 'packet loss' | awk '{print $6}'" % ( + count, self.server_ip) + for _ in range(self.retries): + result = self.command.run_cmd(cmd) +diff -Naur rpm/tests/compatible/nvme/nvme.py oech/tests/compatible/nvme/nvme.py +--- rpm/tests/compatible/nvme/nvme.py 2024-04-16 18:17:05.030569417 +0800 ++++ oech/tests/compatible/nvme/nvme.py 2024-04-16 18:08:37.772536959 +0800 +@@ -19,6 +19,7 @@ + from subprocess import getoutput + from hwcompatible.test import Test + from hwcompatible.command import Command ++from tests.compatible.disk.common import raw_test + + + class NvmeTest(Test): +@@ -95,6 +96,11 @@ + return_code = False + + self.command.run_cmd("nvme list", ignore_errors=True) ++ ++ # run fio ++ if not raw_test(self.logger, self.command, disk): ++ return_code = False ++ + if return_code: + self.logger.info("Test nvme succeed.") + else: +diff -Naur rpm/tests/compatible/system/system.py oech/tests/compatible/system/system.py +--- rpm/tests/compatible/system/system.py 2024-04-16 18:17:05.034569465 +0800 ++++ oech/tests/compatible/system/system.py 2024-04-16 18:08:37.772536959 +0800 +@@ -90,6 +90,10 @@ + os_version = self.sysinfo.product + " " + self.sysinfo.get_version() + elif product == "KylinSec": + os_version = getoutput("cat /etc/dnf/vars/osversion | sed 's/[^0-9]//g'") ++ elif product == "Kylin": ++ os_version = getoutput("cat /etc/os-release | grep -i version_id | awk -F = '{print $2}' | sed 's/[\"]//g'") ++ elif product == "UOS": ++ os_version = getoutput("cat /etc/os-release | grep -i version_id | awk -F = '{print $2}' | sed 's/[\"]//g'") + else: + self.logger.error("Failed to get os version info.") + self.logger.info("OS Version: %s" % os_version, terminal_print=False) +@@ -107,6 +111,10 @@ + kernel_release = kernel_dict.document[product][os_version] + elif product == "KylinSec": + kernel_release = kernel_dict.document[product][os_version].split('/')[1].split('-')[0] ++ elif product == "Kylin": ++ kernel_release = kernel_dict.document[product][os_version].split('/')[1].split('-')[0] ++ elif product == "UOS": ++ kernel_release = kernel_dict.document[product][os_version].split('/')[1].split('-')[0] + try: + if kernel_release != self.sysinfo.kernel_version: + self.logger.error("Failed to check kernel %s GA status." % +diff -Naur rpm/tests/virtualization/Makefile oech/tests/virtualization/Makefile +--- rpm/tests/virtualization/Makefile 2024-04-16 18:17:05.054569703 +0800 ++++ oech/tests/virtualization/Makefile 2024-04-16 18:08:37.772536959 +0800 +@@ -13,7 +13,7 @@ + .PHONY: all clean install + + HWCERT_TEST_LIB := $(DESTDIR)/usr/share/oech/lib/tests/virtualization +-SUBDIRS := $(shell ls | grep -v Makefile) ++SUBDIRS := $(shell ls | grep -v "Makefile\|stratovirt.xml\|__init__.py\|console_cmd.sh\|qemu.xml") + + all: + for i in $(SUBDIRS); do $(MAKE) -C $$i; done diff --git a/oec-hardware.spec b/oec-hardware.spec index 067c7e9..769b723 100644 --- a/oec-hardware.spec +++ b/oec-hardware.spec @@ -4,7 +4,7 @@ Name: oec-hardware Summary: openEuler Hardware Compatibility Test Suite Version: 1.1.5 -Release: 1 +Release: 2 Group: Development/Tools License: Mulan PSL v2 URL: https://gitee.com/openeuler/oec-hardware @@ -12,6 +12,7 @@ Source0: https://gitee.com/openeuler/oec-hardware/repository/archive/v%{v # patch fix issue Patch0001: oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch +Patch0002: oec-hardware-1.1.5-2-fix-bug.patch Buildroot: %{_tmppath}/%{name}-%{version}-root BuildRequires: gcc @@ -36,6 +37,7 @@ openEuler Hardware Compatibility Test Server %prep %setup -q -c %patch1 -p1 +%patch2 -p1 %build %ifarch x86_64 aarch64 @@ -80,6 +82,14 @@ DESTDIR=$RPM_BUILD_ROOT make install rm -rf /var/lock/oech.lock %changelog +* Wed Nov 29 2023 cuixucui - 1.1.5-1 +- Resolve kdump\watchdog\cpufreq\kabiwhitelist\network test failure issue +- Add fio test cases:read,write,randread,randwrite +- Solve the nvme line break issue in the command line interface +- Fix compilation errors in the make command +- Add Vulkan testcase for nvida GPU +- Resolve the issue of oech server startup failure on version 24.03 + * Wed Nov 29 2023 cuixucui - 1.1.5-1 - Add virtual cases - Resolve IB startup IB_Read_BW service failure issue From d7a64ec4bf97eb23e5e7e1e94ff6e3036b27065f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alwill=20Xiao=28=E8=82=96=E4=BC=A0=E6=A5=A0=29?= Date: Tue, 4 Jun 2024 16:59:56 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug=E5=92=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit cea434bf15e535988b2fdf034fea85069ab2aab6) --- ....5-3-functional-optimization-fix-bug.patch | 82 +++++++++++++++++++ oec-hardware.spec | 16 +++- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch diff --git a/oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch b/oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch new file mode 100644 index 0000000..170461d --- /dev/null +++ b/oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch @@ -0,0 +1,82 @@ +diff -Naur rpm/tests/compatible/kabi/kabi.py oech/tests/compatible/kabi/kabi.py +--- rpm/tests/compatible/kabi/kabi.py 2024-06-04 15:27:10.013346551 +0800 ++++ oech/tests/compatible/kabi/kabi.py 2024-06-04 15:30:53.001506902 +0800 +@@ -121,8 +121,8 @@ + if product == "openEuler": + standard_kernel_version = getoutput( + "dnf list --repo=source | grep '^kernel.src' | awk '{print $2}'") +- self.command.run_cmd("dnf download --source kernel-%s" +- % standard_kernel_version) ++ self.command.run_cmd("dnf download --source kernel-%s --downloaddir %s" ++ % (standard_kernel_version, rpmpath)) + elif product == "KylinSec": + kylinsec_version = getoutput("cat /etc/dnf/vars/osversion | sed 's/[^0-9]//g'") + kernel_dict = Document(CertEnv.kernelinfo, self.logger) +@@ -138,7 +138,7 @@ + self.logger.info("Currently, this system is not supported to test kabi," + " Please add the corresponding system in kernelrelease.json.") + +- rpm = os.path.join("kernel-" + standard_kernel_version + ".src.rpm") ++ rpm = os.path.join(rpmpath, "kernel-" + standard_kernel_version + ".src.rpm") + getoutput("rpm -ivh %s" % rpm) + os.remove(rpm) + return standard_symvers +diff -Naur rpm/tests/compatible/kabiwhitelist/kabi_check.sh oech/tests/compatible/kabiwhitelist/kabi_check.sh +--- rpm/tests/compatible/kabiwhitelist/kabi_check.sh 2024-06-04 15:27:10.013346551 +0800 ++++ oech/tests/compatible/kabiwhitelist/kabi_check.sh 2024-06-04 15:29:30.189447349 +0800 +@@ -19,6 +19,10 @@ + arch=`uname -m` + url="https://gitee.com/src-openeuler/kernel/raw/$os_version/kabi_whitelist_$arch" + wget $url ++# if get kabi_whitelist failed because of internet or other ++if [ ! -f $testdir"/kabi_whitelist_"$arch ]; then ++ cp /root/kabi_whitelist_$arch $testdir/ ++fi + kernel_version=`uname -r` + symvers_gz="symvers-"$kernel_version".gz" + cp /boot/$symvers_gz /usr/share/oech/lib/tests/compatible/kabiwhitelist/test_log +@@ -103,6 +107,9 @@ + if [ -f /root/$line ]; then + cp /root/$line ./ + echo $line >> dirth ++ else ++ echo "no ko or rpm file" >> nofile.txt ++ exit 0 + fi + done + cat dirth|while read line; +diff -Naur rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py oech/tests/compatible/kabiwhitelist/kabiwhitelist.py +--- rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py 2024-06-04 15:27:10.013346551 +0800 ++++ oech/tests/compatible/kabiwhitelist/kabiwhitelist.py 2024-06-04 15:30:38.354496369 +0800 +@@ -46,6 +46,10 @@ + if ko_result[2] == 0: + self.logger.error("Please configure the board information in the configuration file") + return False ++ ko_file_result = self.command.run_cmd("ls %s/test_log/ | grep nofile" % kabi_whitelist_dir) ++ if ko_file_result[2] == 0: ++ self.logger.error("Please put ko or rpm file configured in the configuration file into the /root") ++ return False + self.logger.info("Ko or rpm check complete") + + test_result = self.command.run_cmd("ls %s/test_log | grep change" % kabi_whitelist_dir) +diff -Naur rpm/tests/compatible/system/system.py oech/tests/compatible/system/system.py +--- rpm/tests/compatible/system/system.py 2024-06-04 15:27:10.019346555 +0800 ++++ oech/tests/compatible/system/system.py 2024-06-04 15:32:25.527573326 +0800 +@@ -94,6 +94,8 @@ + os_version = getoutput("cat /etc/os-release | grep -i version_id | awk -F = '{print $2}' | sed 's/[\"]//g'") + elif product == "UOS": + os_version = getoutput("cat /etc/os-release | grep -i version_id | awk -F = '{print $2}' | sed 's/[\"]//g'") ++ elif self.sysinfo.product is not None and self.sysinfo.get_version() is not None: ++ os_version = self.sysinfo.product + " " + self.sysinfo.get_version() + else: + self.logger.error("Failed to get os version info.") + self.logger.info("OS Version: %s" % os_version, terminal_print=False) +@@ -115,6 +117,8 @@ + kernel_release = kernel_dict.document[product][os_version].split('/')[1].split('-')[0] + elif product == "UOS": + kernel_release = kernel_dict.document[product][os_version].split('/')[1].split('-')[0] ++ elif kernel_dict.document[product] is not None and kernel_dict.document[product][os_version] is not None: ++ kernel_release = kernel_dict.document[product][os_version] + try: + if kernel_release != self.sysinfo.kernel_version: + self.logger.error("Failed to check kernel %s GA status." % diff --git a/oec-hardware.spec b/oec-hardware.spec index 769b723..f941389 100644 --- a/oec-hardware.spec +++ b/oec-hardware.spec @@ -1,10 +1,12 @@ %global _build_id_links none %undefine __brp_mangle_shebangs +%define vendor %{?_vendor:%{_vendor}}%{!?_vendor:openEuler} +%define vendor_lowercase %{?_vendor:%(echo %{_vendor} | tr '[:upper:]' '[:lower:]')}%{!?_vendor:openeuler} Name: oec-hardware Summary: openEuler Hardware Compatibility Test Suite Version: 1.1.5 -Release: 2 +Release: 3 Group: Development/Tools License: Mulan PSL v2 URL: https://gitee.com/openeuler/oec-hardware @@ -13,6 +15,7 @@ Source0: https://gitee.com/openeuler/oec-hardware/repository/archive/v%{v # patch fix issue Patch0001: oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch Patch0002: oec-hardware-1.1.5-2-fix-bug.patch +Patch0003: oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch Buildroot: %{_tmppath}/%{name}-%{version}-root BuildRequires: gcc @@ -38,6 +41,7 @@ openEuler Hardware Compatibility Test Server %setup -q -c %patch1 -p1 %patch2 -p1 +%patch3 -p1 %build %ifarch x86_64 aarch64 @@ -51,6 +55,9 @@ DESTDIR=$RPM_BUILD_ROOT VERSION_RELEASE=%{version} make %install DESTDIR=$RPM_BUILD_ROOT make install +# Custom vendor +sed -i 's#grep openeulerversion /etc/openEuler-latest#grep %{vendor_lowercase}version /etc/%{vendor}-latest#g' %{buildroot}/usr/share/oech/lib/hwcompatible/cert_info.py + %clean [ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; @@ -82,6 +89,13 @@ DESTDIR=$RPM_BUILD_ROOT make install rm -rf /var/lock/oech.lock %changelog +* Tue Jun 4 2024 xiaochn - 1.1.5-3 +- Resolve the issue of different kernel source download locations in kabi test case +- Resolve the issue that kabiwhitelist still passes when the ko and rpm file does not exist +- Add the way for manually adding kabiwhitelist file +- For custom vendors, refer to the method of obtaining openEuler os information +- Supports custom vendor + * Wed Nov 29 2023 cuixucui - 1.1.5-1 - Resolve kdump\watchdog\cpufreq\kabiwhitelist\network test failure issue - Add fio test cases:read,write,randread,randwrite From 498998b927dc7698120b3dcbff4c333b61e0e981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alwill=20Xiao=28=E8=82=96=E4=BC=A0=E6=A5=A0=29?= Date: Fri, 7 Jun 2024 17:05:41 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E8=A7=A3=E5=86=B3gpu=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=A1=B9DISPLAY=E5=88=A4=E6=96=AD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 273617cf89de68f518f41a5568999a28e7d39b17) --- oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch | 12 ++++++++++++ oec-hardware.spec | 7 ++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch diff --git a/oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch b/oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch new file mode 100644 index 0000000..badc83f --- /dev/null +++ b/oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch @@ -0,0 +1,12 @@ +diff -Naur rpm/tests/compatible/gpu/nvidia_gpu.py oech/tests/compatible/gpu/nvidia_gpu.py +--- rpm/tests/compatible/gpu/nvidia_gpu.py 2024-06-07 16:37:44.542417257 +0800 ++++ oech/tests/compatible/gpu/nvidia_gpu.py 2024-06-07 16:38:57.149472108 +0800 +@@ -174,7 +174,7 @@ + self.logger.error("Using nvidia-smi to test Drvier failed.") + + env_display = os.getenv('DISPLAY') +- if env_display != '': ++ if env_display is not None and env_display != '': + self.logger.info("Start to test Vulkan.") + self.set_default_gpu() + code = self.command.run_cmd( diff --git a/oec-hardware.spec b/oec-hardware.spec index f941389..ae2d9ce 100644 --- a/oec-hardware.spec +++ b/oec-hardware.spec @@ -6,7 +6,7 @@ Name: oec-hardware Summary: openEuler Hardware Compatibility Test Suite Version: 1.1.5 -Release: 3 +Release: 4 Group: Development/Tools License: Mulan PSL v2 URL: https://gitee.com/openeuler/oec-hardware @@ -16,6 +16,7 @@ Source0: https://gitee.com/openeuler/oec-hardware/repository/archive/v%{v Patch0001: oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch Patch0002: oec-hardware-1.1.5-2-fix-bug.patch Patch0003: oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch +Patch0004: oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch Buildroot: %{_tmppath}/%{name}-%{version}-root BuildRequires: gcc @@ -42,6 +43,7 @@ openEuler Hardware Compatibility Test Server %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 %build %ifarch x86_64 aarch64 @@ -89,6 +91,9 @@ sed -i 's#grep openeulerversion /etc/openEuler-latest#grep %{vendor_lowercase}ve rm -rf /var/lock/oech.lock %changelog +* Fri Jun 7 2024 xiaochn - 1.1.5-4 +- Resolve the issue of executing Vulkan even if DISPLAY is not defined in the env + * Tue Jun 4 2024 xiaochn - 1.1.5-3 - Resolve the issue of different kernel source download locations in kabi test case - Resolve the issue that kabiwhitelist still passes when the ko and rpm file does not exist From 3afe5ee1295adb8ef590aa641dcbd5abbbf7637e Mon Sep 17 00:00:00 2001 From: "Shine.Wang" Date: Wed, 25 Sep 2024 15:51:47 +0800 Subject: [PATCH 4/8] update-v1.1.6 --- ...e-1.1.5-1-add-virtual-branch-fix-bug.patch | 29904 ---------------- oec-hardware-1.1.5-2-fix-bug.patch | 1598 - ....5-3-functional-optimization-fix-bug.patch | 82 - ...ardware-1.1.5-4-fix-gpu-testcase-bug.patch | 12 - oec-hardware.spec | 18 +- v1.1.5.tar.gz | Bin 1323184 -> 0 bytes v1.1.6.tar.gz | Bin 0 -> 9595113 bytes 7 files changed, 8 insertions(+), 31606 deletions(-) delete mode 100644 oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch delete mode 100644 oec-hardware-1.1.5-2-fix-bug.patch delete mode 100644 oec-hardware-1.1.5-3-functional-optimization-fix-bug.patch delete mode 100644 oec-hardware-1.1.5-4-fix-gpu-testcase-bug.patch delete mode 100644 v1.1.5.tar.gz create mode 100644 v1.1.6.tar.gz diff --git a/oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch b/oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch deleted file mode 100644 index e2b5a7e..0000000 --- a/oec-hardware-1.1.5-1-add-virtual-branch-fix-bug.patch +++ /dev/null @@ -1,29904 +0,0 @@ -diff -Naur rpm/config/test_config.yaml oech/config/test_config.yaml ---- rpm/config/test_config.yaml 2023-10-24 22:25:50.000000000 +0800 -+++ oech/config/test_config.yaml 2023-12-07 15:01:42.217942181 +0800 -@@ -1,75 +1,75 @@ --# Copyright (c) 2023 Huawei Technologies Co., Ltd. --# # oec-hardware is licensed under the Mulan PSL v2.gica's --# # You can use this software according to the terms and conditions of the Mulan PSL v2. --# # You may obtain a copy of Mulan PSL v2 at: --# # http://license.coscl.org.cn/MulanPSL2 --# # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# # PURPOSE. --# # See the Mulan PSL v2 for more details. --# # Author: --# # # Create: 2023-09-11 --# #device: fc\raid\ethernet\infiniband testcase need configuration, It is obtained from the OECH command line interface and --# needs to be enclosed in single quotation marks --#disk: fc\raid\disk testcase need configuration, The disk to be tested, such as sda; Or all, test all qualified disks. --#if_rdma: ethernet testcase need configuration, N means to test according to ordinary network card, y means to test according to RDMA card --#server_ip: ethernet\infiniband testcase need configuration. If the server port is modified, need to add the port number after the IP address. eg: 2.2.2.4:8090. --# User need to delete the ip manually which are configured by tool after testing. --#clent_ip: ethernet\infiniband testcase need configuration. IP to be configured for the client port --fc: -- fc1: -- device: '0000:03:00.0' -- disk: all -- fc2: -- device: '0000:03:00.1' -- disk: sda --raid: -- raid1: -- device: '0000:02:00.0' -- disk: all -- raid2: -- device: '0000:0a:00.1' -- disk: sdb --disk: all --ethernet: -- # IP has been manually configured, get server IP. -- eth1: -- device: enp125s0f0 -- if_rdma: N -- client_ip: -- server_ip: 2.2.2.4 -- # Configure the IP obtained here. -- eth2: -- device: enp125s0f1 -- if_rdma: N -- client_ip: 2.2.2.3 -- server_ip: 2.2.2.4 -- # The program automatically generates an IP address for IP configuration -- eth3: -- device: enp125s0f2 -- if_rdma: y -- client_ip: -- server_ip: --infiniband: -- # IP has been manually configured, get server IP. -- ib1: -- device: ibp1s0 -- client_ip: -- server_ip: 2.2.2.4 -- # Configure the IP obtained here. -- ib2: -- device: ibp1s0 -- client_ip: 2.2.2.3 -- server_ip: 2.2.2.4:8090 -- # The program automatically generates an IP address for IP configuration -- ib3: -- device: ibp1s0 -- client_ip: -- server_ip: --kabiwhitelist: -- ko1: -- ko_name: '' -- ko2: -- ko_name: '' -- rpm: -- rpm_name: '' -+# Copyright (c) 2023 Huawei Technologies Co., Ltd. -+# # oec-hardware is licensed under the Mulan PSL v2.gica's -+# # You can use this software according to the terms and conditions of the Mulan PSL v2. -+# # You may obtain a copy of Mulan PSL v2 at: -+# # http://license.coscl.org.cn/MulanPSL2 -+# # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# # PURPOSE. -+# # See the Mulan PSL v2 for more details. -+# # Author: -+# # # Create: 2023-09-11 -+# #device: fc\raid\ethernet\infiniband testcase need configuration, It is obtained from the OECH command line interface and -+# needs to be enclosed in single quotation marks -+#disk: fc\raid\disk testcase need configuration, The disk to be tested, such as sda; Or all, test all qualified disks. -+#if_rdma: ethernet testcase need configuration, N means to test according to ordinary network card, y means to test according to RDMA card -+#server_ip: ethernet\infiniband testcase need configuration. If the server port is modified, need to add the port number after the IP address. eg: 2.2.2.4:8090. -+# User need to delete the ip manually which are configured by virtualization after testing. -+#clent_ip: ethernet\infiniband testcase need configuration. IP to be configured for the client port -+fc: -+ fc1: -+ device: '0000:03:00.0' -+ disk: all -+ fc2: -+ device: '0000:03:00.1' -+ disk: sda -+raid: -+ raid1: -+ device: '0000:02:00.0' -+ disk: all -+ raid2: -+ device: '0000:0a:00.1' -+ disk: sdb -+disk: all -+ethernet: -+ # IP has been manually configured, get server IP. -+ eth1: -+ device: enp125s0f0 -+ if_rdma: N -+ client_ip: -+ server_ip: 2.2.2.4 -+ # Configure the IP obtained here. -+ eth2: -+ device: enp125s0f1 -+ if_rdma: N -+ client_ip: 2.2.2.3 -+ server_ip: 2.2.2.4 -+ # The program automatically generates an IP address for IP configuration -+ eth3: -+ device: enp125s0f2 -+ if_rdma: y -+ client_ip: -+ server_ip: -+infiniband: -+ # IP has been manually configured, get server IP. -+ ib1: -+ device: ibp1s0 -+ client_ip: -+ server_ip: 2.2.2.4 -+ # Configure the IP obtained here. -+ ib2: -+ device: ibp1s0 -+ client_ip: 2.2.2.3 -+ server_ip: 2.2.2.4:8090 -+ # The program automatically generates an IP address for IP configuration -+ ib3: -+ device: ibp1s0 -+ client_ip: -+ server_ip: -+kabiwhitelist: -+ ko1: -+ ko_name: '' -+ ko2: -+ ko_name: '' -+ rpm: -+ rpm_name: '' -diff -Naur rpm/hwcompatible/cert_info.py oech/hwcompatible/cert_info.py ---- rpm/hwcompatible/cert_info.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/cert_info.py 2023-12-07 15:01:42.221942234 +0800 -@@ -28,16 +28,17 @@ - self.logger = logger - self.command = command - -- def create_json(self, device): -+ def create_json(self, device_name, device): - """ - Create hardware information json - Args: -+ device_name: device name - device: hardware device - Returns: True/False - """ - if not device or not device.quad: - self.logger.warning( -- "The %s doesn't have quadruple information, couldn't get hardware." % device.name) -+ "The %s doesn't have quadruple information, couldn't get hardware." % device_name) - return False - - if device.quad in self.cert_quads: -@@ -49,7 +50,7 @@ - - self.logger.info( - "Please input sha256, driverSize, downloadLink for %s manually " -- "if you use outbox driver." % device.name) -+ "if you use outbox driver." % device_name) - - oec_json["vendorID"] = device.quad[0] - oec_json["deviceID"] = device.quad[1] -@@ -62,7 +63,7 @@ - oec_json["chipVendor"] = chip_vendor[0].strip("\n") - oec_json["boardModel"] = device.board - oec_json["chipModel"] = device.chip -- oec_json["type"] = device.name.upper() -+ oec_json["type"] = device_name.upper() - arch = self.command.run_cmd("uname -m", log_print=False) - oec_json["architecture"] = arch[0].strip("\n") - os_cmd = self.command.run_cmd( -diff -Naur rpm/hwcompatible/common.py oech/hwcompatible/common.py ---- rpm/hwcompatible/common.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/common.py 2023-12-07 15:01:42.221942234 +0800 -@@ -25,12 +25,13 @@ - from .command import Command - - --def create_test_suite(test_factory, logger, subtests_filter=None): -+def create_test_suite(test_factory, logger, category="compatible", subtests_filter=None): - """ - Create test suites for job testing - Args: - test_factory (list): total test factory - logger (Logger): logger object to record -+ category (str): test category - subtests_filter (list, optional): filter object. Defaults to None. - - Returns: -@@ -47,7 +48,7 @@ - test_suite.append(testcase) - test_name.append(test["name"]) - -- if test["name"] not in NODEVICE: -+ if category == "compatible" and test["name"] not in NODEVICE: - kabi_select = 1 - if "kabi" in test_name: - kabi_select = 0 -diff -Naur rpm/hwcompatible/compatibility.py oech/hwcompatible/compatibility.py ---- rpm/hwcompatible/compatibility.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/compatibility.py 2023-12-07 15:01:42.221942234 +0800 -@@ -30,7 +30,7 @@ - from .client import Client - from .common import create_test_suite, copy_pci, search_factory - from .constants import NODEVICE, GPU_DRIVER, IB, CDTYPES, KEYCARD_VENDORS, \ -- BOARD, VERSION, DRIVER, CHIP, DEVICE_INFO -+ BOARD, VERSION, DRIVER, CHIP, DEVICE_INFO, TEST_CATEGORY - - - class EulerCertification(): -@@ -47,17 +47,24 @@ - self.dir_name = None - self.logger = logger - self.command = Command(logger) -+ self.category = '' - - def run(self): - """ - Openeuler compatibility verification - :return: - """ -- self.logger.info( -- "The openEuler Hardware Compatibility Test Suite", log_print=False) -- copy_pci() -+ self._select_category() -+ if self.category == "virtualization": -+ self.logger.info( -+ "The openEuler Virtualization Test Suite") -+ elif self.category == "compatible": -+ self.logger.info( -+ "The openEuler Hardware Compatibility Test Suite") -+ copy_pci() -+ certdevice = CertDevice(self.logger) -+ - self.load() -- certdevice = CertDevice(self.logger) - - while True: - self.submit() -@@ -66,15 +73,17 @@ - self.logger.info("All cases are passed, test end.") - return True - -- oec_devices = certdevice.get_devices() -- self.devices = DeviceDocument(CertEnv.devicefile, self.logger, oec_devices) -- self.devices.save() -+ oec_devices = list() -+ if self.category == "compatible": -+ oec_devices = certdevice.get_devices() -+ self.devices = DeviceDocument(CertEnv.devicefile, self.logger, oec_devices) -+ self.devices.save() - test_factory = self.get_tests(oec_devices) - self.update_factory(test_factory) - if not self.choose_tests(): - return True - -- test_suite = create_test_suite(self.test_factory, self.logger) -+ test_suite = create_test_suite(self.test_factory, self.logger, self.category) - args = argparse.Namespace( - test_factory=self.test_factory, test_suite=test_suite) - job = Job(args) -@@ -116,6 +125,8 @@ - os.remove(CertEnv.certificationfile) - if os.path.exists(CertEnv.factoryfile): - os.remove(CertEnv.factoryfile) -+ if os.path.exists(CertEnv.virtfactoryfile): -+ os.remove(CertEnv.virtfactoryfile) - if os.path.exists(CertEnv.devicefile): - os.remove(CertEnv.devicefile) - self.logger.info("Clean compatibility test data succeed.") -@@ -134,7 +145,10 @@ - self.certification.new() - self.certification.save() - if not self.test_factory: -- factory_doc = FactoryDocument(CertEnv.factoryfile, self.logger) -+ if self.category == "virtualization": -+ factory_doc = FactoryDocument(CertEnv.virtfactoryfile, self.logger) -+ elif self.category == "compatible": -+ factory_doc = FactoryDocument(CertEnv.factoryfile, self.logger) - self.test_factory = factory_doc.get_factory() - - oec_id = self.certification.get_certify() -@@ -145,12 +159,12 @@ - self.certification.save() - - display_message = " %s: ".ljust(20) % name + version + "\n" \ -- " Compatibility Test ID: ".ljust(30) + oec_id + "\n" \ -- " Hardware Info: ".ljust(30) + hardware_info + "\n" \ -- " Product URL: ".ljust(30) + self.certification.get_url() + "\n" \ -- " OS Info: ".ljust(30) + self.certification.get_os() + "\n" \ -- " Kernel Info: ".ljust(30) + self.certification.get_kernel() + "\n" \ -- " Test Server: ".ljust(30) + self.certification.get_server() -+ " Compatibility Test ID: ".ljust(30) + oec_id + "\n" \ -+ " Hardware Info: ".ljust(30) + hardware_info + "\n" \ -+ " Product URL: ".ljust(30) + self.certification.get_url() + "\n" \ -+ " OS Info: ".ljust(30) + self.certification.get_os() + "\n" \ -+ " Kernel Info: ".ljust(30) + self.certification.get_kernel() + "\n" \ -+ " Test Server: ".ljust(30) + self.certification.get_server() - self.logger.info(display_message, log_print=False) - - def save(self, job): -@@ -162,10 +176,14 @@ - doc_dir = os.path.join(CertEnv.logdirectoy, job.job_id) - if not os.path.exists(doc_dir): - return -- FactoryDocument(CertEnv.factoryfile, self.logger, self.test_factory).save() -+ if self.category == "virtualization": -+ FactoryDocument(CertEnv.virtfactoryfile, self.logger, self.test_factory).save() -+ shutil.copy(CertEnv.virtfactoryfile, doc_dir) -+ else: -+ FactoryDocument(CertEnv.factoryfile, self.logger, self.test_factory).save() -+ shutil.copy(CertEnv.factoryfile, doc_dir) -+ shutil.copy(CertEnv.devicefile, doc_dir) - shutil.copy(CertEnv.certificationfile, doc_dir) -- shutil.copy(CertEnv.devicefile, doc_dir) -- shutil.copy(CertEnv.factoryfile, doc_dir) - - cwd = os.getcwd() - os.chdir(os.path.dirname(doc_dir)) -@@ -173,13 +191,13 @@ - + "-" + job.job_id - pack_name = self.dir_name + ".tar" - os.rename(job.job_id, self.dir_name) -- -+ - cmd_result = self.command.run_cmd( - "tar -cf %s --exclude '*.lock' %s" % (pack_name, self.dir_name), log_print=False) - if cmd_result[2] != 0: - self.logger.error("Collect job log failed.") - return -- -+ - self.logger.info("Log saved to file: %s succeed." % - os.path.join(os.getcwd(), pack_name)) - shutil.copy(pack_name, CertEnv.datadirectory) -@@ -234,45 +252,58 @@ - self.client = Client(hardware_info, oec_id, self.logger) - return self.client.upload(path, server) - -- def get_tests(self, devices): -+ def get_tests(self, devices=None): - """ - get test items - :param devices: - :return: - """ -+ if devices is None: -+ devices = list() - sort_devices = self.sort_tests(devices) - empty_device = Device(logger=self.logger) - test_factory = list() - casenames = [] -- for (_, dirs, filenames) in os.walk(CertEnv.testdirectoy): -+ test_path = os.path.join(CertEnv.testdirectoy, self.category) -+ for (_, dirs, filenames) in os.walk(test_path): - dirs.sort() - for filename in filenames: - if filename.endswith(".py") and \ - not filename.startswith("__init__"): - casenames.append(filename.split(".")[0]) - -- with open(CertEnv.pcifile) as file: -+ if self.category == "virtualization": - for testname in casenames: -- if sort_devices.get(testname): -- for device in sort_devices[testname]: -+ test = dict() -+ test["name"] = testname -+ test["device"] = empty_device -+ test["run"] = True -+ test["status"] = "NotRun" -+ test["reboot"] = False -+ test_factory.append(test) -+ else: -+ with open(CertEnv.pcifile) as file: -+ for testname in casenames: -+ if sort_devices.get(testname): -+ for device in sort_devices[testname]: -+ test = dict() -+ test["name"] = testname -+ test["device"] = device -+ test["run"] = True -+ test["status"] = "NotRun" -+ test["reboot"] = False -+ test["driverName"] = test.get("device", "").get_driver() -+ test["driverVersion"] = test.get("device", "").get_driver_version() -+ test["boardModel"], test["chipModel"] = test.get("device", "").get_model(testname, file) -+ test_factory.append(test) -+ elif testname in NODEVICE: - test = dict() - test["name"] = testname -- test["device"] = device -+ test["device"] = empty_device - test["run"] = True - test["status"] = "NotRun" - test["reboot"] = False -- test["driverName"] = test.get("device", "").get_driver() -- test["driverVersion"] = test.get("device", "").get_driver_version() -- test["boardModel"], test["chipModel"] = test.get("device", "").get_model(testname, file) - test_factory.append(test) -- elif testname in NODEVICE: -- test = dict() -- test["name"] = testname -- test["device"] = empty_device -- test["run"] = True -- test["status"] = "NotRun" -- test["reboot"] = False -- test_factory.append(test) - return test_factory - - def sort_tests(self, devices): -@@ -370,7 +401,7 @@ - if any([k in id_vendor for k in KEYCARD_VENDORS]): - sort_devices["keycard"] = [device] - continue -- -+ - cmd_result = self.command.run_cmd("dmidecode | grep 'IPMI Device Information'") - if cmd_result[2] == 0: - sort_devices["ipmi"] = [empty_device] -@@ -391,7 +422,10 @@ - - self.logger.info('\033c', log_print=False) - self.logger.info("Select tests to run:", log_print=False) -- self.show_tests() -+ if self.category == "virtualization": -+ self.show_virt_tests() -+ else: -+ self.show_tests() - reply = self.ui.prompt("Selection (|all|none|quit|run): ") - reply = reply.lower() - if reply in ["r", "run"]: -@@ -461,6 +495,33 @@ - device, driver, version, chip, board) - self._print_tests(device) - -+ def show_virt_tests(self): -+ """ -+ show virtualization test items -+ :return: -+ """ -+ self.logger.info("\033[1;35m" + "No.".ljust(4) + "Run-Now?".ljust(10) -+ + "status".ljust(10) + "%s\033[0m" % "Class".ljust(14), log_print=False) -+ num = 0 -+ for test in self.test_factory: -+ name = test["name"] -+ status = test["status"] -+ run = "no" -+ if test["run"] is True: -+ run = "yes" -+ num = num + 1 -+ if status == "PASS": -+ color = "2" -+ elif status == "FAIL": -+ color = "1" -+ elif status == "Force": -+ color = "3" -+ else: -+ color = "4" -+ self.logger.info("%-6d" % num + run.ljust(8) -+ + "\033[0;3%sm%s \033[0m" % (color, status.ljust(8)) -+ + name.ljust(14), log_print=False) -+ - def choose_tests(self): - """ - choose test behavior -@@ -473,8 +534,11 @@ - test["run"] = True - self.logger.info('\033c', log_print=False) - self.logger.info("These tests are recommended to " -- "complete the compatibility test: ", log_print=False) -- self.show_tests() -+ "complete the %s test: " % self.category, log_print=False) -+ if self.category == "virtualization": -+ self.show_virt_tests() -+ else: -+ self.show_tests() - action = self.ui.prompt("Ready to begin testing?", - ["run", "edit", "quit"]) - action = action.lower() -@@ -508,29 +572,33 @@ - if not self.test_factory: - self.test_factory = test_factory - else: -- for test in self.test_factory: -- if not search_factory(test, test_factory): -- self.test_factory.remove(test) -- self.logger.info("delete %s test %s" % (test["name"], -- test["device"].get_name())) -- for test in test_factory: -- if not search_factory(test, self.test_factory): -- self.test_factory.append(test) -- self.logger.info("add %s test %s" % (test["name"], -- test["device"].get_name())) -- for index, test in enumerate(self.test_factory): -- for test_new in test_factory: -- if test["name"] != test_new["name"]: -- continue -- self_test_path = test["device"].path -- new_test_path = test_new["device"].path -- if not self_test_path and not new_test_path: -- continue -- if self_test_path == new_test_path: -- self.test_factory[index]['device'] = test_new['device'] -- -+ if self.category == 'compatible': -+ for test in self.test_factory: -+ if not search_factory(test, test_factory): -+ self.test_factory.remove(test) -+ self.logger.info("delete %s test %s" % (test["name"], -+ test["device"].get_name())) -+ for test in test_factory: -+ if not search_factory(test, self.test_factory): -+ self.test_factory.append(test) -+ self.logger.info("add %s test %s" % (test["name"], -+ test["device"].get_name())) -+ for index, test in enumerate(self.test_factory): -+ for test_new in test_factory: -+ if test["name"] != test_new["name"]: -+ continue -+ self_test_path = test["device"].path -+ new_test_path = test_new["device"].path -+ if not self_test_path and not new_test_path: -+ continue -+ if self_test_path == new_test_path: -+ self.test_factory[index]['device'] = test_new['device'] -+ if self.category == "virtualization": -+ factoryfile_path = CertEnv.virtfactoryfile -+ else: -+ factoryfile_path = CertEnv.factoryfile - self.test_factory.sort(key=lambda k: k["name"]) -- FactoryDocument(CertEnv.factoryfile, self.logger, self.test_factory).save() -+ FactoryDocument(factoryfile_path, self.logger, self.test_factory).save() - - def _print_tests(self, device): - """ -@@ -540,3 +608,17 @@ - + "\033[0;3%sm%s \033[0m" % (device.color, device.status.ljust(8)) - + device.name.ljust(14) + device.device.ljust(15) + device.driver.ljust(15) - + device.version.ljust(18) + device.chip.ljust(20) + device.board, log_print=False) -+ -+ def _select_category(self): -+ self.logger.info("Please select test category.", log_print=False) -+ self.logger.info("\033[1;35m" + "No.".ljust(6) + "category".ljust(35) + "\033[0m", log_print=False) -+ categories = dict(enumerate(TEST_CATEGORY)) -+ for num, category in categories.items(): -+ self.logger.info("%-6d" % (num + 1) + category.ljust(4)) -+ no = self.ui.prompt("Please select test category No:") -+ if no.isdigit(): -+ no = int(no) -+ if 1 <= no <= len(categories): -+ self.category = categories[no - 1] -+ return -+ self._select_category() -diff -Naur rpm/hwcompatible/constants.py oech/hwcompatible/constants.py ---- rpm/hwcompatible/constants.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/constants.py 2023-12-07 15:01:42.221942234 +0800 -@@ -25,7 +25,7 @@ - DRIVER = "driverName" - VERSION = "driverVersion" - NODEVICE = ("cpufreq", "memory", "clock", "profiler", "system", -- "stress", "kdump", "perf", "acpi", "watchdog", "kabi", "kabiwhitelist") -+ "stress", "kdump", "perf", "acpi", "watchdog", "kabi", "kabiwhitelist", "longtermstability") - TEST_KABI_ARCH = ("aarch64", "x86_64") - CDTYPES = ("DVD_RW", "DVD_PLUS_RW", "DVD_R", "DVD_PLUS_R", "DVD", - "BD_RE", "BD_R", "BD", "CD_RW", "CD_R", "CD") -@@ -35,6 +35,7 @@ - DEVICE_INFO = ('color', 'status', 'num', 'run', 'name', - 'device', 'driver', 'version', 'chip', 'board') - NO_CONFIG_DEVICES = ("gpu", "vgpu", "nvme", "dpdk", "cdrom", "keycard", "spdk") -+TEST_CATEGORY = ("compatible", "virtualization") - - # File access control - FILE_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC -diff -Naur rpm/hwcompatible/env.py oech/hwcompatible/env.py ---- rpm/hwcompatible/env.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/env.py 2023-12-07 15:01:42.221942234 +0800 -@@ -26,6 +26,7 @@ - certificationfile = os.path.join(datadirectory, "compatibility.json") - devicefile = os.path.join(datadirectory, "device.json") - factoryfile = os.path.join(datadirectory, "factory.json") -+ virtfactoryfile = os.path.join(datadirectory, "virtfactory.json") - rebootfile = os.path.join(datadirectory, "reboot.json") - testdirectoy = "/usr/share/oech/lib/tests" - logdirectoy = "/usr/share/oech/logs" -diff -Naur rpm/hwcompatible/job.py oech/hwcompatible/job.py ---- rpm/hwcompatible/job.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/job.py 2023-12-07 15:01:42.221942234 +0800 -@@ -101,7 +101,7 @@ - testcase["name"], terminal_print=False) - - if testcase["name"] not in NODEVICE: -- cert_infos.create_json(testcase["device"]) -+ cert_infos.create_json(testcase["name"], testcase["device"]) - else: - testcase["status"] = "FAIL" - self.logger.error("Test %s failed." % -diff -Naur rpm/hwcompatible/sysinfo.py oech/hwcompatible/sysinfo.py ---- rpm/hwcompatible/sysinfo.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/hwcompatible/sysinfo.py 2023-12-07 15:01:42.221942234 +0800 -@@ -12,7 +12,6 @@ - # See the Mulan PSL v2 for more details. - # Create: 2020-04-01 - --import os - import re - from subprocess import getoutput - -diff -Naur rpm/oec-hardware.spec oech/oec-hardware.spec ---- rpm/oec-hardware.spec 2023-10-24 22:25:50.000000000 +0800 -+++ oech/oec-hardware.spec 2023-12-07 15:01:42.221942234 +0800 -@@ -25,7 +25,7 @@ - Summary: openEuler Hardware Compatibility Test Server - Group: Development/Tools - Requires: python3, python3-devel, python3-flask, python3-uWSGI, python3-werkzeug --Requires: nginx, tar, qperf, psmisc, dpdk, dpdk-tools, dpdk-devel, net-tools -+Requires: nginx, tar, qperf, psmisc, dpdk, dpdk-tools, dpdk-devel, net-tools, perftest - - %description - openEuler Hardware Compatibility Test Suite -@@ -38,7 +38,7 @@ - - %build - %ifarch x86_64 aarch64 --strip tests/keycard/libswsds_%{_arch}.so -+strip tests/compatible/keycard/libswsds_%{_arch}.so - %endif - [ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; - DESTDIR=$RPM_BUILD_ROOT VERSION_RELEASE=%{version} make -diff -Naur rpm/server/server.py oech/server/server.py ---- rpm/server/server.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/server/server.py 2023-12-07 15:01:42.225942288 +0800 -@@ -97,7 +97,10 @@ - job = secure_filename(job) - dir_job = os.path.join(dir_results, host, oec_id, job) - json_info = os.path.join(dir_job, 'compatibility.json') -- json_results = os.path.join(dir_job, 'factory.json') -+ files = os.listdir(dir_job) -+ for file in files: -+ if "factory.json" in file: -+ json_results = os.path.join(dir_job, file) - if not os.path.exists(json_info) or not os.path.exists(json_results): - abort(404) - -@@ -110,7 +113,8 @@ - sys.stderr.write("The file %s is not json file.\n") - return False - -- return render_template('job.html', host=host, id=oec_id, job=job, info=info, results=results) -+ return render_template('job.html', host=host, id=oec_id, job=job, info=info, results=results, -+ json_results=json_results) - - - @app.route('/results////devices/') -@@ -127,7 +131,10 @@ - oec_id = secure_filename(oec_id) - job = secure_filename(job) - dir_job = os.path.join(dir_results, host, oec_id, job) -- json_results = os.path.join(dir_job, 'factory.json') -+ files = os.listdir(dir_job) -+ for file in files: -+ if "factory.json" in file: -+ json_results = os.path.join(dir_job, file) - if not os.path.exists(json_results): - abort(404) - -@@ -159,7 +166,10 @@ - oec_id = secure_filename(oec_id) - job = secure_filename(job) - dir_job = os.path.join(dir_results, host, oec_id, job) -- json_devices = os.path.join(dir_job, 'device.json') -+ files = os.listdir(dir_job) -+ for file in files: -+ if "factory.json" in file: -+ json_devices = os.path.join(dir_job, file) - if not os.path.exists(json_devices): - abort(404) - -diff -Naur rpm/server/templates/job.html oech/server/templates/job.html ---- rpm/server/templates/job.html 2023-10-24 22:25:50.000000000 +0800 -+++ oech/server/templates/job.html 2023-12-07 15:01:42.225942288 +0800 -@@ -41,6 +41,7 @@ - -

Testcase

- -+ {% if json_results == "factory.json" %} - -

Device

- -@@ -56,6 +57,7 @@ - -

boardModel

- -+ {% endif %} - -

Result

- -@@ -78,6 +80,7 @@ - {% endif %} - - {{ testcase }} -+ {% if json_results == "factory.json" %} - - {{ int }} - -@@ -85,6 +88,7 @@ - {{ d.get('driverVersion', '') }} - {{ d.get('chipModel', '') }} - {{ d.get('boardModel', '') }} -+ {% endif %} - - {{ result }} - -diff -Naur rpm/tests/acpi/acpi.py oech/tests/acpi/acpi.py ---- rpm/tests/acpi/acpi.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/acpi/acpi.py 1970-01-01 08:00:00.000000000 +0800 -@@ -1,38 +0,0 @@ --#!/usr/bin/env python3 --# coding: utf-8 -- --# Copyright (c) 2020 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 -- --from hwcompatible.test import Test -- -- --class AcpiTest(Test): -- """ -- acpi test -- """ -- -- def __init__(self): -- Test.__init__(self) -- self.requirements = ["acpica-tools"] -- -- def test(self): -- """ -- Test case -- :return: -- """ -- result = self.command.run_cmd("acpidump") -- if result[2] == 0: -- self.logger.info("Test acpi succeed.") -- return True -- -- self.logger.error("Test acpi failed.\n%s" % result[1]) -- return False -diff -Naur rpm/tests/acpi/Makefile oech/tests/acpi/Makefile ---- rpm/tests/acpi/Makefile 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/acpi/Makefile 1970-01-01 08:00:00.000000000 +0800 -@@ -1,22 +0,0 @@ --# Copyright (c) 2020 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 -- --.PHONY: install clean -- --all: ; -- --install: -- mkdir -p $(DEST) -- cp -a *.py $(DEST) -- chmod a+x $(DEST)/*.py -- --clean: -- rm -rf $(DEST) -diff -Naur rpm/tests/cdrom/cdrom.py oech/tests/cdrom/cdrom.py ---- rpm/tests/cdrom/cdrom.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/cdrom/cdrom.py 1970-01-01 08:00:00.000000000 +0800 -@@ -1,271 +0,0 @@ --#!/usr/bin/env python3 --# coding: utf-8 -- --# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 --# Desc: CDRom test -- --import os --import shutil --import argparse --from time import sleep --from hwcompatible.test import Test --from hwcompatible.command_ui import CommandUI --from hwcompatible.command import Command -- -- --class CDRomTest(Test): -- def __init__(self): -- Test.__init__(self) -- self.requirements = ["dvd+rw-tools", -- "cdrkit", "genisoimage", "util-linux"] -- self.method = None -- self.device = None -- self.type = None -- self.com_ui = CommandUI() -- self.test_dir = "/usr/share/doc" -- read_dir = os.getcwd() -- self.mnt_dir = os.path.join(read_dir, "mnt_cdrom") -- self.device_dir = os.path.join(read_dir, "device_dir") -- -- def setup(self, args=None): -- """ -- The Setup before testing -- :param args: -- :return: -- """ -- self.args = args or argparse.Namespace() -- self.logger = getattr(args, "test_logger", None) -- self.device = getattr(args, "device", None) -- self.type = self.get_type(self.device) -- self.command = Command(self.logger) -- self.get_mode(self.type) -- -- def test(self): -- """ -- Test case -- :return: -- """ -- if not (self.method and self.device and self.type): -- return False -- -- if self.method not in dir(self): -- return False -- -- devname = self.device.get_property("DEVNAME") -- self.command.run_cmd("eject %s" % devname, ignore_errors=True) -- while True: -- self.logger.info("Please insert %s disc into %s, then close the tray manually." % ( -- self.type.lower(), devname)) -- if self.method == "write_test": -- self.logger.info("Tips: disc should be new.") -- elif self.method == "read_test": -- self.logger.info("Tips: disc should not be blank.") -- if self.com_ui.prompt_confirm("Done well?"): -- break -- self.command.run_cmd("eject -t %s" % devname, ignore_errors=True) -- self.logger.info( -- "Please wait seconds for media to be inserted.", terminal_print=True) -- sleep(20) -- -- if not getattr(self, self.method)(): -- return False -- return True -- -- def get_type(self, device): -- """ -- Get the type of CDROM -- :param device: -- :return: -- """ -- if not device: -- return None -- -- bd_types = ["BD_RE", "BD_R", "BD"] -- dvd_types = ["DVD_RW", "DVD_PLUS_RW", "DVD_R", "DVD_PLUS_R", "DVD"] -- cd_types = ["CD_RW", "CD_R", "CD"] -- for bd_type in bd_types: -- if device.get_property("ID_CDROM_" + bd_type) == "1": -- return bd_type -- for dvd_type in dvd_types: -- if device.get_property("ID_CDROM_" + dvd_type) == "1": -- return dvd_type -- for cd_type in cd_types: -- if device.get_property("ID_CDROM_" + cd_type) == "1": -- return cd_type -- -- self.logger.error("Find proper test-type for %s failed." % -- device.get_name()) -- return None -- -- def get_mode(self, device_type): -- """ -- Get the read-write mode of CDROM -- :param device_type: -- :return: -- """ -- if not device_type: -- return -- -- if "RW" in device_type or "RE" in device_type: -- self.method = "rw_test" -- elif "_R" in device_type: -- self.method = "write_test" -- else: -- self.method = "read_test" -- -- def rw_test(self): -- """ -- RW mode test of CDROM -- :return: -- """ -- devname = self.device.get_property("DEVNAME") -- self.command.run_cmd("umount %s" % devname, ignore_errors=True) -- if "BD" in self.type: -- self.logger.info("It will format the cdrom.", terminal_print=True) -- self.command.run_cmd("dvd+rw-format -format=full %s" % devname) -- self.reload_disc(devname) -- return self.write_test() -- elif "DVD_PLUS" in self.type: -- self.logger.info("It will format the cdrom.", terminal_print=True) -- self.command.run_cmd("dvd+rw-format -force %s" % devname) -- self.reload_disc(devname) -- return self.write_test() -- else: -- self.logger.info("It will clear data in cdrom.", -- terminal_print=True) -- self.command.run_cmd("cdrecord -v dev=%s blank=fast" % devname) -- self.reload_disc(devname) -- return self.write_test() -- -- def write_test(self): -- """ -- Write mode test of CDROM -- :return: -- """ -- devname = self.device.get_property("DEVNAME") -- self.command.run_cmd("umount %s" % devname, ignore_errors=True) -- if "BD" in self.type or "DVD_PLUS" in self.type: -- grow_cmd = self.command.run_cmd( -- "growisofs -Z %s --quiet -R %s " % (devname, self.test_dir)) -- reload_flag = self.reload_disc(devname) -- if grow_cmd[2] == 0 and reload_flag: -- return True -- return False -- -- write_opts = "-sao" -- cmd_result = self.command.run_cmd( -- "cdrecord dev=%s -checkdrive | grep 'Supported modes'" % devname, ignore_errors=True) -- modes = cmd_result[0] -- if "TAO" in modes: -- write_opts = "-tao" -- if "SAO" in modes: -- write_opts = "-sao" -- cmd_result = self.command.run_cmd( -- "cdrecord dev=%s -checkdrive | grep 'Driver flags'" % devname, ignore_errors=True) -- if "BURNFREE" in cmd_result[0]: -- write_opts += " driveropts=burnfree" -- -- size = self.command.run_cmd( -- "mkisofs -quiet -R -print-size %s" % self.test_dir) -- blocks = int(size[0]) -- -- self.command.run_cmd( -- "mkisofs -o test_cdrom.iso --quiet -r %s" % self.test_dir) -- mkisofs_cmd = self.command.run_cmd( -- "cdrecord -v %s dev=%s fs=32M test_cdrom.iso" % (write_opts, devname)) -- reload_flag = self.reload_disc(devname) -- os.remove("test_cdrom.iso") -- if mkisofs_cmd[2] == 0 and reload_flag: -- return True -- return False -- -- def read_test(self): -- """ -- Read mode test of CDROM -- :return: -- """ -- devname = self.device.get_property("DEVNAME") -- if os.path.exists(self.mnt_dir): -- shutil.rmtree(self.mnt_dir) -- os.mkdir(self.mnt_dir) -- self.logger.info("Check to mount media.", terminal_print=True) -- self.command.run_cmd("umount %s" % devname, ignore_errors=True) -- self.command.run_cmd("mount -o ro %s %s" % (devname, self.mnt_dir)) -- -- cmd_result = self.command.run_cmd( -- "df %s | tail -n1 | awk '{print $3}'" % devname) -- size = int(cmd_result[0]) -- if size == 0: -- self.logger.error("This is a blank disc.") -- self.command.run_cmd("umount %s" % self.mnt_dir) -- shutil.rmtree(self.mnt_dir) -- return False -- -- if os.path.exists(self.device_dir): -- shutil.rmtree(self.device_dir) -- os.mkdir(self.device_dir) -- self.logger.info("Check to copy files.", terminal_print=True) -- self.command.run_cmd("cp -dprf %s/. %s" % (self.mnt_dir, self.device_dir)) -- -- self.logger.info( -- "Check to compare files in directory.", terminal_print=True) -- return_code = self.cmp_tree(self.mnt_dir, self.device_dir) -- self.command.run_cmd("umount %s" % self.mnt_dir) -- if return_code: -- self.logger.info("Compare directory succeed.") -- else: -- self.logger.error("Compare directory failed.") -- -- return return_code -- -- def cmp_tree(self, dir1, dir2): -- """ -- Compare the differences between the two directories -- :param dir1: -- :param dir2: -- :return: -- """ -- if not (dir1 and dir2): -- self.logger.error("Invalid input directory.") -- return False -- -- cmd_result = self.command.run_cmd("diff -r %s %s" % (dir1, dir2)) -- return cmd_result[2] == 0 -- -- def reload_disc(self, device): -- """ -- Reloading the media -- :param device: -- :return: -- """ -- if not device: -- return False -- -- self.logger.info("Check to reload the media.") -- self.command.run_cmd("eject %s" % device) -- self.logger.info("Tray ejected.") -- -- cmd = self.command.run_cmd("eject -t %s" % device) -- if cmd[2] != 0: -- self.logger.error( -- "Could not auto-close the tray, please close the tray manually.") -- self.com_ui.prompt_confirm("Done well?") -- -- sleep(20) -- self.logger.info("Tray auto-closed.\n") -- return True -- -- def teardown(self): -- if os.path.exists(self.mnt_dir): -- shutil.rmtree(self.mnt_dir) -- if os.path.exists(self.device_dir): -- shutil.rmtree(self.device_dir) -diff -Naur rpm/tests/cdrom/Makefile oech/tests/cdrom/Makefile ---- rpm/tests/cdrom/Makefile 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/cdrom/Makefile 1970-01-01 08:00:00.000000000 +0800 -@@ -1,22 +0,0 @@ --# Copyright (c) 2020 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 -- --.PHONY: install clean -- --all: ; -- --install: -- mkdir -p $(DEST) -- cp -a *.py $(DEST) -- chmod a+x $(DEST)/*.py -- --clean: -- rm -rf $(DEST) -diff -Naur rpm/tests/clock/clock.c oech/tests/clock/clock.c ---- rpm/tests/clock/clock.c 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/clock/clock.c 1970-01-01 08:00:00.000000000 +0800 -@@ -1,94 +0,0 @@ --/* -- * Copyright (c) 2020 Huawei Technologies Co., Ltd. -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of version 2 of the GNU General Public -- * License as published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- * 02110-1301, USA -- */ -- --#define _GNU_SOURCE 1 -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --int test_clock_direction() --{ -- time_t starttime = 0; -- time_t stoptime = 0; -- int sleeptime = 60; -- int delta = 0; -- -- printf("clock direction test start\n"); -- time(&starttime); -- sleep(sleeptime); -- time(&stoptime); -- -- delta = (int)stoptime - (int)starttime - sleeptime; -- if (delta != 0) { -- printf("clock direction test fail\n"); -- return 1; -- } else { -- printf("clock direction test complete\n"); -- return 0; -- } --} -- --int test_rtc_clock() --{ -- int rtc, delta; -- struct tm rtc_tm1, rtc_tm2; -- int sleeptime = 120; -- -- printf("rtc_clock test start\n"); -- if ((rtc = open("/dev/rtc", O_WRONLY)) < 0) { -- perror("could not open RTC device"); -- return 1; -- } -- -- if (ioctl(rtc, RTC_RD_TIME, &rtc_tm1) < 0) { -- perror("could not get the RTC time"); -- close(rtc); -- return 1; -- } -- sleep(sleeptime); -- if (ioctl(rtc, RTC_RD_TIME, &rtc_tm2) < 0) { -- perror("could not get the RTC time"); -- close(rtc); -- return 1; -- } -- -- close(rtc); -- delta = (int)mktime(&rtc_tm2) - (int)mktime(&rtc_tm1) - sleeptime; -- if (delta != 0) { -- printf("rtc_clock test fail\n"); -- return 1; -- } else { -- printf("rtc_clock test complete\n"); -- return 0; -- } --} -- --int main() --{ -- int ret = 0; -- ret += test_clock_direction(); -- ret += test_rtc_clock(); -- return ret; --} -diff -Naur rpm/tests/clock/clock.py oech/tests/clock/clock.py ---- rpm/tests/clock/clock.py 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/clock/clock.py 1970-01-01 08:00:00.000000000 +0800 -@@ -1,37 +0,0 @@ --#!/usr/bin/env python3 --# coding: utf-8 -- --# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 --# Desc: Clock test -- --import os --from hwcompatible.test import Test -- --clock_dir = os.path.dirname(os.path.realpath(__file__)) -- -- --class ClockTest(Test): -- def __init__(self): -- Test.__init__(self) -- -- def test(self): -- """ -- Clock test case -- :return: -- """ -- result = self.command.run_cmd("%s/clock" % clock_dir) -- if result[2] == 0: -- self.logger.info("Test clock succeed.") -- return True -- -- self.logger.error("Test clock failed.\n %s" % result[1]) -- return False -diff -Naur rpm/tests/clock/Makefile oech/tests/clock/Makefile ---- rpm/tests/clock/Makefile 2023-10-24 22:25:50.000000000 +0800 -+++ oech/tests/clock/Makefile 1970-01-01 08:00:00.000000000 +0800 -@@ -1,34 +0,0 @@ --# Copyright (c) 2020 Huawei Technologies Co., Ltd. --# oec-hardware is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. --# Create: 2020-04-01 -- --.PHONY: all install clean -- --all: clock -- --CFLAGS+=-Wall --CFLAGS+=-DCPU_ALLOC --# sched_setaffinity has no size_t argument on older systems. --ifeq ($(shell grep 'sched_setaffinity.*size_t' /usr/include/sched.h),) --CFLAGS+=-DOLD_SCHED_SETAFFINITY --endif -- --clock: clock.c -- $(CC) $(CFLAGS) -lrt $< -o $@ -- --install: -- mkdir -p $(DEST) -- cp -a clock *.py $(DEST) -- chmod a+x $(DEST)/*.py -- --clean: -- rm -rf $(DEST) -- rm -rf clock -- -diff -Naur rpm/tests/compatible/acpi/acpi.py oech/tests/compatible/acpi/acpi.py ---- rpm/tests/compatible/acpi/acpi.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/acpi/acpi.py 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,38 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+from hwcompatible.test import Test -+ -+ -+class AcpiTest(Test): -+ """ -+ acpi test -+ """ -+ -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["acpica-tools"] -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ result = self.command.run_cmd("acpidump") -+ if result[2] == 0: -+ self.logger.info("Test acpi succeed.") -+ return True -+ -+ self.logger.error("Test acpi failed.\n%s" % result[1]) -+ return False -diff -Naur rpm/tests/compatible/acpi/Makefile oech/tests/compatible/acpi/Makefile ---- rpm/tests/compatible/acpi/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/acpi/Makefile 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/cdrom/cdrom.py oech/tests/compatible/cdrom/cdrom.py ---- rpm/tests/compatible/cdrom/cdrom.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/cdrom/cdrom.py 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,271 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: CDRom test -+ -+import os -+import shutil -+import argparse -+from time import sleep -+from hwcompatible.test import Test -+from hwcompatible.command_ui import CommandUI -+from hwcompatible.command import Command -+ -+ -+class CDRomTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["dvd+rw-tools", -+ "cdrkit", "genisoimage", "util-linux"] -+ self.method = None -+ self.device = None -+ self.type = None -+ self.com_ui = CommandUI() -+ self.test_dir = "/usr/share/doc" -+ read_dir = os.getcwd() -+ self.mnt_dir = os.path.join(read_dir, "mnt_cdrom") -+ self.device_dir = os.path.join(read_dir, "device_dir") -+ -+ def setup(self, args=None): -+ """ -+ The Setup before testing -+ :param args: -+ :return: -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(args, "test_logger", None) -+ self.device = getattr(args, "device", None) -+ self.type = self.get_type(self.device) -+ self.command = Command(self.logger) -+ self.get_mode(self.type) -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ if not (self.method and self.device and self.type): -+ return False -+ -+ if self.method not in dir(self): -+ return False -+ -+ devname = self.device.get_property("DEVNAME") -+ self.command.run_cmd("eject %s" % devname, ignore_errors=True) -+ while True: -+ self.logger.info("Please insert %s disc into %s, then close the tray manually." % ( -+ self.type.lower(), devname)) -+ if self.method == "write_test": -+ self.logger.info("Tips: disc should be new.") -+ elif self.method == "read_test": -+ self.logger.info("Tips: disc should not be blank.") -+ if self.com_ui.prompt_confirm("Done well?"): -+ break -+ self.command.run_cmd("eject -t %s" % devname, ignore_errors=True) -+ self.logger.info( -+ "Please wait seconds for media to be inserted.", terminal_print=True) -+ sleep(20) -+ -+ if not getattr(self, self.method)(): -+ return False -+ return True -+ -+ def get_type(self, device): -+ """ -+ Get the type of CDROM -+ :param device: -+ :return: -+ """ -+ if not device: -+ return None -+ -+ bd_types = ["BD_RE", "BD_R", "BD"] -+ dvd_types = ["DVD_RW", "DVD_PLUS_RW", "DVD_R", "DVD_PLUS_R", "DVD"] -+ cd_types = ["CD_RW", "CD_R", "CD"] -+ for bd_type in bd_types: -+ if device.get_property("ID_CDROM_" + bd_type) == "1": -+ return bd_type -+ for dvd_type in dvd_types: -+ if device.get_property("ID_CDROM_" + dvd_type) == "1": -+ return dvd_type -+ for cd_type in cd_types: -+ if device.get_property("ID_CDROM_" + cd_type) == "1": -+ return cd_type -+ -+ self.logger.error("Find proper test-type for %s failed." % -+ device.get_name()) -+ return None -+ -+ def get_mode(self, device_type): -+ """ -+ Get the read-write mode of CDROM -+ :param device_type: -+ :return: -+ """ -+ if not device_type: -+ return -+ -+ if "RW" in device_type or "RE" in device_type: -+ self.method = "rw_test" -+ elif "_R" in device_type: -+ self.method = "write_test" -+ else: -+ self.method = "read_test" -+ -+ def rw_test(self): -+ """ -+ RW mode test of CDROM -+ :return: -+ """ -+ devname = self.device.get_property("DEVNAME") -+ self.command.run_cmd("umount %s" % devname, ignore_errors=True) -+ if "BD" in self.type: -+ self.logger.info("It will format the cdrom.", terminal_print=True) -+ self.command.run_cmd("dvd+rw-format -format=full %s" % devname) -+ self.reload_disc(devname) -+ return self.write_test() -+ elif "DVD_PLUS" in self.type: -+ self.logger.info("It will format the cdrom.", terminal_print=True) -+ self.command.run_cmd("dvd+rw-format -force %s" % devname) -+ self.reload_disc(devname) -+ return self.write_test() -+ else: -+ self.logger.info("It will clear data in cdrom.", -+ terminal_print=True) -+ self.command.run_cmd("cdrecord -v dev=%s blank=fast" % devname) -+ self.reload_disc(devname) -+ return self.write_test() -+ -+ def write_test(self): -+ """ -+ Write mode test of CDROM -+ :return: -+ """ -+ devname = self.device.get_property("DEVNAME") -+ self.command.run_cmd("umount %s" % devname, ignore_errors=True) -+ if "BD" in self.type or "DVD_PLUS" in self.type: -+ grow_cmd = self.command.run_cmd( -+ "growisofs -Z %s --quiet -R %s " % (devname, self.test_dir)) -+ reload_flag = self.reload_disc(devname) -+ if grow_cmd[2] == 0 and reload_flag: -+ return True -+ return False -+ -+ write_opts = "-sao" -+ cmd_result = self.command.run_cmd( -+ "cdrecord dev=%s -checkdrive | grep 'Supported modes'" % devname, ignore_errors=True) -+ modes = cmd_result[0] -+ if "TAO" in modes: -+ write_opts = "-tao" -+ if "SAO" in modes: -+ write_opts = "-sao" -+ cmd_result = self.command.run_cmd( -+ "cdrecord dev=%s -checkdrive | grep 'Driver flags'" % devname, ignore_errors=True) -+ if "BURNFREE" in cmd_result[0]: -+ write_opts += " driveropts=burnfree" -+ -+ size = self.command.run_cmd( -+ "mkisofs -quiet -R -print-size %s" % self.test_dir) -+ blocks = int(size[0]) -+ -+ self.command.run_cmd( -+ "mkisofs -o test_cdrom.iso --quiet -r %s" % self.test_dir) -+ mkisofs_cmd = self.command.run_cmd( -+ "cdrecord -v %s dev=%s fs=32M test_cdrom.iso" % (write_opts, devname)) -+ reload_flag = self.reload_disc(devname) -+ os.remove("test_cdrom.iso") -+ if mkisofs_cmd[2] == 0 and reload_flag: -+ return True -+ return False -+ -+ def read_test(self): -+ """ -+ Read mode test of CDROM -+ :return: -+ """ -+ devname = self.device.get_property("DEVNAME") -+ if os.path.exists(self.mnt_dir): -+ shutil.rmtree(self.mnt_dir) -+ os.mkdir(self.mnt_dir) -+ self.logger.info("Check to mount media.", terminal_print=True) -+ self.command.run_cmd("umount %s" % devname, ignore_errors=True) -+ self.command.run_cmd("mount -o ro %s %s" % (devname, self.mnt_dir)) -+ -+ cmd_result = self.command.run_cmd( -+ "df %s | tail -n1 | awk '{print $3}'" % devname) -+ size = int(cmd_result[0]) -+ if size == 0: -+ self.logger.error("This is a blank disc.") -+ self.command.run_cmd("umount %s" % self.mnt_dir) -+ shutil.rmtree(self.mnt_dir) -+ return False -+ -+ if os.path.exists(self.device_dir): -+ shutil.rmtree(self.device_dir) -+ os.mkdir(self.device_dir) -+ self.logger.info("Check to copy files.", terminal_print=True) -+ self.command.run_cmd("cp -dprf %s/. %s" % (self.mnt_dir, self.device_dir)) -+ -+ self.logger.info( -+ "Check to compare files in directory.", terminal_print=True) -+ return_code = self.cmp_tree(self.mnt_dir, self.device_dir) -+ self.command.run_cmd("umount %s" % self.mnt_dir) -+ if return_code: -+ self.logger.info("Compare directory succeed.") -+ else: -+ self.logger.error("Compare directory failed.") -+ -+ return return_code -+ -+ def cmp_tree(self, dir1, dir2): -+ """ -+ Compare the differences between the two directories -+ :param dir1: -+ :param dir2: -+ :return: -+ """ -+ if not (dir1 and dir2): -+ self.logger.error("Invalid input directory.") -+ return False -+ -+ cmd_result = self.command.run_cmd("diff -r %s %s" % (dir1, dir2)) -+ return cmd_result[2] == 0 -+ -+ def reload_disc(self, device): -+ """ -+ Reloading the media -+ :param device: -+ :return: -+ """ -+ if not device: -+ return False -+ -+ self.logger.info("Check to reload the media.") -+ self.command.run_cmd("eject %s" % device) -+ self.logger.info("Tray ejected.") -+ -+ cmd = self.command.run_cmd("eject -t %s" % device) -+ if cmd[2] != 0: -+ self.logger.error( -+ "Could not auto-close the tray, please close the tray manually.") -+ self.com_ui.prompt_confirm("Done well?") -+ -+ sleep(20) -+ self.logger.info("Tray auto-closed.\n") -+ return True -+ -+ def teardown(self): -+ if os.path.exists(self.mnt_dir): -+ shutil.rmtree(self.mnt_dir) -+ if os.path.exists(self.device_dir): -+ shutil.rmtree(self.device_dir) -diff -Naur rpm/tests/compatible/cdrom/Makefile oech/tests/compatible/cdrom/Makefile ---- rpm/tests/compatible/cdrom/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/cdrom/Makefile 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/clock/clock.c oech/tests/compatible/clock/clock.c ---- rpm/tests/compatible/clock/clock.c 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/clock/clock.c 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (c) 2020 Huawei Technologies Co., Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of version 2 of the GNU General Public -+ * License as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ */ -+ -+#define _GNU_SOURCE 1 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int test_clock_direction() -+{ -+ time_t starttime = 0; -+ time_t stoptime = 0; -+ int sleeptime = 60; -+ int delta = 0; -+ -+ printf("clock direction test start\n"); -+ time(&starttime); -+ sleep(sleeptime); -+ time(&stoptime); -+ -+ delta = (int)stoptime - (int)starttime - sleeptime; -+ if (delta != 0) { -+ printf("clock direction test fail\n"); -+ return 1; -+ } else { -+ printf("clock direction test complete\n"); -+ return 0; -+ } -+} -+ -+int test_rtc_clock() -+{ -+ int rtc, delta; -+ struct tm rtc_tm1, rtc_tm2; -+ int sleeptime = 120; -+ -+ printf("rtc_clock test start\n"); -+ if ((rtc = open("/dev/rtc", O_WRONLY)) < 0) { -+ perror("could not open RTC device"); -+ return 1; -+ } -+ -+ if (ioctl(rtc, RTC_RD_TIME, &rtc_tm1) < 0) { -+ perror("could not get the RTC time"); -+ close(rtc); -+ return 1; -+ } -+ sleep(sleeptime); -+ if (ioctl(rtc, RTC_RD_TIME, &rtc_tm2) < 0) { -+ perror("could not get the RTC time"); -+ close(rtc); -+ return 1; -+ } -+ -+ close(rtc); -+ delta = (int)mktime(&rtc_tm2) - (int)mktime(&rtc_tm1) - sleeptime; -+ if (delta != 0) { -+ printf("rtc_clock test fail\n"); -+ return 1; -+ } else { -+ printf("rtc_clock test complete\n"); -+ return 0; -+ } -+} -+ -+int main() -+{ -+ int ret = 0; -+ ret += test_clock_direction(); -+ ret += test_rtc_clock(); -+ return ret; -+} -diff -Naur rpm/tests/compatible/clock/clock.py oech/tests/compatible/clock/clock.py ---- rpm/tests/compatible/clock/clock.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/clock/clock.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,37 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: Clock test -+ -+import os -+from hwcompatible.test import Test -+ -+clock_dir = os.path.dirname(os.path.realpath(__file__)) -+ -+ -+class ClockTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ -+ def test(self): -+ """ -+ Clock test case -+ :return: -+ """ -+ result = self.command.run_cmd("%s/clock" % clock_dir) -+ if result[2] == 0: -+ self.logger.info("Test clock succeed.") -+ return True -+ -+ self.logger.error("Test clock failed.\n %s" % result[1]) -+ return False -diff -Naur rpm/tests/compatible/clock/Makefile oech/tests/compatible/clock/Makefile ---- rpm/tests/compatible/clock/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/clock/Makefile 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,34 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: all install clean -+ -+all: clock -+ -+CFLAGS+=-Wall -+CFLAGS+=-DCPU_ALLOC -+# sched_setaffinity has no size_t argument on older systems. -+ifeq ($(shell grep 'sched_setaffinity.*size_t' /usr/include/sched.h),) -+CFLAGS+=-DOLD_SCHED_SETAFFINITY -+endif -+ -+clock: clock.c -+ $(CC) $(CFLAGS) -lrt $< -o $@ -+ -+install: -+ mkdir -p $(DEST) -+ cp -a clock *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -+ rm -rf clock -+ -diff -Naur rpm/tests/compatible/cpufreq/cal.py oech/tests/compatible/cpufreq/cal.py ---- rpm/tests/compatible/cpufreq/cal.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/cpufreq/cal.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,34 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+import decimal -+import time -+ -+ -+def cal(): -+ """Call test_case""" -+ decimal.getcontext().prec = 1000 -+ one = decimal.Decimal(1) -+ for i in range(1000): -+ (i * one).sqrt() -+ -+ -+if __name__ == '__main__': -+ time_start = time.time() -+ while 1: -+ cal() -+ time_delta = time.time() - time_start -+ if time_delta >= 2: -+ print(time_delta) -+ break -diff -Naur rpm/tests/compatible/cpufreq/cpufreq.py oech/tests/compatible/cpufreq/cpufreq.py ---- rpm/tests/compatible/cpufreq/cpufreq.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/cpufreq/cpufreq.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,460 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: cpufreq test -+ -+import argparse -+from random import randint -+from time import sleep -+from threading import Thread -+from hwcompatible.env import CertEnv -+from hwcompatible.test import Test -+from hwcompatible.command import Command -+ -+ -+class CPU: -+ """ -+ cpufreq test -+ """ -+ -+ def __init__(self, logger, command): -+ self.cpu = None -+ self.nums = 0 -+ self.list = None -+ self.original_governor = None -+ self.max_freq = 0 -+ self.min_freq = 0 -+ self.logger = logger -+ self.command = command -+ -+ def get_info(self): -+ """ -+ Get CPU info -+ :return: -+ """ -+ cmd_result = self.command.run_cmd( -+ "lscpu | grep '^CPU(s):' | awk '{print $2}'") -+ self.logger.info("Get the CPU(s) succeed.") -+ self.nums = int(cmd_result[0]) -+ self.list = range(self.nums) -+ -+ cmd = self.command.run_cmd( -+ "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") -+ if cmd[2] != 0: -+ self.logger.error("Get the scaling_max_freq of cpu failed.") -+ return False -+ self.max_freq = int(cmd[0]) -+ -+ cmd = self.command.run_cmd( -+ "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq") -+ if cmd[2] != 0: -+ self.logger.error("Get the scaling_min_freq of cpu failed.") -+ return False -+ self.min_freq = int(cmd[0]) -+ -+ return True -+ -+ def set_freq(self, freq, cpu='all'): -+ """ -+ Set CPU frequency -+ :param freq: -+ :param cpu: -+ :return: -+ """ -+ cmd = self.command.run_cmd( -+ "cpupower -c %s frequency-set --freq %s" % (cpu, freq), log_print=False) -+ return cmd[2] == 0 -+ -+ def get_freq(self, cpu): -+ """ -+ Get CPU frequency -+ :param cpu: -+ :return: -+ """ -+ cmd = self.command.run_cmd( -+ "cpupower -c %s frequency-info -w | grep 'frequency' | cut -d ' ' -f 6" % cpu) -+ try: -+ if int(cmd[0]) and cmd[2] == 0: -+ self.logger.info("Get cpu frequency succeed.") -+ except ValueError as e: -+ self.logger.error("Get cpu frequency failed, %s" % e) -+ self.logger.info("Please use 'cpupower frequency-info' to check current frequency manually.") -+ return False -+ return int(cmd[0]) -+ -+ def set_governor(self, governor, cpu='all'): -+ """ -+ Set the frequency governor mode of CPU -+ :param governor: -+ :param cpu: -+ :return: -+ """ -+ cmd = self.command.run_cmd( -+ "cpupower -c %s frequency-set --governor %s" % (cpu, governor), log_print=False) -+ return cmd[2] == 0 -+ -+ def get_governor(self, cpu): -+ """ -+ Get cpu governor -+ :param cpu: -+ :return: -+ """ -+ cmd = self.command.run_cmd( -+ "cpupower -c %s frequency-info -p | grep governor | cut -d '\"' -f 2" % cpu) -+ if cmd[2] != 0: -+ self.logger.error("Get cpu governor failed.") -+ return False -+ self.logger.info("Get cpu governor succeed.") -+ return cmd[0].strip() -+ -+ -+class Load(Thread): -+ """ -+ Let a program run on a specific CPU -+ """ -+ -+ def __init__(self, cpu, command): -+ Thread.__init__(self) -+ self.cpu = cpu -+ self.command = command -+ self.process = None -+ self.returncode = None -+ -+ def run(self): -+ """ -+ Process started -+ :return: -+ """ -+ self.process = self.command.run_cmd( -+ "taskset -c %s python -u %s/cpufreq/cal.py" % (self.cpu, CertEnv.testdirectoy), log_print=False) -+ -+ def get_runtime(self): -+ """ -+ Get the running time of the process -+ :return: -+ """ -+ while self.is_alive(): -+ sleep(0.02) -+ -+ self.returncode = self.process[2] -+ if self.returncode == 0: -+ line = self.process[0] -+ return float(line) -+ return 0 -+ -+ -+class CPUFreqTest(Test): -+ """ -+ CPU frequency test -+ """ -+ -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ['util-linux', 'kernel-tools'] -+ self.cpu = None -+ self.original_governor = None -+ -+ def setup(self, args=None): -+ """ -+ Initialization before test -+ :param args: -+ :return: -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ self.cpu = CPU(self.logger, self.command) -+ self.original_governor = self.cpu.get_governor(0) -+ -+ def test_userspace(self): -+ """ -+ userspace mode of testing CPU frequency -+ :return: -+ """ -+ target_cpu = randint(0, self.cpu.nums-1) -+ target_freq = randint(self.cpu.min_freq, self.cpu.max_freq) -+ if not self.cpu.set_freq(target_freq, cpu=target_cpu): -+ self.logger.error("Set CPU%s to freq %d failed." % -+ (target_cpu, target_freq)) -+ return False -+ self.logger.info("Set CPU%s to freq %d." % (target_cpu, target_freq)) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ self.logger.info("Current freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ target_cpu_governor = self.cpu.get_governor(target_cpu) -+ if target_cpu_governor != 'userspace': -+ self.logger.error("The governor of CPU%s(%s) is not userspace." % -+ (target_cpu, target_cpu_governor)) -+ return False -+ self.logger.info("The governor of CPU%s is %s." % -+ (target_cpu, target_cpu_governor)) -+ -+ # min_freq -> max_runtime -+ self.cpu.set_freq(self.cpu.min_freq) -+ load_list = [] -+ runtime_list = [] -+ for cpu in self.cpu.list: -+ load_test = Load(cpu, self.command) -+ load_test.start() -+ load_list.append(load_test) -+ for cpu in self.cpu.list: -+ runtime = load_list[cpu].get_runtime() -+ runtime_list.append(runtime) -+ max_average_runtime = 1.0 * sum(runtime_list) / len(runtime_list) -+ if max_average_runtime == 0: -+ self.logger.error("Max average time is 0.") -+ return False -+ self.logger.info( -+ "Max average time of all CPUs userspace load test: %.2f" % max_average_runtime) -+ -+ # max_freq -> min_runtime -+ self.cpu.set_freq(self.cpu.max_freq) -+ load_list = [] -+ runtime_list = [] -+ for cpu in self.cpu.list: -+ load_test = Load(cpu, self.command) -+ load_test.start() -+ load_list.append(load_test) -+ for cpu in self.cpu.list: -+ runtime = load_list[cpu].get_runtime() -+ runtime_list.append(runtime) -+ min_average_runtime = 1.0 * sum(runtime_list) / len(runtime_list) -+ if min_average_runtime == 0: -+ self.logger.info("Min average time is 0.") -+ return False -+ self.logger.info( -+ "Min average time of all CPUs userspace load test: %.2f" % min_average_runtime) -+ -+ measured_speedup = 1.0 * max_average_runtime / min_average_runtime -+ expected_speedup = 1.0 * self.cpu.max_freq / self.cpu.min_freq -+ tolerance = 1.0 -+ min_speedup = expected_speedup - (expected_speedup - 1.0) * tolerance -+ max_speedup = expected_speedup + (expected_speedup - 1.0) * tolerance -+ if not min_speedup <= measured_speedup <= max_speedup: -+ self.logger.error("The speedup(%.2f) is not between %.2f and %.2f" % ( -+ measured_speedup, min_speedup, max_speedup)) -+ return False -+ self.logger.info("The speedup(%.2f) is between %.2f and %.2f" % -+ (measured_speedup, min_speedup, max_speedup)) -+ -+ return True -+ -+ def test_ondemand(self): -+ """ -+ ondemand mode of testing CPU frequency -+ :return: -+ """ -+ if not self.cpu.set_governor('powersave'): -+ self.logger.error("Set governor of all CPUs to powersave failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to powersave succeed.") -+ -+ if not self.cpu.set_governor('ondemand'): -+ self.logger.error("Set governor of all CPUs to ondemand failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to ondemand succeed.") -+ -+ target_cpu = randint(0, self.cpu.nums-1) -+ target_cpu_governor = self.cpu.get_governor(target_cpu) -+ if target_cpu_governor != 'ondemand': -+ self.logger.error("The governor of CPU%s(%s) is not ondemand." % ( -+ target_cpu, target_cpu_governor)) -+ return False -+ self.logger.info("The governor of CPU%s is %s." % -+ (target_cpu, target_cpu_governor)) -+ -+ load_test = Load(target_cpu, self.command) -+ load_test.start() -+ sleep(1) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ if target_cpu_freq != self.cpu.max_freq: -+ self.logger.error("The freq of CPU%s(%d) is not scaling_max_freq(%d)." % ( -+ target_cpu, target_cpu_freq, self.cpu.max_freq)) -+ return False -+ self.logger.info("The freq of CPU%s is scaling_max_freq(%d)." % -+ (target_cpu, target_cpu_freq)) -+ -+ load_test_time = load_test.get_runtime() -+ self.logger.info("Time of CPU%s ondemand load test: %.2f" % -+ (target_cpu, load_test_time)) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ if not target_cpu_freq <= self.cpu.max_freq: -+ self.logger.error("The freq of CPU%s(%d) is not less equal than %d." % ( -+ target_cpu, target_cpu_freq, self.cpu.max_freq)) -+ return False -+ self.logger.info("The freq of CPU%s(%d) is less equal than %d." % ( -+ target_cpu, target_cpu_freq, self.cpu.max_freq)) -+ -+ return True -+ -+ def test_conservative(self): -+ """ -+ conservative mode of testing CPU frequency -+ :return: -+ """ -+ if not self.cpu.set_governor('powersave'): -+ self.logger.error("Set governor of all CPUs to powersave failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to powersave.") -+ -+ if not self.cpu.set_governor('conservative'): -+ self.logger.error( -+ "Set governor of all CPUs to conservative failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to conservative.") -+ -+ target_cpu = randint(0, self.cpu.nums-1) -+ target_cpu_governor = self.cpu.get_governor(target_cpu) -+ if target_cpu_governor != 'conservative': -+ self.logger.error("The governor of CPU%s(%s) is not conservative." % -+ (target_cpu, target_cpu_governor)) -+ return False -+ self.logger.info("The governor of CPU%s is %s." % -+ (target_cpu, target_cpu_governor)) -+ -+ load_test = Load(target_cpu, self.command) -+ load_test.start() -+ sleep(1) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ if not self.cpu.min_freq <= target_cpu_freq <= self.cpu.max_freq: -+ self.logger.error("The freq of CPU%s(%d) is not between %d~%d." % -+ (target_cpu, target_cpu_freq, self.cpu.min_freq, self.cpu.max_freq)) -+ return False -+ self.logger.info("The freq of CPU%s(%d) is between %d~%d." % -+ (target_cpu, target_cpu_freq, self.cpu.min_freq, self.cpu.max_freq)) -+ -+ load_test_time = load_test.get_runtime() -+ self.logger.info("Time of CPU%s conservative load test: %.2f" % -+ (target_cpu, load_test_time)) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ self.logger.info("Current freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ return True -+ -+ def test_powersave(self): -+ """ -+ Powersave mode of testing CPU frequency -+ :return: -+ """ -+ if not self.cpu.set_governor('powersave'): -+ self.logger.error("Set governor of all CPUs to powersave failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to powersave.") -+ -+ target_cpu = randint(0, self.cpu.nums-1) -+ target_cpu_governor = self.cpu.get_governor(target_cpu) -+ if target_cpu_governor != 'powersave': -+ self.logger.error("The governor of CPU%s(%s) is not powersave." % -+ (target_cpu, target_cpu_governor)) -+ return False -+ self.logger.info("The governor of CPU%s is %s." % -+ (target_cpu, target_cpu_governor)) -+ -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ if target_cpu_freq != self.cpu.min_freq: -+ self.logger.error("The freq of CPU%s(%d) is not scaling_min_freq(%d)." % -+ (target_cpu, target_cpu_freq, self.cpu.min_freq)) -+ return False -+ self.logger.info("The freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ load_test = Load(target_cpu, self.command) -+ load_test.start() -+ load_test_time = load_test.get_runtime() -+ self.logger.info("Time of CPU%s powersave load test: %.2f" % -+ (target_cpu, load_test_time)) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ self.logger.info("Current freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ return True -+ -+ def test_performance(self): -+ """ -+ Performance mode of testing CPU frequency -+ :return: -+ """ -+ if not self.cpu.set_governor('performance'): -+ self.logger.error( -+ "Set governor of all CPUs to performance failed.") -+ return False -+ self.logger.info("Set governor of all CPUs to performance.") -+ -+ target_cpu = randint(0, self.cpu.nums-1) -+ target_cpu_governor = self.cpu.get_governor(target_cpu) -+ if target_cpu_governor != 'performance': -+ self.logger.error("The governor of CPU%s(%s) is not performance." % -+ (target_cpu, target_cpu_governor)) -+ return False -+ self.logger.info("The governor of CPU%s is %s." % -+ (target_cpu, target_cpu_governor)) -+ -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ if target_cpu_freq != self.cpu.max_freq: -+ self.logger.error("The freq of CPU%s(%d) is not scaling_max_freq(%d)." % -+ (target_cpu, target_cpu_freq, self.cpu.max_freq)) -+ return False -+ self.logger.info("The freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ load_test = Load(target_cpu, self.command) -+ load_test.start() -+ load_test_time = load_test.get_runtime() -+ self.logger.info("Time of CPU%s performance load test: %.2f" % -+ (target_cpu, load_test_time)) -+ target_cpu_freq = self.cpu.get_freq(target_cpu) -+ self.logger.info("Current freq of CPU%s is %d." % -+ (target_cpu, target_cpu_freq)) -+ -+ return True -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ if not self.cpu.get_info(): -+ self.logger.error( -+ "Fail to get CPU info.\n Please check if the CPU supports cpufreq.") -+ return False -+ -+ ret = True -+ self.logger.info("Test userspace.") -+ if not self.test_userspace(): -+ self.logger.error("Test userspace failed.") -+ ret = False -+ -+ self.logger.info("Test ondemand.") -+ if not self.test_ondemand(): -+ self.logger.error("Test ondemand failed.") -+ ret = False -+ -+ self.logger.info("Test conservative.") -+ if not self.test_conservative(): -+ self.logger.error("Test conservative failed.") -+ ret = False -+ -+ self.logger.info("Test powersave.") -+ if not self.test_powersave(): -+ self.logger.error("Test powersave failed.") -+ ret = False -+ -+ self.logger.info("Test performance.") -+ if not self.test_performance(): -+ self.logger.error("Test performance failed.") -+ ret = False -+ -+ self.cpu.set_governor(self.original_governor) -+ return ret -diff -Naur rpm/tests/compatible/cpufreq/Makefile oech/tests/compatible/cpufreq/Makefile ---- rpm/tests/compatible/cpufreq/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/cpufreq/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/disk/common.py oech/tests/compatible/disk/common.py ---- rpm/tests/compatible/disk/common.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/disk/common.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,208 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @cuixucui -+# Create: 2022-09-23 -+ -+import os -+import shutil -+from subprocess import getoutput -+from hwcompatible.device import CertDevice -+ -+ -+def query_disk(logger, command): -+ """ -+ query disk info -+ """ -+ logger.info("Disk Info:", terminal_print=False) -+ command.run_cmd("fdisk -l") -+ logger.info("Partition Info:", terminal_print=False) -+ command.run_cmd("df -h") -+ logger.info("Mount Info:", terminal_print=False) -+ command.run_cmd("mount") -+ logger.info("Swap Info:", terminal_print=False) -+ command.run_cmd("cat /proc/swaps") -+ logger.info("LVM Info:", terminal_print=False) -+ command.run_cmd("pvdisplay") -+ command.run_cmd("vgdisplay") -+ command.run_cmd("lvdisplay") -+ logger.info("Md Info:", terminal_print=False) -+ command.run_cmd("cat /proc/mdstat") -+ -+ -+def get_disk(logger, command, config_data, pci_num=""): -+ """ -+ Get disk info -+ """ -+ disks = list() -+ test_disks = [] -+ devices = CertDevice(logger).get_devices() -+ for device in devices: -+ if (device.get_property("DEVTYPE") == "disk" and not device.get_property("ID_TYPE")) or\ -+ device.get_property("ID_TYPE") == "disk": -+ if "/host" in device.get_property("DEVPATH"): -+ if isinstance(config_data, str): -+ disks.append(device.get_name()) -+ elif pci_num in device.get_property("DEVPATH"): -+ disks.append(device.get_name()) -+ -+ command.run_cmd("/usr/sbin/swapon -a") -+ with open("/proc/partitions", "r") as partition_file: -+ partition = partition_file.read() -+ -+ with open("/proc/swaps", "r") as swap_file: -+ swap = swap_file.read() -+ -+ with open("/proc/mdstat", "r") as mdstat_file: -+ mdstat = mdstat_file.read() -+ -+ with open("/proc/mounts", "r") as mount_file: -+ mounts = mount_file.read() -+ -+ for disk in disks: -+ if disk not in partition or ("/dev/%s" % disk) in swap: -+ continue -+ if ("/dev/%s" % disk) in mounts or disk in mdstat: -+ continue -+ result = command.run_cmd("pvs | grep -q '/dev/%s'" % disk) -+ if result[2] == 0: -+ continue -+ test_disks.append(disk) -+ -+ un_suitable = list(set(disks).difference(set(test_disks))) -+ if len(un_suitable) > 0: -+ logger.info("These disks %s are in use now, skip them." % "|".join(un_suitable)) -+ return test_disks -+ -+ -+def raw_test(logger, command, disk): -+ """ -+ Raw test -+ """ -+ logger.info("%s raw IO test" % disk) -+ device = os.path.join("/dev", disk) -+ if not os.path.exists(device): -+ logger.error("Device %s doesn't exist." % device) -+ return False -+ proc_path = os.path.join("/sys/block/", disk) -+ if not os.path.exists(proc_path): -+ proc_path = os.path.join("/sys/block/*/", disk) -+ size = getoutput("cat %s/size" % proc_path) -+ size = int(size) / 2 -+ if size <= 0: -+ logger.error( -+ "Device %s size is not suitable for testing." % device) -+ return False -+ elif size > 1048576: -+ size = 1048576 -+ -+ logger.info("Starting sequential raw IO test...") -+ opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" -+ if not do_fio(logger, command, device, size, opts): -+ logger.error("%s sequential raw IO test failed." % device) -+ return False -+ -+ logger.info("Starting rand raw IO test...") -+ opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ -+ "-group_reporting -name=file -runtime=300" -+ if not do_fio(logger, command, device, size, opts): -+ logger.error("%s rand raw IO test failed." % device) -+ return False -+ -+ return True -+ -+ -+def vfs_test(logger, command, disk, filesystems): -+ """ -+ Vfs test -+ """ -+ logger.info("%s vfs test" % disk) -+ device = os.path.join("/dev/", disk) -+ if not os.path.exists(device): -+ logger.error("Device %s doesn't exist." % device) -+ return False -+ proc_path = os.path.join("/sys/block/", disk) -+ if not os.path.exists(proc_path): -+ proc_path = os.path.join("/sys/block/*/", disk) -+ size = getoutput("cat %s/size" % proc_path) -+ size = int(size) / 2 / 2 -+ if size <= 0: -+ logger.error( -+ "Device %s size is not suitable for testing." % device) -+ return False -+ elif size > 1048576: -+ size = 1048576 -+ -+ if os.path.exists("vfs_test"): -+ shutil.rmtree("vfs_test") -+ os.mkdir("vfs_test") -+ path = os.path.join(os.getcwd(), "vfs_test") -+ -+ return_code = True -+ for file_sys in filesystems: -+ logger.info("Formatting %s to %s ..." % -+ (device, file_sys), terminal_print=False) -+ command.run_cmd("umount %s" % device, ignore_errors=True) -+ command.run_cmd("mkfs -t %s -F %s" % (file_sys, device)) -+ command.run_cmd("mount -t %s %s %s" % -+ (file_sys, device, "vfs_test")) -+ logger.info("Starting sequential vfs IO test...") -+ opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -name=directoy -runtime=300" -+ if not do_fio(logger, command, path, size, opts): -+ return_code = False -+ break -+ -+ logger.info("Starting rand vfs IO test...") -+ opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 -name=directoy -runtime=300" -+ if not do_fio(logger, command, path, size, opts): -+ return_code = False -+ break -+ -+ command.run_cmd("umount %s" % device) -+ shutil.rmtree("vfs_test") -+ return return_code -+ -+ -+def do_fio(logger, command, filepath, size, option): -+ """ -+ Fio test -+ """ -+ if os.path.isdir(filepath): -+ file_opt = "-directory=%s" % filepath -+ else: -+ file_opt = "-filename=%s" % filepath -+ max_bs = 64 -+ a_bs = 4 -+ while a_bs <= max_bs: -+ cmd_result = command.run_cmd( -+ "fio %s -size=%dK -bs=%dK %s" % (file_opt, size, a_bs, option)) -+ if cmd_result[2] != 0: -+ logger.error("%s fio failed." % filepath) -+ return False -+ a_bs = a_bs * 2 -+ logger.info("%s fio succeed." % filepath) -+ return True -+ -+ -+def valid_disk(logger, disk, disks): -+ """ -+ Is the disk valid -+ """ -+ result = True -+ if disk: -+ if disk != "all" and disk not in disks: -+ logger.error("%s is in use or disk does not exist." % disk) -+ result = False -+ else: -+ logger.error("Failed to get disk information.") -+ result = False -+ return result -diff -Naur rpm/tests/compatible/disk/disk.py oech/tests/compatible/disk/disk.py ---- rpm/tests/compatible/disk/disk.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/disk/disk.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,66 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: Disk test -+ -+import argparse -+from hwcompatible.test import Test -+from hwcompatible.command import Command -+from common import query_disk, get_disk, raw_test, vfs_test, valid_disk -+ -+ -+class DiskTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.disks = list() -+ self.requirements = ["fio"] -+ self.filesystems = ["ext4"] -+ self.config_data = "" -+ -+ def setup(self, args=None): -+ """ -+ The Setup before testing -+ :return: -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ self.config_data = getattr(self.args, "config_data", None) -+ query_disk(self.logger, self.command) -+ -+ def test(self): -+ """ -+ Start test -+ """ -+ self.disks = get_disk(self.logger, self.command, self.config_data) -+ if len(self.disks) == 0: -+ self.logger.error("No suite disk found to test.") -+ return False -+ -+ if not self.config_data: -+ self.logger.error("Failed to get disk from configuration file.") -+ return False -+ disk = self.config_data -+ result = valid_disk(self.logger, disk, self.disks) -+ if not result: -+ return False -+ -+ return_code = True -+ if disk != "all": -+ self.disks = [disk] -+ for disk in self.disks: -+ if not raw_test(self.logger, self.command, disk): -+ return_code = False -+ if not vfs_test(self.logger, self.command, disk, self.filesystems): -+ return_code = False -+ return return_code -diff -Naur rpm/tests/compatible/disk/Makefile oech/tests/compatible/disk/Makefile ---- rpm/tests/compatible/disk/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/disk/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/dpdk/dpdk.py oech/tests/compatible/dpdk/dpdk.py ---- rpm/tests/compatible/dpdk/dpdk.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/dpdk/dpdk.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,439 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Author: @ylzhangah -+# Create: 2022-12-01 -+# Desc: DPDK test -+ -+ -+import os -+import argparse -+import json -+import time -+import subprocess -+ -+from urllib.parse import urlencode -+from urllib.request import urlopen, Request -+ -+from hwcompatible.test import Test -+from hwcompatible.command import Command -+from hwcompatible.document import CertDocument -+from hwcompatible.env import CertEnv -+from hwcompatible.constants import FILE_FLAGS, FILE_MODES -+from hugepages import ShowHugepages -+ -+ -+class DPDKTest(Test): -+ """ -+ DPDK test -+ """ -+ -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["dpdk", "dpdk-tools", "dpdk-devel"] -+ self.config_data = dict() -+ self.interface = None -+ self.server_ip = "" -+ self.server_port = 80 -+ self.portmask = "0xffff" -+ self.packet_size = 1514 -+ self.support_driver = ['mlx4_core', 'mlx5_core', 'ixgbe', 'ice', 'hinic', 'igc'] -+ self.dpdk_driver = 'uio_pci_generic' -+ self.kernel_driver = None -+ self.retries = 3 -+ self.speed = 0 # Mb/s -+ self.target_bandwidth_percent = 0.8 -+ self.device = "" -+ self.pci = "" -+ self.card_id = None -+ self.ethpeer = None -+ self.test_dpdk_file = "" -+ -+ def setup(self, args=None): -+ """ -+ Initialization before test -+ :return: -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ self.hugepage = ShowHugepages(self.logger, self.command) -+ self.test_dpdk_file = os.path.join(self.logger.logdir, 'test_dpdk.log') -+ self.device = getattr(self.args, 'device', None) -+ self.interface = self.device.get_property("INTERFACE") -+ self.show_driver_info() -+ self.pci = self.device.get_pci() -+ self.kernel_driver = self.device.get_driver() -+ self.card_id = self.device.get_quadruple() -+ self.command.run_cmd("dpdk-hugepages.py -u", terminal_print=False) -+ self.command.run_cmd("dpdk-hugepages.py -c", terminal_print=False) -+ self.command.run_cmd("dpdk-hugepages.py --setup 2G", terminal_print=True) -+ self.config_data = getattr(args, "config_data", None) -+ self.server_ip = CertDocument(CertEnv.certificationfile, self.logger).get_server() -+ self.test_prepare() -+ -+ def get_interface_speed(self): -+ """ -+ Get speed on the interface -+ :return: -+ """ -+ speed = self.command.run_cmd( -+ "ethtool %s | grep Speed | awk '{print $2}'" % self.interface) -+ if speed[2] != 0: -+ self.logger.error("No speed found on the interface.") -+ return 0 -+ -+ return int(speed[0][:-5]) -+ -+ def check_bind(self): -+ """ -+ Check whether binding card is required -+ :return: -+ """ -+ # set interface down so that bind the dpdk driver. -+ if self.kernel_driver not in self.support_driver: -+ self.logger.error("The card driver %s doesn't support dpdk test, Supported drivers are %s." -+ % (self.kernel_driver, self.support_driver)) -+ return False -+ else: -+ self.logger.info("DPDK driver is loading...") -+ subprocess.getoutput("modprobe uio; modprobe %s" % self.dpdk_driver) -+ if self.command.run_cmd("lsmod | grep %s" % self.dpdk_driver, terminal_print=True)[2] != 0: -+ self.logger.error("DPDK driver is loaded failed!") -+ return False -+ else: -+ self.logger.info("Get server card's ethpeer...") -+ if not self.get_ethpeer(): -+ return False -+ if self.kernel_driver == "mlx4_core" or self.kernel_driver == "mlx5_core": -+ self.logger.info("The mellanox network card does not need to be bound.") -+ self.command.run_cmd("modprobe -a ib_uverbs mlx5_core mlx5_ib mlx4_core", terminal_print=True) -+ else: -+ self.logger.info("Server dpdk is binding...") -+ if not self.server_dpdk_bind(): -+ return False -+ self.logger.info("Client dpdk is binding...") -+ if not self.client_dpdk_bind(): -+ return False -+ return True -+ -+ def get_ethpeer(self): -+ """ -+ Get ethpeer. -+ :return: -+ """ -+ form = {'serverip': self.server_ip, 'cardid': self.card_id} -+ url = 'http://{}:%s/api/get/ethpeer'.format(self.server_ip) % self.server_port -+ data = urlencode(form).encode('utf8') -+ headers = { -+ 'Content-type': 'application/x-www-form-urlencoded', -+ 'Accept': 'text/plain' -+ } -+ request = Request(url, data=data, headers=headers) -+ try: -+ response = urlopen(request) -+ except Exception: -+ self.logger.error("Call remote server url %s failed." % url) -+ return False -+ self.logger.info(str(response.headers), terminal_print=False) -+ self.ethpeer = json.loads(response.read())['ethpeer'] -+ self.logger.info("The mac of the server card is %s" % self.ethpeer) -+ self.logger.info("Status: %u %s" % (response.code, response.msg)) -+ if response.code != 200: -+ return False -+ return True -+ -+ def client_dpdk_bind(self): -+ """ -+ Bind client card with dpdk driver -+ :return: -+ """ -+ self.logger.info("Setting client interface %s down." % self.interface) -+ if not self.ifdown(self.interface): -+ self.logger.error("Setting client interface down failed!") -+ return False -+ else: -+ self.logger.info("Client dpdk is binding...") -+ cmd = self.command.run_cmd("dpdk-devbind.py -b %s %s" % (self.dpdk_driver, self.interface)) -+ if cmd[2] == 0: -+ self.logger.info("Client dpdk is bound successfully!") -+ self.command.run_cmd("dpdk-devbind.py -s") -+ return True -+ else: -+ self.logger.error("Bind card with dpdk driver failed!") -+ return False -+ -+ def server_dpdk_bind(self): -+ """ -+ Bind the server card. -+ :return: -+ """ -+ form = {'serverip': self.server_ip, 'cardid': self.card_id} -+ url = 'http://{}:%s/api/bind/server'.format(self.server_ip) % self.server_port -+ data = urlencode(form).encode('utf8') -+ headers = { -+ 'Content-type': 'application/x-www-form-urlencoded', -+ 'Accept': 'text/plain' -+ } -+ request = Request(url, data=data, headers=headers) -+ try: -+ response = urlopen(request) -+ except Exception: -+ self.logger.error("Call remote server url %s failed." % url) -+ return False -+ self.logger.info(str(response.headers), terminal_print=False) -+ self.logger.info("Status: %u %s" % (response.code, response.msg)) -+ if response.code != 200: -+ return False -+ return True -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ if not self.test_icmp(): -+ return False -+ -+ if not self.check_bind(): -+ return False -+ -+ self.logger.info("Start dpdk-testpmd server...") -+ if not self.call_remote_server('dpdk-testpmd', 'start'): -+ self.logger.error("[X] start dpdk-testpmd server failed.") -+ return False -+ -+ self.logger.info("Test dpdk speed...") -+ if not self.test_speed(): -+ self.logger.error("Test dpdk speed failed.") -+ return False -+ -+ self.logger.info("Stop dpdk-testpmd server...") -+ if not self.call_remote_server('dpdk-testpmd', 'stop'): -+ self.logger.error("[X] Stop dpdk-testpmd server failed.") -+ return False -+ -+ return True -+ -+ def show_hugepage(self): -+ """ -+ Show Hugepages on system. -+ :return: -+ """ -+ if self.hugepage.is_numa(): -+ self.hugepage.show_numa_pages() -+ else: -+ self.hugepage.show_non_numa_pages() -+ -+ def test_prepare(self): -+ """ -+ Preparation before test -+ :return: -+ """ -+ if not self.hugepage.check_hugepage_allocate(self.hugepage.is_numa()): -+ self.logger.error("No hugepage allocated.") -+ return False -+ -+ if not self.hugepage.get_mountpoints(): -+ self.logger.error("No hugepage mounted.") -+ return False -+ -+ self.logger.info("Hugepage successfully configured.") -+ self.show_hugepage() -+ -+ return True -+ -+ def test_speed(self): -+ """ -+ Test speed -+ :return: -+ """ -+ command = [ -+ 'dpdk-testpmd', -+ '-l', '0-1', -+ '-n', '1', -+ '-a', self.pci, -+ '--', -+ '--portmask=0x1', -+ '--txpkts=%d' % self.packet_size, -+ '--rxq=4', -+ '--txq=4', -+ '--forward-mode=txonly', -+ '--eth-peer=0,%s' % self.ethpeer, -+ '--stats-period=2' -+ ] -+ res = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -+ self.logger.info("Please wait 30 seconds.") -+ time.sleep(30) -+ res.terminate() -+ with os.fdopen(os.open(self.test_dpdk_file, FILE_FLAGS, FILE_MODES), "w") as log: -+ log.write(str(res.stdout.read(), 'UTF-8')) -+ time.sleep(30) -+ res = self.command.run_cmd("grep Tx-bps %s | awk '{print $4}'" % self.test_dpdk_file) -+ if res[2] != 0: -+ self.logger.error("The test data result is empty, Please check if the server is configured properly!") -+ res_list = res[0].split("\n")[-10:-1] -+ int_list = [int(x) for x in res_list] -+ number = len(int_list) -+ if number != 0: -+ bandwidth = float(sum(int_list) / number / 1e6) -+ # 1e6 = 1000000.0 -+ target_bandwidth = self.target_bandwidth_percent * self.speed -+ self.logger.info("Current bandwidth is around %.2f Mb/s, target is %.2fMb/s" % -+ (bandwidth, target_bandwidth)) -+ if bandwidth > target_bandwidth: -+ self.logger.info("Test dpdk bandwidth successfully.") -+ return True -+ self.logger.error("Test dpdk bandwidth failed!") -+ return False -+ else: -+ self.logger.error("No data obtained for testing dpdk, Please manually check!") -+ return False -+ -+ def ifdown(self, interface): -+ """ -+ Judge whether the specified interface is closed successfully -+ :param interface: -+ :return: -+ """ -+ self.command.run_cmd("ip link set down %s" % interface) -+ for _ in range(10): -+ result = self.command.run_cmd( -+ "ip link show %s | grep 'state DOWN'" % interface, ignore_errors=True) -+ if result[2] == 0: -+ self.logger.info("Set interface %s down succeed." % self.interface) -+ return True -+ time.sleep(1) -+ -+ self.logger.error("Set interface %s down failed." % self.interface) -+ return False -+ -+ def ifup(self, interface): -+ """ -+ Judge whether the specified interface is enabled successfully -+ :param interface: -+ :return: -+ """ -+ self.command.run_cmd("ip link set up %s" % interface) -+ for _ in range(10): -+ result = self.command.run_cmd( -+ "ip link show %s | grep 'state UP'" % interface, ignore_errors=True) -+ if result[2] == 0: -+ self.logger.info("Set interface %s up succeed." % self.interface) -+ return True -+ time.sleep(1) -+ -+ self.logger.error("Set interface %s up failed." % self.interface) -+ return False -+ -+ def test_icmp(self): -+ """ -+ Test ICMP -+ :return: -+ """ -+ self.speed = self.get_interface_speed() -+ if self.speed: -+ self.logger.info("The speed of %s is %sMb/s." % -+ (self.interface, self.speed)) -+ else: -+ self.logger.error("Set speed of %s failed." % self.interface) -+ -+ count = 500 -+ cmd = "ping -q -c %d -i 0 %s | grep 'packet loss' | awk '{print $6}'" % ( -+ count, self.server_ip) -+ for _ in range(self.retries): -+ result = self.command.run_cmd(cmd, ignore_errors=True) -+ if result[0].strip() == "0%": -+ self.logger.info("Test icmp succeed.") -+ return True -+ self.logger.error("Test icmp failed.") -+ return False -+ -+ def call_remote_server(self, cmd, act='start'): -+ """ -+ Connect to the server somehow. -+ :param cmd: -+ :param act: -+ :return: -+ """ -+ form = dict() -+ form = {'cmd': cmd, 'serverip': self.server_ip, 'cardid': self.card_id} -+ url = 'http://%s/api/%s' % (self.server_ip, act) -+ data = urlencode(form).encode('utf8') -+ headers = { -+ 'Content-type': 'application/x-www-form-urlencoded', -+ 'Accept': 'text/plain' -+ } -+ request = Request(url, data=data, headers=headers) -+ try: -+ response = urlopen(request) -+ except Exception: -+ self.logger.error("Call remote dpdk server url %s failed." % url) -+ return False -+ self.logger.info("Status: %u %s" % (response.code, response.msg)) -+ return int(response.code) == 200 -+ -+ def server_dpdk_unbind(self): -+ """ -+ Unbind the server card. -+ :return: -+ """ -+ form = {'serverip': self.server_ip, 'cardid': self.card_id} -+ url = 'http://{}/api/unbind/server'.format(self.server_ip) -+ data = urlencode(form).encode('utf8') -+ headers = { -+ 'Content-type': 'application/x-www-form-urlencoded', -+ 'Accept': 'text/plain' -+ } -+ request = Request(url, data=data, headers=headers) -+ try: -+ response = urlopen(request) -+ except Exception: -+ self.logger.error("Call remote server url %s failed." % url) -+ return False -+ -+ self.logger.info("Status: %u %s" % (response.code, response.msg)) -+ if response.code != 200: -+ return False -+ return True -+ -+ def dev_unbind(self): -+ """ -+ dpdk unbind -+ :return: -+ """ -+ self.logger.info("Unbinding server card...") -+ if self.server_dpdk_unbind(): -+ self.logger.info("Unbind server card successfully!") -+ -+ self.logger.info("Unbinding client card...") -+ self.command.run_cmd("dpdk-devbind.py -u %s" % self.pci) -+ cmd = self.command.run_cmd("dpdk-devbind.py -b %s %s" % (self.kernel_driver, self.pci)) -+ if cmd[0] == "": -+ self.logger.info("Unbinding client card successfully!") -+ -+ self.logger.info("Setting client interface %s up..." % self.interface) -+ if not self.ifup(self.interface): -+ return False -+ return True -+ -+ def teardown(self): -+ """ -+ Environment recovery after test -+ :return: -+ """ -+ if self.kernel_driver == "mlx4_core" or self.kernel_driver == "mlx5_core": -+ self.logger.info("The Mellanox card need not unbind!") -+ else: -+ self.dev_unbind() -+ self.call_remote_server('all', 'stop') -+ self.logger.info("Stop all test servers.") -diff -Naur rpm/tests/compatible/dpdk/hugepages.py oech/tests/compatible/dpdk/hugepages.py ---- rpm/tests/compatible/dpdk/hugepages.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/dpdk/hugepages.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,106 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @ylzhangah -+# Create: 2022-12-01 -+# Desc: DPDK test -+ -+ -+import os -+import glob -+from math import log2 -+ -+ -+class ShowHugepages: -+ """ -+ Format memsize, get moutpoint, show hugepages -+ """ -+ -+ def __init__(self, logger, command): -+ self.logger = logger -+ self.command = command -+ -+ def format_memsize(self, kb): -+ """" -+ format memsize. this is a code snippit from dpdk repo -+ """ -+ binary_prefix = "KMG" -+ logk = int(log2(kb) / 10) -+ suffix = binary_prefix[logk] -+ unit = 2 ** (logk * 10) -+ if unit != 0: -+ return '{}{}b'.format(int(kb / unit), suffix) -+ else: -+ return False -+ -+ def get_mountpoints(self): -+ """ -+ Get list of where hugepage filesystem is mounted -+ """ -+ mounted = self.command.run_cmd("mount | grep hugetlbfs | awk '{print $2}'")[0].strip('\n') -+ return mounted -+ -+ def is_numa(self): -+ """ -+ Test if numa is used on this system -+ """ -+ return os.path.exists('/sys/devices/system/node') -+ -+ def show_numa_pages(self): -+ """ -+ Show huge page reservations on numa system -+ """ -+ self.logger.info('Node Pages Size Total') -+ for numa_path in glob.glob('/sys/devices/system/node/node*'): -+ node = numa_path[29:] # slice after /sys/devices/system/node/node -+ path = os.path.join(numa_path, 'hugepages') -+ for hdir in os.listdir(path): -+ comm = self.command.run_cmd("cat %s/%s/nr_hugepages" % (path, hdir)) -+ pages = int(comm[0].strip('\n')) -+ if pages > 0: -+ kb = int(hdir[10:-2]) # slice out of hugepages-NNNkB -+ self.logger.info('{:<4} {:<5} {:<6} {}'.format(node, pages, -+ self.format_memsize(kb), self.format_memsize(pages * kb))) -+ -+ def show_non_numa_pages(self): -+ """ -+ Show huge page reservations on non numa system -+ """ -+ self.logger.info('Pages Size Total') -+ hugepagedir = '/sys/kernel/mm/hugepages/' -+ for hdir in os.listdir(hugepagedir): -+ comm = self.command.run_cmd("cat %s/%s/nr_hugepages" % (hugepagedir, hdir)) -+ pages = int(comm[0].strip('\n')) -+ if pages > 0: -+ kb = int(hdir[10:-2]) -+ -+ self.logger.info('{:<5} {:<6} {}'.format(pages, self.format_memsize(kb), -+ self.format_memsize(pages * kb))) -+ -+ def check_hugepage_allocate(self, isnuma): -+ if not isnuma: -+ hugepagedir = '/sys/kernel/mm/hugepages/' -+ else: -+ numaid = 0 -+ hugepagedir = '/sys/devices/system/node/node%d/hugepages/' % numaid -+ -+ for (_, dirs, _) in os.walk(hugepagedir): -+ for directory in dirs: -+ comm = self.command.run_cmd("cat %s/%s/nr_hugepages" % (hugepagedir, directory)) -+ if comm[0] != 0: -+ return True -+ break -+ -+ return False -+ -+ # return false when -+ # 1. no files in hugepagedir; -+ # 2. no non-zero entry was found; -diff -Naur rpm/tests/compatible/dpdk/Makefile oech/tests/compatible/dpdk/Makefile ---- rpm/tests/compatible/dpdk/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/dpdk/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,24 @@ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @ylzhangah -+# Create: 2022-12-01 -+# Desc: DPDK test -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a $(SUBDIR)/build *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/fc/fc.py oech/tests/compatible/fc/fc.py ---- rpm/tests/compatible/fc/fc.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/fc/fc.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,96 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-04-09 -+# Desc: Fibre channel test -+ -+import argparse -+from hwcompatible.test import Test -+from hwcompatible.command import Command -+from tests.compatible.disk.common import query_disk, get_disk, raw_test, vfs_test, valid_disk -+ -+ -+class FCTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.disks = list() -+ self.requirements = ["fio"] -+ self.filesystems = ["ext4"] -+ self.device = "" -+ self.pci_num = "" -+ self.config_data = dict() -+ -+ def setup(self, args=None): -+ """ -+ The Setup before testing -+ :return: -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ self.config_data = getattr(self.args, "config_data", None) -+ -+ self.device = getattr(self.args, 'device', None) -+ self.pci_num = self.device.get_property("DEVPATH").split('/')[-1] -+ self.show_driver_info() -+ self.logger.info("Vendor Info:", terminal_print=False) -+ self.command.run_cmd("lspci -s %s -v" % self.pci_num) -+ query_disk(self.logger, self.command) -+ -+ def test(self): -+ """ -+ Start test -+ """ -+ pci_num = self.check_link_state() -+ if not pci_num: -+ return False -+ self.disks = get_disk(self.logger, self.command, self.config_data, pci_num) -+ if len(self.disks) == 0: -+ self.logger.error("No suite disk found to test.") -+ return False -+ -+ if not self.config_data: -+ self.logger.error("Failed to get disk from configuration file.") -+ return False -+ -+ disk = self.config_data.get('disk', '') -+ if not valid_disk(self.logger, disk, self.disks): -+ return False -+ -+ return_code = True -+ if disk != "all": -+ self.disks = [disk] -+ for disk in self.disks: -+ if not raw_test(self.logger, self.command, disk): -+ return_code = False -+ if not vfs_test(self.logger, self.command, disk, self.filesystems): -+ return_code = False -+ return return_code -+ -+ def check_link_state(self): -+ """ -+ check HBA link state -+ """ -+ host_name = self.command.run_cmd("ls -l /sys/class/fc_host | grep %s | awk '{print $9}'" -+ % self.pci_num)[0].strip('\n') -+ port_state = self.command.run_cmd("cat /sys/class/fc_host/%s/port_state" % host_name)[0].strip('\n') -+ if port_state == "Linkdown": -+ self.logger.error("The HBA's port_state is linkdown, Please check the connection state!") -+ return "" -+ elif port_state == "Online": -+ pci_num = self.pci_num -+ self.logger.info("The HBA's port_state is Online, start testing...") -+ return pci_num -+ else: -+ self.logger.info("The HBA's port_state can't be viewed") -+ return False -+ -diff -Naur rpm/tests/compatible/fc/Makefile oech/tests/compatible/fc/Makefile ---- rpm/tests/compatible/fc/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/fc/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-04-09 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/gpu/amd_gpu.py oech/tests/compatible/gpu/amd_gpu.py ---- rpm/tests/compatible/gpu/amd_gpu.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/amd_gpu.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,141 @@ -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-10-15 -+# Desc: AMD GPU test (This test could only execute on graphical.target) -+ -+import os -+from subprocess import getstatusoutput -+ -+gpu_dir = os.path.dirname(os.path.realpath(__file__)) -+ -+ -+class AMDGpuTest(): -+ def __init__(self, device, logger, command): -+ self.device = device -+ self.logger = logger -+ self.command = command -+ self.radeontop_log = os.path.join(self.logger.logdir, 'radeontop.log') -+ self.screen_info_log = os.path.join( -+ self.logger.logdir, 'screen_info.log') -+ self.glmark_log = os.path.join(self.logger.logdir, 'glmark2.log') -+ -+ def get_driver_info(self): -+ """ -+ Get driver info, includings name, version -+ """ -+ self.logger.info("Vendor Info:", terminal_print=False) -+ self.command.run_cmd('lspci -vs %s' % self.device.pci) -+ -+ self.logger.info("Driver Info:", terminal_print=False) -+ driver = self.device.driver -+ self.logger.info("Driver Name: %s" % driver) -+ -+ driver_version = self.device.get_driver_version() -+ if driver_version: -+ self.logger.info("Driver Version: %s" % driver_version) -+ else: -+ self.logger.warning( -+ "The driver version information cannot be obtained. Please view it manually.") -+ -+ def test_pressure(self): -+ """ -+ Set pressure for gpu to test -+ This test need graphical.target to support -+ Returns: -+ bool: -+ """ -+ os.chdir("/opt/glmark2/build/src") -+ cmd = getstatusoutput( -+ './glmark2 --off-screen | tee %s' % self.glmark_log) -+ if cmd[0] != 0: -+ self.logger.error("Test gpu pressure failed.") -+ return False -+ self.logger.info("Test gpu pressure succeed.") -+ -+ cmd = self.command.run_cmd( -+ "grep 'glmark2 Score' %s" % self.glmark_log) -+ if cmd[2] == 0: -+ self.logger.info("Check gpu glmark2 score succeed.") -+ else: -+ self.logger.error("Check gpu glmark2 score failed.") -+ return False -+ -+ return True -+ -+ def test_screen_info(self): -+ """ -+ Test screen information for gpu -+ This test need graphical.target to support -+ Returns: -+ bool: -+ """ -+ os.chdir("/opt/glmark2/build/src") -+ cmd = self.command.run_cmd( -+ "./glmark2 -l | tee %s " % self.screen_info_log) -+ if cmd[2] == 0: -+ self.logger.info("Test gpu screen information succeed.") -+ else: -+ self.logger.error("Test gpu screen information failed.") -+ return False -+ -+ return True -+ -+ def test_radeontop(self): -+ """ -+ Check gpu utilization by radeontop, it can execute multi times and has log file -+ Returns: -+ bool: -+ """ -+ os.chdir("/opt/radeontop") -+ cmd = getstatusoutput( -+ "echo q | ./radeontop | tee %s" % self.radeontop_log) -+ if cmd[0] == 0: -+ self.logger.info("Check gpu radeontop succeed.") -+ else: -+ self.logger.error("Check gpu radeontop failed.") -+ return False -+ -+ return True -+ -+ def test_amd_gpu(self): -+ """ -+ AMD gpu test entry function -+ Returns: -+ bool: -+ """ -+ result = True -+ self.get_driver_info() -+ self.command.run_cmd( -+ "bash %s/test_amd_gpu.sh install_readontop" % gpu_dir) -+ self.command.run_cmd( -+ "bash %s/test_amd_gpu.sh install_glmark2" % gpu_dir) -+ -+ self.logger.info("Check gpu radeontop.") -+ try: -+ if not self.test_radeontop(): -+ result = False -+ -+ if not self.test_screen_info(): -+ result = False -+ -+ self.logger.info("Start to test gpu pressure.") -+ if not self.test_pressure(): -+ result = False -+ self.logger.info("End to test gpu pressure.") -+ -+ except Exception as e: -+ self.logger.error( -+ "Failed to run the script because compiling or setting variables: %s" % e) -+ result = False -+ -+ return result -diff -Naur rpm/tests/compatible/gpu/gpu.py oech/tests/compatible/gpu/gpu.py ---- rpm/tests/compatible/gpu/gpu.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/gpu.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,54 @@ -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-04-13 -+# Desc: GPU test, support AMD/NVIDIA series gpu -+ -+import argparse -+from hwcompatible.command import Command -+from hwcompatible.test import Test -+from nvidia_gpu import NvidiaGpuTest -+from amd_gpu import AMDGpuTest -+ -+ -+class GpuTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["gcc-c++", "make", "git"] -+ self.device = None -+ -+ def setup(self, args=None): -+ """ -+ Initialization before test -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(args, "test_logger", None) -+ self.device = getattr(args, 'device', None) -+ self.command = Command(self.logger) -+ -+ def test(self): -+ """ -+ Test case -+ Returns: -+ bool: Execution result -+ """ -+ driver = self.device.driver -+ if driver == "amdgpu": -+ amd_test = AMDGpuTest(self.device, self.logger, self.command) -+ result = amd_test.test_amd_gpu() -+ else: -+ nvidia_test = NvidiaGpuTest(self.device, self.logger, self.command) -+ result = nvidia_test.test_nvidia_gpu() -+ -+ return result -+ -+ -\ No newline at end of file -diff -Naur rpm/tests/compatible/gpu/Makefile oech/tests/compatible/gpu/Makefile ---- rpm/tests/compatible/gpu/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,23 @@ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-04-13 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ cp -a *.sh $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/gpu/nvidia_gpu.py oech/tests/compatible/gpu/nvidia_gpu.py ---- rpm/tests/compatible/gpu/nvidia_gpu.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/nvidia_gpu.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,154 @@ -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-10-14 -+# Desc: Nvidia GPU test -+ -+import os -+import re -+import time -+from subprocess import getstatusoutput -+gpu_dir = os.path.dirname(os.path.realpath(__file__)) -+ -+ -+class NvidiaGpuTest(): -+ def __init__(self, device, logger, command): -+ self.device = device -+ self.logger = logger -+ self.command = command -+ self.cuda_samples_log = os.path.join( -+ self.logger.logdir, 'cuda_samples.log') -+ self.gpu_burn = os.path.join(self.logger.logdir, 'gpu_burn.log') -+ self.smi_name = "nvidia-smi" -+ -+ def get_driver_info(self): -+ """ -+ Get driver info, includings name, version -+ """ -+ self.logger.info("Vendor Info:", terminal_print=False) -+ self.command.run_cmd('lspci -vs %s' % self.device.pci) -+ -+ self.logger.info("Driver Info:", terminal_print=False) -+ driver = self.device.driver -+ if driver == "iluvatar-itr": -+ self.smi_name = "ixsmi" -+ driver = "bi_driver" -+ self.device.set_driver(driver) -+ self.logger.info("Driver Name: %s" % driver) -+ -+ driver_version = self.device.get_driver_version() -+ if driver_version: -+ self.logger.info("Driver Version: %s" % driver_version) -+ else: -+ self.logger.warning( -+ "The driver version information cannot be obtained. Please view it manually.") -+ -+ def set_default_gpu(self): -+ pci = [] -+ num = [] -+ pci_key = "GPU 0000" + self.device.get_pci() -+ gpu = self.command.run_cmd('%s -q' % self.smi_name, log_print=False) -+ for line in gpu[0].split("\n"): -+ if "GPU 0000" in line: -+ pci.append(line) -+ if "Minor Number" in line: -+ num.append(line) -+ id_num = 0 -+ output = dict(zip(pci, num)) -+ if pci_key in output.keys(): -+ id_num = str(re.findall("\d+", output[pci_key])).strip("['']") -+ os.environ['CUDA_VISIBLE_DEVICES'] = id_num -+ -+ self.logger.info("Set default test gpu as %s." % id_num) -+ -+ def test_pressure(self): -+ """ -+ Set pressure for gpu to test -+ Returns: -+ bool: -+ """ -+ self.logger.info("Monitor GPU temperature and utilization rate.") -+ pci_num = self.device.get_pci() -+ self.command.run_cmd(self.smi_name) -+ self.command.run_cmd( -+ "bash %s/test_nvidia_gpu.sh install_gpu_burn" % gpu_dir) -+ -+ os.chdir("/opt/gpu-burn") -+ cmd = self.command.run_cmd( -+ "nvidia-smi -q | grep -i -A1 '%s' | grep 'Product Name' | cut -d ':' -f 2" % pci_num) -+ device_name = cmd[0].strip() -+ cmd = self.command.run_cmd( -+ "./gpu_burn -l | grep -i '%s' | cut -d ':' -f 1 | awk '{print $2}'" % device_name) -+ run_id = cmd[0].strip() -+ cmd = getstatusoutput( -+ 'nohup ./gpu_burn -i%s 10 &> %s &' % (run_id, self.gpu_burn)) -+ if cmd[0] != 0: -+ self.logger.error("Execute gpu_burn failed.") -+ return False -+ self.logger.info("Execute gpu_burn succeed.") -+ -+ time_start = time.time() -+ while 1: -+ cmd = self.command.run_cmd( -+ "ps -ef | grep 'gpu_burn' | grep -v grep", ignore_errors=True) -+ if cmd[2] != 0: -+ break -+ time_delta = time.time() - time_start -+ if time_delta >= 500: -+ break -+ self.command.run_cmd(self.smi_name) -+ time.sleep(5) -+ -+ return True -+ -+ def test_nvidia_gpu(self): -+ """ -+ Nvidia gpu test entry function -+ Returns: -+ bool: -+ """ -+ result = True -+ self.get_driver_info() -+ -+ self.logger.info("Check gpu information.") -+ self.command.run_cmd('%s -q' % self.smi_name) -+ self.logger.info("Check cuda version.") -+ self.command.run_cmd('/usr/local/cuda/bin/nvcc --version') -+ -+ self.logger.info("Start to test gpu pressure.") -+ try: -+ if not self.test_pressure(): -+ result = False -+ -+ check_result = self.command.run_cmd( -+ "grep 'GPU 0: OK' %s" % self.gpu_burn) -+ if os.path.exists(self.gpu_burn) and check_result[2] == 0: -+ self.logger.info("Test gpu pressure succeed.") -+ else: -+ self.logger.error("Test gpu pressure failed.") -+ result = False -+ -+ self.logger.info("Start to test cuda samples.") -+ self.set_default_gpu() -+ sample_case = "simpleOccupancy,bandwidthTest,p2pBandwidthLatencyTest,deviceQuery,clock" -+ code = self.command.run_cmd( -+ "bash %s/test_nvidia_gpu.sh test_cuda_samples '%s %s'" % (gpu_dir, self.cuda_samples_log, sample_case)) -+ if code[2] == 0: -+ self.logger.info("Test cuda samples succeed.") -+ else: -+ result = False -+ self.logger.error("Test cuda samples failed.") -+ except Exception as e: -+ self.logger.error( -+ "Failed to run the script because compiling or setting variables: %s" % e) -+ result = False -+ -+ return result -diff -Naur rpm/tests/compatible/gpu/test_amd_gpu.sh oech/tests/compatible/gpu/test_amd_gpu.sh ---- rpm/tests/compatible/gpu/test_amd_gpu.sh 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/test_amd_gpu.sh 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,56 @@ -+#!/usr/bin/bash -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-10-13 -+# Desc: Shell script used for testing AMD gpu -+ -+function install_readontop() { -+ cd /opt -+ res_code=0 -+ if [ ! -d radeontop ]; then -+ git clone https://github.com/clbr/radeontop.git -+ dnf install -y libdrm-devel ncurses-devel ncurses-libs libpciaccess-devel libxcb-devel -+ fi -+ cd radeontop -+ make &>/dev/null || res_code=1 -+ -+ return $res_code -+} -+ -+function install_glmark2() { -+ cd /opt -+ res_code=0 -+ if [ ! -d glmark2 ]; then -+ git clone https://github.com/glmark2/glmark2.git -+ dnf install -y meson libX11-devel libpng-devel cmake pkgconf libjpeg libjpeg-turbo-devel libdrm-devel mesa-libgbm-devel libgudev-devel -+ fi -+ cd glmark2 -+ meson setup build -Dflavors=drm-gl,drm-glesv2,wayland-gl,wayland-glesv2,x11-gl,x11-glesv2 -+ ninja -C build &>/dev/null -+ ninja -C build install &>/dev/null || res_code=1 -+ -+ return $res_code -+} -+ -+function main() { -+ func_name=$1 -+ -+ if [[ $func_name == "install_readontop" ]]; then -+ install_readontop -+ elif [[ $func_name == "install_glmark2" ]]; then -+ install_glmark2 -+ else -+ echo "The function doesn't exist, please check!" -+ return 1 -+ fi -+} -+ -+main "$@" -diff -Naur rpm/tests/compatible/gpu/test_nvidia_gpu.sh oech/tests/compatible/gpu/test_nvidia_gpu.sh ---- rpm/tests/compatible/gpu/test_nvidia_gpu.sh 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/gpu/test_nvidia_gpu.sh 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,135 @@ -+#!/usr/bin/bash -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-05-05 -+# Desc: Shell script used for testing nvidia gpu -+ -+cuda_version=$(nvidia-smi -q | grep "CUDA Version" | awk '{print $4}') -+cuda_name="cuda-samples-${cuda_version}" -+ -+function install_gpu_burn() { -+ cd /opt -+ res_code=0 -+ if [ ! -d gpu-burn ]; then -+ git clone https://github.com/wilicc/gpu-burn.git -+ fi -+ cd gpu-burn -+ lsmod | grep bi_driver >/dev/null -+ if [ $? -eq 0 ]; then -+ COREX_PATH=${COREX_PATH:-/usr/local/corex} -+ clang++ compare.cu -o compare.ll -I${COREX_PATH}/include --cuda-gpu-arch=ivcore10 --cuda-path=${COREX_PATH} --cuda-device-only -S -x cuda || res_code=1 -+ llc -mcpu=ivcore10 -mtriple=bi-iluvatar-ilurt -show-mc-encoding -filetype=obj compare.ll -o compare.o || res_code=1 -+ lld -flavor ld.lld --no-undefined compare.o -o compare.ptx || res_code=1 -+ rm compare.ll compare.o -+ sed -i '/cuFuncSet/d' gpu_burn-drv.cpp -+ sed -i '/cuParamSet/d' gpu_burn-drv.cpp -+ sed -i 's/nvidia-smi/ixsmi/g' gpu_burn-drv.cpp -+ sed -i 's/.*cuLaunchGridAsync.*/void\* kargs[] = {\&d_Cdata, \&d_faultyElemData, \&d_iters};checkError(cuLaunchKernel(d_function, SIZE\/g_blockSize, SIZE\/g_blockSize, 1, g_blockSize, g_blockSize, 1, 0, 0, kargs, nullptr));/g' gpu_burn-drv.cpp -+ clang++ -std=c++11 -I${COREX_PATH}/include -L${COREX_PATH}/lib64 -lcudart -lcuda -lcublas -o gpu_burn ./gpu_burn-drv.cpp || res_code=1 -+ else -+ make &>/dev/null || res_code=1 -+ fi -+ return $res_code -+} -+ -+function install_cuda_samples() { -+ cd /opt -+ if [ ! -d ${cuda_name} ]; then -+ wget https://github.com/NVIDIA/cuda-samples/archive/refs/tags/v${cuda_version}.zip -+ unzip v${cuda_version}.zip >/dev/null -+ rm -rf v${cuda_version}.zip -+ fi -+ return 0 -+} -+ -+function test_nvidia_case() { -+ casename=$1 -+ logfile=$2 -+ res_code=0 -+ cd /opt/${cuda_name} -+ path=$(find ./ -name $casename -type d) -+ cd $path -+ make &>/dev/null -+ ./$casename &>>$logfile -+ if [[ $? -eq 0 ]]; then -+ echo "Test $casename succeed." >>$logfile -+ else -+ echo "Test $casename failed." >>$logfile -+ res_code=1 -+ fi -+ return $res_code -+} -+ -+function test_iluvatar_case() { -+ casename=$1 -+ logfile=$2 -+ res_code=0 -+ CUDA_PATH=${CUDA_PATH:-/usr/local/corex} -+ cd /opt/${cuda_name} -+ path=$(find ./ -name $casename) -+ cd $path -+ src_file=${casename}.cu -+ if [ ! -f ./$src_file ] && [ -f ./${casename}.cpp ]; then -+ src_file=${casename}.cpp -+ fi -+ clang++ -std=c++11 -I../../../Common -I${CUDA_PATH}/include --cuda-path=${CUDA_PATH} -L${CUDA_PATH}/lib64 -lcudart -lixlogger -lcuda -lixthunk -o ${casename} ./${src_file} -+ ./$casename &>>$logfile -+ if [[ $? -eq 0 ]]; then -+ echo "Test $casename succeed." -+ else -+ echo "Test $casename failed." -+ res_code=1 -+ fi -+ return $res_code -+} -+ -+function test_cuda_samples() { -+ logfile=$1 -+ allcases=(${2//,/ }) -+ res_code=0 -+ install_cuda_samples -+ cd /opt/${cuda_name} -+ lsmod | grep bi_driver -+ if [[ $? -eq 0 ]]; then -+ for casename in ${allcases[@]}; do -+ test_iluvatar_case $casename $logfile -+ if [[ $? -eq 1 ]]; then -+ res_code=1 -+ fi -+ done -+ else -+ for casename in ${allcases[@]}; do -+ test_nvidia_case $casename $logfile -+ if [[ $? -eq 1 ]]; then -+ res_code=1 -+ fi -+ done -+ fi -+ return $res_code -+} -+ -+function main() { -+ func_name=$1 -+ param_list=$2 -+ -+ if [[ $func_name == "install_gpu_burn" ]]; then -+ install_gpu_burn -+ elif [[ $func_name == "install_cuda_samples" ]]; then -+ install_cuda_samples -+ elif [[ $func_name == "test_cuda_samples" ]]; then -+ test_cuda_samples $param_list -+ else -+ echo "The function doesn't exist, please check!" -+ return 1 -+ fi -+} -+ -+main "$@" -diff -Naur rpm/tests/compatible/infiniband/infiniband.py oech/tests/compatible/infiniband/infiniband.py ---- rpm/tests/compatible/infiniband/infiniband.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/infiniband/infiniband.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,47 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-05-24 -+# Desc: InfiniBand Test -+ -+from tests.compatible.network.rdma import RDMATest -+ -+ -+class InfiniBandTest(RDMATest): -+ def __init__(self): -+ RDMATest.__init__(self) -+ self.subtests = [self.test_ip_info, self.test_ibstatus, -+ self.test_ib_link, self.test_icmp, self.test_rdma] -+ -+ def test_ib_link(self): -+ """ -+ IB Link test -+ :return: -+ """ -+ if 'LinkUp' not in self.phys_state: -+ self.logger.error("Device is not LinkUp.") -+ -+ if 'ACTIVE' not in self.state: -+ self.logger.error("Link is not ACTIVE.") -+ -+ if self.base_lid == 0x0: -+ self.logger.error("Fail to get base lid of %s." % self.interface) -+ return False -+ self.logger.info("The base lid is %s." % self.base_lid) -+ -+ if self.sm_lid == 0x0: -+ self.logger.error( -+ "Fail to get subnet manager lid of %s." % self.interface) -+ return False -+ self.logger.info("The subnet manager lid is %s." % self.sm_lid) -+ -+ return True -diff -Naur rpm/tests/compatible/infiniband/Makefile oech/tests/compatible/infiniband/Makefile ---- rpm/tests/compatible/infiniband/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/infiniband/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2022-05-23 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/__init__.py oech/tests/compatible/__init__.py ---- rpm/tests/compatible/__init__.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/__init__.py 2023-12-07 15:01:42.225942288 +0800 -@@ -0,0 +1,10 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -diff -Naur rpm/tests/compatible/ipmi/ipmi.py oech/tests/compatible/ipmi/ipmi.py ---- rpm/tests/compatible/ipmi/ipmi.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/ipmi/ipmi.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,60 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: Intelligent Platform Management Interface test -+ -+from hwcompatible.test import Test -+ -+ -+class IpmiTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["OpenIPMI", "ipmitool"] -+ -+ def start_ipmi(self): -+ """ -+ Start IPMI test -+ :return: -+ """ -+ self.command.run_cmd("systemctl start ipmi") -+ result = self.command.run_cmd("systemctl status ipmi.service | grep 'Active: active'" ) -+ if result[2] != 0: -+ self.logger.error("Ipmi service start failed.") -+ return False -+ self.logger.info("Ipmi service start succeed.") -+ return True -+ -+ def ipmitool(self): -+ """ -+ Testing with iptool tools -+ :return: -+ """ -+ cmd_list = ["ipmitool fru", "ipmitool sensor"] -+ for cmd in cmd_list: -+ result = self.command.run_cmd(cmd) -+ if result[2] != 0: -+ self.logger.error("%s execute failed." % cmd) -+ return False -+ self.logger.info("%s execute successfully." % cmd) -+ return True -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ if not self.start_ipmi(): -+ return False -+ if not self.ipmitool(): -+ return False -+ return True -diff -Naur rpm/tests/compatible/ipmi/Makefile oech/tests/compatible/ipmi/Makefile ---- rpm/tests/compatible/ipmi/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/ipmi/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,22 @@ -+# Copyright (c) 2020 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/kabi/kabi.py oech/tests/compatible/kabi/kabi.py ---- rpm/tests/compatible/kabi/kabi.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kabi/kabi.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,144 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2.gica's -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-05-30 -+# Desc: Public kabi test -+ -+import os -+import argparse -+from subprocess import getoutput -+from hwcompatible.command import Command -+from hwcompatible.test import Test -+from hwcompatible.constants import TEST_KABI_ARCH -+from hwcompatible.sysinfo import SysInfo -+from hwcompatible.env import CertEnv -+from hwcompatible.document import Document -+ -+kabi_dir = os.path.dirname(os.path.realpath(__file__)) -+ -+ -+class KabiTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.kernel_version = getoutput("uname -r") -+ self.requirements = ["gzip", "rpm-build"] -+ self.symvers = None -+ self.wl_logpath = "" -+ self.miss_logpath = "" -+ self.changed_logpath = "" -+ self.sysinfo = SysInfo(CertEnv.releasefile) -+ -+ def setup(self, args=None): -+ """ -+ Initialization before test -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ self.wl_logpath = os.path.join( -+ self.logger.logdir, "kabi-whitelist.log") -+ self.miss_logpath = os.path.join( -+ self.logger.logdir, "kabi-missing.log") -+ self.changed_logpath = os.path.join( -+ self.logger.logdir, "kabi-changed.log") -+ self.symvers = os.path.join( -+ CertEnv.datadirectory, "symvers-" + self.kernel_version) -+ -+ def test(self): -+ """ -+ Run kabi test case -+ return: result -+ """ -+ arch = self.command.run_cmd("uname -m")[0].strip() -+ if arch not in TEST_KABI_ARCH: -+ self.logger.info(" %s architecture does not support kabi testing." % arch) -+ return True -+ -+ result = True -+ self.logger.info("Start to test, please wait...") -+ if not os.path.exists(self.symvers): -+ symvers_gz = "symvers-" + self.kernel_version + ".gz" -+ self.command.run_cmd("cp /boot/%s %s" % -+ (symvers_gz, CertEnv.datadirectory)) -+ self.command.run_cmd("gzip -d %s/%s" % -+ (CertEnv.datadirectory, symvers_gz)) -+ -+ standard_symvers = self._get_kernel_source_rpm(arch) -+ with open(standard_symvers, "r") as f: -+ for line in f.readlines(): -+ line = line.strip().replace("\n", "") -+ if line == "": -+ continue -+ -+ hsdp = line.split() -+ if len(hsdp) < 4 : -+ continue -+ -+ result = self.command.run_cmd("grep %s %s" % ( -+ hsdp[1], self.symvers), log_print=False) -+ data = result[0] -+ if data and hsdp[0] in data: -+ continue -+ elif data and hsdp[0] not in data: -+ if not os.path.exists(self.changed_logpath): -+ self.command.run_cmd("echo 'standard_symvers cur_symvers' | tee %s" % ( -+ self.changed_logpath), log_print=False) -+ -+ self.command.run_cmd("echo '{%s} {%s}' | tee %s" % ( -+ line, data, self.changed_logpath), log_print=False) -+ result = False -+ else: -+ self.command.run_cmd("echo '%s' | tee %s" % ( -+ line, self.miss_logpath), log_print=False) -+ result = False -+ -+ if result: -+ self.logger.info("Test kabi succeed.") -+ else: -+ self.logger.error("Test kabi failed.") -+ -+ return result -+ -+ def _get_kernel_source_rpm(self, arch): -+ """ -+ get the path of kernel source rpm -+ """ -+ rpmpath = "/root/rpmbuild/SOURCES" -+ standard_symvers = os.path.join(rpmpath, "Module.kabi_" + arch) -+ if os.path.exists(standard_symvers): -+ return standard_symvers -+ -+ product = self.sysinfo.product.split(" ")[0] -+ if product == "openEuler": -+ standard_kernel_version = getoutput( -+ "dnf list --repo=source | grep '^kernel.src' | awk '{print $2}'") -+ self.command.run_cmd("dnf download --source kernel-%s" -+ % standard_kernel_version) -+ elif product == "KylinSec": -+ kylinsec_version = getoutput("cat /etc/dnf/vars/osversion | sed 's/[^0-9]//g'") -+ kernel_dict = Document(CertEnv.kernelinfo, self.logger) -+ if not kernel_dict.load(): -+ self.logger.error("Failed to get kernel info.") -+ return False -+ openeuler_version = kernel_dict.document[product][kylinsec_version].split('/')[0] -+ standard_kernel_version = kernel_dict.document[product][kylinsec_version].split('/')[1] -+ url = "https://repo.openeuler.org/%s/source/Packages/kernel-%s.src.rpm" \ -+ % (openeuler_version, standard_kernel_version) -+ self.command.run_cmd("wget %s -P %s" % (url, rpmpath)) -+ else: -+ self.logger.info("Currently, this system is not supported to test kabi," -+ " Please add the corresponding system in kernelrelease.json.") -+ -+ rpm = os.path.join("kernel-" + standard_kernel_version + ".src.rpm") -+ getoutput("rpm -ivh %s" % rpm) -+ os.remove(rpm) -+ return standard_symvers -diff -Naur rpm/tests/compatible/kabi/Makefile oech/tests/compatible/kabi/Makefile ---- rpm/tests/compatible/kabi/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kabi/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,23 @@ -+# Copyright (c) 2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2.gica's -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @meitingli -+# Create: 2022-05-30 -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a *.py $(DEST) -+ chmod a+x $(DEST)/*.py -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/kabiwhitelist/kabi_check.sh oech/tests/compatible/kabiwhitelist/kabi_check.sh ---- rpm/tests/compatible/kabiwhitelist/kabi_check.sh 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kabiwhitelist/kabi_check.sh 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,179 @@ -+#!/usr/bin/bash -+# Copyright (c) 2023 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @liqiang1118 -+# Create: 2023-05-15 -+ -+mkdir /usr/share/oech/lib/tests/kabiwhitelist/test_log -+testdir="/usr/share/oech/lib/tests/kabiwhitelist/test_log" -+cd $testdir -+ -+os_version=`cat /etc/openEuler-latest|grep openeulerversion |awk -F = '{print $2}'` -+arch=`uname -m` -+url="https://gitee.com/src-openeuler/kernel/raw/$os_version/kabi_whitelist_$arch" -+wget $url -+kernel_version=`uname -r` -+symvers_gz="symvers-"$kernel_version".gz" -+cp /boot/$symvers_gz /usr/share/oech/lib/tests/kabiwhitelist/test_log -+gunzip /usr/share/oech/lib/tests/kabiwhitelist/test_log/$symvers_gz -+ -+# Desc: Test kabi -+# Input: xxx.ko or xxx.rpm -+function test_kabi() { -+ cat $kabi.kabi |while read line; -+ do -+ kabiname=`echo $line |awk '{print $2}'` -+ filename=`echo $line |awk '{print $1}'` -+ cat kabi_whitelist_$arch|grep "$kabiname" >> $filename.txt -+ have=`cat $filename.txt|wc -l` -+ if [ $have == 0 ]; then -+ echo $line >> $kabi"_change_"$arch -+ fi -+ done -+ cat $kabi.kabi |while read line; -+ do -+ real=`echo $line|awk '{print $2}'` -+ if [ -f $kabi"_change_"$arch ]; then -+ white_list=`cat $kabi"_change_"$arch|grep "$real" |wc -l` -+ if [ $white_list == 0 ]; then -+ echo $line >> $kabi"_white_"$arch -+ fi -+ else -+ echo $line >> $kabi"_white_"$arch -+ fi -+ done -+} -+ -+ -+function test_inlist(){ -+ if [ -f $kabi"_change_"$arch ]; then -+ cat $kabi"_change_"$arch |while read line; -+ do -+ changekb=`echo $line |awk '{print $2}'` -+ inos=`cat symvers-"$kernel_version" |grep $changekb|wc -l` -+ if [ $inos == 0 ]; then -+ echo $changekb >> $kabi"_changeos" -+ else -+ echo $changekb >> $kabi"_inlist" -+ fi -+ done -+ fi -+} -+ -+ -+function real_result(){ -+ if [ -f $kabi"_change_"$arch ]; then -+ cat $kabi"_change_"$arch|while read line; -+ do -+ inlist=`echo $line|awk '{print $2}'` -+ noin=`cat $kabi"_changeos" |grep $inlist|wc -l` -+ if [ $noin == 0 ]; then -+ echo $line >> $kabi"_change" -+ -+ fi -+ -+ done -+ fi -+} -+ -+echo "####################KABI TEST START####################" -+cat /usr/share/oech/lib/config/test_config.yaml|grep name|awk -F "'" '{print $2}' >> dir.txt -+if_test=`cat dir.txt|wc -w` -+if [ $if_test == 0 ]; then -+ echo "Please configure the board information in the configuration file" > change.txt -+ echo "no ko or rpm" >> nokorpm.txt -+ cat change.txt -+fi -+cat dir.txt|while read line; -+do -+ lineword=`echo $line |wc -w` -+ if [ "$lineword" -gt 0 ]; then -+ echo $line >> dirt.txt -+ fi -+done -+cat dirt.txt |while read line; -+do -+ if [ -f /root/$line ]; then -+ cp /root/$line ./ -+ echo $line >> dirth -+ fi -+done -+cat dirth|while read line; -+do -+ for i in $line -+ do -+ class=`echo $i|awk -F . '{print $NF}'` -+ if [ $class == ko ]; then -+ kabi=`echo $i|awk -F . '{print $1}'` -+ modprobe --dump $i > $kabi.kabi -+ test_kabi -+ test_inlist -+ real_result -+ elif [ $class == rpm ]; then -+ echo "this is a rpm please wait" > /dev/null -+ rpm2cpio $i |cpio -div -+ find ./ -name "*.ko*" |grep module >> rpmko -+ ifrpm=`cat rpmko|wc -l` -+ if [ $ifrpm == 0 ]; then -+ echo "Please check rpm" > rpmchange -+ echo "Please check rpm" -+ exit 0 -+ else -+ echo "$i rpm decompression completed" -+ fi -+ cat rpmko|while read line; -+ do -+ cp $line ./ -+ koname=`echo $line |awk -F "/" '{print $NF}'` -+ kabi=`echo $koname|awk -F . '{print $1}' ` -+ modprobe --dump $koname > $kabi.kabi -+ echo $koname >> realname -+ test_kabi -+ test_inlist -+ real_result -+ done -+ fi -+ done -+done -+ -+ -+# save test log -+cat dirth |grep ko >> realname -+cat realname |while read line; -+do -+ kabi=`echo $line |awk -F . '{print $1}'` -+ if [ ! -f $kabi"_change_"$arch ]; then -+ echo "$kabi kabi $arch test pass" >> result -+ else -+ echo "$kabi kabi $arch test fail" >> result -+ fi -+done -+echo "Test results are as follows" -+cat result -+cat realname|grep ko |awk -F . '{print $1}' > res.txt -+cat res.txt |while read line; -+do -+ if [ -f $line"_change" ] || [ -f $line"_white_"$arch ]; then -+ if [ -f $line"_change" ]; then -+ whitenum=`cat $line"_change" |wc -l` -+ echo "Here are $line.ko KABI not in whitelist count=$whitenum" -+ cat $line"_change" -+ fi -+ if [ -f $line"_white_"$arch ]; then -+ notnum=`cat $line"_white_"$arch |wc -l` -+ echo "Here are $line.ko KABI in whitelist count=$notnum" -+ cat $line"_white_"$arch -+ fi -+ fi -+ if [ -f $line"_changeos" ]; then -+ echo "Here are $line.ko KABI not in OS KABI list" -+ cat $line"_changeos" -+ fi -+done -diff -Naur rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py oech/tests/compatible/kabiwhitelist/kabiwhitelist.py ---- rpm/tests/compatible/kabiwhitelist/kabiwhitelist.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kabiwhitelist/kabiwhitelist.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,64 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+# Copyright (c) 2023 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2.gica's -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @liqiang1118 -+# Create: 2023-05-15 -+# Desc: Public kabi test -+ -+import os -+import shutil -+import argparse -+from subprocess import getoutput -+from hwcompatible.command import Command -+from hwcompatible.test import Test -+ -+kabi_whitelist_dir = os.path.dirname(os.path.realpath(__file__)) -+ -+ -+class KabiWhiteListTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.requirements = ["gzip", "rpm-build"] -+ -+ def setup(self, args=None): -+ """ -+ Initialization before test -+ """ -+ self.args = args or argparse.Namespace() -+ self.logger = getattr(self.args, "test_logger", None) -+ self.command = Command(self.logger) -+ -+ def test(self): -+ """ -+ Run kabi test case -+ return: result -+ """ -+ self.command.run_cmd("bash %s/kabi_check.sh" % kabi_whitelist_dir) -+ ko_result = self.command.run_cmd("ls %s/test_log/ | grep noko" % kabi_whitelist_dir) -+ if ko_result[2] == 0: -+ self.logger.error("Please configure the board information in the configuration file") -+ return False -+ self.logger.info("Ko or rpm check complete") -+ -+ test_result = self.command.run_cmd("ls %s/test_log | grep change" % kabi_whitelist_dir) -+ if test_result[2] == 0: -+ self.logger.error("Kabiwhitelist test fail") -+ return False -+ return True -+ -+ def teardown(self): -+ """ -+ Clear temporary files -+ """ -+ file_name = "/usr/share/oech/lib/tests/kabiwhitelist/test_log" -+ if os.path.exists(file_name): -+ shutil.rmtree(file_name) -+ self.logger.info("Clearing temporary files is complete") -diff -Naur rpm/tests/compatible/kabiwhitelist/Makefile oech/tests/compatible/kabiwhitelist/Makefile ---- rpm/tests/compatible/kabiwhitelist/Makefile 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kabiwhitelist/Makefile 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,26 @@ -+# Copyright (c) 2023 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Author: @liqiang1118 -+# Create: 2023-05-15 -+# Desc: KabiWhitelist test -+ -+.PHONY: install clean -+ -+all: ; -+ -+install: -+ mkdir -p $(DEST) -+ cp -a $(SUBDIR)/build *.py $(DEST) -+ cp -a $(SUBDIR)/build *.sh $(DEST) -+ chmod a+x $(DEST)/*.py -+ chmod a+x $(DEST)/*.sh -+ -+clean: -+ rm -rf $(DEST) -diff -Naur rpm/tests/compatible/kdump/kdump.py oech/tests/compatible/kdump/kdump.py ---- rpm/tests/compatible/kdump/kdump.py 1970-01-01 08:00:00.000000000 +0800 -+++ oech/tests/compatible/kdump/kdump.py 2023-12-07 15:01:42.229942342 +0800 -@@ -0,0 +1,119 @@ -+#!/usr/bin/env python3 -+# coding: utf-8 -+ -+# Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. -+# oec-hardware is licensed under the Mulan PSL v2. -+# You can use this software according to the terms and conditions of the Mulan PSL v2. -+# You may obtain a copy of Mulan PSL v2 at: -+# http://license.coscl.org.cn/MulanPSL2 -+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+# PURPOSE. -+# See the Mulan PSL v2 for more details. -+# Create: 2020-04-01 -+# Desc: Kdump Test -+ -+import os -+import re -+from time import sleep -+from subprocess import getoutput -+from hwcompatible.test import Test -+from hwcompatible.command import Command -+from hwcompatible.command_ui import CommandUI -+from hwcompatible.document import ConfigFile -+ -+ -+class KdumpTest(Test): -+ def __init__(self): -+ Test.__init__(self) -+ self.pri = 9 -+ self.reboot = True -+ self.kernel_version = getoutput("uname -r") -+ self.rebootup = "verify_vmcore" -+ self.kdump_conf = "/etc/kdump.conf" -+ self.vmcore_path = "/var/crash" -+ self.requirements = ["crash", "kexec-tools"] -+ -+ def test(self): -+ """ -+ Test case -+ :return: -+ """ -+ cmd_result = self.command.run_cmd("yum install -y kernel-debuginfo-%s" % self.kernel_version) -+ if len(cmd_result[1]) != 0 and cmd_result[2] != 0: -+ self.logger.error( -+ "Fail to install required packages.\n %s" % cmd_result[1]) -+ return False -+ -+ cmd_result = self.command.run_cmd("grep crashkernel /proc/cmdline") -+ if cmd_result[2] != 0: -+ self.logger.error( -+ "The /proc/cmdline file cannot find crashkernel.") -+ return False -+ crash_kernel = cmd_result[0].split(" ") -+ crash_size = "" -+ for line in crash_kernel: -+ if "crashkernel" in line: -+ crash_size = line.split("=")[1] -+ break -+ self.logger.info("The value of crashkernel is %s" % crash_size) -+ -+ config = ConfigFile(self.kdump_conf) -+ if not config.get_parameter("path"): -+ config.add_parameter("path", self.vmcore_path) -+ else: -+ self.vmcore_path = config.get_parameter("path") -+ -+ if config.get_parameter("kdump_obj") == "kbox": -+ config.remove_parameter("kdump_obj") -+ config.add_parameter("kdump_obj", "all") -+ -+ self.command.run_cmd("systemctl restart kdump") -+ cmd = self.command.run_cmd( -+ "systemctl status kdump | grep 'Active: active'") -+ if cmd[2] != 0: -+ self.logger.error("Kdump service is not active.") -+ return False -+ self.logger.info("Start kdump service succeed.") -+ -+ self.logger.info("kdump config.") -+ config.dump() -+ -+ com_ui = CommandUI() -+ if com_ui.prompt_confirm("System will reboot, are you ready?"): -+ self.logger.info("Trigger crash, please wait seconds.") -+ self.command.run_cmd("sync", log_print=False) -+ self.command.run_cmd("echo 'c' | tee /proc/sysrq-trigger") -+ sleep(30) -+ return False -+ -+ return False -+ -+ def verify_vmcore(self, logger): -+ """ -+ Verify vmcore -+ :return: -+ """ -+ config = ConfigFile(self.kdump_conf) -+ if config.get_parameter("path"): -+ self.vmcore_path = config.get_parameter("path") -+ -+ dir_pattern = re.compile( -+ r'(?P[0-9]+\.[0-9]+\.[0-9]+)-(?P[0-9]+[-.][0-9]+[-.][0-9]+)-' -+ r'(?P