Skip to content

Commit b412b7f

Browse files
committed
add case for attaching interface with target option for nat and direct type
xxxx-296606:Attach interface with --target for nat and direct interface Signed-off-by: nanli <[email protected]>
1 parent a095fab commit b412b7f

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

libvirt/tests/cfg/virsh_cmd/domain/virsh_attach_detach_interface.cfg

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,33 @@
5454
attach_cmd = 'attach-device'
5555
save_restore = 'yes'
5656
at_detach_iface_coalesce = {'max': '32'}
57+
- target_option_test:
58+
# Test attach-interface with --target option for network interface type
59+
# Test matrix based on target name behavior for network type
60+
only vm_running..domname
61+
check_xml_result = "no"
62+
check_domiflist_result = "yes"
63+
check_guest_interface = "yes"
64+
test_target_option = "yes"
65+
variants:
66+
- target_vnet90:
67+
at_detach_iface_target = "vnet90"
68+
expected_target_name = "vnet1"
69+
- target_macvtap90:
70+
at_detach_iface_target = "macvtap90"
71+
expected_target_name = "vnet1"
72+
- target_vif90:
73+
at_detach_iface_target = "vif90"
74+
expected_target_name = "vif90"
75+
- target_macvlan90:
76+
at_detach_iface_target = "macvlan90"
77+
expected_target_name = "vnet1"
78+
- target_testname:
79+
at_detach_iface_target = "testname"
80+
expected_target_name = "testname"
81+
- target_unset:
82+
expected_target_name = "vnet1"
83+
none_target = "yes"
5784

5885
- exist_bridge:
5986
at_detach_iface_type = "bridge"
@@ -102,6 +129,35 @@
102129
at_detach_link_state = "up"
103130
at_detach_rom_bar = "{'bar':'on'}"
104131
at_detach_iface_backend = "{'vhost':'/dev/vhost-net'}"
132+
- target_option_test:
133+
# Test attach-interface with --target option for direct interface type
134+
# Test matrix based on target name behavior for direct type
135+
only vm_running..domname
136+
check_xml_result = "no"
137+
check_domiflist_result = "yes"
138+
check_guest_interface = "yes"
139+
test_target_option = "yes"
140+
# Override the default target from parent direct section
141+
at_detach_iface_target = ""
142+
variants:
143+
- target_vnet90:
144+
at_detach_iface_target = "vnet90"
145+
expected_target_name = "macvtap0"
146+
- target_macvtap90:
147+
at_detach_iface_target = "macvtap90"
148+
expected_target_name = "macvtap0"
149+
- target_vif90:
150+
at_detach_iface_target = "vif90"
151+
expected_target_name = "vif90"
152+
- target_macvlan90:
153+
at_detach_iface_target = "macvlan90"
154+
expected_target_name = "macvtap0"
155+
- target_testname:
156+
at_detach_iface_target = "testname"
157+
expected_target_name = "testname"
158+
- target_unset:
159+
expected_target_name = "macvtap0"
160+
none_target = "yes"
105161
# TODO: There are a lot of type:user,ethernet,direct and etc.
106162
variants:
107163
- vm_running:

libvirt/tests/src/virsh_cmd/domain/virsh_attach_detach_interface.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from virttest.utils_test import libvirt
1414
from virttest.libvirt_xml import vm_xml
1515
from virttest.libvirt_xml.devices.interface import Interface
16+
from virttest.utils_libvirt import libvirt_misc
1617

1718

1819
# Using as lower capital is not the best way to do, but this is just a
@@ -224,6 +225,75 @@ def check_coalesce(vm_name, mac, coalesce):
224225
return 0, ''
225226

226227

228+
229+
def check_target_option_behavior(test, vm_name, iface_mac, expected_target_name):
230+
"""
231+
Check target option behavior according to test matrix
232+
233+
:param test: Test object for test.fail() calls
234+
:param vm_name: Name of the virtual machine
235+
:param iface_mac: MAC address of the interface to check
236+
:param expected_target_name: Expected exact target name for "keep" behavior
237+
"""
238+
239+
# Get actual target from XML using fetch_attrs
240+
vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
241+
interfaces = vmxml.devices.by_device_tag('interface')
242+
actual_target = None
243+
for iface in interfaces:
244+
if iface.mac_address == iface_mac:
245+
actual_target = iface.fetch_attrs().get('target', {}).get('dev')
246+
break
247+
if not re.findall(expected_target_name, actual_target):
248+
test.fail("Expected target '%s', got '%s'" % (expected_target_name, actual_target))
249+
test.log.debug("PASS: Expected target '%s' in vm xml for MAC %s", expected_target_name, iface_mac)
250+
251+
252+
def check_domiflist_target(test, vm_name, iface_mac, expected_target_name, existed=True):
253+
"""
254+
Check target device name from virsh domiflist.
255+
256+
:param test: Test object for test.fail() calls
257+
:param vm_name: Name of the virtual machine
258+
:param iface_mac: MAC address of the interface to find
259+
:param: expected_target_name: expected Target device name.
260+
:raises: test.fail() if domiflist command fails or MAC not found
261+
"""
262+
result = virsh.domiflist(vm_name, ignore_status=True, debug=True)
263+
for line in result.stdout.strip().split('\n'):
264+
if iface_mac.lower() in line.lower():
265+
iflist_info = libvirt_misc.convert_to_dict(line, pattern=r'(\S+) +(.*)')
266+
target_names = list(iflist_info.keys())[0]
267+
if existed:
268+
if not re.findall(expected_target_name, target_names):
269+
test.fail("Expected '%s' is existed, but got '%s' in domiflist" % (expected_target_name, target_names))
270+
else:
271+
if re.findall(expected_target_name, target_names):
272+
test.fail("Expected '%s' is not existed, but got '%s' in domiflist" % (expected_target_name, target_names))
273+
test.log.debug("Checking PASS: Interface target '%s' with domiflist for MAC %s", expected_target_name, iface_mac)
274+
275+
276+
def check_guest_interface_exists(test, vm, iface_mac):
277+
"""
278+
Check if interface exists in guest OS
279+
280+
:param test: Test object for test.fail() calls
281+
:param vm: Virtual machine object.
282+
:param iface_mac: MAC address of the interface to verify in guest.
283+
"""
284+
try:
285+
session = vm.wait_for_login()
286+
status, output = session.cmd_status_output("ip -4 -o link list")
287+
session.close()
288+
289+
if re.search(iface_mac.lower(), output.lower()):
290+
test.fail("Interface with MAC %s was found in guest: %s" % (iface_mac, output))
291+
logging.info("PASS: Interface with MAC %s found in guest", iface_mac)
292+
293+
except Exception as e:
294+
test.fail("Failed to check guest interface: %s" % str(e))
295+
296+
227297
def run(test, params, env):
228298
"""
229299
Test virsh {at|de}tach-interface command.
@@ -281,6 +351,14 @@ def run(test, params, env):
281351
paused_after_vm_start = "yes" == params.get("paused_after_vm_start", "no")
282352
machine_type = params.get("machine_type")
283353

354+
# Target option test specific parameters
355+
test_target_option = params.get_boolean("test_target_option")
356+
check_domiflist_result = params.get_boolean("check_domiflist_result")
357+
check_guest_interface = params.get_boolean("check_guest_interface")
358+
expected_target_name = params.get("expected_target_name", "")
359+
if params.get_boolean("none_target"):
360+
iface_target = None
361+
284362
# Get iface name if iface_type is direct
285363
if iface_type == "direct":
286364
links = utils_net.get_net_if(state="UP")
@@ -472,9 +550,17 @@ def _check_coalesce(fail_flag):
472550
# Check coalesce info if needed
473551
fail_flag = _check_coalesce(fail_flag)
474552

553+
# Check attach-interface with --target option part.
554+
if test_target_option and not fail_flag:
555+
check_target_option_behavior(
556+
test, vm_name, iface_mac, expected_target_name)
557+
if check_domiflist_result:
558+
check_domiflist_target(test, vm_name, iface_mac, expected_target_name)
559+
iface_target = params.get("expected_target_name")
560+
475561
# Check on host for direct type
476562
if iface_type == 'direct':
477-
cmd_result = process.run("ip -d link show test").stdout_text.strip()
563+
cmd_result = process.run("ip -d link show %s" % iface_target).stdout_text.strip()
478564
logging.info("cmd output is %s", cmd_result)
479565
check_patten = ("%s@%s.*\n.*%s.*\n.*macvtap.*mode.*%s"
480566
% (iface_target, iface_source, iface_mac, iface_mode))
@@ -521,6 +607,10 @@ def _check_coalesce(fail_flag):
521607
# If command with --config parameter, ignore below checking.
522608
if options_suffix.count("config"):
523609
return
610+
if test_target_option:
611+
check_guest_interface_exists(test, vm, iface_mac)
612+
check_domiflist_target(test, vm_name, iface_mac, expected_target_name, existed=False)
613+
fail_flag = 0
524614
# Check the xml after detach and clean up if needed.
525615
time.sleep(5)
526616
status, _ = check_dumpxml_iface(vm_name, iface_format)

0 commit comments

Comments
 (0)