Skip to content

Improve virtual_network.qos cases to support new test tool - #6848

Closed
yanglei-rh wants to merge 1 commit into
autotest:masterfrom
yanglei-rh:LIBVIRTAT-22417
Closed

yanglei-rh wants to merge 1 commit into
autotest:masterfrom
yanglei-rh:LIBVIRTAT-22417

Conversation

@yanglei-rh

@yanglei-rh yanglei-rh commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

1.Add some parameters to allow the framework provide guest xml
2.Add "only Linux" to limit guest type
3.Add a check about host bridge type for check_actual_network_throughput and check_bandwidth_by_domiftune
4.Change the method for specifying different bridge types via the test command intead of case cfg varaint for check_actual_network_throughput

ID: LIBVIRTAT-22417
Assisted-by: Gemini AI
Signed-off-by: Lei Yang leiyang@redhat.com

Summary by CodeRabbit

  • Tests
    • Standardized VM lifecycle management across network QoS tests with Linux-only execution constraints.
    • Enhanced network throughput validation with local netperf compilation on both host and VM.
    • Improved VM session initialization and dynamic interface configuration for bridge and OVS scenarios.

@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The pull request standardizes VM lifecycle management and network configuration across four libvirt QoS test configurations while refactoring their supporting Python implementations. Configuration files add Linux platform restrictions, libvirt-based VM creation and termination, no-reboot execution mode, and OVMF NVRAM-specific kill options. The source code replaces static bridge creation with dynamic interface/network XML attributes driven by configuration, introduces OVS bridge detection and conditional setup, refactors netperf handling from package installation to source compilation, updates VM console session management, and consolidates bridge teardown logic within a unified cleanup flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: improving virtual_network.qos test cases to support new test tool infrastructure (libvirt-driven VM lifecycle, framework-provided guest XML, bridge type flexibility).
Docstring Coverage ✅ Passed Docstring coverage is 88.73% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/qos/check_actual_network_throughput.py`:
- Around line 36-37: The code reads params.get('netdst') but the cfg now uses
${bridge_name}, causing bridge_name to be empty; update the parameter reads to
use params.get('bridge_name', params.get('netdst', '')) (or consistently prefer
'bridge_name') where iface_type and bridge_name are set so
setup_ovs_bridge_attrs in provider/virtual_network/network_base.py sees the
correct value; ensure all occurrences (including the block around lines 53–66
that set iface_type and bridge_name) use the same 'bridge_name' key or fall back
to 'netdst' to preserve backward compatibility.
- Line 72: The test captures the initial firewall state in fw_was_running via
firewalld.status() but unconditionally starts the service later, which can
change host state; change the cleanup/teardown logic so any firewalld.start() or
firewalld.stop() calls are conditional based on fw_was_running (i.e., only start
firewalld at the end if fw_was_running was True, and only stop it if it was
running at the start), updating the code paths that call firewalld.start() (and
firewalld.stop()) in this test (referencing fw_was_running and
firewalld.status()) so the host firewall is restored to its original state.
- Around line 158-163: Initialize cleanup handles before the try block to avoid
UnboundLocalError: declare and set host_nserver = None and vm_sess = None (or
appropriate falsy placeholders) prior to network setup/login, then in the
finally block check for truthiness (if host_nserver: ... and if vm_sess:
vm_sess.close()) so early failures won’t raise when cleaning up; update
references to host_nserver and vm_sess in the surrounding function (the
variables used in the finally) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d24947dc-8ded-4974-937c-37af5c1aac04

📥 Commits

Reviewing files that changed from the base of the PR and between 73ff476 and d278874.

📒 Files selected for processing (6)
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py
  • libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py (1)

36-65: ⚠️ Potential issue | 🟠 Major

Resolve the bridge from bridge_name before falling back to netdst.

bridge_name is now the public knob in the cfg and it is defined with a blank default. Reading only netdst here can overwrite the already-expanded bridge attrs with '', skip the virbr0 guard, and pass an empty bridge into network_base.setup_ovs_bridge_attrs(). Use params.get("bridge_name") or params.get("netdst", "") in this flow, and make the helper use the same fallback.

Possible fix
-    bridge_name = params.get('netdst', '')
+    bridge_name = params.get('bridge_name') or params.get('netdst', '')
@@
     if iface_type == 'bridge':
-        iface_attrs['source'] = {'bridge': bridge_name}
+        if bridge_name:
+            iface_attrs['source'] = {'bridge': bridge_name}
         network_base.setup_ovs_bridge_attrs(params, iface_attrs)
@@
     elif iface_type == 'network' and params.get('net_fwm') == 'bridge':
-        net_attrs['bridge'] = {'name': bridge_name}
+        if bridge_name:
+            net_attrs['bridge'] = {'name': bridge_name}
         if is_ovs_bridge:
             net_attrs['virtualport_type'] = 'openvswitch'
# provider/virtual_network/network_base.py
-    netdst = params.get('netdst', '')
+    netdst = params.get('bridge_name') or params.get('netdst', '')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`
around lines 36 - 65, The code currently reads bridge_name from
params.get('netdst', '') which can overwrite an already-resolved public knob and
lead to blank/incorrect bridge values; change the bridge resolution to use
params.get("bridge_name") or params.get("netdst", "") wherever bridge_name is
derived so the public param wins, and update the helper call sites (e.g., where
network_base.setup_ovs_bridge_attrs is invoked) to use the same fallback; ensure
variables iface_attrs and net_attrs continue to be populated based on this
resolved bridge_name and preserve the virbr0 guard and the is_ovs_bridge
detection that calls utils_net.find_bridge_manager(bridge_name).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@provider/virtual_network/netperf_base.py`:
- Around line 166-172: The guest branch currently always sets install_path to
guest_netperf_path which ignores the new client_path; change the logic in the
address-handling block so that when address is a VM you prefer
params.get("client_path") (falling back to guest_netperf_path) to set
install_path (while retaining session = vm.wait_for_login()); update any code
that consumes install_path (e.g., paths used by
check_actual_network_throughput.py) to rely on this chosen install_path. Ensure
the variable names referenced are guest_netperf_path, client_path
(params.get("client_path")), vm.wait_for_login(), session, and install_path so
the correct guest-side install directory is honored.

---

Duplicate comments:
In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`:
- Around line 36-65: The code currently reads bridge_name from
params.get('netdst', '') which can overwrite an already-resolved public knob and
lead to blank/incorrect bridge values; change the bridge resolution to use
params.get("bridge_name") or params.get("netdst", "") wherever bridge_name is
derived so the public param wins, and update the helper call sites (e.g., where
network_base.setup_ovs_bridge_attrs is invoked) to use the same fallback; ensure
variables iface_attrs and net_attrs continue to be populated based on this
resolved bridge_name and preserve the virbr0 guard and the is_ovs_bridge
detection that calls utils_net.find_bridge_manager(bridge_name).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7aaf656a-444e-4a20-9466-62fa2d2b8bdf

📥 Commits

Reviewing files that changed from the base of the PR and between d278874 and a21b311.

📒 Files selected for processing (3)
  • libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py
  • provider/virtual_network/netperf_base.py
  • provider/virtual_network/network_base.py

Comment thread provider/virtual_network/netperf_base.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

♻️ Duplicate comments (2)
libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py (2)

169-169: ⚠️ Potential issue | 🟠 Major

Conditionally restore firewall based on its original state.

fw_was_running is captured at line 72, but firewalld.start() is called unconditionally here. If the host firewall was intentionally stopped before the test, this leaves the system in a different state than expected, potentially affecting subsequent tests.

Proposed fix
-        firewalld.start()
+        if fw_was_running:
+            firewalld.start()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py` at
line 169, The tear-down unconditionally calls firewalld.start() which ignores
the recorded fw_was_running state; update the cleanup to check the boolean
captured as fw_was_running (from where it was set earlier) and only call
firewalld.start() if fw_was_running is True, otherwise leave the firewall
stopped (or call firewalld.stop() if you need to enforce the original stopped
state); locate the teardown/cleanup block that invokes firewalld.start() and
wrap it with a conditional referencing fw_was_running so the host firewall is
restored to its original state.

67-73: ⚠️ Potential issue | 🔴 Critical

Initialize vm_sess and host_nserver before the try block to prevent UnboundLocalError.

These variables are assigned at lines 93 and 132 respectively, but the finally block (lines 160-163) checks them. If an exception occurs before their assignment (e.g., during vm.start() at line 90), the finally block will raise UnboundLocalError, masking the real failure.

Proposed fix
     net_xml = NetworkXML.new_from_net_dumpxml('default')
     bk_net_xml = net_xml.copy()
     firewalld = service.Factory.create_service("firewalld")
     fw_was_running = firewalld.status()
+    vm_sess = None
+    host_nserver = None
 
     try:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`
around lines 67 - 73, The finally block references vm_sess and host_nserver but
they are only assigned inside the try block (after vm.start() and later), which
can cause UnboundLocalError if an earlier exception occurs; initialize vm_sess
and host_nserver to None before the try so the finally can safely check/cleanup
them (e.g., set vm_sess = None and host_nserver = None just before the try that
contains vm.start(), and keep the existing checks in the finally to only act
when they are not None).
🤖 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/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py`:
- Around line 41-49: The current sequence batches setup and daemon start into
multi_cmd1/multi_cmd2 so failures are masked and chcon/chown may race virtiofsd
socket creation; instead run and check each preparatory command (mkdir ->
process.run/remote.run_remote_cmd for cmd1), then start virtiofsd separately
(cmd2) without combining it with mkdir, then poll/wait for socket_path to appear
(with a timeout) before running cmd3/cmd4 via process.run so chcon -t
svirt_image_t and chown qemu:qemu are executed only after the socket exists and
their failures are visible; update uses of multi_cmd1/multi_cmd2 to individual
calls and add a small wait-loop for socket_path after invoking virtiofsd.
- Around line 98-109: The cleanup_test function can short-circuit remaining
teardown when migration_obj.cleanup_connection() raises, leaving virtiofsd
remnants; change cleanup_test to collect cleanup actions (e.g., append lambdas
or callables for migration_obj.cleanup_connection, remote.run_remote_cmd('pkill
virtiofsd', ...), remote.run_remote_cmd(f"rm -rf {socket_path}", ...),
process.run("pkill virtiofsd", ...), process.run(f"rm -rf {socket_path}", ...))
into a list as each resource is created/required, then in a finally block
iterate that list and run each cleanup action inside its own try/except so one
failure doesn’t prevent the others from running; ensure you reference
cleanup_test and migration_obj.cleanup_connection when locating the code to
modify.

In `@libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py`:
- Line 35: The code uses eval on params.get to parse dict literals (e.g.,
iface_attrs = eval(params.get('iface_attrs', '{}'))), which is unsafe; replace
these eval(...) calls with ast.literal_eval(...) and add an import ast at the
top of the module, ensuring all occurrences that parse parameter dict strings
(the iface_attrs assignment and the other two eval usages in this file) are
converted to use ast.literal_eval to safely parse the literal dictionaries.

In `@v2v/tests/src/nbdkit/nbdkit.py`:
- Around line 746-749: The hard-coded "instances" endpoints (e.g., the instances
list with ports 10809/10810 and hard-coded nbd://localhost and /tmp/test.sock)
cause flakes; change the nbdkit server helper to generate per-test endpoints by
creating unique Unix socket paths inside the test temporary directory (use
tmp_path or tempfile.mkdtemp) or by selecting ephemeral TCP ports (bind a socket
to port 0 to get a free port) and use those values when constructing "instances"
and any nbd:// URLs; update the helper that starts/stops servers (and all places
that build socket paths or URLs — the code around the instances definition and
the other similar blocks called in this file) to accept/use these generated
endpoints and ensure cleanup only removes sockets from the test temp dir.
- Around line 875-890: Tighten the base64 test by verifying exit status and
exact payload: after running process.run(...) in the positive branch (where
test_state is not "negative"), assert result.exit_code == 0 and that
result.stdout (or cmd_output) exactly equals original_text (not just contains
it) before calling test.fail; in the negative branch assert result.exit_code !=
0 and then check that params_get(params, "expected_err_msg") appears in
result.stderr_text (and call test.fail if either condition is not met). Use the
existing variables result, cmd_output/result.stdout, result.stderr_text,
params_get and test.fail to implement these checks.
- Around line 822-856: The test reads the subprocess output before stopping
nbdkit, but the count-filter only emits its aggregate summary on unload; update
the test to call p.stop() (or p.terminate()/p.wait() as appropriate) before
capturing logs via p.get_stdout()/p.get_stderr(), then check for the aggregate
summary emitted on unload (e.g., match the "count bytes: read X, written Y,
zeroed Z, trimmed W" format) instead of per-request "count:
pwrite/pread/zero/trim" lines; adjust the expected_patterns (or replace them
with a single regex/assertion) to look for the aggregate summary after p.stop()
completes.

In `@v2v/tests/src/v2v_options.py`:
- Around line 960-975: The code builds and runs cmd with unchecked vpx_ipv6_addr
and uses process.run(..., shell=True) which risks command injection; instead
validate/sanitize vpx_ipv6_addr (e.g. via the ipaddress.IPv6Address constructor)
before embedding it into cmd, perform the re.sub replacements only after
validation, and avoid shell=True by constructing an argument list for
process.run (use a list of args and pass env={'LIBVIRT_DEBUG': '1'} or merge
into os.environ) when calling process.run in the branch handling checkpoint ==
'vpx_with_invalid_esx_ipv6'; update the process.run call sites (the calls that
set cmd_result) to use shell=False and an args list so the parameter cannot
inject shell metacharacters.

---

Duplicate comments:
In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`:
- Line 169: The tear-down unconditionally calls firewalld.start() which ignores
the recorded fw_was_running state; update the cleanup to check the boolean
captured as fw_was_running (from where it was set earlier) and only call
firewalld.start() if fw_was_running is True, otherwise leave the firewall
stopped (or call firewalld.stop() if you need to enforce the original stopped
state); locate the teardown/cleanup block that invokes firewalld.start() and
wrap it with a conditional referencing fw_was_running so the host firewall is
restored to its original state.
- Around line 67-73: The finally block references vm_sess and host_nserver but
they are only assigned inside the try block (after vm.start() and later), which
can cause UnboundLocalError if an earlier exception occurs; initialize vm_sess
and host_nserver to None before the try so the finally can safely check/cleanup
them (e.g., set vm_sess = None and host_nserver = None just before the try that
contains vm.start(), and keep the existing checks in the finally to only act
when they are not None).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6cc06bf2-721c-4107-956f-6724e67a9c04

📥 Commits

Reviewing files that changed from the base of the PR and between a21b311 and a202a38.

📒 Files selected for processing (20)
  • libvirt/tests/cfg/libvirt_mem.cfg
  • libvirt/tests/cfg/memory/memory_discard.cfg
  • libvirt/tests/cfg/memory/memory_misc.cfg
  • libvirt/tests/cfg/memory/nvdimm.cfg
  • libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py
  • libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py
  • libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py
  • libvirt/tests/src/virtual_network/elements_and_attributes/driver_packed.py
  • libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py
  • libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py
  • v2v/tests/cfg/function_test_esx.cfg
  • v2v/tests/cfg/nbdkit/nbdkit.cfg
  • v2v/tests/cfg/v2v_options.cfg
  • v2v/tests/src/nbdkit/nbdkit.py
  • v2v/tests/src/v2v_options.py
✅ Files skipped from review due to trivial changes (4)
  • libvirt/tests/cfg/libvirt_mem.cfg
  • libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg
  • v2v/tests/cfg/function_test_esx.cfg
  • libvirt/tests/cfg/memory/memory_discard.cfg
🚧 Files skipped from review as they are similar to previous changes (3)
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg

Comment thread v2v/tests/src/nbdkit/nbdkit.py
Comment thread v2v/tests/src/nbdkit/nbdkit.py
Comment thread v2v/tests/src/nbdkit/nbdkit.py
Comment thread v2v/tests/src/v2v_options.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libvirt/tests/src/virtual_disks/virtual_disks_https.py (1)

139-159: ⚠️ Potential issue | 🔴 Critical

Cleanup can crash with UnboundLocalError on early setup failure.

If setup_test() fails, qemu_config is undefined but still restored in finally.

🔧 Suggested fix
-    try:
+    qemu_config = None
+    try:
         qemu_config = setup_test()
@@
     finally:
         backup_vmxml.sync()
