Skip to content

Conversation

@ericbsd
Copy link
Member

@ericbsd ericbsd commented Jan 21, 2026

  • Replace Popen with subprocess.run() for cleaner code and better resource handling across all devd scripts
  • Use proper raw string prefix (r"") for regex patterns
  • Remove deprecated close_fds parameter (default True in Python 3)
  • Change devd priority from 100 to 5 for faster event handling

auto-switch.py:

  • Create marker file /tmp/link-down-{nic} for coordination with link-up.py
  • Replace os.system() calls with subprocess.run()

link-up.py:

  • Simplify logic using marker file from auto-switch.py
  • Remove complex /tmp/network-{nic} state tracking
  • Use explicit service calls instead of shell command strings

setup-nic.py:

  • Use sysrc command instead of manual rc.conf file writing
  • Fix wlan configuration logic to check wlans_{nic} only once
  • Use appropriate pccard_ether action (startchildren for WiFi, start forEthernet)

Summary by Sourcery

Streamline devd-based NIC management scripts for link up/down handling and configuration, and bump the application version.

New Features:

  • Coordinate link-down and link-up handling using a temporary marker file to distinguish runtime link events from boot state.

Bug Fixes:

  • Correct regular expressions used to filter network interfaces and detect inet addresses in devd scripts.

Enhancements:

  • Simplify link-up handling logic to use explicit service calls and conditional netif restart instead of ad-hoc state files and shell command strings.
  • Refactor auto-switch and setup-nic scripts to use subprocess.run and sysrc for safer, more maintainable system interaction and configuration updates.
  • Adjust devd notification priority to a lower value for faster processing of network interface events.

Chores:

  • Bump the project version from 6.7 to 6.8.

- Replace Popen with subprocess.run() for cleaner code and better resource handling across all devd scripts
- Use proper raw string prefix (r"") for regex patterns
- Remove deprecated close_fds parameter (default True in Python 3)
- Change devd priority from 100 to 5 for faster event handling

auto-switch.py:
- Create marker file /tmp/link-down-{nic} for coordination with link-up.py
- Replace os.system() calls with subprocess.run()

link-up.py:
- Simplify logic using marker file from auto-switch.py
- Remove complex /tmp/network-{nic} state tracking
- Use explicit service calls instead of shell command strings

setup-nic.py:
- Use sysrc command instead of manual rc.conf file writing
- Fix wlan configuration logic to check wlans_{nic} only once
- Use appropriate pccard_ether action (startchildren for WiFi, start forEthernet)
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 21, 2026

Reviewer's Guide

Refactors the devd helper scripts to use subprocess.run and more explicit service invocations, simplifies NIC/link state handling via a shared marker file, switches NIC setup to sysrc and proper pccard_ether actions, tightens regex usage, lowers devd notification priority to improve responsiveness, and bumps the package version to 6.8.

Sequence diagram for updated link state handling between auto-switch.py and link-up.py

sequenceDiagram
    participant devd
    participant networkmgr_conf
    participant auto_switch_py as auto-switch.py
    participant link_up_py as link-up.py
    participant netif_service as service_netif
    participant routing_service as service_routing
    participant dhclient_service as service_dhclient
    participant ifconfig_cmd as ifconfig
    participant sysrc_cmd as sysrc
    participant marker_file as tmp_link_down_nic

    devd->>networkmgr_conf: IFNET LINK_DOWN event
    networkmgr_conf->>auto_switch_py: exec auto-switch.py nic
    auto_switch_py->>ifconfig_cmd: ifconfig nic
    auto_switch_py->>sysrc_cmd: sysrc -n ifconfig_nic
    auto_switch_py->>auto_switch_py: evaluate link status and DHCP
    alt nic inactive and another nic active
        auto_switch_py->>netif_service: service netif stop nic
        auto_switch_py->>marker_file: create /tmp/link-down-nic
        alt nic uses DHCP
            auto_switch_py->>ifconfig_cmd: ifconfig other_nic
            auto_switch_py->>dhclient_service: service dhclient restart other_nic
        else nic uses static config
            auto_switch_py->>routing_service: service routing restart
        end
    else nic still active or no fallback
        auto_switch_py-->>devd: exit without changes
    end

    devd->>networkmgr_conf: IFNET LINK_UP event
    networkmgr_conf->>link_up_py: exec link-up.py nic
    alt marker file exists
        link_up_py->>marker_file: check /tmp/link-down-nic
        link_up_py->>ifconfig_cmd: ifconfig nic
        alt nic has no inet address
            link_up_py->>netif_service: service netif start nic
        end
        link_up_py->>routing_service: service routing restart
        link_up_py->>dhclient_service: service dhclient restart nic
        link_up_py->>marker_file: remove /tmp/link-down-nic
    else no marker file (boot or cold plug)
        link_up_py->>dhclient_service: service dhclient quietstart nic
    end
