|
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,79 @@ def check_coalesce(vm_name, mac, coalesce): |
224 | 225 | return 0, '' |
225 | 226 |
|
226 | 227 |
|
| 228 | +def check_target_option_behavior(test, vm_name, iface_mac, expected_target_name): |
| 229 | + """ |
| 230 | + Check target option behavior according to test matrix |
| 231 | +
|
| 232 | + :param test: Test object for test.fail() calls |
| 233 | + :param vm_name: Name of the virtual machine |
| 234 | + :param iface_mac: MAC address of the interface to check |
| 235 | + :param expected_target_name: Expected exact target name for "keep" behavior |
| 236 | + """ |
| 237 | + |
| 238 | + # Get actual target from XML using fetch_attrs |
| 239 | + vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name) |
| 240 | + interfaces = vmxml.devices.by_device_tag('interface') |
| 241 | + actual_target = None |
| 242 | + for iface in interfaces: |
| 243 | + if iface.mac_address == iface_mac: |
| 244 | + actual_target = iface.fetch_attrs().get('target', {}).get('dev') |
| 245 | + break |
| 246 | + if not re.findall(expected_target_name, actual_target): |
| 247 | + test.fail("Expected target '%s', got '%s'" % (expected_target_name, actual_target)) |
| 248 | + test.log.debug("PASS: Expected target '%s' in vm xml for MAC %s", expected_target_name, iface_mac) |
| 249 | + |
| 250 | + |
| 251 | +def check_domiflist_target(test, vm_name, iface_mac, expected_target_name, existed=True): |
| 252 | + """ |
| 253 | + Check target device name from virsh domiflist. |
| 254 | +
|
| 255 | + :param test: Test object for test.fail() calls |
| 256 | + :param vm_name: Name of the virtual machine |
| 257 | + :param iface_mac: MAC address of the interface to find |
| 258 | + :param expected_target_name: Expected target device name pattern |
| 259 | + :param existed: Whether the target should exist (True) or not exist (False) |
| 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, expected_existed=True): |
| 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 | + :param expected_existed: Expected iface_mac is existed or not. |
| 284 | + """ |
| 285 | + try: |
| 286 | + session = vm.wait_for_login() |
| 287 | + status, output = session.cmd_status_output("ip -4 -o link list") |
| 288 | + session.close() |
| 289 | + if expected_existed: |
| 290 | + if not re.search(iface_mac.lower(), output.lower()): |
| 291 | + test.fail("Interface with MAC %s was not found in guest: %s" % (iface_mac, output)) |
| 292 | + else: |
| 293 | + if re.search(iface_mac.lower(), output.lower()): |
| 294 | + test.fail("Interface with MAC %s was found in guest: %s" % (iface_mac, output)) |
| 295 | + logging.info("PASS checking for the Interface with MAC %s in guest", iface_mac) |
| 296 | + |
| 297 | + except Exception as e: |
| 298 | + test.fail("Failed to check guest interface: %s" % str(e)) |
| 299 | + |
| 300 | + |
227 | 301 | def run(test, params, env): |
228 | 302 | """ |
229 | 303 | Test virsh {at|de}tach-interface command. |
@@ -281,6 +355,14 @@ def run(test, params, env): |
281 | 355 | paused_after_vm_start = "yes" == params.get("paused_after_vm_start", "no") |
282 | 356 | machine_type = params.get("machine_type") |
283 | 357 |
|
| 358 | + # Target option test specific parameters |
| 359 | + test_target_option = params.get_boolean("test_target_option") |
| 360 | + check_domiflist_result = params.get_boolean("check_domiflist_result") |
| 361 | + check_guest_interface = params.get_boolean("check_guest_interface") |
| 362 | + expected_target_name = params.get("expected_target_name", "") |
| 363 | + if params.get_boolean("none_target"): |
| 364 | + iface_target = None |
| 365 | + |
284 | 366 | # Get iface name if iface_type is direct |
285 | 367 | if iface_type == "direct": |
286 | 368 | links = utils_net.get_net_if(state="UP") |
@@ -472,9 +554,17 @@ def _check_coalesce(fail_flag): |
472 | 554 | # Check coalesce info if needed |
473 | 555 | fail_flag = _check_coalesce(fail_flag) |
474 | 556 |
|
| 557 | + # Check attach-interface with --target option part. |
| 558 | + if test_target_option and not fail_flag: |
| 559 | + check_target_option_behavior( |
| 560 | + test, vm_name, iface_mac, expected_target_name) |
| 561 | + if check_domiflist_result: |
| 562 | + check_domiflist_target(test, vm_name, iface_mac, expected_target_name) |
| 563 | + iface_target = params.get("expected_target_name") |
| 564 | + |
475 | 565 | # Check on host for direct type |
476 | 566 | if iface_type == 'direct': |
477 | | - cmd_result = process.run("ip -d link show test").stdout_text.strip() |
| 567 | + cmd_result = process.run("ip -d link show %s" % iface_target).stdout_text.strip() |
478 | 568 | logging.info("cmd output is %s", cmd_result) |
479 | 569 | check_patten = ("%s@%s.*\n.*%s.*\n.*macvtap.*mode.*%s" |
480 | 570 | % (iface_target, iface_source, iface_mac, iface_mode)) |
@@ -521,6 +611,10 @@ def _check_coalesce(fail_flag): |
521 | 611 | # If command with --config parameter, ignore below checking. |
522 | 612 | if options_suffix.count("config"): |
523 | 613 | return |
| 614 | + if test_target_option: |
| 615 | + check_guest_interface_exists(test, vm, iface_mac, expected_existed=False) |
| 616 | + check_domiflist_target(test, vm_name, iface_mac, expected_target_name, existed=False) |
| 617 | + fail_flag = 0 |
524 | 618 | # Check the xml after detach and clean up if needed. |
525 | 619 | time.sleep(5) |
526 | 620 | status, _ = check_dumpxml_iface(vm_name, iface_format) |
|
0 commit comments