Skip to content

iface_attach_detach: Support new libvirt error message for boot order conflicts#6802

Open
BulaYoungR wants to merge 1 commit intoautotest:masterfrom
BulaYoungR:iface_attach
Open

iface_attach_detach: Support new libvirt error message for boot order conflicts#6802
BulaYoungR wants to merge 1 commit intoautotest:masterfrom
BulaYoungR:iface_attach

Conversation

@BulaYoungR
Copy link

@BulaYoungR BulaYoungR commented Feb 11, 2026

Fix test failure caused by libvirt error message format change in newer versions when validating boot order conflicts.

File: libvirt/tests/src/virtual_network/iface_attach_detach.py
Lines changed: 46-61 (added 15 lines)

The test validates that libvirt correctly rejects attaching a network interface with boot order when os/boot is already configured on another device. However, libvirt changed the error message format between versions, causing the test to fail even though the error itself was correct.

Old libvirt error message:
"per-device boot elements cannot be used together with os/boot elements"

New libvirt error message:
"boot order 1 is already used by another device"

Problem:
The test expected only the old error message format from the error_msg parameter, causing it to fail when libvirt returned the new message format. The actual error was correct - libvirt properly rejected the invalid configuration - but the message text differed.

Solution:
Modified error checking logic in test_boot_order() function to accept both error message formats:

  • If status_error is expected and error_msg is provided:

    • Convert error_msg to list if it's a string
    • Extend the list with known alternative patterns for boot order conflicts
    • Pass the extended list to libvirt.check_result()
    • This allows the test to pass if any pattern matches
  • If status_error is expected but error_msg is empty:

    • Call libvirt.check_result() with original parameters

The solution adds fallback patterns locally in the test rather than modifying the shared libvirt.check_result() function in utils_test/libvirt.py, ensuring this specific test works across libvirt versions without affecting other tests that may depend on check_result() behavior.

Alternative patterns cover both old and new libvirt error message formats:

  • "boot order .* is already used by another device"
  • "per-device boot elements cannot be used together with os/boot elements"
    Committer: Bolatbek Issakh bissakh@redhat.com

Summary by CodeRabbit

  • Tests
    • Broadened boot-order error matching so virtual-network tests accept both legacy and new libvirt messages, improving compatibility across libvirt versions.
  • Chores
    • Cleaned up and standardized test code formatting and parameter handling for readability and more consistent test behavior.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Walkthrough

Changes across the virtual network iface_attach_detach test add minor code refactors and formatting consistency, update test parameter handling, and adjust configuration error patterns. In the test code: removed VIRSH_ARGS, standardized string quoting to double quotes, replaced concatenation with f-strings, switched new_from_dumpxml calls to new_from_inactive_dumpxml, simplified boolean parsing for params, adjusted logging/f-string usage, and made small readability tweaks (e.g., splitting long argument lists). In the test cfg: broadened error message regexes to accept multiple libvirt message variants for boot-order and integer validation scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: supporting new libvirt error messages for boot order conflicts in the iface_attach_detach test.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

@BulaYoungR
Copy link
Author

Before fix

(.libvirt-ci-venv-ci-runtest-3tSibe) [root@ampere-mtsnow-altramax-62 libvirt-ci-latest-venv]# bin/avocado run --vt-type libvirt --vt-omit-data-loss --vt-machine-type arm64-mmio virtual_network.iface_attach_detach.boot_order.with_os_boot.hot --job-timeout 1200 --vt-connect-uri qemu:///system
No python imaging library installed. Screendump and Windows guest BSOD detection are disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. PPM image conversion to JPEG disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. Screendump and Windows guest BSOD detection are disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. PPM image conversion to JPEG disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
JOB ID     : a2803f3bf20290dab7dd2fbb2995a7a643a05040
JOB LOG    : /var/log/avocado/job-results/job-2026-02-11T11.16-a2803f3/job.log
 (1/1) type_specific.io-github-autotest-libvirt.virtual_network.iface_attach_detach.boot_order.with_os_boot.hot: STARTED
 (1/1) type_specific.io-github-autotest-libvirt.virtual_network.iface_attach_detach.boot_order.with_os_boot.hot: FAIL: Expect should fail with one of ['per-device boot elements cannot be used together with os/boot elements'], but failed with:\n\n\nerror: Failed to attach device from /var/tmp/xml_utils_temp_iar27zp_.xml\nerror: unsupported configuration: boot order 1 is alread... (7.75 s)