Loading

Flow diagram for updated setup-nic.py NIC configuration logic

flowchart TD
    A[start setup-nic.py with nic] --> B[Load rc_conf_content]
    B --> C[Check if nic matches wifi_driver_regex]
    C -->|wifi driver| D[Ensure wpa_supplicant.conf exists and permissions set]
    C -->|not wifi driver| K[Ethernet branch]

    D --> E[Check if wlans_nic entry exists in rc_conf_content]
    E -->|missing| F[For wlanNum in range 0..8]
    F --> G[Check if wlanN not in rc_conf_content]
    G -->|free wlanN| H[sysrc wlans_nic='wlanN']
    H --> I[sysrc ifconfig_wlanN='WPA DHCP']
    I --> J[Break loop]
    G -->|in use| F

    E -->|exists| L
    J --> L[Wifi configured]

    L --> M[Run /etc/pccard_ether nic startchildren]
    M --> N[exit]

    K --> O[Check if ifconfig_nic exists in rc_conf_content]
    O -->|missing| P[sysrc ifconfig_nic=DHCP]
    O -->|exists| Q
    P --> Q[Ethernet configured]

    Q --> R[Run /etc/pccard_ether nic start]
    R --> S[exit]
Loading

File-Level Changes

Change Details Files
Refactor link-up logic to use a link-down marker file and explicit service calls instead of ad‑hoc state files and shell command strings.
  • Replace Popen-based command execution with subprocess.run and drop close_fds where it is already the default.
  • Introduce a check for /tmp/link-down-{nic} to distinguish runtime link events from boot-time DHCP startup.
  • On marker presence, ensure interface has no inet address, bring netif up, then restart routing and dhclient explicitly via separate service calls.
  • On no marker, fall back to a lightweight dhclient quietstart to avoid unnecessary restarts.
  • Use raw string regex for NIC exclusion patterns.
src/link-up.py
Improve auto-switch behavior when a NIC goes down, using subprocess.run, a shared marker file, and safer regex patterns.
  • Replace Popen and os.system with subprocess.run, simplifying stdout handling via .stdout.
  • Fix and simplify the not_nics_regex and inet matching regexes using proper raw string syntax.
  • Create /tmp/link-down-{nic} when stopping a NIC so link-up.py can coordinate behavior.
  • When DHCP is enabled, iterate remaining NICs and restart dhclient only on an interface that is active/associated and has inet/inet6; otherwise just restart routing.
src/auto-switch.py
Change NIC setup to rely on sysrc and correct pccard_ether actions, while simplifying WLAN configuration probing.
  • Convert not_nics_regex to a raw string for correctness and consistency.
  • For WiFi NICs, only check wlans_{nic} once, then iterate wlan0–wlan8 to pick an unused wlanX, writing settings via sysrc instead of manually appending to rc.conf.
  • Call /etc/pccard_ether {nic} startchildren for WiFi NICs and /etc/pccard_ether {nic} start for Ethernet NICs.
  • For Ethernet NICs, create ifconfig_{nic}=DHCP using sysrc when not already present.
src/setup-nic.py
Adjust devd configuration priorities to make NIC events handled sooner.
  • Lower IFNET ATTACH, LINK_UP, LINK_DOWN notify blocks and wifi-driver attach block priority from 100 to 5 to run networkmgr helpers earlier in the devd queue.
