sync: auto-sync from DESKTOP-0O8A1RL at 2026-05-15 07:50:23

Author: Mike Swanson
Machine: DESKTOP-0O8A1RL
Timestamp: 2026-05-15 07:50:23
This commit is contained in:
2026-05-15 07:50:26 -07:00
parent 85f234e67b
commit fc3a769320
2 changed files with 172 additions and 1 deletions

View File

@@ -217,3 +217,174 @@ INFO gururmm_server::ws: Agent fa99e913... reconnected after update: 0.6.18 ->
- **Fleet status as of session end**:
- Online on 0.6.19: CS-SERVER, DESKTOP-0O8A1RL, DESKTOP-BTR2AM3, DESKTOP-DLTAGOI, DESKTOP-H6QHRR7, DESKTOP-KQSL232, DF-GAGETRAK, GND-SERVER, IMC1, LAPTOP-DRQ5L558, LAPTOP-E0STJJE8, MAINTENANCE-PC, MDIRECTOR-PC, NURSESTATION-PC, gururmm (15 agents)
- Online on 0.6.1: AD2 (offline since 2026-04-20, unreachable)
---
## Update: 07:50 PT — Network discovery: hostname lookup, subnet auto-detection, fleet update to 0.6.20
## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
- **Session Span:** ~07:00 PT 07:50 PT (continued from prior context window)
---
## Session Summary
This session picked up from a prior context window that had implemented the network discovery hostname lookup and subnet auto-detection features. All code changes across 8 files had been applied but a compile error was blocking the build: `format!({}/{}, network, prefix)` on line 775 of `agent/src/metrics/mod.rs` was missing quotes around the format string. Fixed with a single `sed` line-number substitution.
Agent and server release builds were launched in parallel. Agent (0.6.19) compiled clean. Server failed with a second missing-quotes error in the new `get_suggested_subnets` handler: `iface.get(ipv4_subnets)` instead of `iface.get("ipv4_subnets")` at line 301 of `server/src/api/discovery.rs`. Fixed and server rebuilt successfully. Dashboard TypeScript build then failed with multiple missing string literals: `.join(, )` instead of `.join(", ")` in two places, bare `manual` instead of `"manual"` in two places (one the earlier Python fix missed), `api.get<string[]>()` with no URL argument, and `setIpRanges()`/`setExclusions()` with no empty-string argument. Each required a targeted fix. The `_getSensorUnit` function in `AgentDetail.tsx` was declared but unused (pre-existing dead code that TS6133 finally flagged); it was deleted.
All three artifacts built clean after the fixes. Server binary was deployed (stop/copy/start pattern), dashboard dist was copied to `/var/www/gururmm/dashboard/`, and all changes were committed to the gururmm repo as `0c60d36`. The `latest` symlink and `gururmm-agent-linux-amd64-latest` were both pointing at 0.6.19, which meant the scanner would not dispatch updates. Version bumped to 0.6.20, rebuilt, and the binary + sha256 placed at `/var/www/gururmm/downloads/gururmm-agent-linux-amd64-0.6.20`. The version bump was committed as `c97b0f3`.
At the 14:47 UTC scan (5-minute interval), the server found 50 binaries (up from 49), immediately identified agents on 0.6.19 as needing an update, dispatched to the first connected agent, and that agent reconnected on 0.6.20 within 11 seconds. Fleet rollout is proceeding automatically on heartbeat.
---
## Key Decisions
- **Single-quoted SSH heredocs do not protect backtick template literals**: Despite using `<< 'ENDSCRIPT'`, bash inside an SSH double-quoted command still executed backtick template literals in the heredoc content as command substitution. Workaround: build the TypeScript template literal string using Python's `chr(96)` to represent the backtick character, passing everything via `python3 -c '...'` with single-quoted outer shell quoting.
- **Version bump to 0.6.20 required to trigger fleet update**: The scanner only dispatches updates when the available version is strictly greater than the agent's reported version. Since the discovery feature changes (PTR lookup, subnet reporting) were built at 0.6.19, a bump to 0.6.20 was needed to push the update to the fleet. Alternative (editing the binary in-place without a version bump) would have left agents unaware of the new capabilities.
- **Correct downloads directory was `/var/www/gururmm/downloads/`, not `/opt/gururmm/updates/`**: The server's `DOWNLOADS_DIR` env var (from `/opt/gururmm/.env`) points to the web-accessible path. The `/opt/gururmm/updates/` directory is not scanned. This was discovered when the scanner continued reporting 49 binaries after placing the file in the wrong location.
- **`latest` symlink updated alongside versioned binary**: The `gururmm-agent-linux-amd64-latest` symlink is used by agent self-updaters that don't know the target version ahead of time. Updated atomically with `ln -sf` to point at 0.6.20.
---
## Problems Encountered
- **`format!({}/{}, network, prefix)` compile error**: Missing double quotes around the format string in the subnet CIDR formatting line. Fixed with `sed -i '775s/...'` line-number substitution.
- **`iface.get(ipv4_subnets)` compile error in server**: Same pattern — missing quotes made Rust look for a variable named `ipv4_subnets`. Fixed with `sed -i` on the specific line.
- **Dashboard TS errors — multiple missing string literals**: Python patch scripts applied earlier in the session used heredocs that silently dropped or corrupted string content (backticks executed as commands, quotes stripped). Result: `.join(, )`, `setIpRanges()`, `setSchedule(manual)`, `api.get<string[]>()` (no URL) in the compiled TypeScript. Fixed with targeted `sed -i` and `python3 -c` with `chr(96)` for backtick characters.
- **`_getSensorUnit` TS6133 error**: Prefixing with `_` does not suppress TS6133 for function declarations (only works for parameters/variables). Resolved by deleting the unused function entirely.
- **Binary placed in wrong updates directory**: Placed initial 0.6.20 binary at `/opt/gururmm/updates/` (wrong) instead of `/var/www/gururmm/downloads/` (correct, from `.env`). Scanner continued to report 49 binaries. Found the correct path by reading `.env` and confirmed by comparing `ls` counts vs the scanner's "49 binaries" log output.
---
## Configuration Changes
### Server Source (`/home/guru/gururmm/`)
| File | Change |
|------|--------|
| `agent/Cargo.toml` | Bumped version 0.6.19 → 0.6.20 |
| `agent/src/metrics/mod.rs` | Fixed `format!({}/{}, ...)``format!("{}/{}", ...)` on line 775; added `use if_addrs::IfAddr`, `ipv4_subnets` field, subnet collection block |
| `agent/src/discovery/mod.rs` | Replaced stub `reverse_dns()` with working PTR implementation using `dns_lookup::lookup_addr` in `spawn_blocking` |
| `agent/Cargo.toml` | Added `if-addrs = "0.10"` and `dns-lookup = "2"` |
| `server/src/api/discovery.rs` | Added `get_suggested_subnets` handler; fixed `iface.get("ipv4_subnets")` quote |
| `server/src/api/mod.rs` | Added `.route("/agents/:id/discovery/subnets", get(discovery::get_suggested_subnets))` |
| `server/src/ws/mod.rs` | Added `#[serde(default)] pub ipv4_subnets: Vec<String>` to `NetworkInterface` struct |
| `dashboard/src/api/client.ts` | Added `getSuggestedSubnets` to `discoveryApi`; fixed missing URL in `api.get<string[]>()` |
| `dashboard/src/components/DiscoveryTab.tsx` | Two-effect pattern for subnet auto-population; fixed all missing string literals |
| `dashboard/src/pages/AgentDetail.tsx` | Deleted unused `getSensorUnit` / `_getSensorUnit` function |
### Deployed Artifacts
| Path | Change |
|------|--------|
| `/opt/gururmm/gururmm-server` | Replaced with build from 2026-05-15 14:32 UTC |
| `/var/www/gururmm/dashboard/` | Replaced with dashboard dist from 2026-05-15 14:38 UTC |
| `/var/www/gururmm/downloads/gururmm-agent-linux-amd64-0.6.20` | New — 3.9 MB, sha256 `ed5ce77cd5d9e30ee9f5a73a6904e7f6667041ab9fff798e7d255a905efbf1a2` |
| `/var/www/gururmm/downloads/gururmm-agent-linux-amd64-0.6.20.sha256` | New — companion checksum |
| `/var/www/gururmm/downloads/gururmm-agent-linux-amd64-latest` | Symlink updated: 0.6.19 → 0.6.20 |
---
## Credentials & Secrets
None new.
---
## Infrastructure & Servers
- **GuruRMM Server**: `172.16.3.30:3001` — Rust/Axum, systemd unit `gururmm-server`
- **Downloads dir**: `/var/www/gururmm/downloads/` (configured via `DOWNLOADS_DIR` in `/opt/gururmm/.env`)
- **Dashboard nginx root**: `/var/www/gururmm/dashboard/`
- **Downloads base URL**: `https://rmm-api.azcomputerguru.com/downloads`
- **Scanner interval**: 300s (5 min), configured via `SCAN_INTERVAL_SECS` env var (default 300)
---
## Commands & Outputs
```bash
# Fix format! quote (line 775 of agent/src/metrics/mod.rs)
sed -i '775s/.*/ let cidr = format!("{}\/{}", network, prefix);/' \
/home/guru/gururmm/agent/src/metrics/mod.rs
# Fix server quote (line 301 of server/src/api/discovery.rs)
sed -i '301s/iface.get(ipv4_subnets)/iface.get("ipv4_subnets")/' \
/home/guru/gururmm/server/src/api/discovery.rs
# Fix client.ts backtick URL using chr(96) trick
python3 -c "
path = '/home/guru/gururmm/dashboard/src/api/client.ts'
bt = chr(96)
new_line = ' api.get<string[]>(' + bt + '/api/agents/\${agentId}/discovery/subnets' + bt + '),\n'
lines = open(path).readlines()
for i, line in enumerate(lines):
if 'api.get<string[]>()' in line and 'getSuggestedSubnets' not in line:
lines[i] = new_line
open(path, 'w').writelines(lines)
"
# Deploy server
sudo systemctl stop gururmm-server
sudo cp /home/guru/gururmm/server/target/release/gururmm-server /opt/gururmm/gururmm-server
sudo systemctl start gururmm-server
# Deploy dashboard
sudo cp -r /home/guru/gururmm/dashboard/dist/. /var/www/gururmm/dashboard/
# Place 0.6.20 agent binary
DEST=/var/www/gururmm/downloads/gururmm-agent-linux-amd64-0.6.20
sudo cp /home/guru/gururmm/agent/target/release/gururmm-agent "$DEST"
sudo chmod 755 "$DEST"
sha256sum "$DEST" | awk '{print $1}' | sudo tee "$DEST.sha256" > /dev/null
sudo ln -sf gururmm-agent-linux-amd64-0.6.20 \
/var/www/gururmm/downloads/gururmm-agent-linux-amd64-latest
```
14:47 UTC scan confirmation:
```
INFO gururmm_server::updates::scanner: Scanned 50 agent binaries across 5 platform/arch combinations
INFO gururmm_server::updates::scanner: Agent needs update: 0.6.19 -> 0.6.20 (linux-amd64, channel=stable)
INFO gururmm_server::ws: Dispatching update to connected agent 8cd0440f-... on heartbeat: 0.6.19 -> 0.6.20
INFO gururmm_server::ws: Agent 8cd0440f-... reconnected after update: 0.6.19 -> 0.6.20
```
---
## Pending / Incomplete Tasks
- **Fleet update to 0.6.20**: Rollout underway automatically on heartbeat. Agents update one at a time as they heartbeat. Offline agents will update on next reconnect.
- **AD2 (0.6.1, offline since 2026-04-20)**: Requires physical or VPN access. Unchanged.
- **BB-SERVER enrollment loop**: `duplicate key value violates unique constraint "idx_agents_site_device"` on every WS connect. Agent already enrolled, auth flow re-attempting first-time enrollment. Needs code fix.
- **`unsupported Unicode escape sequence` on hardware inventory for IMC1**: Logged at WARN after 0.6.19 update. Unresolved — likely a problematic character in a serial number or software name field.
- **Policy wiring plan** (`ticklish-questing-stallman.md`): Full end-to-end policy propagation deferred. Server sends ConfigUpdate on connect (wired), agent-side handling not complete.
- **Windows/macOS agents**: Only Linux 0.6.20 built this session. Windows and macOS builds require the `build-agents.sh` script (which handles cross-compilation / signing). Not run this session.
- **LHM bundling in MSI**: LibreHardwareMonitor files not in build pipeline; self-healing download not implemented.
- **Build lock**: No flock on `build-agents.sh` to prevent concurrent invocations.
- **Safesite Glendale MSI machine**: Waiting for user to be away to push DisplayLink driver update.
---
## Reference Information
- **Feature commit**: `0c60d36` — feat: network discovery hostname lookup, subnet auto-detection, fix IP display and new_devices count
- **Version bump commit**: `c97b0f3` — chore: bump agent version to 0.6.20 (hostname lookup + subnet reporting)
- **Gururmm Gitea repo**: `http://172.16.3.20:3000/azcomputerguru/gururmm`
- **Downloads dir**: `/var/www/gururmm/downloads/` (from `DOWNLOADS_DIR` in `/opt/gururmm/.env`)
- **Agent 0.6.20 sha256**: `ed5ce77cd5d9e30ee9f5a73a6904e7f6667041ab9fff798e7d255a905efbf1a2`
- **New API endpoint**: `GET /api/agents/:id/discovery/subnets` → returns `Vec<String>` of CIDR subnets from agent's reported network interfaces
- **Discovery DB fixes**: `server/src/db/discovery.rs``host(ip_address)` instead of `ip_address::text`; `complete_scan()` computes `new_devices` via CTE
- **Subnet field**: agents now report `ipv4_subnets: Vec<String>` alongside `ipv4_addresses` in `NetworkInterface` struct (both agent and server side)
- **PTR lookup**: `agent/src/discovery/mod.rs``dns_lookup::lookup_addr(&ip)` wrapped in `spawn_blocking`