ipmg 3.2.0__tar.gz → 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ipmg-4.0.0/PKG-INFO +254 -0
- ipmg-4.0.0/README.md +202 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/pyproject.toml +20 -12
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/__init__.py +1 -1
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/cli/commands.py +6 -1
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/cli/parser.py +20 -3
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/ui.py +8 -3
- ipmg-4.0.0/src/ipmg/web/network.py +242 -0
- ipmg-4.0.0/src/ipmg/web/server.py +164 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/index.html +2 -2
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/js/app.js +2 -2
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/js/views.js +11 -3
- ipmg-4.0.0/src/ipmg.egg-info/PKG-INFO +254 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg.egg-info/SOURCES.txt +2 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg.egg-info/requires.txt +0 -2
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_commands.py +1 -0
- ipmg-4.0.0/tests/test_web_network.py +263 -0
- ipmg-3.2.0/PKG-INFO +0 -1093
- ipmg-3.2.0/README.md +0 -1040
- ipmg-3.2.0/src/ipmg/web/server.py +0 -117
- ipmg-3.2.0/src/ipmg.egg-info/PKG-INFO +0 -1093
- {ipmg-3.2.0 → ipmg-4.0.0}/LICENSE +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/setup.cfg +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/__main__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/cli/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/cli/completion.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/cli/config.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/cron.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/diff.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/discovery.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/engine.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/health.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/httpcheck.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/neighbours.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/ping.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/portscan.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/security.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/core/wake.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/data/oui.tsv.gz +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/exceptions.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/database.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/file_io.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/incremental.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/notify.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/infrastructure/retention.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/diff_report.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/frames.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/live.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/machine.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/metrics.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/reporting/summary.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/services/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/services/history_service.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/services/scan_service.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/utils/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/utils/helpers.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/__init__.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/app.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/db.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/manager.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/scheduler.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/schemas.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/css/app.css +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/js/api.js +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/js/charts.js +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg/web/static/js/demo.js +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg.egg-info/dependency_links.txt +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg.egg-info/entry_points.txt +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/src/ipmg.egg-info/top_level.txt +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_api_contract.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_completion.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_config.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_contrib.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_database_history.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_diff.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_diff_report.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_discover.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_engine.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_file_io.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_health.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_history_service.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_httpcheck.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_incremental.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_ipv6.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_live.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_machine_output.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_metrics.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_neighbours.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_notify.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_parser.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_ping.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_ping_command.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_portscan.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_retention.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_scan_service.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_schedules.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_tcp_probe.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_ui.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_utils.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_wake.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_web_api.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_web_db.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_web_manager.py +0 -0
- {ipmg-3.2.0 → ipmg-4.0.0}/tests/test_web_server.py +0 -0
ipmg-4.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ipmg
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: Network discovery and change detection: ping sweeps, scan history, and reports for what changed on your network
|
|
5
|
+
Author: Sameer Alam
|
|
6
|
+
Maintainer-email: Sameer Alam <sameeralam3127@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://sameeralam3127.github.io/ipmg/
|
|
9
|
+
Project-URL: Documentation, https://github.com/sameeralam3127/ipmg#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/sameeralam3127/ipmg
|
|
11
|
+
Project-URL: Issues, https://github.com/sameeralam3127/ipmg/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/sameeralam3127/ipmg/releases
|
|
13
|
+
Keywords: ip,network,ping,monitoring,cli,port-scan,network-scanner,ping-sweep,subnet-scanner,homelab,sysadmin
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Internet
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Classifier: Topic :: System :: Monitoring
|
|
24
|
+
Classifier: Intended Audience :: System Administrators
|
|
25
|
+
Classifier: Intended Audience :: Information Technology
|
|
26
|
+
Classifier: Operating System :: OS Independent
|
|
27
|
+
Classifier: Environment :: Console
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: openpyxl>=3.1
|
|
32
|
+
Requires-Dist: rich>=13.0
|
|
33
|
+
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
34
|
+
Provides-Extra: web
|
|
35
|
+
Requires-Dist: fastapi>=0.110; extra == "web"
|
|
36
|
+
Requires-Dist: pydantic>=2.7; extra == "web"
|
|
37
|
+
Requires-Dist: uvicorn>=0.27; extra == "web"
|
|
38
|
+
Requires-Dist: websockets>=12; extra == "web"
|
|
39
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "web"
|
|
40
|
+
Provides-Extra: all
|
|
41
|
+
Requires-Dist: ipmg[web]; extra == "all"
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: ipmg[web]; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
46
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
47
|
+
Requires-Dist: pre-commit>=3.5.0; extra == "dev"
|
|
48
|
+
Requires-Dist: python-semantic-release>=10.5.3; extra == "dev"
|
|
49
|
+
Requires-Dist: httpx>=0.27; extra == "dev"
|
|
50
|
+
Requires-Dist: httpx2>=2.0; extra == "dev"
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# IPMG — IP Management & Ping Monitoring Tool
|
|
54
|
+
|
|
55
|
+
[](https://pypi.org/project/ipmg/)
|
|
56
|
+

|
|
57
|
+

|
|
58
|
+
[](https://github.com/sameeralam3127/ipmg/actions/workflows/publish.yml)
|
|
59
|
+
|
|
60
|
+
**Know what changed on your network since the last scan.**
|
|
61
|
+
|
|
62
|
+
IPMG scans IPs, CIDR blocks, and ranges in parallel, keeps a history of every
|
|
63
|
+
scan, and tells you what moved between two of them: hosts that went offline or
|
|
64
|
+
appeared, IP addresses, hostnames, and MAC addresses that changed, latency that
|
|
65
|
+
shifted, web services that started failing. Every change carries a severity,
|
|
66
|
+
so only the ones that matter reach Slack, Teams, a webhook, or email, or fail a
|
|
67
|
+
cron job or CI step. Use it from the command line or from IPMG Web, a local
|
|
68
|
+
dashboard that works offline.
|
|
69
|
+
|
|
70
|
+
<p align="center">
|
|
71
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-compare.gif" alt="ipmg scans 13 hosts with --stream, printing each one as it answers; a new address is added to the target file; a second scan with --compare reports it as a new host (warning) against the first" width="820">
|
|
72
|
+
</p>
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
curl -sSL https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.sh | bash
|
|
76
|
+
ipmg --discover # scan the network you are on, right now
|
|
77
|
+
ipmg --discover --compare # later: scan again and see what changed
|
|
78
|
+
ipmg web --lan # open the dashboard from any machine on your network
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **Please read:** only scan networks you are authorized to scan. Unauthorized
|
|
82
|
+
> scanning may violate your organization's policies or the law.
|
|
83
|
+
|
|
84
|
+
**Website:** [sameeralam3127.github.io/ipmg](https://sameeralam3127.github.io/ipmg/) ·
|
|
85
|
+
**Live demo:** [IPMG Web with sample data](https://sameeralam3127.github.io/ipmg/demo/) ·
|
|
86
|
+
**Command builder:** [pick what you want, copy the command](https://sameeralam3127.github.io/ipmg/#builder) ·
|
|
87
|
+
**Docs:** [everything else](#documentation)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## What it does
|
|
92
|
+
|
|
93
|
+
- **Scans fast, without root.** IPv4 and IPv6, CIDR blocks, ranges, and
|
|
94
|
+
target files (text, CSV, Excel, JSON), `--threads` hosts at a time, using
|
|
95
|
+
your system's own `ping`.
|
|
96
|
+
- **Finds hosts that block ping** with TCP probes (`--probe icmp,tcp`), and
|
|
97
|
+
checks web services (`--http-check`: status, response time, TLS, certificate
|
|
98
|
+
expiry).
|
|
99
|
+
- **Identifies devices** by reverse DNS name and, on your LAN, by MAC address
|
|
100
|
+
and vendor (`--mac`). Wakes them with Wake-on-LAN (`ipmg wake`).
|
|
101
|
+
- **Remembers every scan** and reports what changed, with severities and
|
|
102
|
+
alerts to Slack, Teams, webhooks, or email.
|
|
103
|
+
- **Fits into automation:** exit codes for cron and CI, a GitHub Action,
|
|
104
|
+
`--json` for scripts, systemd and launchd templates, Prometheus metrics.
|
|
105
|
+
- **IPMG Web**, a local dashboard: live scans, history, changes, inventory,
|
|
106
|
+
and scheduled scans.
|
|
107
|
+
- **Reports** in Excel, CSV, JSON, JSON Lines, and Markdown, written as the
|
|
108
|
+
scan runs, so an interrupted scan keeps its results and can be resumed.
|
|
109
|
+
|
|
110
|
+
[How it compares](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMPARISON.md)
|
|
111
|
+
with nmap, fping, and Uptime Kuma.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Install
|
|
116
|
+
|
|
117
|
+
**Linux and macOS**, on any distribution, with no Python needed:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
curl -sSL https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.sh | bash
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Windows** (PowerShell, no administrator rights):
|
|
124
|
+
|
|
125
|
+
```powershell
|
|
126
|
+
irm https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.ps1 | iex
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Homebrew:** `brew install sameeralam3127/tap/ipmg` ·
|
|
130
|
+
**uv:** `uv tool install --python ">=3.10" "ipmg[web]"` ·
|
|
131
|
+
**pipx:** `pipx install "ipmg[web]"` ·
|
|
132
|
+
**Docker:** `docker run --rm ghcr.io/sameeralam3127/ipmg --input 10.0.0.0/24`
|
|
133
|
+
|
|
134
|
+
IPMG needs Python 3.10 or newer (the installers bring their own) and the
|
|
135
|
+
system `ping` command. Minimal images, version pinning, upgrading from 3.x,
|
|
136
|
+
tab completion, and the systems CI verifies are in the
|
|
137
|
+
[install guide](https://github.com/sameeralam3127/ipmg/blob/main/docs/INSTALL.md).
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Your first scan
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
ipmg --input 192.168.1.0/24 --stream # each host as it answers
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
ipmg X.Y.Z · scan
|
|
149
|
+
ICMP probes only — scan only networks you are authorized to scan.
|
|
150
|
+
|
|
151
|
+
Source 192.168.1.0/24
|
|
152
|
+
Targets 254 hosts
|
|
153
|
+
Config 50 threads · 2s timeout · 1 ping
|
|
154
|
+
|
|
155
|
+
Results
|
|
156
|
+
● Active 12 ━─────────────────────── 4.7%
|
|
157
|
+
● Timeout 242 ━━━━━━━━━━━━━━━━━━━━━━━━ 95.3%
|
|
158
|
+
|
|
159
|
+
254 hosts · 4.7% active · 3.1 ms avg · 5.21s · 2026-10-18 09:15:02
|
|
160
|
+
|
|
161
|
+
Saved results_20261018_091502.xlsx
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Every scan is stored in a local history (`~/.ipmg/dashboard.db`). Scan again
|
|
165
|
+
with `--compare` to see what changed, or open IPMG Web to browse it.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Common tasks
|
|
170
|
+
|
|
171
|
+
| I want to… | Command |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| Scan the network I am on | `ipmg --discover` |
|
|
174
|
+
| Scan hosts listed in a file, plus a few more | `ipmg --input targets.txt 10.0.0.5` |
|
|
175
|
+
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
176
|
+
| Get alerted when something changes | `ipmg --input targets.txt --interval 15 --notify-slack` |
|
|
177
|
+
| Find hosts that block ping | `ipmg --input 10.0.0.0/24 --probe icmp,tcp` |
|
|
178
|
+
| Know which device each address is | `ipmg --discover --resolve --mac` |
|
|
179
|
+
| Check that a web service works | `ipmg --http-check https://intranet.example.com/` |
|
|
180
|
+
| See which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
181
|
+
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
182
|
+
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
183
|
+
| Fail a cron job or CI step when hosts are down | `ipmg --input servers.txt --fail-on-down` |
|
|
184
|
+
| Wake a machine | `ipmg wake AA:BB:CC:DD:EE:FF` |
|
|
185
|
+
| Use the dashboard from another machine | `ipmg web --lan` |
|
|
186
|
+
| Keep it running after logout and reboots | [systemd and launchd templates](https://github.com/sameeralam3127/ipmg/blob/main/docs/SERVICES.md) |
|
|
187
|
+
| See every option | `ipmg --help`, or the [command reference](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMMANDS.md) |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## IPMG Web
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
ipmg web # this machine: opens http://127.0.0.1:8080 in your browser
|
|
195
|
+
ipmg web --lan # any machine on your network: prints the link to open
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
With `--lan`, IPMG Web prints the link with this machine's address and access
|
|
199
|
+
token, checks the firewall, and tells you the exact command that opens the
|
|
200
|
+
port if it is blocked (`sudo ipmg web --open-firewall` opens it only while
|
|
201
|
+
IPMG Web runs). Every request needs the token in that link.
|
|
202
|
+
|
|
203
|
+
<p align="center">
|
|
204
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-web.png" alt="IPMG Web dashboard: scan totals, a status donut of 16 active, 1 timeout and 1 inactive host, a latency trend chart, and a list of recent scans" width="820">
|
|
205
|
+
</p>
|
|
206
|
+
|
|
207
|
+
Dashboard, live monitor, history, changes, inventory with Wake-on-LAN, and
|
|
208
|
+
scheduled scans; see the
|
|
209
|
+
[IPMG Web guide](https://github.com/sameeralam3127/ipmg/blob/main/docs/WEB.md).
|
|
210
|
+
Try it first with the [live demo](https://sameeralam3127.github.io/ipmg/demo/).
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Documentation
|
|
215
|
+
|
|
216
|
+
| Guide | What is in it |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
| [Install](https://github.com/sameeralam3127/ipmg/blob/main/docs/INSTALL.md) | Installers, Docker, pip, Python versions, upgrading from 3.x, tab completion, verified systems |
|
|
219
|
+
| [Command reference](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMMANDS.md) | Every command and flag with examples: targets, probes, HTTP checks, reports, history, change detection, notifications, `ipmg.toml`, exit codes |
|
|
220
|
+
| [IPMG Web](https://github.com/sameeralam3127/ipmg/blob/main/docs/WEB.md) | The dashboard, opening it from other machines, the firewall, scheduled scans, Prometheus metrics |
|
|
221
|
+
| [Web API](https://github.com/sameeralam3127/ipmg/blob/main/docs/API.md) | Scripting IPMG Web over HTTP and WebSocket |
|
|
222
|
+
| [Running as a service](https://github.com/sameeralam3127/ipmg/blob/main/docs/SERVICES.md) | systemd and launchd templates for scheduled scans and IPMG Web |
|
|
223
|
+
| [GitHub Action](https://github.com/sameeralam3127/ipmg/blob/main/docs/GITHUB-ACTION.md) | Reachability checks in CI, before a deploy or on a schedule |
|
|
224
|
+
| [How it compares](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMPARISON.md) | IPMG next to nmap, fping, and Uptime Kuma |
|
|
225
|
+
| [Troubleshooting](https://github.com/sameeralam3127/ipmg/blob/main/docs/TROUBLESHOOTING.md) and [FAQ](https://github.com/sameeralam3127/ipmg/blob/main/docs/FAQ.md) | Install errors, timeouts, slow scans, empty MAC addresses, common questions |
|
|
226
|
+
| [Architecture](https://github.com/sameeralam3127/ipmg/blob/main/docs/ARCHITECTURE.md) | How the code fits together, for contributors |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Security
|
|
231
|
+
|
|
232
|
+
IPMG runs `ping` as a direct process call with no shell, validates every
|
|
233
|
+
target first, and needs no root. IPMG Web listens on `127.0.0.1` unless you
|
|
234
|
+
pass `--lan`, serves everything locally, and requires its access token on
|
|
235
|
+
every request, behind a strict Content-Security-Policy. The only outbound
|
|
236
|
+
requests IPMG makes are the notifications and HTTP checks you ask for. Found a
|
|
237
|
+
vulnerability? See
|
|
238
|
+
[SECURITY.md](https://github.com/sameeralam3127/ipmg/blob/main/.github/SECURITY.md).
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Contributing
|
|
243
|
+
|
|
244
|
+
Contributions are welcome.
|
|
245
|
+
[CONTRIBUTING.md](https://github.com/sameeralam3127/ipmg/blob/main/.github/CONTRIBUTING.md)
|
|
246
|
+
covers the development setup, the tests, and the commit format that drives
|
|
247
|
+
releases, and
|
|
248
|
+
[ARCHITECTURE.md](https://github.com/sameeralam3127/ipmg/blob/main/docs/ARCHITECTURE.md)
|
|
249
|
+
explains the code. Everyone taking part is expected to follow the
|
|
250
|
+
[Code of Conduct](https://github.com/sameeralam3127/ipmg/blob/main/.github/CODE_OF_CONDUCT.md).
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT — free for commercial and personal use.
|
ipmg-4.0.0/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# IPMG — IP Management & Ping Monitoring Tool
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/ipmg/)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
[](https://github.com/sameeralam3127/ipmg/actions/workflows/publish.yml)
|
|
7
|
+
|
|
8
|
+
**Know what changed on your network since the last scan.**
|
|
9
|
+
|
|
10
|
+
IPMG scans IPs, CIDR blocks, and ranges in parallel, keeps a history of every
|
|
11
|
+
scan, and tells you what moved between two of them: hosts that went offline or
|
|
12
|
+
appeared, IP addresses, hostnames, and MAC addresses that changed, latency that
|
|
13
|
+
shifted, web services that started failing. Every change carries a severity,
|
|
14
|
+
so only the ones that matter reach Slack, Teams, a webhook, or email, or fail a
|
|
15
|
+
cron job or CI step. Use it from the command line or from IPMG Web, a local
|
|
16
|
+
dashboard that works offline.
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-compare.gif" alt="ipmg scans 13 hosts with --stream, printing each one as it answers; a new address is added to the target file; a second scan with --compare reports it as a new host (warning) against the first" width="820">
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
curl -sSL https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.sh | bash
|
|
24
|
+
ipmg --discover # scan the network you are on, right now
|
|
25
|
+
ipmg --discover --compare # later: scan again and see what changed
|
|
26
|
+
ipmg web --lan # open the dashboard from any machine on your network
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> **Please read:** only scan networks you are authorized to scan. Unauthorized
|
|
30
|
+
> scanning may violate your organization's policies or the law.
|
|
31
|
+
|
|
32
|
+
**Website:** [sameeralam3127.github.io/ipmg](https://sameeralam3127.github.io/ipmg/) ·
|
|
33
|
+
**Live demo:** [IPMG Web with sample data](https://sameeralam3127.github.io/ipmg/demo/) ·
|
|
34
|
+
**Command builder:** [pick what you want, copy the command](https://sameeralam3127.github.io/ipmg/#builder) ·
|
|
35
|
+
**Docs:** [everything else](#documentation)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## What it does
|
|
40
|
+
|
|
41
|
+
- **Scans fast, without root.** IPv4 and IPv6, CIDR blocks, ranges, and
|
|
42
|
+
target files (text, CSV, Excel, JSON), `--threads` hosts at a time, using
|
|
43
|
+
your system's own `ping`.
|
|
44
|
+
- **Finds hosts that block ping** with TCP probes (`--probe icmp,tcp`), and
|
|
45
|
+
checks web services (`--http-check`: status, response time, TLS, certificate
|
|
46
|
+
expiry).
|
|
47
|
+
- **Identifies devices** by reverse DNS name and, on your LAN, by MAC address
|
|
48
|
+
and vendor (`--mac`). Wakes them with Wake-on-LAN (`ipmg wake`).
|
|
49
|
+
- **Remembers every scan** and reports what changed, with severities and
|
|
50
|
+
alerts to Slack, Teams, webhooks, or email.
|
|
51
|
+
- **Fits into automation:** exit codes for cron and CI, a GitHub Action,
|
|
52
|
+
`--json` for scripts, systemd and launchd templates, Prometheus metrics.
|
|
53
|
+
- **IPMG Web**, a local dashboard: live scans, history, changes, inventory,
|
|
54
|
+
and scheduled scans.
|
|
55
|
+
- **Reports** in Excel, CSV, JSON, JSON Lines, and Markdown, written as the
|
|
56
|
+
scan runs, so an interrupted scan keeps its results and can be resumed.
|
|
57
|
+
|
|
58
|
+
[How it compares](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMPARISON.md)
|
|
59
|
+
with nmap, fping, and Uptime Kuma.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
**Linux and macOS**, on any distribution, with no Python needed:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
curl -sSL https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.sh | bash
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Windows** (PowerShell, no administrator rights):
|
|
72
|
+
|
|
73
|
+
```powershell
|
|
74
|
+
irm https://raw.githubusercontent.com/sameeralam3127/ipmg/main/install.ps1 | iex
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Homebrew:** `brew install sameeralam3127/tap/ipmg` ·
|
|
78
|
+
**uv:** `uv tool install --python ">=3.10" "ipmg[web]"` ·
|
|
79
|
+
**pipx:** `pipx install "ipmg[web]"` ·
|
|
80
|
+
**Docker:** `docker run --rm ghcr.io/sameeralam3127/ipmg --input 10.0.0.0/24`
|
|
81
|
+
|
|
82
|
+
IPMG needs Python 3.10 or newer (the installers bring their own) and the
|
|
83
|
+
system `ping` command. Minimal images, version pinning, upgrading from 3.x,
|
|
84
|
+
tab completion, and the systems CI verifies are in the
|
|
85
|
+
[install guide](https://github.com/sameeralam3127/ipmg/blob/main/docs/INSTALL.md).
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Your first scan
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
ipmg --input 192.168.1.0/24 --stream # each host as it answers
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
ipmg X.Y.Z · scan
|
|
97
|
+
ICMP probes only — scan only networks you are authorized to scan.
|
|
98
|
+
|
|
99
|
+
Source 192.168.1.0/24
|
|
100
|
+
Targets 254 hosts
|
|
101
|
+
Config 50 threads · 2s timeout · 1 ping
|
|
102
|
+
|
|
103
|
+
Results
|
|
104
|
+
● Active 12 ━─────────────────────── 4.7%
|
|
105
|
+
● Timeout 242 ━━━━━━━━━━━━━━━━━━━━━━━━ 95.3%
|
|
106
|
+
|
|
107
|
+
254 hosts · 4.7% active · 3.1 ms avg · 5.21s · 2026-10-18 09:15:02
|
|
108
|
+
|
|
109
|
+
Saved results_20261018_091502.xlsx
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Every scan is stored in a local history (`~/.ipmg/dashboard.db`). Scan again
|
|
113
|
+
with `--compare` to see what changed, or open IPMG Web to browse it.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Common tasks
|
|
118
|
+
|
|
119
|
+
| I want to… | Command |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| Scan the network I am on | `ipmg --discover` |
|
|
122
|
+
| Scan hosts listed in a file, plus a few more | `ipmg --input targets.txt 10.0.0.5` |
|
|
123
|
+
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
124
|
+
| Get alerted when something changes | `ipmg --input targets.txt --interval 15 --notify-slack` |
|
|
125
|
+
| Find hosts that block ping | `ipmg --input 10.0.0.0/24 --probe icmp,tcp` |
|
|
126
|
+
| Know which device each address is | `ipmg --discover --resolve --mac` |
|
|
127
|
+
| Check that a web service works | `ipmg --http-check https://intranet.example.com/` |
|
|
128
|
+
| See which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
129
|
+
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
130
|
+
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
131
|
+
| Fail a cron job or CI step when hosts are down | `ipmg --input servers.txt --fail-on-down` |
|
|
132
|
+
| Wake a machine | `ipmg wake AA:BB:CC:DD:EE:FF` |
|
|
133
|
+
| Use the dashboard from another machine | `ipmg web --lan` |
|
|
134
|
+
| Keep it running after logout and reboots | [systemd and launchd templates](https://github.com/sameeralam3127/ipmg/blob/main/docs/SERVICES.md) |
|
|
135
|
+
| See every option | `ipmg --help`, or the [command reference](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMMANDS.md) |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## IPMG Web
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
ipmg web # this machine: opens http://127.0.0.1:8080 in your browser
|
|
143
|
+
ipmg web --lan # any machine on your network: prints the link to open
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
With `--lan`, IPMG Web prints the link with this machine's address and access
|
|
147
|
+
token, checks the firewall, and tells you the exact command that opens the
|
|
148
|
+
port if it is blocked (`sudo ipmg web --open-firewall` opens it only while
|
|
149
|
+
IPMG Web runs). Every request needs the token in that link.
|
|
150
|
+
|
|
151
|
+
<p align="center">
|
|
152
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-web.png" alt="IPMG Web dashboard: scan totals, a status donut of 16 active, 1 timeout and 1 inactive host, a latency trend chart, and a list of recent scans" width="820">
|
|
153
|
+
</p>
|
|
154
|
+
|
|
155
|
+
Dashboard, live monitor, history, changes, inventory with Wake-on-LAN, and
|
|
156
|
+
scheduled scans; see the
|
|
157
|
+
[IPMG Web guide](https://github.com/sameeralam3127/ipmg/blob/main/docs/WEB.md).
|
|
158
|
+
Try it first with the [live demo](https://sameeralam3127.github.io/ipmg/demo/).
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
| Guide | What is in it |
|
|
165
|
+
| --- | --- |
|
|
166
|
+
| [Install](https://github.com/sameeralam3127/ipmg/blob/main/docs/INSTALL.md) | Installers, Docker, pip, Python versions, upgrading from 3.x, tab completion, verified systems |
|
|
167
|
+
| [Command reference](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMMANDS.md) | Every command and flag with examples: targets, probes, HTTP checks, reports, history, change detection, notifications, `ipmg.toml`, exit codes |
|
|
168
|
+
| [IPMG Web](https://github.com/sameeralam3127/ipmg/blob/main/docs/WEB.md) | The dashboard, opening it from other machines, the firewall, scheduled scans, Prometheus metrics |
|
|
169
|
+
| [Web API](https://github.com/sameeralam3127/ipmg/blob/main/docs/API.md) | Scripting IPMG Web over HTTP and WebSocket |
|
|
170
|
+
| [Running as a service](https://github.com/sameeralam3127/ipmg/blob/main/docs/SERVICES.md) | systemd and launchd templates for scheduled scans and IPMG Web |
|
|
171
|
+
| [GitHub Action](https://github.com/sameeralam3127/ipmg/blob/main/docs/GITHUB-ACTION.md) | Reachability checks in CI, before a deploy or on a schedule |
|
|
172
|
+
| [How it compares](https://github.com/sameeralam3127/ipmg/blob/main/docs/COMPARISON.md) | IPMG next to nmap, fping, and Uptime Kuma |
|
|
173
|
+
| [Troubleshooting](https://github.com/sameeralam3127/ipmg/blob/main/docs/TROUBLESHOOTING.md) and [FAQ](https://github.com/sameeralam3127/ipmg/blob/main/docs/FAQ.md) | Install errors, timeouts, slow scans, empty MAC addresses, common questions |
|
|
174
|
+
| [Architecture](https://github.com/sameeralam3127/ipmg/blob/main/docs/ARCHITECTURE.md) | How the code fits together, for contributors |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Security
|
|
179
|
+
|
|
180
|
+
IPMG runs `ping` as a direct process call with no shell, validates every
|
|
181
|
+
target first, and needs no root. IPMG Web listens on `127.0.0.1` unless you
|
|
182
|
+
pass `--lan`, serves everything locally, and requires its access token on
|
|
183
|
+
every request, behind a strict Content-Security-Policy. The only outbound
|
|
184
|
+
requests IPMG makes are the notifications and HTTP checks you ask for. Found a
|
|
185
|
+
vulnerability? See
|
|
186
|
+
[SECURITY.md](https://github.com/sameeralam3127/ipmg/blob/main/.github/SECURITY.md).
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Contributing
|
|
191
|
+
|
|
192
|
+
Contributions are welcome.
|
|
193
|
+
[CONTRIBUTING.md](https://github.com/sameeralam3127/ipmg/blob/main/.github/CONTRIBUTING.md)
|
|
194
|
+
covers the development setup, the tests, and the commit format that drives
|
|
195
|
+
releases, and
|
|
196
|
+
[ARCHITECTURE.md](https://github.com/sameeralam3127/ipmg/blob/main/docs/ARCHITECTURE.md)
|
|
197
|
+
explains the code. Everyone taking part is expected to follow the
|
|
198
|
+
[Code of Conduct](https://github.com/sameeralam3127/ipmg/blob/main/.github/CODE_OF_CONDUCT.md).
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT — free for commercial and personal use.
|
|
@@ -13,10 +13,10 @@ build-backend = "setuptools.build_meta"
|
|
|
13
13
|
|
|
14
14
|
[project]
|
|
15
15
|
name = "ipmg"
|
|
16
|
-
version = "
|
|
16
|
+
version = "4.0.0" # Managed automatically by semantic-release
|
|
17
17
|
description = "Network discovery and change detection: ping sweeps, scan history, and reports for what changed on your network"
|
|
18
18
|
readme = "README.md"
|
|
19
|
-
requires-python = ">=3.
|
|
19
|
+
requires-python = ">=3.10"
|
|
20
20
|
license = "MIT"
|
|
21
21
|
license-files = ["LICENSE"]
|
|
22
22
|
|
|
@@ -33,7 +33,6 @@ keywords = ["ip", "network", "ping", "monitoring", "cli", "port-scan", "network-
|
|
|
33
33
|
classifiers = [
|
|
34
34
|
"Programming Language :: Python :: 3",
|
|
35
35
|
"Programming Language :: Python :: 3 :: Only",
|
|
36
|
-
"Programming Language :: Python :: 3.9",
|
|
37
36
|
"Programming Language :: Python :: 3.10",
|
|
38
37
|
"Programming Language :: Python :: 3.11",
|
|
39
38
|
"Programming Language :: Python :: 3.12",
|
|
@@ -84,10 +83,10 @@ dev = [
|
|
|
84
83
|
"pre-commit>=3.5.0",
|
|
85
84
|
"python-semantic-release>=10.5.3",
|
|
86
85
|
# The TestClient's HTTP client. Starlette 1.x wants httpx2 and warns
|
|
87
|
-
# about httpx; the Starlette
|
|
88
|
-
#
|
|
86
|
+
# about httpx; the older Starlette the lowest-deps job resolves to
|
|
87
|
+
# predates httpx2 and needs httpx.
|
|
89
88
|
"httpx>=0.27",
|
|
90
|
-
"httpx2>=2.0
|
|
89
|
+
"httpx2>=2.0",
|
|
91
90
|
]
|
|
92
91
|
|
|
93
92
|
[project.scripts]
|
|
@@ -107,10 +106,10 @@ dev = [
|
|
|
107
106
|
"pre-commit>=3.5.0",
|
|
108
107
|
"python-semantic-release>=10.5.3",
|
|
109
108
|
# The TestClient's HTTP client. Starlette 1.x wants httpx2 and warns
|
|
110
|
-
# about httpx; the Starlette
|
|
111
|
-
#
|
|
109
|
+
# about httpx; the older Starlette the lowest-deps job resolves to
|
|
110
|
+
# predates httpx2 and needs httpx.
|
|
112
111
|
"httpx>=0.27",
|
|
113
|
-
"httpx2>=2.0
|
|
112
|
+
"httpx2>=2.0",
|
|
114
113
|
]
|
|
115
114
|
|
|
116
115
|
|
|
@@ -121,7 +120,6 @@ dev = [
|
|
|
121
120
|
# Publishing is done by the workflow (pypa/gh-action-pypi-publish), not by
|
|
122
121
|
# semantic-release itself.
|
|
123
122
|
[tool.semantic_release]
|
|
124
|
-
branch = "main"
|
|
125
123
|
version_toml = ["pyproject.toml:project.version"]
|
|
126
124
|
version_variables = ["src/ipmg/__init__.py:__version__"]
|
|
127
125
|
tag_format = "v{version}"
|
|
@@ -129,6 +127,16 @@ commit_message = "chore(release): {version}"
|
|
|
129
127
|
build_command = "python -m build"
|
|
130
128
|
major_on_zero = false
|
|
131
129
|
|
|
130
|
+
# main releases; v4 releases betas (4.0.0-beta.N) until it merges into main.
|
|
131
|
+
[tool.semantic_release.branches.main]
|
|
132
|
+
match = "^main$"
|
|
133
|
+
prerelease = false
|
|
134
|
+
|
|
135
|
+
[tool.semantic_release.branches.v4]
|
|
136
|
+
match = "^v4$"
|
|
137
|
+
prerelease = true
|
|
138
|
+
prerelease_token = "beta"
|
|
139
|
+
|
|
132
140
|
[tool.semantic_release.changelog.default_templates]
|
|
133
141
|
changelog_file = ".github/CHANGELOG.md"
|
|
134
142
|
|
|
@@ -178,7 +186,7 @@ fail_under = 90
|
|
|
178
186
|
|
|
179
187
|
[tool.ruff]
|
|
180
188
|
line-length = 100
|
|
181
|
-
target-version = "
|
|
189
|
+
target-version = "py310"
|
|
182
190
|
|
|
183
191
|
[tool.ruff.lint]
|
|
184
192
|
select = ["E", "F", "W", "I", "C90"]
|
|
@@ -195,4 +203,4 @@ known-first-party = ["ipmg"]
|
|
|
195
203
|
|
|
196
204
|
[tool.black]
|
|
197
205
|
line-length = 100
|
|
198
|
-
target-version = ["
|
|
206
|
+
target-version = ["py310"]
|
|
@@ -40,6 +40,9 @@ WEB_EXTRA_MISSING = (
|
|
|
40
40
|
" pip install 'ipmg[web]'"
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
+
#: Where ``ipmg web --lan`` listens; only ever used when asked for with --lan.
|
|
44
|
+
ALL_INTERFACES = "0.0.0.0" # nosec B104
|
|
45
|
+
|
|
43
46
|
EXIT_OK = 0
|
|
44
47
|
EXIT_ERROR = 1
|
|
45
48
|
EXIT_CHANGES_DETECTED = 2
|
|
@@ -96,13 +99,15 @@ def _web_command(argv: List[str]) -> int:
|
|
|
96
99
|
raise
|
|
97
100
|
raise IPMGError(WEB_EXTRA_MISSING) from exc
|
|
98
101
|
|
|
102
|
+
host = args.host or (ALL_INTERFACES if args.lan or args.open_firewall else "127.0.0.1")
|
|
99
103
|
run_dashboard(
|
|
100
|
-
host=
|
|
104
|
+
host=host,
|
|
101
105
|
port=args.port,
|
|
102
106
|
open_browser=not args.no_browser,
|
|
103
107
|
db_path=args.db,
|
|
104
108
|
metrics_sources=max(args.metrics_sources, 1) if args.metrics else None,
|
|
105
109
|
max_scans=max(args.max_scans, 1),
|
|
110
|
+
open_firewall=args.open_firewall,
|
|
106
111
|
)
|
|
107
112
|
return EXIT_OK
|
|
108
113
|
|
|
@@ -571,10 +571,19 @@ def build_web_parser() -> argparse.ArgumentParser:
|
|
|
571
571
|
"ipmg web",
|
|
572
572
|
description="Start IPMG Web, the local browser UI.",
|
|
573
573
|
)
|
|
574
|
-
parser.
|
|
574
|
+
where = parser.add_mutually_exclusive_group()
|
|
575
|
+
where.add_argument(
|
|
575
576
|
"--host",
|
|
576
|
-
default=
|
|
577
|
-
help="Interface to bind (default: 127.0.0.1,
|
|
577
|
+
default=None,
|
|
578
|
+
help="Interface to bind (default: 127.0.0.1, this machine only).",
|
|
579
|
+
)
|
|
580
|
+
where.add_argument(
|
|
581
|
+
"--lan",
|
|
582
|
+
action="store_true",
|
|
583
|
+
help=(
|
|
584
|
+
"Let other machines open IPMG Web: listen on every interface (as --host "
|
|
585
|
+
"0.0.0.0) and print the link with this machine's network address."
|
|
586
|
+
),
|
|
578
587
|
)
|
|
579
588
|
parser.add_argument(
|
|
580
589
|
"--port",
|
|
@@ -582,6 +591,14 @@ def build_web_parser() -> argparse.ArgumentParser:
|
|
|
582
591
|
default=8080,
|
|
583
592
|
help="Port to listen on (default: 8080).",
|
|
584
593
|
)
|
|
594
|
+
parser.add_argument(
|
|
595
|
+
"--open-firewall",
|
|
596
|
+
action="store_true",
|
|
597
|
+
help=(
|
|
598
|
+
"Open the port in firewalld or ufw while IPMG Web runs, and close it again "
|
|
599
|
+
"when it stops (needs root; implies --lan)."
|
|
600
|
+
),
|
|
601
|
+
)
|
|
585
602
|
parser.add_argument(
|
|
586
603
|
"--no-browser",
|
|
587
604
|
action="store_true",
|
|
@@ -121,13 +121,18 @@ def heading(title: str) -> None:
|
|
|
121
121
|
console.print(Text(INDENT + title, style="ipmg.heading"))
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
def field(label: str, value: object, value_style: str = "ipmg.value") -> None:
|
|
125
|
-
"""One aligned ``label value`` line.
|
|
124
|
+
def field(label: str, value: object, value_style: str = "ipmg.value", wrap: bool = True) -> None:
|
|
125
|
+
"""One aligned ``label value`` line.
|
|
126
|
+
|
|
127
|
+
``wrap=False`` keeps the value on one line however narrow the terminal,
|
|
128
|
+
for a URL or a command someone will copy: a line break rich inserted
|
|
129
|
+
would end up in the pasted text.
|
|
130
|
+
"""
|
|
126
131
|
text = Text(INDENT)
|
|
127
132
|
# A label as long as the column still gets one space before its value.
|
|
128
133
|
text.append(f"{label:<{LABEL_WIDTH - 1}} ", style="ipmg.label")
|
|
129
134
|
text.append(str(value), style=value_style)
|
|
130
|
-
console.print(text)
|
|
135
|
+
console.print(text, soft_wrap=not wrap)
|
|
131
136
|
|
|
132
137
|
|
|
133
138
|
def fields(pairs: Iterable[Tuple[str, object]]) -> None:
|