-        qemu_config.restore()
+        if qemu_config is not None:
+            qemu_config.restore()
         Libvirtd('virtqemud').restart()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_disks/virtual_disks_https.py` around lines 139 -
159, The finally block can raise UnboundLocalError if setup_test() fails because
qemu_config (and possibly disk_dev) are not defined; to fix, initialize
qemu_config (and any other variables used in finally like disk_dev) to None
before the try, and in the finally guard calls with checks (e.g., if qemu_config
is not None: qemu_config.restore(); if backup_vmxml is not None:
backup_vmxml.sync(); and only call Libvirtd('virtqemud').restart() if
appropriate), so replace direct restores with conditional calls around
qemu_config.restore() and backup_vmxml.sync() while keeping the same cleanup
intent.
♻️ Duplicate comments (7)
libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py (2)

41-50: ⚠️ Potential issue | 🟠 Major

Split setup/start/relabel steps; current flow still masks failures and races socket relabeling.

Line 44/Line 49 only reflect the last subcommand in each ; chain, and nohup ... & can return before the socket exists, so chcon/chown may run too early on slower hosts.

Suggested fix
-        multi_cmd1 = f"{cmd1}; {cmd2}"
-        process.run(multi_cmd1, shell=True, ignore_status=False, ignore_bg_processes=True)
-        remote.run_remote_cmd(multi_cmd1, params, ignore_status=False)
+        process.run(cmd1, shell=True, ignore_status=False)
+        remote.run_remote_cmd(cmd1, params, ignore_status=False)
+        process.run(cmd2, shell=True, ignore_status=False, ignore_bg_processes=True)
+        remote.run_remote_cmd(cmd2, params, ignore_status=False)
+        wait_cmd = (
+            f'for _ in $(seq 1 50); do [ -S "{socket_path}" ] && exit 0; '
+            'sleep 0.2; done; exit 1'
+        )
+        process.run(wait_cmd, shell=True, ignore_status=False)
+        remote.run_remote_cmd(wait_cmd, params, ignore_status=False)

-        multi_cmd2 = f"{cmd3}; {cmd4}"
-        process.run(multi_cmd2, shell=True, ignore_status=False)
-        remote.run_remote_cmd(multi_cmd2, params, ignore_status=False)
+        process.run(cmd3, shell=True, ignore_status=False)
+        process.run(cmd4, shell=True, ignore_status=False)
+        remote.run_remote_cmd(cmd3, params, ignore_status=False)
+        remote.run_remote_cmd(cmd4, params, ignore_status=False)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py`
around lines 41 - 50, The current setup chains commands (multi_cmd1/multi_cmd2)
which masks failures and races the socket relabeling; instead split into
distinct steps: run the mkdir (cmd1) via process.run/remote.run_remote_cmd,
start virtiofsd (cmd2) without chaining and then poll/wait for the socket file
to appear (check -S {socket_path} or loop with timeout) before proceeding, and
only after the socket exists run the relabel/chown commands (cmd3/cmd4)
individually via process.run/remote.run_remote_cmd so each failure is visible
and ordering is guaranteed; also avoid relying on immediate success of nohup/&
(do not use ignore_bg_processes to hide background startup errors).

105-109: ⚠️ Potential issue | 🟠 Major

Prevent cleanup short-circuit; one teardown failure currently skips the rest.

If Line 105 raises, later local/remote pkill and socket cleanup never run, which can hide the real test failure and leak state.

Suggested fix
-        migration_obj.cleanup_connection()
-        remote.run_remote_cmd('pkill virtiofsd', params, ignore_status=True)
-        remote.run_remote_cmd(f"rm -rf {socket_path}", params, ignore_status=True)
-        process.run("pkill virtiofsd", shell=True, ignore_status=True)
-        process.run(f"rm -rf {socket_path}", shell=True, ignore_status=True)
+        cleanup_steps = [
+            lambda: migration_obj.cleanup_connection(),
+            lambda: remote.run_remote_cmd("pkill virtiofsd", params, ignore_status=True),
+            lambda: remote.run_remote_cmd(f"rm -rf {socket_path}", params, ignore_status=True),
+            lambda: process.run("pkill virtiofsd", shell=True, ignore_status=True),
+            lambda: process.run(f"rm -rf {socket_path}", shell=True, ignore_status=True),
+        ]
+        for step in cleanup_steps:
+            try:
+                step()
+            except Exception as err:
+                test.log.warning("Cleanup step failed: %s", err)

Based on learnings, in tp-libvirt tests prefer using a list of cleanup lambda functions appended for performed actions, then executed in finally with per-action error handling.

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

