Skip to content

Improve package installation for network utilities#4277

Open
quanwenli wants to merge 1 commit intoavocado-framework:masterfrom
quanwenli:install-pkg
Open

Improve package installation for network utilities#4277
quanwenli wants to merge 1 commit intoavocado-framework:masterfrom
quanwenli:install-pkg

Conversation

@quanwenli
Copy link
Copy Markdown
Contributor

@quanwenli quanwenli commented Dec 3, 2025

utils_package: add package_install_any to try multiple candidates
utils_net: update package install to support multiple dhcp clients

ID: LIBVIRTAT-22185
Signed-off-by: Wenli Quan wquan@redhat.com

Summary by CodeRabbit

  • New Features

    • Added a utility that tries multiple package candidates and returns success on the first available installer.
  • Improvements

    • Installation sequence now installs terminal tooling first, then ensures a DHCP client from available options.
    • Network bridge setup is more flexible across distributions.
  • Bug Fixes

    • Reduced false failures by splitting installation checks and adjusting error handling for independent steps.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 3, 2025

Walkthrough

Added package_install_any(candidates, session=None, timeout=PKG_MGR_TIMEOUT) to virttest/utils_package.py, which iterates candidate package names and returns on the first successful install. Updated virttest/utils_net.py bridge routines (create_ovs_bridge, delete_ovs_bridge, create_linux_bridge_tmux) to perform package installation in two steps: install tmux (and other required packages where present) first, then attempt to install any DHCP client from ["dhcp-client", "dhcpcd"]. Error handling and control flow were adjusted to check the two installation steps independently.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify package_install_any() iteration, return semantics (True on first success, False if none), timeout and session handling.
  • Inspect the two-step install sequence and ensure independent failure checks are correct in create_ovs_bridge, delete_ovs_bridge, and create_linux_bridge_tmux.
  • Confirm logging/error messages and early returns consistently surface failures and do not mask installation errors.

Pre-merge checks

✅ 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 changes: adding package_install_any function and updating network utilities to support multiple DHCP clients.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84ed244 and 880f142.

