The outer loop over network interfaces had no break, so ip_address was
overwritten by every subsequent up/non-loopback interface with a
matching address family. On hosts with Docker, this meant the bridge
IP (e.g. 172.18.0.1) was returned instead of the actual LAN address,
because virtual interfaces can sort after the real one in dict order.
Add a break once a match is found so the function returns the first
qualifying interface, plus regression tests covering the Docker case,
loopback/down-interface skipping, and the no-match case.
Fixes#3617
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015NJfi2d6yvmmDzvPmm4eof
On Jetson (Tegra) the integrated GPU is enumerated by NVML
(nvidia-l4t-nvml) and reports its name (e.g. "Orin (nvgpu)"), but the
per-metric NVML queries return NVML_ERROR_NOT_SUPPORTED, so the GPU
plugin only ever showed N/A for proc/mem/temperature.
Add a Tegra sysfs backend (glances/plugins/gpu/cards/tegra.py) and wire
it into the NVIDIA card as a per-metric fallback: when NVML returns None
for a device detected as Tegra (name contains "nvgpu", or the Tegra GPU
sysfs node exists), read:
- proc: /sys/devices/platform/gpu.0/load (per-mille -> percent)
- temperature: the gpu-thermal /sys/class/thermal zone (milli-C -> C)
Memory stays N/A by design: the Tegra GPU shares system RAM, already
reported by the MEM plugin. Scales verified against tegrastats
(GR3D_FREQ and gpu@).
Adds unit tests with committed sysfs fixtures, a NEWS.rst entry and a
docs note.
Verified on JetPack 6.2.1 (L4T R36.4.7) and JetPack 7.2 (L4T R39.2):
identical sysfs node layout and gpu-thermal zone selection on both, with
temperature cross-checked against tegrastats on each.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror v4: a horizontal rule now sits between the header line (system/uptime)
and the top row, in addition to the existing top↔body rule. Both use the ─
box-drawing glyph by default (v4 paints curses.ACS_HLINE). The [outputs]
separator config key (default True) governs both; when False the rule rows
are left blank rather than collapsed, preserving the vertical rhythm.
Add end-to-end test asserting that uptime/system/now appear in the TUI
registry while core/version/psutilversion are discovered (REST-served)
but filtered out of TUI rendering. Add system/uptime/now sections to
the tui-v4-rendering-patterns.md catalogue with v4 layout notes and v5
source pointers.
Both plugins are scalar, constant-data, DISPLAY_IN_TUI=False.
_grab_stats() returns the live symbol value directly (no psutil call,
no asyncio.to_thread). 4 tests added; round-trip verified via the real
glances.__version__ and psutil_version_info imports.
DISPLAY_IN_TUI=False mirrors v4 display_curse=False — the load plugin
surfaces the core count in the TUI; core data remains accessible via
REST and exporters. Tolerates psutil.cpu_count() failure (OSError,
RuntimeError, NameError) with an empty-payload fallback.
Fix config_v5 interpolation bug: use ConfigParser(interpolation=None) to
prevent strftime format strings (e.g. %Y) from tripping BasicInterpolation,
matching v4 behaviour (glances/config.py uses the same flag).
Add `_paint_header` method that places the first block flush-left and the
last block flush-right (v4 fidelity). Update `_paint` to call it first and
shift the top row + separator + sidebars down by `header_height` (0 when
`frame.header` is empty, so existing layout is unchanged). Covered by three
new TDD tests (fail→pass order verified before implementation).
Add HEADER_SLOT = ("system", "uptime"), update slot_for() to check header
first, extend Frame with a header list (first field, keyword-only default so
no positional-arg regression), dispatch in build_frame, and sort on
HEADER_SLOT order. system/uptime no longer leak into left/top/right.
Add ClassVar[bool] DISPLAY_IN_TUI = True to GlancesPluginBase (mirrors v4
display_curse=False). Filter the TUI registry in assemble() to skip plugins
with DISPLAY_IN_TUI=False; REST registration is unaffected.