diff -Naur a/docs/design_docs/dev_design.md b/docs/design_docs/dev_design.md --- a/docs/design_docs/dev_design.md 2022-10-10 14:39:15.909994757 +0800 +++ b/docs/design_docs/dev_design.md 2022-10-10 14:42:07.001992872 +0800 @@ -95,7 +95,7 @@ │ ├── compatibility.py 框架核心功能 │ ├── client.py 上传测试结果到服务端 │ ├── command.py bash命令执行封装 -│ ├── command_ui.py 命令行交互工具 +│ ├── command_ui.py 命令行交互工具 │ ├── device.py 扫描设备信息 │ ├── document.py 收集配置信息 │ ├── env.py 全局变量,主要是各个配置文件或目录的路径 @@ -103,6 +103,7 @@ │ ├── log.py 日志模块 │ ├── reboot.py 重启类任务专用,便于机器重启后仍能继续执行测试 │ ├── sysinfo.py 收集系统信息 +│ ├── config_ip.py 自动检测并配置网卡IP │ └── test.py 测试套模板 ├── scripts 工具脚本 │ ├── oech 工具客户端命令行工具 @@ -239,24 +240,43 @@ # 网卡测试项配置信息,指定测试的端口设备号、测试RDMA、服务端IP # device为网卡端口设备号,可通过oech或ip a查看 # if_rdma表示是否测试网卡RDMA,默认是N,表示不测试RDMA -# server_ip为服务端直连的网卡配置的IP +# client_ip为客户端测试网卡配置的IP +# server_ip为服务端测试网卡配置的IP +# 服务端的端口默认是80,如果有修改,需要添加上修改后的端口号,如下面的eth2示例。 ethernet: + # 已手动配置客户端和服务端测试网卡的IP,这里需要添加上服务端的IP地址。 eth1: device: enp125s0f0 if_rdma: N - server_ip: 127.0.0.1 + client_ip: + server_ip: 2.2.2.4 + # 未手动配置IP,使用这里提供的IP进行客户端和服务端配置。 eth2: device: enp125s0f1 if_rdma: N - server_ip: 127.0.0.1:8090 -# IB卡测试项配置信息,指定测试的端口设备号、服务端IP + client_ip: 2.2.2.3 + server_ip: 2.2.2.4:8090 + # 前面两种情况都没有满足,且客户端和服务端的IP地址未提供,程序会自动生成IP,进行配置。 + eth3: + device: enp125s0f2 + if_rdma: y + client_ip: + server_ip: +# IB卡测试项配置信息,指定测试的端口设备号、服务端IP。 +# IB卡IP的配置原则同普通网卡。 infiniband: ib1: device: ibp1s0 - server_ip: 127.0.0.1 + client_ip: + server_ip: 2.2.2.4 ib2: + device: ibp1s1 + client_ip: 2.2.2.3 + server_ip: 2.2.2.4:8090 + ib3 device: ibp1s0 - server_ip: 127.0.0.1:8090 + client_ip: + server_ip: ``` ### 3.5 内部模块间接口清单 @@ -280,6 +300,7 @@ | 15 | `ConfigFile()` | 文档模块 | 配置信息读取 | | 16 | `CertEnv()` | 工具环境信息模块 | 提供工具文件环境路径 | | 17 | `SysInfo()` | 系统信息模块 | 系统信息获取 | +| 18 | `ConfigIP()` | 网卡IP配置模块 | 查询并配置网卡IP | ### 3.6 web服务接口清单 @@ -297,6 +318,7 @@ | 10 | `/files/` | | 文件下载,辅助客户端网卡测试 | | 11 | `/api/file/upload` | GET/POST | 文件上传,辅助客户端网卡测试 | | 12 | `/api/` | GET/POST | 文件读写,辅助客户端网卡测试 | +| 13 | `/api/config/ip`| GET/POST | 配置服务端网卡IP | ### 3.7 日志查看和转储 diff -Naur a/hwcompatible/common.py b/hwcompatible/common.py --- a/hwcompatible/common.py 2022-08-29 19:51:34.000000000 +0800 +++ b/hwcompatible/common.py 2022-10-10 14:42:07.002992872 +0800 @@ -12,6 +12,7 @@ # See the Mulan PSL v2 for more details. # Author: @meitingli # Create: 2022-07-09 +# Desc: Common functions import os import sys @@ -20,31 +21,45 @@ import importlib from .test import Test from .env import CertEnv +from .constants import NODEVICE def create_test_suite(test_factory, logger, subtests_filter=None): """ - Create test suites - :param subtests_filter: - :return: + Create test suites for job testing + Args: + test_factory (list): total test factory + logger (Logger): logger object to record + subtests_filter (list, optional): filter object. Defaults to None. + + Returns: + test_suite (list): available test suites """ test_suite = [] test_name = [] + kabi_select = 0 + kabi_test = None for test in test_factory: if test["run"]: - testclass = discover(test["name"], logger, subtests_filter) - if not testclass: - if not subtests_filter: - test["status"] = "FAIL" - logger.error("The testcase %s is not found." % test["name"]) - continue - testcase = dict() - testcase["test"] = testclass - testcase["name"] = test["name"] - testcase["device"] = test["device"] - testcase["status"] = "FAIL" + testcase = __create_testcase(test, logger, subtests_filter) + if testcase: + test_suite.append(testcase) + test_name.append(test["name"]) + + if test["name"] not in NODEVICE: + kabi_select = 1 + if "kabi" in test_name: + kabi_select = 0 + if test["name"] == "kabi": + kabi_test = test + + if kabi_select: + logger.info("The hardware will test kabi automatically.") + kabi_test["run"] = True + testcase = __create_testcase(kabi_test, logger, subtests_filter) + if testcase: test_suite.append(testcase) - test_name.append(test["name"]) + test_name.append("kabi") total_count = len(test_suite) if total_count: @@ -53,6 +68,31 @@ return test_suite +def __create_testcase(test, logger, subtests_filter): + """ + Create testcase + Args: + test (dict): _description_ + logger (Logger): logger object to record + subtests_filter (list, optional): filter object. Defaults to None. + + Returns: + testcase (dict): available testcase or None + """ + testclass = discover(test["name"], logger, subtests_filter) + if not testclass and not subtests_filter: + test["status"] = "FAIL" + logger.error("The testcase %s is not found." % test["name"]) + return False + + testcase = dict() + testcase["test"] = testclass + testcase["name"] = test["name"] + testcase["device"] = test["device"] + testcase["status"] = "FAIL" + return testcase + + def copy_pci(): """ copy the PCI file if it exists diff -Naur a/hwcompatible/config_ip.py b/hwcompatible/config_ip.py --- a/hwcompatible/config_ip.py 2022-10-10 14:39:15.910994757 +0800 +++ b/hwcompatible/config_ip.py 2022-10-10 14:42:07.002992872 +0800 @@ -63,6 +63,7 @@ if self.client_ip: self.logger.info("The client IP address already configured.") if self.server_ip and self.ping_ip(self.server_ip): + self.config_data["client_ip"] = self.client_ip return True self.client_ip = "" self.server_ip = "" diff -Naur a/hwcompatible/job.py b/hwcompatible/job.py --- a/hwcompatible/job.py 2022-10-10 14:39:15.910994757 +0800 +++ b/hwcompatible/job.py 2022-10-10 14:42:07.002992872 +0800 @@ -51,6 +51,7 @@ self.command = Command(self.logger) self.total_count = 0 self.current_num = 0 + self.config_flag = 0 def check_test_depends(self): """ @@ -180,11 +181,14 @@ """ types = testcase["name"] device_name = testcase["device"].get_name() + self.config_flag = 0 if types == "disk": - return self.config_info.get("disk") + self.config_flag = 1 + return self.config_info.get("disk", "all") if device_name and types not in NO_CONFIG_DEVICES: for device in self.config_info.get(types).values(): if device.get("device") == device_name: + self.config_flag = 1 return device return None @@ -196,18 +200,14 @@ :return: """ name = testcase["name"] - if testcase["device"].get_name(): - name = testcase["name"] + "-" + testcase["device"].get_name() + device_name = testcase["device"].get_name() + if device_name: + name = testcase["name"] + "-" + device_name logname = name + ".log" reboot = None test = None logger = Logger(logname, self.job_id, sys.stdout, sys.stderr) logger.start() - if testcase['name'] in ('ethernet', 'infiniband'): - auto_config_ip = ConfigIP(config_data, logger, testcase["device"]) - if not auto_config_ip.config_ip(): - self.logger.error("Config IP address failed.") - return False try: test = testcase["test"] if subtests_filter and name != "system": @@ -216,6 +216,17 @@ self.current_num += 1 self.logger.info("Start to run %s/%s test suite: %s." % (self.current_num, self.total_count, name)) + + if device_name and self.config_flag == 0 and testcase["name"] not in NO_CONFIG_DEVICES: + self.logger.error("Please configure the board information in the configuration file.") + return False + + if testcase['name'] in ('ethernet', 'infiniband'): + auto_config_ip = ConfigIP(config_data, logger, testcase["device"]) + if not auto_config_ip.config_ip(): + self.logger.error("Config IP address failed.") + return False + args = argparse.Namespace( device=testcase["device"], config_data=config_data, test_logger=logger, logdir=logger.logdir, testname=name) diff -Naur a/hwcompatible/test.py b/hwcompatible/test.py --- a/hwcompatible/test.py 2022-08-29 19:51:34.000000000 +0800 +++ b/hwcompatible/test.py 2022-10-10 14:42:07.003992872 +0800 @@ -32,21 +32,6 @@ self.command = None self.log_path = "" - @staticmethod - def valid_disk(disk, disks): - """ - Is the disk valid - """ - result = True - if disk: - if disk != "all" and disk not in disks: - print("%s is in use or disk does not exist." % disk) - result = False - else: - print("Failed to get disk information.") - result = False - return result - def setup(self, args=None): """ setup diff -Naur a/server/server.py b/server/server.py --- a/server/server.py 2022-10-10 14:39:15.910994757 +0800 +++ b/server/server.py 2022-10-10 14:42:07.003992872 +0800 @@ -175,7 +175,7 @@ :return: """ dir_job = os.path.join(dir_results, host, oec_id, job) - attachment = dir_job + '.tar.gz' + attachment = dir_job + '.tar' filedir = os.path.dirname(attachment) filename = os.path.basename(attachment) return send_from_directory(filedir, filename, as_attachment=True) @@ -212,7 +212,7 @@ :return: """ dir_job = os.path.join(dir_results, host, oec_id, job) - tar_job = dir_job + '.tar.gz' + tar_job = dir_job + '.tar' json_cert = os.path.join(dir_job, 'compatibility.json') if not os.path.exists(json_cert) or not os.path.exists(tar_job): abort(500) @@ -221,7 +221,7 @@ try: with open(json_cert, 'r') as file_content: cert = json.load(file_content) - except json.decoder.JSONDecodeError as error: + except json.decoder.JSONDecodeError: sys.stderr.write("The file %s is not json file.\n") return False @@ -268,17 +268,25 @@ return render_template('upload.html', host=host, id=id, job=job, filetext=filetext, ret='Failed'), 400 + ori_file = base64.b64decode(filetext) + filesize = len(ori_file) + if filesize > 1073741824: + sys.stderr.write( + "The file size is more than 1GB, upload file failed.\n") + return render_template('upload.html', host=host, id=id, job=job, + filetext=filetext, ret='Failed'), 500 + dir_job = os.path.join(dir_results, host, oec_id, job) - tar_job = dir_job + '.tar.gz' if not os.path.exists(dir_job): os.makedirs(dir_job) + tar_job = dir_job + '.tar' with open(tar_job, 'wb') as file_content: - file_content.write(base64.b64decode(filetext)) + file_content.write(ori_file) result = subprocess.getstatusoutput( "tar xf '%s' -C '%s'" % (tar_job, os.path.dirname(dir_job))) if result[0] != 0: - sys.stderr.write("Decompress log file failed.") + sys.stderr.write("Decompress log file failed.\n") return render_template('upload.html', host=host, id=oec_id, job=job, filetext=filetext, ret='Successful') @@ -343,9 +351,9 @@ pci_num = data.split(':', 1)[1].strip() quad = __get_quad(pci_num) if operator.eq(quad, eval(card_id)): - subprocess.getoutput("ifconfig %s:0 %s/24" % (pt, sever_ip)) - with os.fdopen(os.open(ip_file, os.O_WRONLY | os.O_CREAT, - stat.S_IRUSR), 'w+') as f: + subprocess.getoutput( + "ifconfig %s:0 %s/24" % (pt, sever_ip)) + with os.fdopen(os.open(ip_file, os.O_WRONLY | os.O_CREAT, stat.S_IRUSR), 'w+') as f: f.write('{},{}'.format(pt, sever_ip)) break diff -Naur a/tests/disk/common.py b/tests/disk/common.py --- a/tests/disk/common.py 1970-01-01 08:00:00.000000000 +0800 +++ b/tests/disk/common.py 2022-10-10 14:42:07.005992872 +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 a/tests/disk/disk.py b/tests/disk/disk.py --- a/tests/disk/disk.py 2022-08-29 19:51:34.000000000 +0800 +++ b/tests/disk/disk.py 2022-10-10 14:42:07.005992872 +0800 @@ -13,13 +13,10 @@ # Create: 2020-04-01 # Desc: Disk test -import os -import shutil import argparse -from subprocess import getoutput from hwcompatible.test import Test from hwcompatible.command import Command -from hwcompatible.device import CertDevice +from common import query_disk, get_disk, raw_test, vfs_test, valid_disk class DiskTest(Test): @@ -39,27 +36,13 @@ self.logger = getattr(self.args, "test_logger", None) self.command = Command(self.logger) self.config_data = getattr(self.args, "config_data", None) - - self.logger.info("Disk Info:", terminal_print=False) - self.command.run_cmd("fdisk -l") - self.logger.info("Partition Info:", terminal_print=False) - self.command.run_cmd("df -h") - self.logger.info("Mount Info:", terminal_print=False) - self.command.run_cmd("mount") - self.logger.info("Swap Info:", terminal_print=False) - self.command.run_cmd("cat /proc/swaps") - self.logger.info("LVM Info:", terminal_print=False) - self.command.run_cmd("pvdisplay") - self.command.run_cmd("vgdisplay") - self.command.run_cmd("lvdisplay") - self.logger.info("Md Info:", terminal_print=False) - self.command.run_cmd("cat /proc/mdstat") + query_disk(self.logger, self.command) def test(self): """ Start test """ - self.get_disk() + self.disks = get_disk(self.logger, self.command, self.config_data, self.pci_num) if len(self.disks) == 0: self.logger.error("No suite disk found to test.") return False @@ -68,164 +51,16 @@ self.logger.error("Failed to get disk from configuration file.") return False disk = self.config_data - result = self.valid_disk(disk, self.disks) + 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 self.raw_test(disk): - return_code = False - if not self.vfs_test(disk): - return_code = False - - return return_code - - def get_disk(self): - """ - Get disk info - """ - disks = list() - devices = CertDevice(self.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"): - disks.append(device.get_name()) - - self.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 = self.command.run_cmd("pvs | grep -q '/dev/%s'" % disk) - if result[2] == 0: - continue - self.disks.append(disk) - - un_suitable = list(set(disks).difference(set(self.disks))) - if len(un_suitable) > 0: - self.logger.info("These disks %s are in use now, skip them." % - "|".join(un_suitable)) - - def raw_test(self, disk): - """ - Raw test - """ - self.logger.info("%s raw IO test" % disk) - device = os.path.join("/dev", disk) - if not os.path.exists(device): - self.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: - self.logger.error( - "Device %s size is not suitable for testing." % device) - return False - elif size > 1048576: - size = 1048576 - - self.logger.info("Starting sequential raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.error("%s sequential raw IO test failed." % device) - return False - - self.logger.info("Starting rand raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ - "-group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.error("%s rand raw IO test failed." % device) - return False - - return True - - def vfs_test(self, disk): - """ - Vfs test - """ - self.logger.info("%s vfs test" % disk) - device = os.path.join("/dev/", disk) - if not os.path.exists(device): - self.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: - self.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 self.filesystems: - self.logger.info("Formatting %s to %s ..." % - (device, file_sys), terminal_print=False) - self.command.run_cmd("umount %s" % device, ignore_errors=True) - self.command.run_cmd("mkfs -t %s -F %s" % (file_sys, device)) - self.command.run_cmd("mount -t %s %s %s" % - (file_sys, device, "vfs_test")) - self.logger.info("Starting sequential vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): + if not raw_test(self.logger, self.command, disk): return_code = False - break - - self.logger.info("Starting rand vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): + if not vfs_test(self.logger, self.command, disk, self.filesystems): return_code = False - break - - self.command.run_cmd("umount %s" % device) - shutil.rmtree("vfs_test") return return_code - - def do_fio(self, 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 = self.command.run_cmd( - "fio %s -size=%dK -bs=%dK %s" % (file_opt, size, a_bs, option)) - if cmd_result[2] != 0: - self.logger.error("%s fio failed." % filepath) - return False - a_bs = a_bs * 2 - self.logger.info("%s fio succeed." % filepath) - return True diff -Naur a/tests/fc/fc.py b/tests/fc/fc.py --- a/tests/fc/fc.py 2022-08-29 19:51:34.000000000 +0800 +++ b/tests/fc/fc.py 2022-10-10 14:42:07.005992872 +0800 @@ -13,13 +13,10 @@ # Create: 2022-04-09 # Desc: Fibre channel test -import os -import shutil import argparse -from subprocess import getoutput from hwcompatible.test import Test from hwcompatible.command import Command -from hwcompatible.device import CertDevice +from tests.disk.common import query_disk, get_disk, raw_test, vfs_test, valid_disk class FCTest(Test): @@ -38,35 +35,22 @@ :return: """ self.args = args or argparse.Namespace() - self.device = getattr(self.args, 'device', None) - self.pci_num = self.device.get_property("DEVPATH").split('/')[-1] - self.config_data = getattr(self.args, "config_data", None) 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) - self.logger.info("Disk Info:", terminal_print=False) - self.command.run_cmd("fdisk -l") - self.logger.info("Partition Info:", terminal_print=False) - self.command.run_cmd("df -h") - self.logger.info("Mount Info:", terminal_print=False) - self.command.run_cmd("mount") - self.logger.info("Swap Info:", terminal_print=False) - self.command.run_cmd("cat /proc/swaps") - self.logger.info("LVM Info:", terminal_print=False) - self.command.run_cmd("pvdisplay") - self.command.run_cmd("vgdisplay") - self.command.run_cmd("lvdisplay") - self.logger.info("Md Info:", terminal_print=False) - self.command.run_cmd("cat /proc/mdstat") + query_disk(self.logger, self.command) def test(self): """ Start test """ - self.get_disk() + self.disks = get_disk(self.logger, self.command, self.config_data, self.pci_num) if len(self.disks) == 0: self.logger.error("No suite disk found to test.") return False @@ -76,164 +60,15 @@ return False disk = self.config_data.get('disk', '') - result = self.valid_disk(disk, self.disks) - if not result: + 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 self.raw_test(disk): + if not raw_test(self.logger, self.command, disk): return_code = False - if not self.vfs_test(disk): + if not vfs_test(self.logger, self.command, disk, self.filesystems): return_code = False return return_code - - def get_disk(self): - """ - Get disk info - """ - disks = list() - devices = CertDevice(self.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") and \ - self.pci_num in device.get_property("DEVPATH"): - disks.append(device.get_name()) - - self.command.run_cmd("/usr/sbin/swapon -a 2>/dev/null") - 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 = self.command.run_cmd("pvs | grep -q '/dev/%s'" % disk) - if result[2] == 0: - continue - self.disks.append(disk) - - un_suitable = list(set(disks).difference(set(self.disks))) - if len(un_suitable) > 0: - self.logger.info("These disks %s are in use now, skip them." % - "|".join(un_suitable)) - - def raw_test(self, disk): - """ - Raw test - """ - self.logger.info("%s raw IO test" % disk) - device = os.path.join("/dev", disk) - if not os.path.exists(device): - self.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: - self.logger.error( - "Device %s size is not suitable for testing." % device) - return False - elif size > 1048576: - size = 1048576 - - self.logger.info("Starting sequential raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.error("%s sequential raw IO test failed." % device) - return False - - self.logger.info("Starting rand raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ - "-group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.error("%s rand raw IO test failed." % device) - return False - - return True - - def vfs_test(self, disk): - """ - Vfs test - """ - self.logger.info("%s vfs test" % disk) - device = os.path.join("/dev/", disk) - if not os.path.exists(device): - self.logger.error("Device %s does not exist." % device) - 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: - self.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 self.filesystems: - self.logger.info("Formatting %s to %s ..." % - (device, file_sys), terminal_print=False) - self.command.run_cmd("umount %s" % device, ignore_errors=True) - self.command.run_cmd("mkfs -t %s -F %s" % (file_sys, device)) - self.command.run_cmd("mount -t %s %s %s" % - (file_sys, device, "vfs_test")) - self.logger.info("Starting sequential vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): - return_code = False - break - - self.logger.info("Starting rand vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): - return_code = False - break - - self.command.run_cmd("umount %s" % device) - shutil.rmtree("vfs_test") - return return_code - - def do_fio(self, 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 = self.command.run_cmd( - "fio %s -size=%dK -bs=%dK %s" % (file_opt, size, a_bs, option)) - if cmd_result[2] != 0: - self.logger.error("%s fio failed." % filepath) - return False - a_bs = a_bs * 2 - self.logger.info("%s fio succeed." % filepath) - return True diff -Naur a/tests/infiniband/infiniband.py b/tests/infiniband/infiniband.py --- a/tests/infiniband/infiniband.py 2022-10-10 14:39:15.912994757 +0800 +++ b/tests/infiniband/infiniband.py 2022-10-10 14:42:07.005992872 +0800 @@ -13,24 +13,15 @@ # Create: 2022-05-24 # Desc: InfiniBand Test -import os import re -from network import NetworkTest +from tests.network.rdma import RDMATest -class InfiniBandTest(NetworkTest): +class InfiniBandTest(RDMATest): def __init__(self): - NetworkTest.__init__(self) - self.requirements = ['opensm', 'rdma-core'] - self.ib_device = None - self.ib_port = None - self.base_lid = None - self.sm_lid = None - self.state = None - self.phys_state = None - self.speed = 56000 # Mb/s - self.target_bandwidth_percent = 0.5 - self.testbw_file = "test_bw.log" + 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): """ @@ -55,180 +46,3 @@ self.logger.info("The subnet manager lid is %s." % self.sm_lid) return True - - def get_ibstatus(self): - """ - Get ibstatus - :return: - """ - path_netdev = ''.join(['/sys', self.device.get_property("DEVPATH")]) - path_pci = path_netdev.split('net')[0] - path_ibdev = os.path.join(path_pci, "infiniband_verbs") - ibdev_name = self.command.run_cmd("ls %s" % path_ibdev) - path_ibdev = os.path.join(path_ibdev, ibdev_name[0].strip()) - cmd = self.command.run_cmd("cat %s/ibdev" % path_ibdev) - if cmd[2] != 0: - self.logger.error("Get %s failed." % path_ibdev) - return False - self.ib_device = cmd[0].strip() - - path_ibport = '/sys/class/net/%s/dev_id' % self.interface - cmd = self.command.run_cmd("cat %s" % path_ibport) - if cmd[2] != 0: - self.logger.error("Get %s failed." % path_ibport) - return False - self.ib_port = int(cmd[0], 16) + 1 - - ib_str = "Infiniband device '%s' port %d" % ( - self.ib_device, self.ib_port) - self.logger.info("Interface %s ===> %s" % (self.interface, ib_str)) - - cmd = self.command.run_cmd("ibstatus") - if cmd[2] != 0: - self.logger.error("Execute ibstatus failed.") - return False - - for info in cmd[0].split('\n\n'): - if ib_str not in info: - continue - self.base_lid = re.search(r"base lid:\s+(.*)", info).group(1) - self.sm_lid = re.search(r"sm lid:\s+(.*)", info).group(1) - self.state = re.search(r"state:\s+(.*)", info).group(1) - self.phys_state = re.search(r"phys state:\s+(.*)", info).group(1) - self.link_layer = re.search(r"link_layer:\s+(.*)", info).group(1) - self.speed = int(re.search(r"rate:\s+(\d*)", info).group(1)) * 1024 - - return True - - def test_rping(self): - """ - Test rping - :return: - """ - if not self.call_remote_server('rping', 'start', self.server_ip): - self.logger.info("Start rping server failed.") - return False - - cmd = self.command.run_cmd("rping -c -a %s -C 50 -v" % self.server_ip) - if cmd[2] == 0: - return True - - self.call_remote_server('rping', 'stop', self.server_ip) - return False - - def test_rcopy(self): - """ - Test rcopy - :return: - """ - if not self.call_remote_server('rcopy', 'start', self.server_ip): - self.logger.error("Start rcopy server failed.") - return False - - cmd = self.command.run_cmd("rcopy %s %s" % - (self.testfile, self.server_ip)) - if cmd[2] == 0: - return True - self.call_remote_server('rcopy', 'stop', self.server_ip) - return False - - def test_bw(self, cmd): - """ - Test bandwidth - :param cmd: - :return: - """ - if self.link_layer == 'Ethernet': - cmd = cmd + ' -R' - - if not self.call_remote_server(cmd, 'start', self.server_ip): - self.logger.error("Start %s server failed." % cmd) - return False - get_info = self.command.run_cmd( - "%s %s -d %s -i %s | tee %s" % (cmd, self.server_ip, self.ib_device, self.ib_port, self.testbw_file)) - if get_info[2] != 0: - self.logger.error("Test bandwidth %s failed." % cmd) - self.call_remote_server(cmd, 'stop', self.server_ip) - return False - result = self.command.run_cmd( - "grep -A 1 'BW average' %s | awk '{print $4}' | grep -v 'sec'" % self.testbw_file) - avg_bw = float(result[0]) * 8 - tgt_bw = self.target_bandwidth_percent * self.speed - self.logger.info("Current bandwidth is %.2fMb/s, target is %.2fMb/s" - % (avg_bw, tgt_bw)) - return avg_bw > tgt_bw - - def test_rdma(self): - """ - Test Remote Direct Memory Access - :return: - """ - self.logger.info("Testing rping...") - if not self.test_rping(): - self.logger.error("Test rping failed.") - return False - - self.logger.info("Creating testfile to upload...") - if not self.create_testfile(): - self.logger.error("Create testfile failed.") - return False - - self.logger.info("Testing rcopy...") - if not self.test_rcopy(): - self.logger.error("Test rcopy failed.") - return False - - self.logger.info("Testing ib_read_bw...") - if not self.test_bw('ib_read_bw'): - self.logger.error("Test ib_read_bw failed.") - return False - - self.logger.info("Testing ib_write_bw...") - if not self.test_bw('ib_write_bw'): - self.logger.error("Test ib_write_bw failed.") - return False - - self.logger.info("Testing ib_send_bw...") - if not self.test_bw('ib_send_bw'): - self.logger.error("Test ib_send_bw failed.") - return False - - return True - - def test_ibstatus(self): - """ - Test ibstatus - :return: - """ - cmd = self.command.run_cmd("systemctl start opensm") - if cmd[2] != 0: - self.logger.error("Start opensm failed.") - return False - - cmd = self.command.run_cmd("modprobe ib_umad") - if cmd[2] != 0: - self.logger.error("Try to modprobe ib_umad failed.") - return False - - if not self.get_ibstatus(): - self.logger.error("Get status of InfiniBand/RoCE devices failed.") - return False - - return True - - def teardown(self): - """ - Environment recovery after test - :return: - """ - self.logger.info("Stop all test servers.") - self.call_remote_server('all', 'stop', self.server_ip) - if os.path.exists(self.testfile): - os.remove(self.testfile) - if os.path.exists(self.testbw_file): - os.remove(self.testbw_file) - ip = self.command.run_cmd( - "ifconfig %s:0 | grep '.*inet' | awk '{print $2}'" % self.interface)[0] - if ip: - self.command.run_cmd( - "ip addr del %s dev %s:0" % (ip, self.interface)) diff -Naur a/tests/infiniband/network.py b/tests/infiniband/network.py --- a/tests/infiniband/network.py 2022-10-10 14:39:15.912994757 +0800 +++ b/tests/infiniband/network.py 1970-01-01 08:00:00.000000000 +0800 @@ -1,200 +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: 2022-05-23 -# Desc: Network Test - -import os -import argparse -from urllib.parse import urlencode -from urllib.request import urlopen, Request -from hwcompatible.test import Test -from hwcompatible.command import Command - - -class NetworkTest(Test): - - def __init__(self): - Test.__init__(self) - self.device = None - self.link_layer = 'InfiniBand' - self.requirements = ['ethtool', 'iproute', 'psmisc'] - self.subtests = [self.test_ip_info, self.test_ibstatus, - self.test_ib_link, self.test_icmp, self.test_rdma] - self.config_data = None - self.interface = None - self.server_ip = None - self.client_ip = None - self.server_port = "80" - self.retries = 3 - self.speed = 1000 # Mb/s - self.target_bandwidth_percent = 0.8 - self.testfile = 'testfile' - - def setup(self, args=None): - """ - Initialization before test - :param args: - :return: - """ - self.args = args or argparse.Namespace() - self.device = getattr(self.args, 'device', None) - self.interface = self.device.get_property("INTERFACE") - self.logger = getattr(self.args, "test_logger", None) - self.command = Command(self.logger) - self.config_data = getattr(self.args, "config_data", None) - if not self.config_data: - self.logger.error( - "Failed to test item value from configuration file.") - return False - - self.server_ip = self.config_data.get("server_ip", "") - self.client_ip = self.config_data.get("client_ip", "") - if ":" in self.server_ip: - self.server_ip, self.server_port = self.server_ip.split(":") - - self.show_driver_info() - return True - - def test(self): - """ - Test case - :return: - """ - if not self.server_ip: - self.logger.error( - "Failed to get server ip from configuration file.") - return False - - if not self.check_fibre(): - self.logger.error("Get fibre information failed.") - return False - - for subtest in self.subtests: - if not subtest(): - return False - return True - - def check_fibre(self): - """ - Check fibre information - :return: - """ - cmd = self.command.run_cmd( - "ethtool %s | grep 'Port' | awk '{print $2}'" % self.interface) - port_type = cmd[0].strip() - if port_type != "FIBRE": - self.logger.info("The %s port type is %s, skip checking." % - (self.interface, port_type)) - return True - - cmd = self.command.run_cmd( - "ethtool %s | grep 'Speed' | awk '{print $2}'" % self.interface) - speed = cmd[0].strip() - if speed == "1000Mb/s": - self.logger.info("The %s fibre speed is %s, skip checking." % - (self.interface, speed)) - return True - - self.logger.info( - "The %s port type is fibre, next to check fibre." % self.interface) - cmd = self.command.run_cmd("ethtool -m %s" % self.interface) - return cmd[2] == 0 - - def get_interface_ip(self): - """ - Get interface ip - :return: - """ - com = self.command.run_cmd( - "ip addr show %s | grep inet | awk '{print $2}' | cut -d '/' -f 1" % self.interface) - if com[2] != 0: - self.logger.error("Get available ip on the interface failed.") - return "" - return com[0].strip() - - def test_icmp(self): - """pcipch - Test ICMP - :return: - """ - 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) - 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', ib_server_ip=''): - """ - Call remote server - :param cmd: - :param act: - :param ib_server_ip: - :return: - """ - form = dict() - form['cmd'] = cmd - form['ib_server_ip'] = ib_server_ip - url = 'http://%s:%s/api/%s' % (self.server_ip, self.server_port, 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 server url %s failed." % url) - return False - self.logger.info("Status: %u %s" % (response.code, response.msg)) - return int(response.code) == 200 - - def create_testfile(self): - """ - Create testfile - :return: - """ - b_s = 128 - count = self.speed/8 - cmd = self.command.run_cmd( - "dd if=/dev/urandom of=%s bs=%uk count=%u" % (self.testfile, b_s, count)) - return cmd[2] == 0 - - def test_ip_info(self): - """ - Test ip info - :return: - """ - if not self.interface: - self.logger.error("No interface assigned.") - return False - self.logger.info("The test interface is %s." % self.interface) - - if not self.server_ip: - self.logger.error("No server ip assigned.") - return False - self.logger.info("The server ip is %s." % self.server_ip) - - if not self.client_ip: - self.logger.error("No available ip on %s." % self.interface) - return False - self.logger.info("The client ip is %s on %s." % - (self.client_ip, self.interface)) - - return True diff -Naur a/tests/network/ethernet.py b/tests/network/ethernet.py --- a/tests/network/ethernet.py 2022-10-10 14:39:15.912994757 +0800 +++ b/tests/network/ethernet.py 2022-10-10 14:42:07.015992872 +0800 @@ -45,7 +45,6 @@ self.subtests = [self.test_ip_info, self.test_ibstatus, self.test_eth_link, self.test_icmp, self.test_rdma] return - self.logger.info("It will test normal ethernet %s." % self.interface) self.subtests = [self.test_ip_info, self.test_eth_link, self.test_icmp, - self.test_udp_tcp, self.test_http] + self.test_udp_tcp, self.test_http] \ No newline at end of file diff -Naur a/tests/network/network.py b/tests/network/network.py --- a/tests/network/network.py 2022-10-10 14:39:15.912994757 +0800 +++ b/tests/network/network.py 2022-10-10 14:42:07.015992872 +0800 @@ -40,6 +40,7 @@ self.subtests = [] self.target_bandwidth_percent = 0.75 self.testfile = 'testfile' + self.testbw_file = "test_bw.log" def setup(self, args=None): """ @@ -91,9 +92,16 @@ :return: """ self.logger.info("Stop all test servers.") - self.call_remote_server('all', 'stop') + self.call_remote_server('all', 'stop', self.server_ip) if os.path.exists(self.testfile): os.remove(self.testfile) + if os.path.exists(self.testbw_file): + os.remove(self.testbw_file) + ip = self.command.run_cmd( + "ifconfig %s:0 | grep '.*inet' | awk '{print $2}'" % self.interface)[0] + if ip: + self.command.run_cmd( + "ip addr del %s dev %s:0" % (ip, self.interface)) def check_fibre(self): """ @@ -188,7 +196,7 @@ for _ in range(self.retries): result = self.command.run_cmd(cmd) if result[0].strip() == "0%": - self.logger.error("Test icmp failed.") + self.logger.info("Test icmp succeed.") return True self.logger.error("Test icmp failed.") return False diff -Naur a/tests/network/rdma.py b/tests/network/rdma.py --- a/tests/network/rdma.py 2022-10-10 14:39:15.912994757 +0800 +++ b/tests/network/rdma.py 2022-10-10 14:42:07.015992872 +0800 @@ -15,7 +15,7 @@ import os import re -from network import NetworkTest +from tests.network.network import NetworkTest class RDMATest(NetworkTest): @@ -25,32 +25,20 @@ self.ib_device = None self.ib_port = None self.link_layer = None + self.base_lid = None + self.sm_lid = None + self.state = None + self.phys_state = None + self.speed = 56000 # Mb/s self.target_bandwidth_percent = 0.5 - self.testbw_file = "test_bw.log" def get_ibstatus(self): """ Get ibstatus :return: """ - path_netdev = ''.join(['/sys', self.device.get_property("DEVPATH")]) - path_pci = path_netdev.split('net')[0] - path_ibdev = os.path.join(path_pci, "infiniband_verbs") - ibdev_name = self.command.run_cmd("ls %s" % path_ibdev) - path_ibdev = os.path.join(path_ibdev, ibdev_name[0].strip()) - cmd = self.command.run_cmd("cat %s/ibdev" % path_ibdev) - if cmd[2] != 0: - self.logger.error("Get %s failed." % path_ibdev) + if not self.get_ibdev_ibport(): return False - self.ib_device = cmd[0].strip() - - path_ibport = '/sys/class/net/%s/dev_id' % self.interface - cmd = self.command.run_cmd("cat %s" % path_ibport) - if cmd[2] != 0: - self.logger.error("Get %s failed." % path_ibport) - return False - self.ib_port = int(cmd[0], 16) + 1 - ib_str = "Infiniband device '%s' port %d" % ( self.ib_device, self.ib_port) self.logger.info("Interface %s ===> %s" % (self.interface, ib_str)) @@ -63,9 +51,12 @@ for info in cmd[0].split('\n\n'): if ib_str not in info: continue + self.base_lid = re.search(r"base lid:\s+(.*)", info).group(1) + self.sm_lid = re.search(r"sm lid:\s+(.*)", info).group(1) + self.state = re.search(r"state:\s+(.*)", info).group(1) + self.phys_state = re.search(r"phys state:\s+(.*)", info).group(1) self.link_layer = re.search(r"link_layer:\s+(.*)", info).group(1) self.speed = int(re.search(r"rate:\s+(\d*)", info).group(1)) * 1024 - return True def test_rping(self): @@ -184,19 +175,28 @@ return True - def teardown(self): + def get_ibdev_ibport(self): """ - Environment recovery after test + Get the drive and port of IB card :return: """ - self.logger.info("Stop all test servers.") - self.call_remote_server('all', 'stop', self.server_ip) - if os.path.exists(self.testfile): - os.remove(self.testfile) - if os.path.exists(self.testbw_file): - os.remove(self.testbw_file) - ip = self.command.run_cmd( - "ifconfig %s:0 | grep '.*inet' | awk '{print $2}'" % self.interface)[0] - if ip: - self.command.run_cmd( - "ip addr del %s dev %s:0" % (ip, self.interface)) + path_netdev = ''.join(['/sys', self.device.get_property("DEVPATH")]) + path_pci = path_netdev.split('net')[0] + path_ibdev = os.path.join(path_pci, "infiniband_verbs") + ibdev_name = self.command.run_cmd("ls %s" % path_ibdev) + path_ibdev = os.path.join(path_ibdev, ibdev_name[0].strip()) + cmd = self.command.run_cmd("cat %s/ibdev" % path_ibdev) + if cmd[2] != 0: + self.logger.error("Get %s failed." % path_ibdev) + return False + self.ib_device = cmd[0].strip() + + path_ibport = '/sys/class/net/%s/dev_id' % self.interface + cmd = self.command.run_cmd("cat %s" % path_ibport) + if cmd[2] != 0: + self.logger.error("Get %s failed." % path_ibport) + return False + self.ib_port = int(cmd[0], 16) + 1 + return True + + diff -Naur a/tests/nvme/nvme.py b/tests/nvme/nvme.py --- a/tests/nvme/nvme.py 2022-10-10 14:39:15.913994757 +0800 +++ b/tests/nvme/nvme.py 2022-10-10 14:42:07.015992872 +0800 @@ -13,6 +13,7 @@ # Create: 2020-04-01 # Desc: Test Non-Volatile Memory express +import os import argparse from subprocess import getoutput from hwcompatible.test import Test @@ -25,7 +26,7 @@ self.requirements = ["nvme-cli"] self.args = None self.device = None - self.name = "" + self.filename = "test.file" self.logpath = "" def setup(self, args=None): @@ -54,20 +55,31 @@ block_count = getoutput("cat /sys/block/%s/size" % disk) block_size = getoutput("cat /sys/block/%s/queue/logical_block_size" % disk) size = int(block_count) * int(block_size) - size = size/2/2 + size = size / 2 / 2 if size <= 0: self.logger.error( "The size of %s is not suitable for this test." % disk) return False - elif size > 128*1024: - size = 128*1024 + elif size > 128 * 1024: + size = 128 * 1024 + + size_per_block = int(self.command.run_cmd("nvme list | grep %s | awk '{print $10}'" % disk)[0]) + block_num = 1 + if size_per_block != 0: + block_num = int(int(size) / size_per_block) - 1 + + cmd = "seq -s a 150000 | tee %s" % self.filename + result = self.command.run_cmd(cmd, log_print=False) + if result[2] != 0: + self.logger.error("Create file failed!") + return False self.logger.info("Start to format nvme.") return_code = True cmd_list = [ "nvme format -l 0 -i 0 /dev/%s" % disk, - "nvme write -z %d -s 0 -d /dev/urandom /dev/%s" % (size, disk), - "nvme read -s 0 -z %d /dev/%s" % (size, disk), + "nvme write -c %d -s 0 -z %d -d %s /dev/%s" % (block_num, size, self.filename, disk), + "nvme read -c %d -s 0 -z %d /dev/%s" % (block_num, size, disk), "nvme smart-log /dev/%s" % disk, "nvme get-log -i 1 -l 128 /dev/%s" % disk ] @@ -82,7 +94,6 @@ else: self.logger.info("Test nvme failed.") return return_code - def in_use(self, disk): """ @@ -102,12 +113,19 @@ if ("/dev/%s" % disk) in swap or disk in mdstat: return True - + if ("/dev/%s" % disk) in mounts: return True result = self.command.run_cmd("pvs | grep -q '/dev/%s'" % disk) if result[2] == 0: return True - + return False + + def teardown(self): + """ + Environment recovery + """ + if os.path.exists(self.filename): + os.remove(self.filename) diff -Naur a/tests/raid/raid.py b/tests/raid/raid.py --- a/tests/raid/raid.py 2022-08-29 19:51:34.000000000 +0800 +++ b/tests/raid/raid.py 2022-10-10 14:42:07.015992872 +0800 @@ -13,233 +13,54 @@ # Create: 2022-04-09 # Desc: Raid test -import os -import sys -import shutil import argparse -from subprocess import getoutput -from hwcompatible.test import Test from hwcompatible.command import Command -from hwcompatible.device import CertDevice +from hwcompatible.test import Test +from tests.disk.common import query_disk, get_disk, raw_test, vfs_test, valid_disk class RaidTest(Test): def __init__(self): Test.__init__(self) self.disks = list() - self.requirements = ["fio"] - self.filesystems = ["ext4"] self.device = "" self.pci_num = "" + self.requirements = ["fio"] + self.filesystems = ["ext4"] self.config_data = dict() def setup(self, args=None): - """ - The Setup before testing - :return: - """ self.args = args or argparse.Namespace() - self.device = getattr(self.args, 'device', None) - self.pci_num = self.device.get_property("DEVPATH").split('/')[-1] - self.config_data = getattr(self.args, "config_data", None) 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) - self.logger.info("Disk Info:", terminal_print=False) - self.command.run_cmd("fdisk -l") - self.logger.info("Partition Info:", terminal_print=False) - self.command.run_cmd("df -h") - self.logger.info("Mount Info:", terminal_print=False) - self.command.run_cmd("mount") - self.logger.info("Swap Info:", terminal_print=False) - self.command.run_cmd("cat /proc/swaps") - self.logger.info("LVM Info:", terminal_print=False) - self.command.run_cmd("pvdisplay") - self.command.run_cmd("vgdisplay") - self.command.run_cmd("lvdisplay") - self.logger.info("Md Info:", terminal_print=False) - self.command.run_cmd("cat /proc/mdstat") + query_disk(self.logger, self.command) def test(self): """ Start test """ - self.get_disk() + self.disks = get_disk(self.logger, self.command, self.config_data, self.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', '') - result = self.valid_disk(disk, self.disks) - if not result: + 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 self.raw_test(disk): - return_code = False - if not self.vfs_test(disk): - return_code = False - - return return_code - - def get_disk(self): - """ - Get disk info - """ - disks = list() - devices = CertDevice(self.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") and \ - self.pci_num in device.get_property("DEVPATH"): - disks.append(device.get_name()) - - partition_file = open("/proc/partitions", "r") - partition = partition_file.read() - partition_file.close() - - self.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 = self.command.run_cmd("pvs | grep -q '/dev/%s'" % disk) - if result[2] == 0: - continue - self.disks.append(disk) - - un_suitable = list(set(disks).difference(set(self.disks))) - if len(un_suitable) > 0: - self.logger.info("These disks %s are in use now, skip them." % - "|".join(un_suitable)) - - def raw_test(self, disk): - """ - Raw test - """ - self.logger.info("%s raw IO test" % disk) - device = os.path.join("/dev", disk) - if not os.path.exists(device): - self.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: - self.logger.error( - "Device %s size is not suitable for testing." % device) - return False - elif size > 1048576: - size = 1048576 - - self.logger.info("Starting sequential raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.info("%s sequential raw IO test failed." % device) - return False - - self.logger.info("Starting rand raw IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 " \ - "-group_reporting -name=file -runtime=300" - if not self.do_fio(device, size, opts): - self.logger.error("%s rand raw IO test failed." % device) - return False - - return True - - def vfs_test(self, disk): - """ - Vfs test - """ - self.logger.info("%s vfs test" % disk) - device = os.path.join("/dev/", disk) - if not os.path.exists(device): - self.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: - self.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 self.filesystems: - self.logger.info("Formatting %s to %s ..." % - (device, file_sys), terminal_print=False) - self.command.run_cmd("umount %s" % device, ignore_errors=True) - self.command.run_cmd("mkfs -t %s -F %s" % (file_sys, device)) - self.command.run_cmd("mount -t %s %s %s" % - (file_sys, device, "vfs_test")) - self.logger.info("Starting sequential vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=rw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): + if not raw_test(self.logger, self.command, disk): return_code = False - break - - self.logger.info("Starting rand vfs IO test...") - opts = "-direct=1 -iodepth 4 -rw=randrw -rwmixread=50 -name=directoy -runtime=300" - if not self.do_fio(path, size, opts): + if not vfs_test(self.logger, self.command, disk, self.filesystems): return_code = False - break - - self.command.run_cmd("umount %s" % device) - shutil.rmtree("vfs_test") return return_code - - def do_fio(self, 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 = self.command.run_cmd( - "fio %s -size=%dK -bs=%dK %s" % (file_opt, size, a_bs, option)) - if cmd_result[2] != 0: - self.logger.error("%s fio failed." % filepath) - return False - a_bs = a_bs * 2 - self.logger.info("%s fio succeed." % filepath) - return True