📒 Files selected for processing (2)
  • virttest/utils_net.py (3 hunks)
  • virttest/utils_package.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • virttest/utils_net.py
  • virttest/utils_package.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Static checks
  • GitHub Check: fedora_40 AVOCADO_SRC: SETUP:-m pip install PYPI_UPLOAD/*.whl VT_TYPE:qemu
  • GitHub Check: fedora_40 AVOCADO_SRC:avocado-framework<104.0 SETUP:-m pip install . VT_TYPE:qemu
  • GitHub Check: fedora_40 AVOCADO_SRC:avocado-framework<104.0 SETUP:-m pip install PYPI_UPLOAD/*.whl VT_TYPE:qemu
  • GitHub Check: fedora_40 AVOCADO_SRC: SETUP:-m pip install . VT_TYPE:qemu

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21a1b78 and 44ddaca.

📒 Files selected for processing (2)
  • virttest/utils_net.py (3 hunks)
  • virttest/utils_package.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
virttest/utils_net.py (1)
virttest/utils_package.py (2)
  • package_install (227-237)
  • package_install_any (252-265)
virttest/utils_package.py (1)
virttest/utils_misc.py (2)
  • wait_for (557-592)
  • wait_for (4186-4234)
🪛 GitHub Actions: CI
virttest/utils_net.py

[error] 1-1: Black formatting would reformat 2 files. Run 'black' (or your formatter) to fix code style issues.

virttest/utils_package.py

[error] 1-1: Black formatting would reformat 2 files. Run 'black' (or your formatter) to fix code style issues.

Comment thread virttest/utils_net.py Outdated
Comment on lines 4631 to 4633
if (not utils_package.package_install(["tmux"], session) or
not utils_package.package_install_any(["dhcp-client", "dhcpcd"], session)):
raise exceptions.TestError("Failed to install the required packages.")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

DHCP client install vs usage mismatch; and remember to run Black

The new pattern of always installing tmux and then trying any of ["dhcp-client", "dhcpcd"] via package_install_any() improves flexibility, but there’s a subtle mismatch:

  • The commands later in these functions (create_ovs_bridge, delete_ovs_bridge, create_linux_bridge_tmux) still hard‑code dhclient (dhclient -r, dhclient {iface}, pkill dhclient, etc.).
  • On a system where dhcpcd is the only DHCP client and does not provide a dhclient binary, package_install_any() can succeed by installing dhcpcd, but the subsequent tmux command will still fail at runtime with dhclient: command not found.

This is a functional inconsistency and can turn an early, clear dependency failure into a later, less obvious runtime break. It would be better to either:

  • Restrict package_install_any() candidates here to packages that provide dhclient, or
  • Make these bridge helpers detect and use the actual DHCP client binary (and its appropriate release/renew flags), similar to the restart_guest_network() logic above that switches between dhclient and dhcpcd.

Also, CI indicates Black would reformat this file; please run your formatter so the pipeline passes.

Also applies to: 4676-4678, 4782-4784

🧰 Tools
🪛 Ruff (0.14.7)

4633-4633: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
In virttest/utils_net.py around lines 4631-4633 (also apply same change at
4676-4678 and 4782-4784): the code installs tmux and then any of
["dhcp-client","dhcpcd"] but later bridge helper functions invoke dhclient
unconditionally, causing runtime failures when dhcpcd is installed; change the
install step to only install DHCP clients that provide dhclient or update the
bridge helpers to detect which DHCP client binary is available (dhclient vs
dhcpcd) and call the appropriate release/renew commands accordingly (mirror the
logic used in restart_guest_network()), and finally run Black on the file to fix
formatting before committing.

Comment thread virttest/utils_package.py
Comment on lines +252 to +265
def package_install_any(candidates, session=None, timeout=PKG_MGR_TIMEOUT):
"""
Try to install packages from candidates in order until one succeeds.

:param candidates: iterable of package names to try in order
:param session: session Object
:param timeout: timeout for each install session
:return: True if any candidate installed successfully, else False
"""
for pkg in candidates:
mgr = package_manager(session, pkg)
if utils_misc.wait_for(mgr.install, timeout):
return True
return False
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

New package_install_any() helper looks correct; consider normalizing input + run Black

The control flow (try each candidate, return on first successful install) is sound and consistent with package_install()’s use of wait_for. One small robustness nit: if a caller accidentally passes a single string instead of an iterable, this will iterate over characters rather than treat it as one package name. You can cheaply guard against that:

 def package_install_any(candidates, session=None, timeout=PKG_MGR_TIMEOUT):
@@
-    :return: True if any candidate installed successfully, else False
+    :return: True if any candidate installed successfully, else False
     """
-    for pkg in candidates:
+    if isinstance(candidates, string_types):
+        candidates = [candidates]
+    for pkg in candidates:
         mgr = package_manager(session, pkg)
         if utils_misc.wait_for(mgr.install, timeout):
             return True
     return False

Also, CI reports that Black would reformat this file; please run your standard formatter so the pipeline passes.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In virttest/utils_package.py around lines 252 to 265, package_install_any() will
iterate characters if callers pass a single string; normalize the candidates
argument by detecting a str and wrapping it into a single-item iterable (e.g.,
convert a single package name string to [string]) before the loop, keep existing
behavior for real iterables, and then run Black (or your repository formatter)
on the file to satisfy CI formatting checks.

@quanwenli quanwenli force-pushed the install-pkg branch 2 times, most recently from b393304 to 84ed244 Compare December 3, 2025 09:24
Copy link
Copy Markdown

@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

♻️ Duplicate comments (3)
virttest/utils_package.py (1)

240-253: String input normalization not yet addressed.

The previous review comment about guarding against a single string being passed (which would iterate over characters) has not been implemented. Please add the suggested normalization:

 def package_install_any(candidates, session=None, timeout=PKG_MGR_TIMEOUT):
     """
     Try to install the first available package from candidates.

     :param candidates: iterable of package names to try in order
     :param session: session Object
     :param timeout: timeout for each install session
     :return: True if any candidate installed successfully, else False
     """
+    if isinstance(candidates, string_types):
+        candidates = [candidates]
     for pkg in candidates:
         mgr = package_manager(session, pkg)
         if utils_misc.wait_for(mgr.install, timeout):
             return True
     return False
virttest/utils_net.py (2)

4631-4648: DHCP client installation vs. command usage mismatch remains unaddressed.

The previous review comment identified that installing dhcpcd (when dhcp-client is unavailable) will succeed, but the subsequent command on line 4647 hardcodes dhclient, which won't exist on systems using dhcpcd. This will cause a runtime failure.

Either restrict candidates to packages that provide dhclient, or detect which DHCP client is available and use appropriate commands (similar to restart_guest_network() at lines 1707-1718).


4783-4786: Same DHCP client mismatch applies here.

As noted in the previous review, installing dhcpcd when dhcp-client is unavailable will succeed, but the dhclient command on line 4803 will fail at runtime.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b393304 and 84ed244.

📒 Files selected for processing (2)
  • virttest/utils_net.py (3 hunks)
  • virttest/utils_package.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
virttest/utils_package.py (1)
virttest/utils_misc.py (2)
  • wait_for (557-592)
  • wait_for (4186-4234)
virttest/utils_net.py (1)
virttest/utils_package.py (2)
  • package_install (227-237)
  • package_install_any (240-253)
🪛 GitHub Actions: CI
virttest/utils_net.py

[error] 4681-4681: Black formatting failed to parse the file. Cannot format: 4681:4: res = utils_misc.cmd_status_output( . 407 files would be left unchanged, 1 file would fail to reformat.

Comment thread virttest/utils_net.py
@nanli1
Copy link
Copy Markdown
Contributor

nanli1 commented Dec 3, 2025

@qiankehan hi hhan, yanglei, As we have some discussion on weekly meeting about dhcpcd and dhclient , Could you also review this patch?

@nanli1 nanli1 self-requested a review December 3, 2025 09:56
Comment thread virttest/utils_package.py
"""
for pkg in candidates:
mgr = package_manager(session, pkg)
if utils_misc.wait_for(mgr.install, timeout):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It could be merged into one line:

if utils_misc.wait_for(package_manager(session, pkg).install, timeout):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion.
I think keeping the two-step makes the code consistent with the existing package_install().. implementation

Copy link
Copy Markdown
Contributor

@qiankehan qiankehan left a comment

Choose a reason for hiding this comment

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

The other LGTM

@nanli1
Copy link
Copy Markdown
Contributor

nanli1 commented Jan 12, 2026

@quanwenli hi wenli , you may also need to find some tp-qemu and infrastucture team member to check this patch

@quanwenli
Copy link
Copy Markdown
Contributor Author

@yanglei-rh could you help review this ? thanks a lot.

Copy link
Copy Markdown
Contributor

@dzhengfy dzhengfy left a comment

Choose a reason for hiding this comment

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

LGTM

@quanwenli
Copy link
Copy Markdown
Contributor Author

@dzhengfy @Yingshun This PR already has three acks. Could you merge it if everything looks good?

@Yingshun
Copy link
Copy Markdown
Contributor

Yingshun commented Apr 3, 2026

@quanwenli please fix the conflicts.thx!

utils_package: add package_install_any to try multiple candidates
utils_net: update package install to support multiple dhcp clients

Signed-off-by: Wenli Quan <wquan@redhat.com>
@quanwenli
Copy link
Copy Markdown
Contributor Author

@quanwenli please fix the conflicts.thx!

I have updated. thanks

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.

6 participants