RESULTS    : PASS 0 | ERROR 0 | FAIL 1 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB HTML   : /var/log/avocado/job-results/job-2026-02-11T11.16-a2803f3/results.html
JOB TIME   : 9.05 s

Test summary:
1-type_specific.io-github-autotest-libvirt.virtual_network.iface_attach_detach.boot_order.with_os_boot.hot: FAIL

After fix

(.libvirt-ci-venv-ci-runtest-3tSibe) [root@ampere-mtsnow-altramax-62 libvirt-ci-latest-venv]# bin/avocado run --vt-type libvirt --vt-omit-data-loss --vt-machine-type arm64-mmio virtual_network.iface_attach_detach.boot_order.with_os_boot.hot --job-timeout 1200 --vt-connect-uri qemu:///system
No python imaging library installed. Screendump and Windows guest BSOD detection are disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. PPM image conversion to JPEG disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. Screendump and Windows guest BSOD detection are disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
No python imaging library installed. PPM image conversion to JPEG disabled. In order to enable it, please install python-imaging or the equivalent for your distro.
JOB ID     : 9ddee2cda797bada0a3be6be492a6c76bc41de0f
JOB LOG    : /var/log/avocado/job-results/job-2026-02-11T11.20-9ddee2c/job.log
 (1/1) type_specific.io-github-autotest-libvirt.virtual_network.iface_attach_detach.boot_order.with_os_boot.hot: STARTED
 (1/1) type_specific.io-github-autotest-libvirt.virtual_network.iface_attach_detach.boot_order.with_os_boot.hot: PASS (8.01 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB HTML   : /var/log/avocado/job-results/job-2026-02-11T11.20-9ddee2c/results.html
JOB TIME   : 9.41 s

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@libvirt/tests/src/virtual_network/iface_attach_detach.py`:
- Line 51: Remove the unused import of the re module in the
iface_attach_detach.py test file: delete the standalone "import re" statement
(it’s not referenced anywhere; libvirt.check_result() receives regex strings
itself). Check the top of the file where imports are declared to ensure no other
references to re remain and run tests to confirm no breakage.
- Around line 52-58: The code creates error_messages = error_msg when error_msg
is a list, then calls error_messages.extend(...), which mutates the original
error_msg; change the assignment to make a copy (e.g., use list(error_msg) or
error_msg.copy()) so error_messages is a new list before extending with
alternative_patterns; keep the rest (alternative_patterns and extend) the same
and only modify the creation of error_messages to avoid mutating the passed-in
error_msg.

# Old: "per-device boot elements cannot be used together with os/boot elements"
# New: "boot order X is already used by another device"
if status_error and error_msg:
import re
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unused import.

The re module is imported but never used. The regex patterns are passed as strings to libvirt.check_result(), which handles the matching internally.

Proposed fix
         if status_error and error_msg:
-            import re
             error_messages = error_msg if isinstance(error_msg, list) else [error_msg]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import re
if status_error and error_msg:
error_messages = error_msg if isinstance(error_msg, list) else [error_msg]
🤖 Prompt for AI Agents
In `@libvirt/tests/src/virtual_network/iface_attach_detach.py` at line 51, Remove
the unused import of the re module in the iface_attach_detach.py test file:
delete the standalone "import re" statement (it’s not referenced anywhere;
libvirt.check_result() receives regex strings itself). Check the top of the file
where imports are declared to ensure no other references to re remain and run
tests to confirm no breakage.

Comment on lines +52 to +58
error_messages = error_msg if isinstance(error_msg, list) else [error_msg]
# Add known alternative patterns for boot order conflicts
alternative_patterns = [
"boot order .* is already used by another device",
"per-device boot elements cannot be used together with os/boot elements"
]
error_messages.extend(alternative_patterns)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential list mutation issue.

If error_msg is already a list, line 52 assigns a reference to the same list object (not a copy). The subsequent extend() on line 58 then mutates the original error_msg, which could cause unexpected side effects if the parameter is examined or reused elsewhere.

Proposed fix to avoid mutating the original
-            error_messages = error_msg if isinstance(error_msg, list) else [error_msg]
+            error_messages = list(error_msg) if isinstance(error_msg, list) else [error_msg]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
error_messages = error_msg if isinstance(error_msg, list) else [error_msg]
# Add known alternative patterns for boot order conflicts
alternative_patterns = [
"boot order .* is already used by another device",
"per-device boot elements cannot be used together with os/boot elements"
]
error_messages.extend(alternative_patterns)
error_messages = list(error_msg) if isinstance(error_msg, list) else [error_msg]
# Add known alternative patterns for boot order conflicts
alternative_patterns = [
"boot order .* is already used by another device",
"per-device boot elements cannot be used together with os/boot elements"
]
error_messages.extend(alternative_patterns)
🤖 Prompt for AI Agents
In `@libvirt/tests/src/virtual_network/iface_attach_detach.py` around lines 52 -
58, The code creates error_messages = error_msg when error_msg is a list, then
calls error_messages.extend(...), which mutates the original error_msg; change
the assignment to make a copy (e.g., use list(error_msg) or error_msg.copy()) so
error_messages is a new list before extending with alternative_patterns; keep
the rest (alternative_patterns and extend) the same and only modify the creation
of error_messages to avoid mutating the passed-in error_msg.

error_messages.extend(alternative_patterns)
libvirt.check_result(test_result, expected_fails=error_messages)
elif status_error:
libvirt.check_result(test_result, expected_fails=error_msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is simipler fix. Check the exising codes, then you can find many similar fix. For example,
virtual_network/network_misc.cfg:44: expect_str = 'Expected integer value|Expected non-negative integer value'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like you mention i change it in cfg

… conflicts

Fix test failure caused by libvirt error message format change in newer
versions when validating boot order conflicts.

File: libvirt/tests/src/virtual_network/iface_attach_detach.py
Lines changed: 46-61 (added 15 lines)

The test validates that libvirt correctly rejects attaching a network
interface with boot order when os/boot is already configured on another
device. However, libvirt changed the error message format between versions,
causing the test to fail even though the error itself was correct.

Old libvirt error message:
    "per-device boot elements cannot be used together with os/boot elements"

New libvirt error message:
    "boot order 1 is already used by another device"

Problem:
The test expected only the old error message format from the error_msg
parameter, causing it to fail when libvirt returned the new message format.
The actual error was correct - libvirt properly rejected the invalid
configuration - but the message text differed.

Solution:
Modified error checking logic in test_boot_order() function to accept
both error message formats:

- If status_error is expected and error_msg is provided:
  * Convert error_msg to list if it's a string
  * Extend the list with known alternative patterns for boot order conflicts
  * Pass the extended list to libvirt.check_result()
  * This allows the test to pass if any pattern matches

- If status_error is expected but error_msg is empty:
  * Call libvirt.check_result() with original parameters

The solution adds fallback patterns locally in the test rather than
modifying the shared libvirt.check_result() function in utils_test/libvirt.py,
ensuring this specific test works across libvirt versions without affecting
other tests that may depend on check_result() behavior.

Alternative patterns cover both old and new libvirt error message formats:
- "boot order .* is already used by another device"
- "per-device boot elements cannot be used together with os/boot elements"
Committer: Bolatbek Issakh <bissakh@redhat.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libvirt/tests/src/virtual_network/iface_attach_detach.py`:
- Around line 59-64: The code currently uses eval on user-supplied strings:
replace iface_attrs = eval(params.get("iface_attrs", "{}")) with a safe parser
using ast.literal_eval(params.get("iface_attrs", "{}")) and import ast at top;
for the dynamic dispatch replace test_func = eval(f"test_{case}") with an
explicit whitelist mapping like dispatch = {"boot_order": test_boot_order}
(validate case is in dispatch) and set test_func = dispatch[case] (raise a
controlled error if case is invalid) so only allowed functions are callable;
keep existing use of vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) and
virsh_options unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a61a7ef and 9e7dcfe.