In
`@libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py`
around lines 105 - 109, The current teardown calls
(migration_obj.cleanup_connection(), remote.run_remote_cmd('pkill virtiofsd',
...), remote.run_remote_cmd(f"rm -rf {socket_path}", ...), process.run("pkill
virtiofsd", ...), process.run(f"rm -rf {socket_path}", ...)) are executed
sequentially so an exception in migration_obj.cleanup_connection()
short-circuits remaining cleanup; change to collect cleanup actions as a list of
lambdas/closures when each action is performed (e.g., append a lambda that calls
migration_obj.cleanup_connection(), one for remote.run_remote_cmd('pkill
virtiofsd', params, ignore_status=True), one for remote.run_remote_cmd(f"rm -rf
{socket_path}", ...), and local process.run calls), then in a finally block
iterate over that list and invoke each action inside its own try/except to log
but not raise on error so all pkill and socket removals always run even if one
cleanup fails.
v2v/tests/src/v2v_options.py (1)

960-975: ⚠️ Potential issue | 🟠 Major

Avoid shell=True for parameter-influenced command execution.

The vpx_ipv6_addr parameter is embedded into cmd via re.sub and then executed with shell=True (lines 971-972). While parameters typically come from trusted test configurations, using shell=True is flagged by static analysis (Ruff S604) and is a security anti-pattern. Consider using environment variables instead of string concatenation for LIBVIRT_DEBUG=1.

🔧 Suggested improvement
         if checkpoint == 'vpx_with_invalid_esx_ipv6':
             ipv4_pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'
             vpx_ipv6_addr = params.get('vpx_ipv6_addr')
             if not vpx_ipv6_addr:
                 test.error("vpx_ipv6_addr parameter is missing")
             cmd = re.sub(ipv4_pattern, vpx_ipv6_addr, cmd)
             cmd = re.sub(r'/\[(.*?)\]/', r'/\1/', cmd)
-            cmd_export_env = 'LIBVIRT_DEBUG=1'
-            cmd = "%s %s" % (cmd_export_env, cmd)
 
-        if checkpoint == 'vpx_with_invalid_esx_ipv6':
-            cmd_result = process.run(cmd, timeout=v2v_timeout, verbose=True,
-                                     ignore_status=True, shell=True)
+        if checkpoint == 'vpx_with_invalid_esx_ipv6':
+            env = os.environ.copy()
+            env['LIBVIRT_DEBUG'] = '1'
+            cmd_result = process.run(cmd, timeout=v2v_timeout, verbose=True,
+                                     ignore_status=True, env=env)
         else:
             cmd_result = process.run(cmd, timeout=v2v_timeout, verbose=True,
                                      ignore_status=True)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v2v/tests/src/v2v_options.py` around lines 960 - 975, The code builds a
string command (cmd) by inserting the vpx_ipv6_addr and then calls
process.run(..., shell=True) when checkpoint == 'vpx_with_invalid_esx_ipv6',
which risks shell injection and is flagged; instead construct a safe argument
list and pass an environment dict with LIBVIRT_DEBUG=1 to process.run so you can
remove shell=True: keep using the same checkpoint check and vpx_ipv6_addr lookup
but replace string concatenation of cmd (and the use of cmd_export_env) with a
list/sequence of arguments for process.run (or tokenize the existing cmd into
args safely) and pass env={**os.environ, "LIBVIRT_DEBUG":"1"} (or equivalent in
your test harness) to process.run while calling it without shell=True and still
using timeout=v2v_timeout, verbose=True, ignore_status=True.
provider/virtual_network/netperf_base.py (1)

166-172: ⚠️ Potential issue | 🟡 Minor

client_path parameter is not honored for VM-side netperf builds.

The VM branch always installs under guest_netperf_path, ignoring any client_path parameter that may be configured in the test cfg. This could cause mismatches between where netperf is installed and where subsequent test code expects to find it.

Proposed fix to prefer client_path
-    guest_netperf_path = params.get("guest_netperf_path", "/var/tmp/")
+    guest_netperf_path = (
+        params.get("client_path")
+        or params.get("guest_netperf_path", "/var/tmp/")
+    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@provider/virtual_network/netperf_base.py` around lines 166 - 172, The VM
branch ignores a configured client_path and always sets install_path to
guest_netperf_path; update the branch that handles address in params.get('vms',
'').split() so it prefers params.get("client_path") (falling back to
guest_netperf_path) when assigning install_path for VM builds (the code around
guest_netperf_path, the elif branch using env.get_vm(address) and session,
install_path = vm.wait_for_login(), guest_netperf_path). Ensure install_path is
computed from params.get("client_path", guest_netperf_path) so subsequent code
finds netperf in the expected client location.
libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py (2)

159-163: ⚠️ Potential issue | 🟠 Major

Initialize cleanup handles before entering the try.

vm_sess and host_nserver are assigned much later. Any failure during XML setup, VM boot, or netperf compilation will make this finally raise UnboundLocalError and hide the real test failure.

🧹 Guard cleanup against early failures
     firewalld = service.Factory.create_service("firewalld")
     fw_was_running = firewalld.status()
+    vm_sess = None
+    host_nserver = None
 
     try:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`
around lines 159 - 163, Initialize the cleanup handles before entering the try
block to avoid UnboundLocalError in the finally: explicitly set vm_sess = None
and host_nserver = None (or other appropriate sentinel values) prior to the code
that may raise, then in the finally guard the cleanup calls by checking those
variables (e.g., if host_nserver is not None: process.run(...); if vm_sess is
not None: vm_sess.close()). This ensures the finally block in
check_actual_network_throughput.py safely skips cleanup when
setup/boot/compilation fails.

72-72: ⚠️ Potential issue | 🟠 Major

Restore firewalld only if this case stopped it.

fw_was_running is captured, but cleanup still starts the service unconditionally. If the host firewall was intentionally down before this test, the case leaves the lab in a different state.

🔁 Preserve the original firewall state
-        firewalld.start()
+        if fw_was_running:
+            firewalld.start()

Also applies to: 158-169

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

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py` at
line 72, The test captures the original firewall state in fw_was_running (via
firewalld.status()) but the cleanup logic currently starts the firewalld service
unconditionally; change the teardown to restore the original state instead: call
firewalld.start() only if fw_was_running is True and call firewalld.stop() only
if fw_was_running is False (or otherwise ensure the opposite action is taken
only when the original state differs). Update the cleanup in
check_actual_network_throughput.py (and the similar block around lines 158-169)
to reference fw_was_running rather than always starting the service.
provider/virtual_network/network_base.py (1)

757-791: ⚠️ Potential issue | 🟠 Major

Resolve the bridge name consistently in the new OVS helpers.

Several callers already resolve bridge_name locally, including a 'virbr0' fallback and a netdst or bridge_name fallback, but these helpers re-read only params['netdst']. In those paths, cancel_if_ovs_bridge() can inspect the wrong bridge, and setup_ovs_bridge_attrs() can raise Bridge '' does not exist even though the caller already has a valid bridge value.

🔧 Let callers pass the resolved bridge name
-def cancel_if_ovs_bridge(params, test):
+def cancel_if_ovs_bridge(params, test, bridge_name=None):
     """
     Cancel test if host using OVS bridge (for only Linux Bridge tests).
@@
-    bridge_name = params.get('netdst', '')
+    bridge_name = bridge_name or params.get('netdst') or params.get('bridge_name', '')
@@
-def setup_ovs_bridge_attrs(params, iface_attrs):
+def setup_ovs_bridge_attrs(params, iface_attrs, bridge_name=None):
     """
     Setup OVS bridge attributes based on netdst parameter.
@@
-    netdst = params.get('netdst', '')
-    br_obj = utils_net.find_bridge_manager(netdst)
+    bridge_name = bridge_name or params.get('netdst') or params.get('bridge_name', '')
+    br_obj = utils_net.find_bridge_manager(bridge_name)
     if br_obj is None:
-        raise exceptions.TestError(f"Bridge '{netdst}' does not exist")
+        raise exceptions.TestError(f"Bridge '{bridge_name}' does not exist")
     if "OpenVSwitch" in br_obj.__class__.__name__:
         iface_attrs['type_name'] = 'bridge'
-        iface_attrs['source'] = {'bridge': netdst}
+        iface_attrs['source'] = {'bridge': bridge_name}
         iface_attrs['virtualport'] = {'type': 'openvswitch'}

You'd then pass each caller's already-resolved bridge_name into these helpers.

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

In `@provider/virtual_network/network_base.py` around lines 757 - 791, The helpers
cancel_if_ovs_bridge and setup_ovs_bridge_attrs should use a caller-resolved
bridge name instead of always re-reading params['netdst']; change their
signatures to accept an optional resolved_bridge (e.g., def
cancel_if_ovs_bridge(params, test, resolved_bridge=None) and def
setup_ovs_bridge_attrs(params, iface_attrs, resolved_bridge=None)) and then use
resolved_bridge if provided (falling back to params.get('netdst', '') only if
not), update logic to call utils_net.find_bridge_manager(resolved_bridge) and
adjust the TestError message accordingly, and update all callers to pass the
previously-resolved bridge_name (or leave omitted when they rely on params).
🧹 Nitpick comments (6)
v2v/tests/cfg/convert_from_file.cfg (1)

267-273: Consider adding version_required for consistency.

The corresponding char_slash variant in function_test_esx.cfg specifies version_required = "[virt-v2v-2.10.0-5,)", but this character_slash variant does not. If this feature depends on a specific virt-v2v version, adding the version requirement would ensure test consistency and prevent failures on older versions.

🔧 Suggested addition
                                 - character_slash:
                                     only esx_80
                                     only output_mode.libvirt
                                     boottype = 3
+                                    version_required = "[virt-v2v-2.10.0-5,)"
                                     v2v_debug = ''
                                     checkpoint = 'character_slash'
                                     main_vm = VM_NAME_GUEST_DISK_WITH_CHAR_SLASH_V2V_EXAMPLE
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v2v/tests/cfg/convert_from_file.cfg` around lines 267 - 273, Add a
version_required entry to the character_slash variant to match the corresponding
char_slash variant in function_test_esx.cfg; specifically add version_required =
"[virt-v2v-2.10.0-5,)" under the character_slash block so the test declares the
same minimum virt-v2v version dependency and stays consistent with the
char_slash variant.
virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py (1)

84-85: Consider sharing this staged-bib_ref allowlist.

This literal list now exists here and in virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py. The next variant addition will be easy to miss in one path, so a shared constant/helper in provider.bootc_image_builder.bootc_image_build_utils would keep build/install behavior aligned.

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

In `@virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py` around
lines 84 - 85, Extract the literal list of allowed bib_ref values into a shared
constant (e.g., STAGED_BIB_REFS) in
provider.bootc_image_builder.bootc_image_build_utils, export it, and replace the
inline membership checks that reference bib_ref in functions like the one using
"if bib_ref in [...]" in bootc_disk_image_build.py and the corresponding check
in bootc_disk_image_install.py to use "if bib_ref in STAGED_BIB_REFS" (ensure
you import STAGED_BIB_REFS from bootc_image_build_utils); update any tests or
callers to import the constant so both build and install paths use the same
centralized allowlist.
libvirt/tests/src/virtual_network/link_state/link_state_model_type.py (1)

64-67: Slight comment-to-code mismatch.

The inline comment says "Configure ovs bridge when host using ovs bridge," but the condition params.get("network_test") == "yes" is actually triggered by the interface_type: network config variant. The setup_ovs_bridge_attrs function itself likely handles detecting whether OVS is in use. Consider clarifying the comment to reflect that this handles OVS-specific attributes when running network interface tests.

Suggested comment clarification
-        # Configure ovs bridge when host using ovs bridge
-        if params.get("network_test") == "yes":
+        # Setup OVS bridge attributes if applicable for network interface tests
+        if params.get("network_test") == "yes":
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/link_state/link_state_model_type.py` around
lines 64 - 67, The comment is misleading: replace "Configure ovs bridge when
host using ovs bridge" with a clearer note that this block applies OVS-specific
attribute adjustments for the network interface test variant (triggered by
params.get("network_test") == "yes") because
network_base.setup_ovs_bridge_attrs(params, iface_attrs) will itself detect OVS
usage; update the inline comment near the params check and the call to
network_base.setup_ovs_bridge_attrs to indicate it's applying OVS-related
attributes for the network test case rather than unconditionally configuring an
OVS bridge.
libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg (1)

25-31: Minor indentation inconsistency on line 30.

The kill_vm_libvirt_options line has extra leading spaces compared to standard indentation used in other cfg files. While it may still parse correctly, consider aligning with the standard 4-space indent under ovmf:.

Suggested fix
             ovmf:
-                 kill_vm_libvirt_options = --nvram
+                kill_vm_libvirt_options = --nvram
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg`
around lines 25 - 31, The line with kill_vm_libvirt_options under the ovmf:
block has extra leading spaces causing inconsistent indentation; open the cfg
and align kill_vm_libvirt_options to use the standard 4-space indent under the
ovmf key so it matches other entries (i.e., make the indentation for
kill_vm_libvirt_options consistent with the surrounding
create_vm_libvirt/use_no_reboot entries).
libvirt/tests/src/virtual_network/connectivity/connectivity_check_network_interface.py (1)

69-74: Consider catching a more specific exception.

The broad Exception catch (flagged by Ruff BLE001) works but could mask unexpected errors. Since restart_guest_network likely raises specific exceptions for network failures, consider catching those explicitly, or at minimum use Exception as e with the full traceback logged at debug level.

That said, the current approach is acceptable here since DHCPv6 may legitimately fail in some test environments, and the warning log provides visibility.

Optional: Log traceback for debugging
         for vm_session in [session, ep_session]:
             try:
                 utils_net.restart_guest_network(vm_session, ip_version='ipv6', timeout=15)
                 LOG.info('DHCPv6 request completed')
             except Exception as e:
-                LOG.warning(f'DHCPv6 request failed: {e}')
+                LOG.warning(f'DHCPv6 request failed: {e}', exc_info=True)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libvirt/tests/src/virtual_network/connectivity/connectivity_check_network_interface.py`
around lines 69 - 74, The loop currently catches a broad Exception for calls to
utils_net.restart_guest_network (for vm_session and ep_session); change this to
catch more specific exceptions raised by that function (e.g., RuntimeError,
OSError, subprocess.CalledProcessError or a custom network exception if one
exists) or catch a tuple of those specific types instead of Exception, and keep
the LOG.warning message for expected DHCPv6 failures; if you cannot identify a
single specific exception, still add a debug-level log of the full traceback
(use traceback.format_exc() via LOG.debug) alongside the warning to preserve
diagnostic info while avoiding masking unexpected errors.
libvirt/tests/src/virtual_network/iface_update.py (1)

273-279: Scope the libvirtd restart workaround more narrowly.

This now restarts libvirtd for every live-update path, while the comment and the follow-up serial-console handling only tie the workaround to the link-state flow. Keeping it behind new_iface_link would avoid extra daemon restarts in unrelated iface-update cases.

♻️ Proposed change
-        if not cold_update and vm.is_alive() and not libvirtd_restarted:
+        if new_iface_link and not cold_update and vm.is_alive() and not libvirtd_restarted:
             logging.info("Restart libvirtd server")
             libvirtd = utils_libvirtd.Libvirtd()
             libvirtd.restart()
             libvirtd_restarted = True
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libvirt/tests/src/virtual_network/iface_update.py` around lines 273 - 279,
The libvirtd restart workaround is currently applied for every live-update path;
restrict it to only run when the update involves a link-state change by adding
the new_iface_link condition to the existing check so the block runs only when
not cold_update, vm.is_alive(), not libvirtd_restarted, and new_iface_link is
true; keep the existing instantiation (libvirtd = utils_libvirtd.Libvirtd()) and
restart() call and set libvirtd_restarted = True as before.
🤖 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/cfg/virtual_network/lifecycle/lifecycle_full_xml_interface.cfg`:
- Around line 65-66: The variant key for s390 is inconsistent: the direct_bridge
block uses "s390_virtio" while other blocks and the global override use
"s390-virtio", preventing s390-specific overrides from applying; update the
variant name used in the direct_bridge configuration to "s390-virtio" (or
alternatively make all occurrences "s390_virtio") so the variant key matches
across the file and the s390 overrides like features_xpath and driver_config
(and network_features) will be applied consistently.

In `@libvirt/tests/cfg/virtual_network/passt/passt_function.cfg`:
- Line 109: The cleanup command stored in kill_backend_cmd currently uses
"disown && killall ..." which prevents killall from running if disown fails;
change kill_backend_cmd so killall is executed unconditionally (e.g., use a
sequence operator or ensure disown errors are ignored) so that "killall tshark
dhcpcd" always runs even if disown fails.

In `@libvirt/tests/src/virtual_disks/virtual_disks_https.py`:
- Around line 70-73: iso_path currently hardcodes the leading
"/fedora/linux/releases/..." and ignores the configured base_url; change the
code that sets iso_path (the iso_path assignment) to build a relative_path =
f"fedora/linux/releases/{version}/{server_type}/{arch}/iso/Fedora-{server_type}-netinst-{arch}-{version}-{build}.iso"
and then combine it with the configured base_url (e.g. base_url) in a safe way
(base_url.rstrip('/') + '/' + relative_path.lstrip('/') or via
urllib.parse.urljoin) so the final URL respects any path component in base_url.
- Around line 17-25: Validate the base_url in get_latest_fedora_version before
calling urlopen: parse base_url (e.g., with urllib.parse.urlparse), ensure
scheme == "https" and that netloc/hostname is present, and raise or return a
clear error if validation fails; apply the same validation before any other
urlopen calls in this module so file://, ftp://, or malformed URLs are rejected
and only HTTPS hostnames are allowed.
- Line 104: Replace unsafe eval() usage with ast.literal_eval for parsing test
parameters: import ast at the top of the module and change the parsing of
disk_dict (currently disk_dict = eval(params.get("disk_dict", "{}") %
(network_device, iso_path))) to use ast.literal_eval on the formatted string,
and likewise replace the eval() that produces expected_xpaths (line ~131) with
ast.literal_eval on its parameter string. Keep the same string formatting with
params.get and ensure you call ast.literal_eval(...) on the resulting string to
safely parse literal data from params.

In `@libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py`:
- Around line 35-42: The code currently assigns iface_attrs['source'] =
{'bridge': bridge_name} then immediately checks and deletes
iface_attrs['source']['network'], which is dead; either remove that deletion or
merge instead of overwriting: retrieve the original source dict (orig =
iface_attrs.get('source', {}).copy()), pop 'network' from orig if present, set
orig['bridge'] = bridge_name and then assign iface_attrs['source'] = orig so
existing keys are preserved; update the block around the assignment to use this
merge approach (or simply delete the two lines that check/delete 'network' if a
full replacement is intended) and keep the subsequent call to
network_base.setup_ovs_bridge_attrs(params, iface_attrs).

In
`@libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_options_and_vm_status.py`:
- Around line 76-90: The code currently only returns an address when
address_elem.get('type') == 'pci', which breaks non‑PCI guests; change the logic
in the block that queries dumped_vmxml.devices.by_device_tag('interface') /
iface.xmltreefile.find('address') to read address_elem.get('type') into a
variable (e.g., addr_type) and handle non‑PCI types instead of hardcoding 'pci':
if addr_type == 'pci' keep the existing domain:bus:slot.function formatting,
else for ccw/spapr-vio (or any other addr_type) serialize the address element
into a stable string (for example join its attributes or use its tag+attributes)
and return that along with the addr_type (or a single string prefixed with the
type) so check_pci_address_difference() (or the calling comparison) can either
be gated to only run for pci types or can compare addresses of the same type;
update any callers to expect the new type-aware address format or skip the
comparison for non‑pci types.

In `@libvirt/tests/src/virtual_network/iface_bridge.py`:
- Line 116: The cleanup is unconditionally removing NETWORK_SCRIPT + bridge_name
even when bridge_name was provided via netdst (a pre-existing host bridge);
update the teardown/cleanup logic to detect when bridge_name came from
params.get("netdst") vs when the test created it and skip deleting the host
bridge's ifcfg in netdst cases. Specifically, add a flag or check around the
code that deletes NETWORK_SCRIPT + bridge_name (and the same check used in
bridge teardown) so it only removes files for bridges created by this test
(refer to the bridge_name variable, params.get("netdst"), and NETWORK_SCRIPT)
and apply the same guard at the other occurrence mentioned (lines ~409-410) to
avoid wiping persistent host configs.
- Line 128: The code uses eval() to parse the iface_source test parameter
(iface_source = eval(params.get("iface_source", "{'bridge':'%s'}" %
bridge_name))) which is unsafe; replace eval() with ast.literal_eval() so the
string from params.get(...) is parsed as a literal safe dict (ensure ast is
imported and used to call ast.literal_eval on the same params.get(...)
expression), preserving the default "{'bridge':'%s'}" % bridge_name behavior.

In
`@libvirt/tests/src/virtual_network/migrate/migrate_with_bridge_type_interface.py`:
- Around line 84-90: When interface_timing == "hotplug" the code calls
vm.start() then uses virsh.attach_device(..., flagstr="--config") which only
updates persistent XML and does not attach to the running domain; change the
attach call in that branch to use flagstr="--live --config" (or conditionally
include "--live" when vm.is_alive()) so the device is hotplugged into the live
guest and persisted; update the virsh.attach_device invocation that references
vm_name and iface.xml accordingly.

In `@provider/bootc_image_builder/bootc_image_build_utils.py`:
- Line 67: The helper currently mutates os.environ to change Podman logging,
which creates a process-global side effect; instead, stop writing to os.environ
and make the log-level change local by creating a copy of the environment (e.g.,
local_env = os.environ.copy()), set the desired log variable on that copy, and
pass local_env as the env= parameter to the subprocess invocation that runs cmd
(the variable named "cmd") (or simply rely on the existing "--log-level=error"
flag in cmd and remove the os.environ mutation entirely); remove any direct
assignment to os.environ in this helper.

In `@v2v/tests/cfg/specific_kvm.cfg`:
- Around line 330-341: The os_ver_13 variant under the debian_efi test is
missing msg_content and expect_msg entries that os_ver_12 defines; update the
os_ver_13 variant (the block containing main_vm =
VM_NAME_DEBIAN_EFI_OS_VERSION_13_V2V_EXAMPLE) to include msg_content =
'cache=none' and expect_msg = 'no' so both variants assert the same behavior.

In `@v2v/tests/src/function_test_esx.py`:
- Around line 652-655: The truncation of params["main_vm"] inside the
'char_slash' checkpoint is dead because the test sets skip_vm_check = yes and
the function returns before any virsh operations use the modified name; either
remove the replacement/truncation block (the two lines modifying
params["main_vm"]) or instead update the test configuration to clear
skip_vm_check for the 'char_slash' case so the truncated main_vm is actually
exercised; locate the 'char_slash' checkpoint in function_test_esx.py (and the
corresponding entry in function_test_esx.cfg) and choose one of the two fixes:
delete the params["main_vm"] modification if it is unnecessary, or remove/modify
skip_vm_check in the 'char_slash' cfg so the later VM checks use the truncated
name.

In `@virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg`:
- Line 54: The Fedora selector rename to fedora_legacy wasn’t fully applied:
update the filter named anaconda-iso..upstream_bib..fedora_40 to use the new
selector name (fedora_legacy) so that the case still gets kickstart = "yes" and
use_toml_config = "yes"; search for the anaconda-iso..upstream_bib..fedora_40
filter and replace the old variant name with fedora_legacy to restore the
intended behavior.

In `@virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg`:
- Line 51: The AMI override selector still targets the old variant name so
fedora_legacy cases fall through; update the selector that currently reads
"upstream_bib..fedora.fedora_40" (the AMI override entry) to reference the
renamed variant "fedora_legacy" so the override applies to the fedora_legacy
variant instead of the default AWS config.

---

Outside diff comments:
In `@libvirt/tests/src/virtual_disks/virtual_disks_https.py`:
- Around line 139-159: The finally block can raise UnboundLocalError if
setup_test() fails because qemu_config (and possibly disk_dev) are not defined;
to fix, initialize qemu_config (and any other variables used in finally like
disk_dev) to None before the try, and in the finally guard calls with checks
(e.g., if qemu_config is not None: qemu_config.restore(); if backup_vmxml is not
None: backup_vmxml.sync(); and only call Libvirtd('virtqemud').restart() if
appropriate), so replace direct restores with conditional calls around
qemu_config.restore() and backup_vmxml.sync() while keeping the same cleanup
intent.

---

Duplicate comments:
In
`@libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py`:
- Around line 41-50: The current setup chains commands (multi_cmd1/multi_cmd2)
which masks failures and races the socket relabeling; instead split into
distinct steps: run the mkdir (cmd1) via process.run/remote.run_remote_cmd,
start virtiofsd (cmd2) without chaining and then poll/wait for the socket file
to appear (check -S {socket_path} or loop with timeout) before proceeding, and
only after the socket exists run the relabel/chown commands (cmd3/cmd4)
individually via process.run/remote.run_remote_cmd so each failure is visible
and ordering is guaranteed; also avoid relying on immediate success of nohup/&
(do not use ignore_bg_processes to hide background startup errors).
- Around line 105-109: The current teardown calls
(migration_obj.cleanup_connection(), remote.run_remote_cmd('pkill virtiofsd',
...), remote.run_remote_cmd(f"rm -rf {socket_path}", ...), process.run("pkill
virtiofsd", ...), process.run(f"rm -rf {socket_path}", ...)) are executed
sequentially so an exception in migration_obj.cleanup_connection()
short-circuits remaining cleanup; change to collect cleanup actions as a list of
lambdas/closures when each action is performed (e.g., append a lambda that calls
migration_obj.cleanup_connection(), one for remote.run_remote_cmd('pkill
virtiofsd', params, ignore_status=True), one for remote.run_remote_cmd(f"rm -rf
{socket_path}", ...), and local process.run calls), then in a finally block
iterate over that list and invoke each action inside its own try/except to log
but not raise on error so all pkill and socket removals always run even if one
cleanup fails.

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`:
- Around line 159-163: Initialize the cleanup handles before entering the try
block to avoid UnboundLocalError in the finally: explicitly set vm_sess = None
and host_nserver = None (or other appropriate sentinel values) prior to the code
that may raise, then in the finally guard the cleanup calls by checking those
variables (e.g., if host_nserver is not None: process.run(...); if vm_sess is
not None: vm_sess.close()). This ensures the finally block in
check_actual_network_throughput.py safely skips cleanup when
setup/boot/compilation fails.
- Line 72: The test captures the original firewall state in fw_was_running (via
firewalld.status()) but the cleanup logic currently starts the firewalld service
unconditionally; change the teardown to restore the original state instead: call
firewalld.start() only if fw_was_running is True and call firewalld.stop() only
if fw_was_running is False (or otherwise ensure the opposite action is taken
only when the original state differs). Update the cleanup in
check_actual_network_throughput.py (and the similar block around lines 158-169)
to reference fw_was_running rather than always starting the service.

In `@provider/virtual_network/netperf_base.py`:
- Around line 166-172: The VM branch ignores a configured client_path and always
sets install_path to guest_netperf_path; update the branch that handles address
in params.get('vms', '').split() so it prefers params.get("client_path")
(falling back to guest_netperf_path) when assigning install_path for VM builds
(the code around guest_netperf_path, the elif branch using env.get_vm(address)
and session, install_path = vm.wait_for_login(), guest_netperf_path). Ensure
install_path is computed from params.get("client_path", guest_netperf_path) so
subsequent code finds netperf in the expected client location.

In `@provider/virtual_network/network_base.py`:
- Around line 757-791: The helpers cancel_if_ovs_bridge and
setup_ovs_bridge_attrs should use a caller-resolved bridge name instead of
always re-reading params['netdst']; change their signatures to accept an
optional resolved_bridge (e.g., def cancel_if_ovs_bridge(params, test,
resolved_bridge=None) and def setup_ovs_bridge_attrs(params, iface_attrs,
resolved_bridge=None)) and then use resolved_bridge if provided (falling back to
params.get('netdst', '') only if not), update logic to call
utils_net.find_bridge_manager(resolved_bridge) and adjust the TestError message
accordingly, and update all callers to pass the previously-resolved bridge_name
(or leave omitted when they rely on params).

In `@v2v/tests/src/v2v_options.py`:
- Around line 960-975: The code builds a string command (cmd) by inserting the
vpx_ipv6_addr and then calls process.run(..., shell=True) when checkpoint ==
'vpx_with_invalid_esx_ipv6', which risks shell injection and is flagged; instead
construct a safe argument list and pass an environment dict with LIBVIRT_DEBUG=1
to process.run so you can remove shell=True: keep using the same checkpoint
check and vpx_ipv6_addr lookup but replace string concatenation of cmd (and the
use of cmd_export_env) with a list/sequence of arguments for process.run (or
tokenize the existing cmd into args safely) and pass env={**os.environ,
"LIBVIRT_DEBUG":"1"} (or equivalent in your test harness) to process.run while
calling it without shell=True and still using timeout=v2v_timeout, verbose=True,
ignore_status=True.

---

Nitpick comments:
In `@libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg`:
- Around line 25-31: The line with kill_vm_libvirt_options under the ovmf: block
has extra leading spaces causing inconsistent indentation; open the cfg and
align kill_vm_libvirt_options to use the standard 4-space indent under the ovmf
key so it matches other entries (i.e., make the indentation for
kill_vm_libvirt_options consistent with the surrounding
create_vm_libvirt/use_no_reboot entries).

In
`@libvirt/tests/src/virtual_network/connectivity/connectivity_check_network_interface.py`:
- Around line 69-74: The loop currently catches a broad Exception for calls to
utils_net.restart_guest_network (for vm_session and ep_session); change this to
catch more specific exceptions raised by that function (e.g., RuntimeError,
OSError, subprocess.CalledProcessError or a custom network exception if one
exists) or catch a tuple of those specific types instead of Exception, and keep
the LOG.warning message for expected DHCPv6 failures; if you cannot identify a
single specific exception, still add a debug-level log of the full traceback
(use traceback.format_exc() via LOG.debug) alongside the warning to preserve
diagnostic info while avoiding masking unexpected errors.

In `@libvirt/tests/src/virtual_network/iface_update.py`:
- Around line 273-279: The libvirtd restart workaround is currently applied for
every live-update path; restrict it to only run when the update involves a
link-state change by adding the new_iface_link condition to the existing check
so the block runs only when not cold_update, vm.is_alive(), not
libvirtd_restarted, and new_iface_link is true; keep the existing instantiation
(libvirtd = utils_libvirtd.Libvirtd()) and restart() call and set
libvirtd_restarted = True as before.

In `@libvirt/tests/src/virtual_network/link_state/link_state_model_type.py`:
- Around line 64-67: The comment is misleading: replace "Configure ovs bridge
when host using ovs bridge" with a clearer note that this block applies
OVS-specific attribute adjustments for the network interface test variant
(triggered by params.get("network_test") == "yes") because
network_base.setup_ovs_bridge_attrs(params, iface_attrs) will itself detect OVS
usage; update the inline comment near the params check and the call to
network_base.setup_ovs_bridge_attrs to indicate it's applying OVS-related
attributes for the network test case rather than unconditionally configuring an
OVS bridge.

In `@v2v/tests/cfg/convert_from_file.cfg`:
- Around line 267-273: Add a version_required entry to the character_slash
variant to match the corresponding char_slash variant in function_test_esx.cfg;
specifically add version_required = "[virt-v2v-2.10.0-5,)" under the
character_slash block so the test declares the same minimum virt-v2v version
dependency and stays consistent with the char_slash variant.

In `@virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py`:
- Around line 84-85: Extract the literal list of allowed bib_ref values into a
shared constant (e.g., STAGED_BIB_REFS) in
provider.bootc_image_builder.bootc_image_build_utils, export it, and replace the
inline membership checks that reference bib_ref in functions like the one using
"if bib_ref in [...]" in bootc_disk_image_build.py and the corresponding check
in bootc_disk_image_install.py to use "if bib_ref in STAGED_BIB_REFS" (ensure
you import STAGED_BIB_REFS from bootc_image_build_utils); update any tests or
callers to import the constant so both build and install paths use the same
centralized allowlist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a010dec3-3510-40e0-962e-83ee2b10cbd9

📥 Commits

Reviewing files that changed from the base of the PR and between a202a38 and f1d5812.

📒 Files selected for processing (70)
  • libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg
  • libvirt/tests/cfg/libvirt_mem.cfg
  • libvirt/tests/cfg/memory/memory_discard.cfg
  • libvirt/tests/cfg/memory/memory_misc.cfg
  • libvirt/tests/cfg/memory/nvdimm.cfg
  • libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg
  • libvirt/tests/cfg/resource_abnormal.cfg
  • libvirt/tests/cfg/virtual_disks/virtual_disks_https.cfg
  • libvirt/tests/cfg/virtual_disks/virtual_disks_product.cfg
  • libvirt/tests/cfg/virtual_network/attach_detach_device/attach_ethernet_interface.cfg
  • libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_bridge_interface.cfg
  • libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_ethernet_interface.cfg
  • libvirt/tests/cfg/virtual_network/connectivity/connectivity_check_network_interface.cfg
  • libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg
  • libvirt/tests/cfg/virtual_network/driver/rx_tx_queue_size.cfg
  • libvirt/tests/cfg/virtual_network/fuzzy_test/virConnectListInterface_test.cfg
  • libvirt/tests/cfg/virtual_network/hotplug/attach_detach_interface/attach_interface_with_options_and_vm_status.cfg
  • libvirt/tests/cfg/virtual_network/iface_bridge.cfg
  • libvirt/tests/cfg/virtual_network/iface_options.cfg
  • libvirt/tests/cfg/virtual_network/iface_update.cfg
  • libvirt/tests/cfg/virtual_network/lifecycle/lifecycle_full_xml_interface.cfg
  • libvirt/tests/cfg/virtual_network/link_state/link_state_model_type.cfg
  • libvirt/tests/cfg/virtual_network/migrate/migrate_with_bridge_type_interface.cfg
  • libvirt/tests/cfg/virtual_network/migrate/migrate_with_ethernet_interface.cfg
  • libvirt/tests/cfg/virtual_network/mtu.cfg
  • libvirt/tests/cfg/virtual_network/passt/passt_function.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/cfg/virtual_network/resolve_vm_hostname_by_resolvectl.cfg
  • libvirt/tests/src/guest_os_booting/ovmf_firmware/ovmf_loader.py
  • libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py
  • libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py
  • libvirt/tests/src/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.py
  • libvirt/tests/src/migration/migration_uri/tcp_common.py
  • libvirt/tests/src/virtual_disks/virtual_disks_https.py
  • libvirt/tests/src/virtual_network/attach_detach_device/attach_ethernet_interface.py
  • libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface.py
  • libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py
  • libvirt/tests/src/virtual_network/connectivity/connectivity_check_ethernet_interface.py
  • libvirt/tests/src/virtual_network/connectivity/connectivity_check_network_interface.py
  • libvirt/tests/src/virtual_network/driver/rx_tx_queue_size.py
  • libvirt/tests/src/virtual_network/elements_and_attributes/driver_packed.py
  • libvirt/tests/src/virtual_network/hotplug/attach_detach_interface/attach_interface_with_options_and_vm_status.py
  • libvirt/tests/src/virtual_network/iface_bridge.py
  • libvirt/tests/src/virtual_network/iface_options.py
  • libvirt/tests/src/virtual_network/iface_update.py
  • libvirt/tests/src/virtual_network/link_state/link_state_model_type.py
  • libvirt/tests/src/virtual_network/migrate/migrate_with_bridge_type_interface.py
  • libvirt/tests/src/virtual_network/migrate/migrate_with_ethernet_interface.py
  • libvirt/tests/src/virtual_network/mtu.py
  • libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py
  • libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py
  • provider/bootc_image_builder/bootc_image_build_utils.py
  • provider/virtual_network/netperf_base.py
  • provider/virtual_network/network_base.py
  • v2v/tests/cfg/convert_from_file.cfg
  • v2v/tests/cfg/function_test_esx.cfg
  • v2v/tests/cfg/nbdkit/nbdkit.cfg
  • v2v/tests/cfg/specific_kvm.cfg
  • v2v/tests/cfg/v2v_options.cfg
  • v2v/tests/src/convert_from_file.py
  • v2v/tests/src/function_test_esx.py
  • v2v/tests/src/nbdkit/nbdkit.py
  • v2v/tests/src/v2v_options.py
  • virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg
  • virttools/tests/cfg/bootc_image_builder/bootc_disk_image_install.cfg
  • virttools/tests/src/bootc_image_builder/bootc_disk_image_build.py
  • virttools/tests/src/bootc_image_builder/bootc_disk_image_install.py
💤 Files with no reviewable changes (1)
  • libvirt/tests/src/virtual_network/connectivity/connectivity_check_bridge_interface_unprivileged.py
✅ Files skipped from review due to trivial changes (8)
  • libvirt/tests/cfg/virtual_disks/virtual_disks_product.cfg
  • libvirt/tests/cfg/virtual_network/driver/check_vhost_cpu_affinity_with_emulatorpin.cfg
  • libvirt/tests/cfg/cpu/multi_vms_with_stress.cfg
  • libvirt/tests/cfg/virtual_network/fuzzy_test/virConnectListInterface_test.cfg
  • libvirt/tests/cfg/virtual_network/migrate/migrate_with_ethernet_interface.cfg
  • libvirt/tests/src/memory/memory_devices/dimm_memory_lifecycle.py
  • libvirt/tests/cfg/memory/memory_discard.cfg
  • libvirt/tests/cfg/memory/nvdimm.cfg
🚧 Files skipped from review as they are similar to previous changes (9)
  • libvirt/tests/src/memory/memory_devices/virtio_mem_device_lifecycle.py
  • libvirt/tests/cfg/migration/destructive_operations_around_live_migration/kill_virtiofsd_during_performphase.cfg
  • libvirt/tests/cfg/libvirt_mem.cfg
  • libvirt/tests/src/virtual_network/elements_and_attributes/driver_packed.py
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg
  • v2v/tests/cfg/v2v_options.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg

Comment thread libvirt/tests/cfg/virtual_network/passt/passt_function.cfg
Comment thread libvirt/tests/src/virtual_disks/virtual_disks_https.py
Comment thread libvirt/tests/src/virtual_disks/virtual_disks_https.py
Comment thread libvirt/tests/src/virtual_disks/virtual_disks_https.py
Comment thread provider/bootc_image_builder/bootc_image_build_utils.py
Comment thread v2v/tests/cfg/specific_kvm.cfg
Comment thread v2v/tests/src/function_test_esx.py
Comment thread virttools/tests/cfg/bootc_image_builder/bootc_disk_image_build.cfg

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py (2)

72-73: ⚠️ Potential issue | 🟠 Major

Restore firewalld only if this test changed it.

If the service was already stopped before the case, Line 170 turns it back on and leaves the host in a different state for later tests.

Possible fix
-        firewalld.stop()
+        if fw_was_running:
+            firewalld.stop()
         disable_firewall = params.get("disable_firewall", "systemctl stop firewalld.service")
         vm_sess.cmd(disable_firewall)
@@
-        firewalld.start()
+        if fw_was_running:
+            firewalld.start()

Also applies to: 123-125, 170-170

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

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`
around lines 72 - 73, Record the initial firewalld state in fw_was_running (via
service.Factory.create_service("firewalld") and firewalld.status()) and when
restoring later (where the test currently unconditionally starts/stops firewalld
around line 170 and also at lines 123-125), only change the service if its
current state differs from fw_was_running; i.e., check fw_was_running before
calling start()/stop() so you restore the service to its original state only if
the test actually changed it.

72-73: ⚠️ Potential issue | 🟠 Major

Initialize vm_sess and host_nserver before the try.

A failure before Line 94 or Line 133 leaves these names undefined, and this finally then raises UnboundLocalError, masking the real failure.

Possible fix
     net_xml = NetworkXML.new_from_net_dumpxml('default')
     bk_net_xml = net_xml.copy()
     firewalld = service.Factory.create_service("firewalld")
     fw_was_running = firewalld.status()
+    vm_sess = None
+    host_nserver = None
 
     try:
@@
-        if host_nserver:
+        if host_nserver:
             process.run(f"rm -rf {host_nserver.split('/src/')[0]}", shell=True)
-        if vm_sess:
+        if vm_sess:
             vm_sess.close()

Also applies to: 159-164

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

In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`
around lines 72 - 73, The variables vm_sess and host_nserver are sometimes left
undefined if an exception occurs before they are assigned; initialize them to
None before entering the try block (e.g., vm_sess = None; host_nserver = None)
and update the finally block to check "if vm_sess is not None" and "if
host_nserver is not None" before using/closing them; apply the same
initialization/check pattern for the similar scope around the code referenced at
159-164 so UnboundLocalError is avoided and the original exception is preserved.
🤖 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/qos/check_actual_network_throughput.py`:
- Around line 132-134: The test calls netperf_base.compile_netperf_pkg but that
symbol is not exported from provider/virtual_network/netperf_base.py; fix this
by either adding a compile_netperf_pkg(params, env, target) wrapper in
netperf_base that encapsulates the existing compile/prepare functions and
returns (nserver, nperf), or modify the test to call the existing API provided
by netperf_base (e.g., the existing compile_netperf or prepare_netperf
functions) and adapt the returned values to match how host_nserver, host_nperf,
vm_nserver, vm_nperf are used; reference the netperf_base module and the
compile_netperf_pkg call sites in check_actual_network_throughput.py when making
the change.

---

Duplicate comments:
In `@libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py`:
- Around line 72-73: Record the initial firewalld state in fw_was_running (via
service.Factory.create_service("firewalld") and firewalld.status()) and when
restoring later (where the test currently unconditionally starts/stops firewalld
around line 170 and also at lines 123-125), only change the service if its
current state differs from fw_was_running; i.e., check fw_was_running before
calling start()/stop() so you restore the service to its original state only if
the test actually changed it.
- Around line 72-73: The variables vm_sess and host_nserver are sometimes left
undefined if an exception occurs before they are assigned; initialize them to
None before entering the try block (e.g., vm_sess = None; host_nserver = None)
and update the finally block to check "if vm_sess is not None" and "if
host_nserver is not None" before using/closing them; apply the same
initialization/check pattern for the similar scope around the code referenced at
159-164 so UnboundLocalError is avoided and the original exception is preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bbe8e49f-a8fe-4abe-b633-85e0a1df25f4

📥 Commits

Reviewing files that changed from the base of the PR and between f1d5812 and f9b9822.

📒 Files selected for processing (6)
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_bandwidth_by_domiftune.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/src/virtual_network/qos/check_actual_network_throughput.py
  • libvirt/tests/src/virtual_network/qos/check_bandwidth_by_domiftune.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • libvirt/tests/cfg/virtual_network/qos/test_bandwidth_boundry.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_qos_floor.cfg
  • libvirt/tests/cfg/virtual_network/qos/check_actual_network_throughput.cfg

@yanglei-rh

Copy link
Copy Markdown
Contributor Author

This patch depends on #6845

@yanglei-rh

Copy link
Copy Markdown
Contributor Author

Test pass

 (01/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.boundry.inbound.q35: PASS (10.02 s)
 (02/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.boundry.outbound.q35: PASS (10.04 s)
 (03/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_average.inbound.q35: PASS (9.67 s)
 (04/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_average.outbound.q35: PASS (9.67 s)
 (05/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_peak.inbound.q35: PASS (9.83 s)
 (06/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_peak.outbound.q35: PASS (9.56 s)
 (07/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_burst.inbound.q35: PASS (9.62 s)
 (08/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.test_bandwidth_boundry.over_boundry_burst.outbound.q35: PASS (9.63 s)
 (09/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_qos_floor.with_floor.q35: PASS (11.21 s)
 (10/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_qos_floor.without_floor.q35: PASS (10.46 s)
 (11/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_bandwidth_by_domiftune.nat.q35: PASS (59.15 s)
 (12/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_bandwidth_by_domiftune.br.q35: PASS (54.30 s)
 (13/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_actual_network_throughput.network.nat.net_with_qos.q35: PASS (81.75 s)
 (14/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_actual_network_throughput.network.nat.iface_with_qos.q35: PASS (77.84 s)
 (15/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_actual_network_throughput.network.br.q35: PASS (81.36 s)
 (16/16) Host_RHEL.m10.u2.ovmf.qcow2.virtio_scsi.up.virtio_net.Guest.RHEL.9.8.0.x86_64.io-github-autotest-libvirt.virtual_network.qos.check_actual_network_throughput.br.q35: PASS (83.32 s)

@yanglei-rh

Copy link
Copy Markdown
Contributor Author

Note: if you would like to use avocado runner to run these case, it should be like this command:
avocado run --vt-type libvirt virtual_network.qos.check_actual_network_throughput.network.nat.net_with_qos,virtual_network.qos.check_actual_network_throughput.network.nat.iface_with_qos,check_actual_network_throughput.network.br,virtual_network.qos.check_actual_network_throughput.br,virtual_network.qos.test_bandwidth_boundry.boundry.inbound,virtual_network.qos.test_bandwidth_boundry.boundry.outbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_average.inbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_average.outbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_burst.inbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_burst.outbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_peak.inbound,virtual_network.qos.test_bandwidth_boundry.over_boundry_peak.outbound,virtual_network.qos.check_bandwidth_by_domiftune.nat,virtual_network.qos.check_bandwidth_by_domiftune.br,virtual_network.qos.check_qos_floor.with_floor,virtual_network.qos.check_qos_floor.without_floor --vt-machine-type q35 --vt-arch x86_64 --vt-guest-os RHEL.9.8 --vt-extra-params 'ovmf_code_filename=/usr/share/edk2/ovmf\nnicmodel=virtio_net\nos_variant=rhel-unknown\nnetdst=virbr0\nmem=8096'

1.Add some parameters to allow the framework provide guest xml
2.Add "only Linux" to limit guest type
3.Add a check about host bridge type for check_actual_network_throughput
and check_bandwidth_by_domiftune
4.Change the method for specifying different bridge types via the test
command intead of case cfg varaint for check_actual_network_throughput

Signed-off-by: Lei Yang <leiyang@redhat.com>
@harvey0100

Copy link
Copy Markdown

Closing this PR due to current team constraints. This is part of a broader effort to triage all in-flight work across our upstream repos. If this work is still needed, please feel free to reopen and it will be picked up. Apologies for any inconvenience.

@harvey0100 harvey0100 closed this Jun 4, 2026
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