|
13 | 13 | from virttest.utils_test import libvirt |
14 | 14 | from virttest.libvirt_xml import vm_xml |
15 | 15 | from virttest.libvirt_xml.devices.interface import Interface |
| 16 | +from virttest.utils_libvirt import libvirt_misc |
16 | 17 |
|
17 | 18 |
|
18 | 19 | # 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): |
224 | 225 | return 0, '' |
225 | 226 |
|
226 | 227 |
|
| 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 | + |
227 | 297 | def run(test, params, env): |
228 | 298 | """ |
229 | 299 | Test virsh {at|de}tach-interface command. |
@@ -281,6 +351,14 @@ def run(test, params, env): |
281 | 351 | paused_after_vm_start = "yes" == params.get("paused_after_vm_start", "no") |
282 | 352 | machine_type = params.get("machine_type") |
283 | 353 |
|
| 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 | + |
284 | 362 | # Get iface name if iface_type is direct |
285 | 363 | if iface_type == "direct": |
286 | 364 | links = utils_net.get_net_if(state="UP") |
@@ -472,9 +550,17 @@ def _check_coalesce(fail_flag): |
472 | 550 | # Check coalesce info if needed |
473 | 551 | fail_flag = _check_coalesce(fail_flag) |
474 | 552 |
|
| 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 | + |
475 | 561 | # Check on host for direct type |
476 | 562 | 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() |
478 | 564 | logging.info("cmd output is %s", cmd_result) |
479 | 565 | check_patten = ("%s@%s.*\n.*%s.*\n.*macvtap.*mode.*%s" |
480 | 566 | % (iface_target, iface_source, iface_mac, iface_mode)) |
@@ -521,6 +607,10 @@ def _check_coalesce(fail_flag): |
521 | 607 | # If command with --config parameter, ignore below checking. |
522 | 608 | if options_suffix.count("config"): |
523 | 609 | 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 |
524 | 614 | # Check the xml after detach and clean up if needed. |
525 | 615 | time.sleep(5) |
526 | 616 | status, _ = check_dumpxml_iface(vm_name, iface_format) |
|
0 commit comments