📒 Files selected for processing (2)
  • libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg
  • libvirt/tests/src/virtual_network/iface_attach_detach.py

Comment on lines +59 to +64
iface_attrs = eval(params.get("iface_attrs", "{}"))
virsh_options = params.get("virsh_options", "")

bk_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)

# Get test function
test_func = eval('test_%s' % case)
test_func = eval(f"test_{case}")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n libvirt/tests/src/virtual_network/iface_attach_detach.py | head -80

Repository: autotest/tp-libvirt

Length of output: 2489


🏁 Script executed:

grep -n "^def test_" libvirt/tests/src/virtual_network/iface_attach_detach.py

Repository: autotest/tp-libvirt

Length of output: 45


🏁 Script executed:

grep -n "case" libvirt/tests/src/virtual_network/iface_attach_detach.py | head -20

Repository: autotest/tp-libvirt

Length of output: 139


🏁 Script executed:

grep -n "def " libvirt/tests/src/virtual_network/iface_attach_detach.py

Repository: autotest/tp-libvirt

Length of output: 171


🏁 Script executed:

grep -n "case" libvirt/tests/src/virtual_network/iface_attach_detach.py

Repository: autotest/tp-libvirt

Length of output: 139


🏁 Script executed:

find libvirt/tests -name "*iface_attach*" -type f | head -20

Repository: autotest/tp-libvirt

Length of output: 177


🏁 Script executed:

cat libvirt/tests/cfg/virtual_network/iface_attach_detach.cfg

Repository: autotest/tp-libvirt

Length of output: 1378


Replace eval with safe parsing and explicit dispatch.

Lines 59 and 64 use eval(), creating unnecessary security and maintainability risks. Line 59 allows arbitrary code execution from params; use ast.literal_eval() instead to safely parse the dictionary. Line 64 uses eval() for dynamic function dispatch; replace with a whitelist map since only test_boot_order() is defined and the config specifies only "boot_order" as a valid case.

Proposed fix
+import ast
 import logging
@@
-    iface_attrs = eval(params.get("iface_attrs", "{}"))
+    iface_attrs = ast.literal_eval(params.get("iface_attrs", "{}"))
@@
-    test_func = eval(f"test_{case}")
+    test_func_map = {
+        "boot_order": test_boot_order,
+    }
+    test_func = test_func_map.get(case)
+    if test_func is None:
+        test.error(f"Unsupported case: {case}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
iface_attrs = eval(params.get("iface_attrs", "{}"))
virsh_options = params.get("virsh_options", "")
bk_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
# Get test function
test_func = eval('test_%s' % case)
test_func = eval(f"test_{case}")
iface_attrs = ast.literal_eval(params.get("iface_attrs", "{}"))
virsh_options = params.get("virsh_options", "")
bk_vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
test_func_map = {
"boot_order": test_boot_order,
}
test_func = test_func_map.get(case)
if test_func is None:
test.error(f"Unsupported case: {case}")
🧰 Tools
🪛 Ruff (0.15.2)

[error] 59-59: Use of possibly insecure function; consider using ast.literal_eval

(S307)


[error] 64-64: Use of possibly insecure function; consider using ast.literal_eval

(S307)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/iface_attach_detach.py` around lines 59 -
64, The code currently uses eval on user-supplied strings: replace iface_attrs =
eval(params.get("iface_attrs", "{}")) with a safe parser using
ast.literal_eval(params.get("iface_attrs", "{}")) and import ast at top; for the
dynamic dispatch replace test_func = eval(f"test_{case}") with an explicit
whitelist mapping like dispatch = {"boot_order": test_boot_order} (validate case
is in dispatch) and set test_func = dispatch[case] (raise a controlled error if
case is invalid) so only allowed functions are callable; keep existing use of
vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) and virsh_options unchanged.

variants boot_order:
- -1:
error_msg = 'Expected .*integer value'
error_msg = 'Expected integer value|Expected non-negative integer value'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not old value match "Expected non-negative integer value"? Do you need this change indeed?

error_msg = 'Expected integer value|Expected non-negative integer value'
- ss:
error_msg = 'Expected .*integer value'
error_msg = 'Expected integer value|Expected non-negative integer value'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants