Skip to content

Commit 1f52310

Browse files
committed
Add a case to support test nic driver load/unload
Automate VIRT-95967 Test nic drievr load/unload Signed-off-by: Lei Yang <[email protected]>
1 parent a302a6f commit 1f52310

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
- virtual_network.qemu_test.nicdriver_unload: image_copy
2+
only Linux
3+
type = nicdriver_unload
4+
create_vm_libvirt = yes
5+
kill_vm_libvirt = yes
6+
filesize = 512
7+
rules = 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"'
8+
transfer_timeout = 1000
9+
sessions_num = 5
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import os
2+
import random
3+
import time
4+
5+
from avocado.utils import crypto, process
6+
from virttest import data_dir, error_context, utils_misc, utils_net
7+
8+
9+
@error_context.context_aware
10+
def run(test, params, env):
11+
"""
12+
Test nic driver load/unload.
13+
14+
1) Boot a VM.
15+
2) Get the NIC driver name.
16+
3) Multi-session TCP transfer on test interface.
17+
4) Repeatedly unload/load NIC driver during file transfer.
18+
5) Check whether the test interface should still work.
19+
20+
:param test: QEMU test object.
21+
:param params: Dictionary with the test parameters.
22+
:param env: Dictionary with test environment.
23+
"""
24+
25+
def reset_guest_udevrules(session, rules_file, rules_content):
26+
"""
27+
Write guest udev rules, then reboot the guest and
28+
return the new session
29+
"""
30+
set_cmd = "echo '%s' > %s" % (rules_content, rules_file)
31+
session.cmd_output_safe(set_cmd)
32+
return vm.reboot()
33+
34+
def all_threads_done(threads):
35+
"""
36+
Check whether all threads have finished
37+
"""
38+
for thread in threads:
39+
if thread.is_alive():
40+
return False
41+
else:
42+
continue
43+
return True
44+
45+
def all_threads_alive(threads):
46+
"""
47+
Check whether all threads is alive
48+
"""
49+
for thread in threads:
50+
if not thread.is_alive():
51+
return False
52+
else:
53+
continue
54+
return True
55+
56+
timeout = params.get_numeric("login_timeout", 360)
57+
transfer_timeout = params.get_numeric("transfer_timeout", 1000)
58+
filesize = params.get_numeric("filesize", 512)
59+
60+
vm = env.get_vm(params["main_vm"])
61+
vm.verify_alive()
62+
session = vm.wait_for_login(timeout=timeout)
63+
vm_mac_address = vm.get_mac_address()
64+
udev_rules_file = "/etc/udev/rules.d/70-persistent-net.rules"
65+
rules = params.get("rules")
66+
if not session.cmd_status("[ -e %s ]" % udev_rules_file):
67+
if not rules:
68+
test.cancel("You must set udev rules before test")
69+
rules = rules % vm_mac_address
70+
session = reset_guest_udevrules(session, udev_rules_file, rules)
71+
72+
error_context.base_context("Test env prepare")
73+
error_context.context("Get NIC interface name in guest.", test.log.info)
74+
ethname = utils_net.get_linux_ifname(session, vm.get_mac_address(0))
75+
# get ethernet driver from '/sys' directory.
76+
# ethtool can do the same thing and doesn't care about os type.
77+
# if we make sure all guests have ethtool, we can make a change here.
78+
sys_path = params.get("sys_path") % (ethname)
79+
readlink_cmd = params.get("readlink_command", "readlink -e")
80+
driver = os.path.basename(session.cmd("%s %s" % (readlink_cmd, sys_path)).strip())
81+
test.log.info("The guest interface %s using driver %s", ethname, driver)
82+
83+
error_context.context(
84+
"Host test file prepare, create %dMB file on host" % filesize, test.log.info
85+
)
86+
tmp_dir = data_dir.get_tmp_dir()
87+
host_path = os.path.join(
88+
tmp_dir, "host_file_%s" % utils_misc.generate_random_string(8)
89+
)
90+
guest_path = os.path.join(
91+
"/home", "guest_file_%s" % utils_misc.generate_random_string(8)
92+
)
93+
cmd = "dd if=/dev/zero of=%s bs=1M count=%d" % (host_path, filesize)
94+
process.run(cmd)
95+
file_checksum = crypto.hash_file(host_path, algorithm="md5")
96+
97+
error_context.context(
98+
"Guest test file prepare, Copy file %s from host to guest" % host_path,
99+
test.log.info,
100+
)
101+
vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout)
102+
if session.cmd_status("md5sum %s | grep %s" % (guest_path, file_checksum)):
103+
test.cancel("File MD5SUMs changed after copy to guest")
104+
test.log.info("Test env prepare successfully")
105+
106+
error_context.base_context("Nic driver load/unload testing", test.log.info)
107+
session_serial = vm.wait_for_serial_login(timeout=timeout)
108+
try:
109+
error_context.context("Transfer file between host and guest", test.log.info)
110+
threads = []
111+
file_paths = []
112+
host_file_paths = []
113+
for sess_index in range(int(params.get("sessions_num", "10"))):
114+
sess_path = os.path.join("/home", "dst-%s" % sess_index)
115+
host_sess_path = os.path.join(tmp_dir, "dst-%s" % sess_index)
116+
117+
thread1 = utils_misc.InterruptedThread(
118+
vm.copy_files_to, (host_path, sess_path), {"timeout": transfer_timeout}
119+
)
120+
121+
thread2 = utils_misc.InterruptedThread(
122+
vm.copy_files_from,
123+
(guest_path, host_sess_path),
124+
{"timeout": transfer_timeout},
125+
)
126+
thread1.start()
127+
threads.append(thread1)
128+
thread2.start()
129+
threads.append(thread2)
130+
file_paths.append(sess_path)
131+
host_file_paths.append(host_sess_path)
132+
133+
utils_misc.wait_for(lambda: all_threads_alive(threads), 60, 10, 1)
134+
135+
time.sleep(5)
136+
error_context.context(
137+
"Repeatedly unload/load NIC driver during file transfer", test.log.info
138+
)
139+
while not all_threads_done(threads):
140+
error_context.context(
141+
"Shutdown the driver for NIC interface.", test.log.info
142+
)
143+
sleep_time = random.randint(1, 5)
144+
error_context.context("Unload NIC driver.", test.log.info)
145+
session_serial.cmd_output_safe("modprobe -r %s" % driver)
146+
time.sleep(sleep_time)
147+
error_context.context("Load NIC driver.", test.log.info)
148+
session_serial.cmd_output_safe("modprobe %s" % driver)
149+
time.sleep(sleep_time)
150+
151+
# files md5sums check
152+
error_context.context(
153+
"File transfer finished, checking files md5sums", test.log.info
154+
)
155+
err_info = []
156+
for copied_file in file_paths:
157+
if session_serial.cmd_status(
158+
"md5sum %s | grep %s" % (copied_file, file_checksum)
159+
):
160+
err_msg = "Guest file %s md5sum changed"
161+
err_info.append(err_msg % copied_file)
162+
for copied_file in host_file_paths:
163+
if process.system(
164+
"md5sum %s | grep %s" % (copied_file, file_checksum), shell=True
165+
):
166+
err_msg = "Host file %s md5sum changed"
167+
err_info.append(err_msg % copied_file)
168+
if err_info:
169+
test.error("files MD5SUMs changed after copying %s" % err_info)
170+
except Exception:
171+
for thread in threads:
172+
thread.join(suppress_exception=True)
173+
raise
174+
else:
175+
for thread in threads:
176+
thread.join()
177+
for copied_file in file_paths:
178+
session_serial.cmd("rm -rf %s" % copied_file)
179+
for copied_file in host_file_paths:
180+
process.system("rm -rf %s" % copied_file)
181+
session_serial.cmd("%s %s" % ("rm -rf", guest_path))
182+
os.remove(host_path)
183+
session.close()
184+
session_serial.close()

0 commit comments

Comments
 (0)