1934 lines
70 KiB
Diff
1934 lines
70 KiB
Diff
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/<path:path>` | | 文件下载,辅助客户端网卡测试 |
|
||
| 11 | `/api/file/upload` | GET/POST | 文件上传,辅助客户端网卡测试 |
|
||
| 12 | `/api/<act>` | 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
|