src/networkmgr.conf
Bump project version to 6.8.
  • Update VERSION constant from 6.7 to 6.8.
setup.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In link-up.py, the new subprocess.run(['ifconfig', nic], ...) call never requests a PIPE/captured output, so nic_ifconfig becomes None and the subsequent 'inet ' checks will fail; add stdout=PIPE (or capture_output=True) as done in the other scripts.
  • The updated not_nics_regex in auto-switch.py looks less strict than before (e.g., [0-9] instead of [0-9]+, and vm-[a-z] instead of vm-[a-z]+), which may cause valid interfaces to be filtered incorrectly; consider tightening this regex to match the previous intent.
  • In setup-nic.py, the sysrc call for Ethernet uses ifconfig_{nic}=DHCP without quotes while the WiFi-related sysrc calls use quoted values; align the Ethernet call (e.g., ifconfig_{nic}="DHCP") to avoid unexpected parsing differences.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In link-up.py, the new subprocess.run(['ifconfig', nic], ...) call never requests a PIPE/captured output, so nic_ifconfig becomes None and the subsequent 'inet ' checks will fail; add stdout=PIPE (or capture_output=True) as done in the other scripts.
- The updated not_nics_regex in auto-switch.py looks less strict than before (e.g., `[0-9]` instead of `[0-9]+`, and `vm-[a-z]` instead of `vm-[a-z]+`), which may cause valid interfaces to be filtered incorrectly; consider tightening this regex to match the previous intent.
- In setup-nic.py, the sysrc call for Ethernet uses ifconfig_{nic}=DHCP without quotes while the WiFi-related sysrc calls use quoted values; align the Ethernet call (e.g., ifconfig_{nic}="DHCP") to avoid unexpected parsing differences.

## Individual Comments

### Comment 1
<location> `src/link-up.py:22-26` </location>
<code_context>
     exit(0)

-nic_ifconfig = Popen(
+nic_ifconfig = run(
     ['ifconfig', nic],
     stdout=PIPE,
-    close_fds=True,
     universal_newlines=True
-).stdout.read()
+).stdout

-dhcp = Popen(
</code_context>

<issue_to_address>
**issue (bug_risk):** run() call for ifconfig never captures stdout, so nic_ifconfig will be None and the inet check will fail at runtime.

Because `run()` is called without `stdout=PIPE` (or `capture_output=True`), `CompletedProcess.stdout` will be `None`, and `'inet ' not in nic_ifconfig` will raise a `TypeError`. Add `stdout=PIPE` (and optionally `check=True`) to the `run()` call to match the previous `Popen` behavior of capturing output.
</issue_to_address>

### Comment 2
<location> `src/auto-switch.py:15-16` </location>
<code_context>

-not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|wlan" \
-                    r"ppp|bridge|wg)[0-9]+(\s*)|vm-[a-z]+(\s*)"
+not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \
+                    r"ppp|bridge|wg)[0-9]|vm-[a-z]"

-default_nic = Popen(
</code_context>

<issue_to_address>
**issue (bug_risk):** The updated not_nics_regex no longer matches full interface names correctly and is likely too permissive.

The previous pattern used `[0-9]+(\s*)` and `vm-[a-z]+(\s*)`, while the new one uses only `[0-9]` and `vm-[a-z]`. This now matches only single-digit suffixes / single-letter names, drops the optional trailing whitespace, and allows partial matches (e.g. only `lo1` from `lo10`). Restoring the `+` quantifier (and whitespace handling) or anchoring to the full interface name would avoid these incorrect and overly permissive matches.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

- Updated subprocess.run with `stdout=PIPE` for capturing output
- Removed unnecessary `close_fds` parameter (default True in Python 3)
@ericbsd ericbsd merged commit e2b3a3b into master Jan 21, 2026
1 check passed
@ericbsd ericbsd deleted the devd branch January 21, 2026 21:45
@github-project-automation github-project-automation bot moved this from To triage to Done in NetworkMGR Issue Traker Jan 21, 2026
@ericbsd ericbsd moved this from In Review to Done in Development Tracker Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants